站点图标 AI技术聚合

基于Pytorch的神经网络之CNN

基于Pytorch的神经网络之CNN

内容

1.引言

2.基本结构

2.1 输入层

2.2 卷积层

2.3 激励层

2.4 池化层

2.5 全连接层

3. 数字识别

3.1 搭建部分

这里主要讲一下神经网络的构建部分。

3.2 效果

3.3 全部代码

1.引言

之前几篇文章简单介绍了一下神经网络的基础知识和简单应用,现在我们来学习一个十分有用的神经网络:卷积神经网络(CNN)。

2.基本结构

CNN可以简单分为五个部分,每一部分有不同的用处。

2.1 输入层

输入层的主要功能是对数据进行预处理,以方便后续层的处理。通常的处理步骤是:

  1. 均值化:使数据的平均值为0,也就是使原点成为数据的中心。
  2. 标准化:缩放数据,使其落在给定的时间间隔内。
  3. 线性降维:使用主成分分析法(PCA)对数据进行降维,减少计算量。

2.2 卷积层

CNN的名字便由这一层而来,CNN在“看”一张图片时和我们人很想,我们看一张图片,我们的大脑会将整张图片分为一个个”子图“通过识别这些小部分的特征再整合信息来确定整张图片的内容,CNN也是如此,它在这层会分块扫描整张图片,这称为局部感知,然后在全连接层将这些信息整合处理。

2.3 激励层

这一层的作用于之前讲得激励函数的作用相似,不了解激励函数的同学可以看这里激励函数,就不再赘述了。注意:CNN中一般选取Relu为激励函数

2.4 池化层

池化层的主要功能是压缩数据。我们知道彩色图像是由很多层叠加而成的,池化层的作用就是让图像更厚但尺寸更小,从而减少参数量。有两种主要的池化方法:

  1. 最大池化(MaxPooling):选取每个“子图”中的最大像素点来替代这整个“子图”。
  2. 平均池化(AvgPooling):计算每个“子图”的平均像素点来替代整个“子图”。

2.5 全连接层

全连接层就是前面提到的传统神经网络的结构,主要是基于线性变换,而“子图”就是把信息整合成一张完整的图的地方。

3. 数字识别

前面讲了那么多,我们来试试CNN的经典应用:图像识别。我们这里来识别的是手写数字,类似于这种:

3.1 搭建部分

这里主要讲一下神经网络的构建部分。

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1=nn.Sequential(
            nn.Conv2d(1,16,5,1,2),
            nn.ReLU(),
            nn.MaxPool2d(2),
        )
        self.conv2=nn.Sequential(
            nn.Conv2d(16, 32, 5, 1, 2),
            nn.ReLU(),
            nn.MaxPool2d(2),
        )
        self.out=nn.Linear(32*7*7,10)    #全连接层

    def forward(self,x):
        x=self.conv1(x)
        x=self.conv2(x)
        x=x.view(x.size(0),-1)
        out=self.out(x)
        return out,x

我们先建立了一个卷积网络self.conv1,首先要注意的是Conv2d的四个参数从左到右分别表示:接收的图像的层数、卷出的图像层数、“子图”的大小、分割时的移动步数、填充的格数。然后MaxPool2d这个函数就实施池化,参数表示缩小的多少,例如这里的2表示图像大小变为原来的1/2,这里我们需要计算一下现在图片的规模,层数为32,大小为7*7,这便是全连接层的输入,最后输出即可。

3.2 效果

我们来看看效果:

这是最终分类的结果,效果还是比较好的

这是最后的错误:

Epoch:  0 | train loss: 0.1272 | test accuracy: 0.99

3.3 全部代码

import os
import torch
import torch.nn as nn
import torch.utils.data as Data     #小批量
import torchvision                  #提供图像数据集
import matplotlib.pyplot as plt     #绘图

#超参数
EPOCH=1
BATCH_SIZE=50
LR=0.001
DOWNLOAD_MNIST=True

#数据下载
if not(os.path.exists('./mnist/'))or not os.listdir('./mnist/'):
    DOWNLOAD_MNIST = True

train_data=torchvision.datasets.MNIST(
    root='./mnist/',
    train=True,
    transform=torchvision.transforms.ToTensor(),
    download=DOWNLOAD_MNIST,
)
#展示下载的数据
# print(train_data.train_data.size())                 # (60000, 28, 28)
# print(train_data.train_labels.size())               # (60000)
# plt.imshow(train_data.train_data[2].numpy(), cmap='gray')
# plt.title('%i' % train_data.train_labels[2])
# plt.show()

#小批量数据
train_loader=Data.DataLoader(dataset=train_data,batch_size=BATCH_SIZE,shuffle=True)

#选择部分数据训练

test_data = torchvision.datasets.MNIST(root='./mnist/', train=False)
test_x = torch.unsqueeze(test_data.test_data, dim=1).type(torch.FloatTensor)[:1000]/255.   # shape from (2000, 28, 28) to (2000, 1, 28, 28), value in range(0,1)
test_y = test_data.test_labels[:1000]

#搭建网络
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1=nn.Sequential(
            nn.Conv2d(1,16,5,1,2),
            nn.ReLU(),
            nn.MaxPool2d(2),
        )
        self.conv2=nn.Sequential(
            nn.Conv2d(16, 32, 5, 1, 2),
            nn.ReLU(),
            nn.MaxPool2d(2),
        )
        self.out=nn.Linear(32*7*7,10)    #全连接层

    def forward(self,x):
        x=self.conv1(x)
        x=self.conv2(x)
        x=x.view(x.size(0),-1)
        out=self.out(x)
        return out,x

cnn=CNN()
print(cnn)

#定义优化器和损失函数
optimizer=torch.optim.Adam(cnn.parameters(),lr=LR)
loss_fun=nn.CrossEntropyLoss()

#可视化
from matplotlib import cm
try: from sklearn.manifold import TSNE; HAS_SK = True
except: HAS_SK = False; print('Please install sklearn for layer visualization')
def plot_with_labels(lowDWeights, labels):
    plt.cla()
    X, Y = lowDWeights[:, 0], lowDWeights[:, 1]
    for x, y, s in zip(X, Y, labels):
        c = cm.rainbow(int(255 * s / 9)); plt.text(x, y, s, backgroundcolor=c, fontsize=9)
    plt.xlim(X.min(), X.max()); plt.ylim(Y.min(), Y.max()); plt.title('Visualize last layer'); plt.show(); plt.pause(0.01)

plt.ion()
for epoch in range(EPOCH):
    for step,(b_x,b_y) in enumerate(train_loader):
        output=cnn(b_x)[0]
        loss=loss_fun(output,b_y)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if step % 50 == 0:
            test_output, last_layer = cnn(test_x)
            pred_y = torch.max(test_output, 1)[1].data.numpy()
            accuracy = float((pred_y == test_y.data.numpy()).astype(int).sum()) / float(test_y.size(0))
            print('Epoch: ', epoch, '| train loss: %.4f' % loss.data.numpy(), '| test accuracy: %.2f' % accuracy)
            if HAS_SK:
                # Visualization of trained flatten layer (T-SNE)
                tsne = TSNE(perplexity=30, n_components=2, init='pca', n_iter=5000)
                plot_only = 500
                low_dim_embs = tsne.fit_transform(last_layer.data.numpy()[:plot_only, :])
                labels = test_y.numpy()[:plot_only]
                plot_with_labels(low_dim_embs, labels)
        plt.ioff()

        # print 10 predictions from test data
        test_output, _ = cnn(test_x[:10])
        pred_y = torch.max(test_output, 1)[1].data.numpy()
        print(pred_y, 'prediction number')
        print(test_y[:10].numpy(), 'real number')

文章出处登录后可见!

已经登录?立即刷新
退出移动版