三. 如何实现

1) 全连接层实现

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22  class Autoencoder(nn.Module): def __init__(self, encoding_dim): super(Autoencoder, self).__init__() ## encoder ## self.encoder = nn.Linear(784, encoding_dim) ## decoder ## self.decoder = nn.Linear(encoding_dim, 784) def forward(self, x): # define feedforward behavior # and scale the *output* layer with a sigmoid activation function # print(x.shape) x = x.view(-1, 784) x = F.relu(self.encoder(x)) x = torch.sigmoid(self.decoder(x)) return x # initialize the NN encoding_dim = 128 model = Autoencoder(encoding_dim) 

 1 2 3 4 5  # specify loss function criterion = nn.MSELoss() # specify loss function optimizer = torch.optim.Adam(model.parameters(), lr=0.001) 

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35  # number of epochs to train the model n_epochs = 20 for epoch in range(1, n_epochs+1): # monitor training loss train_loss = 0.0 ################### # train the model # ################### for data in train_loader: # _ stands in for labels, here images, _ = data # flatten images images = images.view(images.size(0), -1) # clear the gradients of all optimized variables optimizer.zero_grad() # forward pass: compute predicted outputs by passing inputs to the model # print(images.shape) outputs = model(images) # calculate the loss loss = criterion(outputs, images) # backward pass: compute gradient of the loss with respect to model parameters loss.backward() # perform a single optimization step (parameter update) optimizer.step() # update running training loss train_loss += loss.item()*images.size(0) # print avg training statistics train_loss = train_loss/len(train_loader) print('Epoch: {} \tTraining Loss: {:.6f}'.format( epoch, train_loss )) 

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20  Epoch: 1 Training Loss: 0.342308 Epoch: 2 Training Loss: 0.081272 Epoch: 3 Training Loss: 0.058724 Epoch: 4 Training Loss: 0.051274 Epoch: 5 Training Loss: 0.047382 Epoch: 6 Training Loss: 0.044760 Epoch: 7 Training Loss: 0.043184 Epoch: 8 Training Loss: 0.042066 Epoch: 9 Training Loss: 0.041246 Epoch: 10 Training Loss: 0.040589 Epoch: 11 Training Loss: 0.040059 Epoch: 12 Training Loss: 0.039646 Epoch: 13 Training Loss: 0.039272 Epoch: 14 Training Loss: 0.038980 Epoch: 15 Training Loss: 0.038733 Epoch: 16 Training Loss: 0.038524 Epoch: 17 Training Loss: 0.038328 Epoch: 18 Training Loss: 0.038162 Epoch: 19 Training Loss: 0.038012 Epoch: 20 Training Loss: 0.037874 

2) 测试: 对有噪声图像的自编码

 1 2 3 4 5 6  a_img = np.squeeze(images[0]) print(a_img.shape) print(np.max(a_img)) print(np.min(a_img)) plt.imshow(a_img, cmap='gray') 

 1 2 3  a_img_x = a_img + 0.08 * np.random.normal(loc=0.0, scale=1.0, size=a_img.shape) plt.imshow(a_img_x, cmap='gray') 

 1 2 3 4 5 6 7  a_img_output = model(torch.Tensor(a_img_x).view(1, -1)) print(a_img_output.shape) output_img = a_img_output.view(28, 28) output_img = output_img.detach().numpy() plt.imshow(output_img, cmap='gray') 

3) 卷积层实现

pytorch实现

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38  import torch.nn as nn import torch.nn.functional as F # define the NN architecture class ConvAutoencoder(nn.Module): def __init__(self): super(ConvAutoencoder, self).__init__() ## encoder layers ## self.conv1 = nn.Conv2d(1, 16, 3, padding=1) self.conv2 = nn.Conv2d(16, 4, 3, padding=1) self.pool = nn.MaxPool2d(2, 2) ## decoder layers ## ## a kernel of 2 and a stride of 2 will increase the spatial dims by 2 self.t_conv1 = nn.ConvTranspose2d(4, 16, 2, stride=2) self.t_conv2 = nn.ConvTranspose2d(16, 1, 2, stride=2) def forward(self, x): ## encode ## ## decode ## ## apply ReLu to all hidden layers *except for the output layer ## apply a sigmoid to the output layer x = F.relu(self.conv1(x)) x = self.pool(x) x = F.relu(self.conv2(x)) x = self.pool(x) x = F.relu(self.t_conv1(x)) x = torch.sigmoid(self.t_conv2(x)) return x # initialize the NN model = ConvAutoencoder() print(model) 

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  Epoch: 1 Training Loss: 0.448799 Epoch: 2 Training Loss: 0.266815 Epoch: 3 Training Loss: 0.251290 Epoch: 4 Training Loss: 0.240823 Epoch: 5 Training Loss: 0.231836 Epoch: 6 Training Loss: 0.220550 Epoch: 7 Training Loss: 0.210341 Epoch: 8 Training Loss: 0.202768 Epoch: 9 Training Loss: 0.197010 Epoch: 10 Training Loss: 0.193259 Epoch: 11 Training Loss: 0.190589 Epoch: 12 Training Loss: 0.188406 Epoch: 13 Training Loss: 0.186529 Epoch: 14 Training Loss: 0.184983 Epoch: 15 Training Loss: 0.183579 

四. 一些小细节

1. numpy 的 squeeze 函数 参考博客 作用：从数组的形状中删除单维度条目，即把shape中为1的维度去掉

2. 给MNIST图片加入噪声的方法

 1  test_img_x = test_img + 0.08 * np.random.normal(loc=0.0, scale=1.0, size=test_img.shape)