基于pytorch的简易卷积神经网络结构搭建-卷积神经网络(CNN)浅析

卷积神经网络

卷积神经网络是近些年逐步兴起的一种人工神经网络结构, 因为利用卷积神经网络在图像和语音识别方面能够给出更优预测结果, 这一种技术也被广泛的传播可应用. 卷积神经网络最常被应用的方面是计算机的图像识别, 不过因为不断地创新, 它也被应用在视频分析, 自然语言处理, 药物发现, 等等. 近期最火的 Alpha Go, 让计算机看懂围棋, 同样也是有运用到这门技术.

卷积 神经网络

我们来具体说说卷积神经网络是如何运作的吧, 举一个识别图片的例子, 我们知道神经网络是由一连串的神经层组成,每一层神经层里面有存在有很多的神经元. 这些神经元就是神经网络识别事物的关键. 每一种神经网络都会有输入输出值, 当输入值是图片的时候, 实际上输入神经网络的并不是那些色彩缤纷的图案,而是一堆堆的数字. 就比如说这个. 当神经网络需要处理这么多输入信息的时候, 也就是卷积神经网络就可以发挥它的优势的时候了. 那什么是卷积神经网络呢?

我们先把卷积神经网络这个词拆开来看. “卷积” 和 “神经网络”. 卷积也就是说神经网络不再是对每个像素的输入信息做处理了,而是图片上每一小块像素区域进行处理, 这种做法加强了图片信息的连续性. 使得神经网络能看到图形, 而非一个点. 这种做法同时也加深了神经网络对图片的理解. 具体来说, 卷积神经网络有一个批量过滤器, 持续不断的在图片上滚动收集图片里的信息,每一次收集的时候都只是收集一小块像素区域, 然后把收集来的信息进行整理, 这时候整理出来的信息有了一些实际上的呈现, 比如这时的神经网络能看到一些边缘的图片信息, 然后在以同样的步骤, 用类似的批量过滤器扫过产生的这些边缘信息, 神经网络从这些边缘信息里面总结出更高层的信息结构,比如说总结的边缘能够画出眼睛,鼻子等等. 再经过一次过滤, 脸部的信息也从这些眼睛鼻子的信息中被总结出来. 最后我们再把这些信息套入几层普通的全连接神经层进行分类, 这样就能得到输入的图片能被分为哪一类的结果了.

我们截取一段 google 介绍卷积神经网络的视频, 具体说说图片是如何被卷积的. 下面是一张猫的图片, 图片有长, , 高 三个参数. ! 图片是有高度的! 这里的高指的是计算机用于产生颜色使用的信息. 如果是黑白照片的话, 高的单位就只有1, 如果是彩色照片, 就可能有红绿蓝三种颜色的信息, 这时的高度为3. 我们以彩色照片为例子. 过滤器就是影像中不断移动的东西, 他不断在图片收集小批小批的像素块, 收集完所有信息后, 输出的值, 我们可以理解成是一个高度更高,长和宽更小的”图片”. 这个图片里就能包含一些边缘信息. 然后以同样的步骤再进行多次卷积, 将图片的长宽再压缩, 高度再增加, 就有了对输入图片更深的理解. 将压缩,增高的信息嵌套在普通的分类神经层上,我们就能对这种图片进行分类了.

 

池化(pooling)

研究发现, 在每一次卷积的时候, 神经层可能会无意地丢失一些信息. 这时, 池化 (pooling) 就可以很好地解决这一问题. 而且池化是一个筛选过滤的过程, 能将 layer 中有用的信息筛选出来, 给下一个层分析. 同时也减轻了神经网络的计算负担 (具体细节参考). 也就是说在卷集的时候, 我们不压缩长宽, 尽量地保留更多信息, 压缩的工作就交给池化了,这样的一项附加工作能够很有效的提高准确性. 有了这些技术,我们就可以搭建一个属于我们自己的卷积神经网络啦.

 

流行的 CNN 结构

 

 

 

比较流行的一种搭建结构是这样, 从下到上的顺序, 首先是输入的图片(image), 经过一层卷积层 (convolution), 然后在用池化(pooling)方式处理卷积的信息, 这里使用的是 max pooling 的方式. 然后在经过一次同样的处理, 把得到的第二次处理的信息传入两层全连接的神经层 (fully connected),这也是一般的两层神经网络层,最后在接上一个分类器(classifier)进行分类预测.

卷积神经网络模型

CNN模型 

用一个 class 来建立 CNN 模型. 这个 CNN 整体流程是 卷积(Conv2d) -> 激励函数(ReLU) -> 池化, 向下采样 (MaxPooling) -> 再来一遍 -> 展平多维的卷积成的特征图 -> 接入全连接层 (Linear) -> 输出

训练 

训练, 将 x y 都用 Variable 包起来, 然后放入 cnn 中计算 output, 最后再计算误差. 

--文章根据莫烦python教学而来,下面给出相应的minist手写体训练代码。

  1 import os
  2 
  3 # third-party library
  4 import torch
  5 import torch.nn as nn
  6 import torch.utils.data as Data
  7 import torchvision
  8 import matplotlib.pyplot as plt
  9 
 10 # torch.manual_seed(1)    # reproducible
 11 
 12 # Hyper Parameters
 13 EPOCH = 1               # train the training data n times, to save time, we just train 1 epoch
 14 BATCH_SIZE = 50
 15 LR = 0.001              # learning rate
 16 DOWNLOAD_MNIST = False
 17 
 18 
 19 # Mnist digits dataset
 20 if not(os.path.exists('./mnist/')) or not os.listdir('./mnist/'):
 21     # not mnist dir or mnist is empyt dir
 22     DOWNLOAD_MNIST = True
 23 
 24 train_data = torchvision.datasets.MNIST(
 25     root='./mnist/',
 26     train=True,                                     # this is training data
 27     transform=torchvision.transforms.ToTensor(),    # Converts a PIL.Image or numpy.ndarray to
 28                                                     # torch.FloatTensor of shape (C x H x W) and normalize in the range [0.0, 1.0]
 29     download=DOWNLOAD_MNIST,
 30 )
 31 
 32 # plot one example
 33 print(train_data.train_data.size())                 # (60000, 28, 28)
 34 print(train_data.train_labels.size())               # (60000)
 35 plt.imshow(train_data.train_data[0].numpy(), cmap='gray')
 36 plt.title('%i' % train_data.train_labels[0])
 37 plt.show()
 38 
 39 # Data Loader for easy mini-batch return in training, the image batch shape will be (50, 1, 28, 28)
 40 train_loader = Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)
 41 
 42 # pick 2000 samples to speed up testing
 43 test_data = torchvision.datasets.MNIST(root='./mnist/', train=False)
 44 test_x = torch.unsqueeze(test_data.test_data, dim=1).type(torch.FloatTensor)[:2000]/255.   # shape from (2000, 28, 28) to (2000, 1, 28, 28), value in range(0,1)
 45 test_y = test_data.test_labels[:2000]
 46 
 47 
 48 class CNN(nn.Module):
 49     def __init__(self):
 50         super(CNN, self).__init__()
 51         self.conv1 = nn.Sequential(         # input shape (1, 28, 28)
 52             nn.Conv2d(
 53                 in_channels=1,              # input height  gray just have one level
 54                 out_channels=16,            # n_filters
 55                 kernel_size=5,              # filter size
 56                 stride=1,                   # filter movement/step
 57                 padding=2,                  # if want same width and length of this image after con2d, padding=(kernel_size-1)/2 if stride=1
 58             ),                              # output shape (16, 28, 28)
 59             nn.ReLU(),                      # activation
 60             nn.MaxPool2d(kernel_size=2),    # choose max value in 2x2 area, output shape (16, 14, 14)
 61         )
 62         self.conv2 = nn.Sequential(         # input shape (16, 14, 14)
 63             nn.Conv2d(16, 32, 5, 1, 2),     # output shape (32, 14, 14)
 64             nn.ReLU(),                      # activation
 65             nn.MaxPool2d(2),                # output shape (32, 7, 7)
 66         )
 67         self.out = nn.Linear(32 * 7 * 7, 10)   # fully connected layer, output 10 classes
 68 
 69     def forward(self, x):
 70         x = self.conv1(x)
 71         x = self.conv2(x)
 72         x = x.view(x.size(0), -1)           # flatten the output of conv2 to (batch_size, 32 * 7 * 7)
 73         output = self.out(x)
 74         return output, x    # return x for visualization
 75 
 76 
 77 cnn = CNN()
 78 print(cnn)  # net architecture
 79 
 80 optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)   # optimize all cnn parameters
 81 loss_func = nn.CrossEntropyLoss()                       # the target label is not one-hotted
 82 
 83 # # following function (plot_with_labels) is for visualization, can be ignored if not interested
 84 # from matplotlib import cm
 85 # try: from sklearn.manifold import TSNE; HAS_SK = True
 86 # except: HAS_SK = False; print('Please install sklearn for layer visualization')
 87 # def plot_with_labels(lowDWeights, labels):
 88 #     plt.cla()
 89 #     X, Y = lowDWeights[:, 0], lowDWeights[:, 1]
 90 #     for x, y, s in zip(X, Y, labels):
 91 #         c = cm.rainbow(int(255 * s / 9)); plt.text(x, y, s, backgroundcolor=c, fontsize=9)
 92 #     plt.xlim(X.min(), X.max()); plt.ylim(Y.min(), Y.max()); plt.title('Visualize last layer'); plt.show(); plt.pause(0.01)
 93 #
 94 # plt.ion()
 95 # training and testing
 96 for epoch in range(EPOCH):
 97     for step, (b_x, b_y) in enumerate(train_loader):   # gives batch data, normalize x when iterate train_loader
 98 
 99         output = cnn(b_x)[0]               # cnn output
100         loss = loss_func(output, b_y)   # cross entropy loss
101         optimizer.zero_grad()           # clear gradients for this training step
102         loss.backward()                 # backpropagation, compute gradients
103         optimizer.step()                # apply gradients
104 
105         if step % 50 == 0:
106             test_output, last_layer = cnn(test_x)
107             pred_y = torch.max(test_output, 1)[1].data.squeeze().numpy()
108             accuracy = float((pred_y == test_y.data.numpy()).astype(int).sum()) / float(test_y.size(0))
109             print('Epoch: ', epoch, '| train loss: %.4f' % loss.data.numpy(), '| test accuracy: %.2f' % accuracy)
110 #             if HAS_SK:
111 #                 # Visualization of trained flatten layer (T-SNE)
112 #                 tsne = TSNE(perplexity=30, n_components=2, init='pca', n_iter=5000)
113 #                 plot_only = 500
114 #                 low_dim_embs = tsne.fit_transform(last_layer.data.nump
115 #
116 #
117 #
118 # .y()[:plot_only, :])
119 #                 labels = test_y.numpy()[:plot_only]
120 #                 plot_with_labels(low_dim_embs, labels)
121 # plt.ioff()
122 
123 # print 10 predictions from test data
124 test_output, _ = cnn(test_x[:100])
125 
126 pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze()
127 print(pred_y, 'prediction number')
128 print(test_y[:100].numpy(), 'real number')

 

posted @ 2018-09-27 19:02  宋朝都  阅读(425)  评论(0编辑  收藏  举报