本篇主讲神经网络,涉及感知机、激活函数、计算图、CNN等,以笔记与实践形式展开。
感知机是最早的监督式学习算法,是神经网络和支持向量机的基础。感知机接收多个输入信号,输出一个信号。
神经网络由输入层、中间层、输出层结构组成。与感知机不同是多输入多输出。
激活函数是连接感知机和神经网络的桥梁。神经网络使用的激活函数有 :Sigmoid函数;阶跃函数;ReLU函数。
神经网络实现:先定义一些符号,如定义权重、神经元及输入层神经元等。在此上各层信号实现传递
下面用神经网络进行手写数字识别,分别介绍MNIST 数据集、神经网络的推理处理和批处理。过程步骤为:装数据,构建神经网络,训练网络及可视化。
MNIST数据集由从0到9的数字图像构成。MNIST数据集的一般使用方法是,先用训练图像进行学习,再用学习到的模型衡量能多大程度地对测试图像进行正确的分类。
- import torch
- from torch import nn
- from torch.nn import functional as F
- from torch import optim
-
- import torchvision
- from matplotlib import pyplot as plot
- from utils import plot_image, plot_curve, one_hot, save_data
-
-
-
- batch_size = 512
-
-
- train_loader = torch.utils.data.DataLoader(
- torchvision.datasets.MNIST('mnist_data', train=True, download=True,
- transform=torchvision.transforms.Compose([
- torchvision.transforms.ToTensor(),
- torchvision.transforms.Normalize(
- (0.1307,), (0.3081,))
- ])),
- batch_size=batch_size, shuffle=True)
-
- test_loader = torch.utils.data.DataLoader(
- torchvision.datasets.MNIST('mnist_data/', train=False, download=True,
- transform=torchvision.transforms.Compose([
- torchvision.transforms.ToTensor(),
- torchvision.transforms.Normalize(
- (0.1307,), (0.3081,))
- ])),
- batch_size=batch_size, shuffle=False)
-
- x,y = next(iter(train_loader))
- print(x.shape,y.shape,x.min(),y.min())
-
-
-
- class Net(nn.Module):
-
- def __init__(self):
- super(Net, self).__init__()
-
-
- self.fc1 = nn.Linear(28*28, 256)
- self.fc2 = nn.Linear(256, 64)
- self.fc3 = nn.Linear(64, 10)
-
- def forward(self, x):
-
-
- x = F.relu(self.fc1(x))
-
- x = F.relu(self.fc2(x))
-
- x = self.fc3(x)
-
- return x
-
- def backward(self, x):
-
-
- x = F.relu(self.fc1(x))
-
- x = F.relu(self.fc2(x))
-
- x = self.fc3(x)
-
- return x
-
- net = Net()
- optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9)
- train_loss = []
- for epoch in range(10):
- for idx,(x,y) in enumerate(train_loader):
- x = x.view(x.size(0),28*28)
-
- out = net(x)
- y_onehot = one_hot(y)
- loss = F.mse_loss(out,y_onehot)
- optimizer.zero_grad()
- loss.backward()
- optimizer.step()
- train_loss.append(loss.item())
- if idx %10 ==0:
- print(epoch,idx,loss.item())
-
- save_data(train_loss,'train_loss.csv')
- plot_curve(train_loss)
-
- total_correct = 0
- for x,y in test_loader:
- x = x.view(x.size(0),28*28)
- out = net(x)
- pred = out.argmax(dim = 1)
- correct = pred.eq(y).sum().float().item()
- total_correct+=correct
- total_num = len(test_loader.dataset)
- acc = total_correct / total_num
-
- print("acuccy",acc)
-
- x,y = next(iter(test_loader))
- out = net(x.view(x.size(0),28*28))
- pred = out.argmax(dim = 1)
- plot_image(x,pred,"test")
-
-
-
仿真运行,第一次会下载MNIST数据集,随后生成可视化训练迭代损失曲线,可以看到是下降趋势,并将数据保存到train_loss.csv文件。
图1:训练迭代损失曲线
图2:测试手写数字识别结果
可以看到仿真在从0到9一直比对完,然后打印出了准确率。对数字识别很直观。
计算图可以将计算过程用图形表示,图形指数据结构图,由多节点和边表示。链式法则的定义如下;如果某个函数由复合函数表示,那么其导数可以用构成复合函数的各个函数的导数的乘积表示。将计算图的思路应用于神经网络,把构成神经网络的层作为一个类进行实现。首先,实现对应于激活函数的 ReLU 层和 Sigmoid 层。
神经网络的训练目的是找到使损失函数的值尽可能小的参数。寻找最优参数的过程称为最优化(Optimization)。在梯度下降算法中,将参数的梯度(导数)作为线索,沿梯度方向更新参数,并不断重复这个步骤,直到找到最优参数,这个过程称为随机梯度下降(Stochastic Gradient Descent,SGD)。
卷积神经网络(Convolutional Neural Network,CNN)。CNN 可用于图像识别、语音识别等场合。CNN 中包含了新的卷积层(Convolution层)和池化层(Pooling层)。卷积层进行卷积运算,卷积运算相当于图像处理中的“滤波器运算”。卷积层有填充、步幅的概念。在进行卷积层的处理前,有时要向输入数据的四周填入固定的数据(比如0等),这称为填充(padding),填充在卷积运算中经常会用到。应用波器的位置间隔称为步幅(stride).
在神经网络的实现中,卷积运算也可以进行批处理,实现处理的高效化。池化是一种缩小高、宽方向上的空间的运算。
神经网络部分设计的理论知识比较多,也有比较多的概念与数学公式,更多的学习在于积累与实践,多思考归纳总结勤动手,常读常新,会有很多新的收获。