内容
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 输入层
输入层的主要功能是对数据进行预处理,以方便后续层的处理。通常的处理步骤是:
- 均值化:使数据的平均值为0,也就是使原点成为数据的中心。
- 标准化:缩放数据,使其落在给定的时间间隔内。
- 线性降维:使用主成分分析法(PCA)对数据进行降维,减少计算量。
2.2 卷积层
CNN的名字便由这一层而来,CNN在“看”一张图片时和我们人很想,我们看一张图片,我们的大脑会将整张图片分为一个个”子图“通过识别这些小部分的特征再整合信息来确定整张图片的内容,CNN也是如此,它在这层会分块扫描整张图片,这称为局部感知,然后在全连接层将这些信息整合处理。
2.3 激励层
这一层的作用于之前讲得激励函数的作用相似,不了解激励函数的同学可以看这里激励函数,就不再赘述了。注意:CNN中一般选取Relu为激励函数
2.4 池化层
池化层的主要功能是压缩数据。我们知道彩色图像是由很多层叠加而成的,池化层的作用就是让图像更厚但尺寸更小,从而减少参数量。有两种主要的池化方法:
- 最大池化(MaxPooling):选取每个“子图”中的最大像素点来替代这整个“子图”。
- 平均池化(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')
文章出处登录后可见!