目录
一、简介
PyTorch是一个开源的Python机器学习库,基于Torch,用于自然语言处理等应用程序。2017年1月, 由Facebook 人工智能 研究院(FAIR)基于Torch推出了PyTorch。它是一个基于Python的可续计算包,提供两个高级功能:1、具有强大的GPU加速的张量计算(如NumPy)。2、包含自动求导系统的深度神经网络[1]。
二、原理及代码
1、数据准备
我们用美国国家标准与技术研究所的数据集-MNIST。这个数据集有两部分:训练集和测试集,顾名思义训练集是用来训练神经网络的,测试集是用来测试神经网络训练后的效果。训练集由250个人手写的数字构成,其中50%是高中学生,50%是人口普查的工作人员。测试数据集也是同样比例的手写数字。这些图片都是28X28灰度像素的。如:
下载
import torchvision.datasets as dsets
#MNIST dataset
train_dataset = dsets.MNIST(root='/ml/pymnist', #选择数据的根目录
train=True,#选择训练集
transform=None,#不考虑使用数据预处理
download=True #是否从网络上下载图片
)
test_dataset = dsets.MNIST(root='/ml/pymnist',#选择数据的根目录
train=False,#选择测试集
transform=None,#不考虑使用任何数据预处理
download=True #是否从网络上下载图片
)
查看数据
x_train=train_dataset.train_data.numpy().reshape(-1,28*28) #将6万张28X28的图片,转换为一维数组
#print(x_train.shape) #输出;(60000, 784)
imgIndex = 22
#取其中的一个图片
x1 = x_train[imgIndex].reshape(28,28) #将一维数组转换为二阶矩阵 28X28,还原图片矩阵
#print(x1) #输出28X28二维矩阵
y_train = train_dataset.train_labels.numpy() #转换为numpy数据
#print(y_train.shape) #输出torch.Size([60000]) ,有60000张图片的标签,正好与上面图片数量对应
y1 = y_train[imgIndex]
#print(y1) #输出:5
#图片显示
import matplotlib.pyplot as plt
plt.imshow(x1,cmap=plt.cm.binary) #显示图片设置
plt.title("number:" + str(y1))
plt.show()
2、构造神经网络
从上述的数据集我们知道一个图片有28X28 = 784个像素,因此,输入层有784个神经元。隐藏层的神经元可以自定义,这里就设置50个。输出层的神经元个数和数据集元素的类别有关,因为数据集中的数字只有0~9,即只有10种类别,因此,我们将输出层的神经元个数设置为10个。激活函数选择现在比较流行的ReLU函数:
图 ReLU函数图
ReLU函数的特点是:在程序中计算快(因为不需要计算指数);在输入为正数的时候不存在梯度饱和问题。
图 神经元连接
图 神经网络层
Affine表示将输入进行加权求和,然后传给激活函数ReLU,也可以认为是隐藏层的子层。
在输出层中加入了Softmaxwithloss层处理误差。由于Softmaxwithloss层之前没提到,现在介绍一下。
先选择损失函数:
y:输出神经元的真实值
p:输出神经元的预测值
C:输出神经元的个数
其中y是经过编码变为one-hot code,即y中的元素只能有一个是1,其他为0, 这样输出神经元每输出一次,我们就可以告诉它那个输出神经元输出的是正确值。 详细可参考
将预测值代入损失函数L即可求出误差。
3、Python代码实现(训练-效果)
from collections import OrderedDict
import numpy as np
import torch
from torch.utils.data import DataLoader
import torchvision.datasets as dsets
import torchvision.transforms as transforms
import numpy as np
batch_size = 100
#MNIST dataset
train_dataset = dsets.MNIST(root='/ml/pymnist', #选择数据的根目录
train=True,#选择训练集
transform=None,#不考虑使用数据预处理
download=False #是否从网络上下载图片,第一次要选True
)
test_dataset = dsets.MNIST(root='/ml/pymnist',#选择数据的根目录
train=False,#选择测试集
transform=None,#不考虑使用任何数据预处理
download=False#是否从网络上下载图片,第一次要选True
)
x_train=train_dataset.train_data.numpy().reshape(-1,28*28)
y_train_tmp=train_dataset.train_labels.reshape(train_dataset.train_labels.shape[0],1)
y_train=torch.zeros(y_train_tmp.shape[0],10).scatter_(1,y_train_tmp,1).numpy()
#print(y_train)
x_test = test_dataset.test_data.numpy().reshape(-1,28*28)
y_test_tmp = test_dataset.test_labels.reshape(test_dataset.test_labels.shape[0],1)
y_test = torch.zeros(y_test_tmp.shape[0],10).scatter_(1,y_test_tmp,1).numpy()
class Relu:
def __init__(self):
self.x=None
return
def forward(self,x):
self.x=np.maximum(0,x)
out=self.x
return out
def backward(self,dout):
dx=dout
dx[self.x>> np.random.choice(5, 3) 输出array([0, 3, 4]) # random
#在train_size范围内随机选batch_size个数,形成一维数组
#print(batch_mask)
x_batch = x_train[batch_mask] #在总数据中选一小批
#print(x_batch.shape)
y_batch = y_train[batch_mask]
##########################梯度下降法####################################
grad = network.gradient(x_batch,y_batch)
#print("grad",grad)
for key in ('W1','b1','W2','b2'):
network.params[key] -= learning_rate*grad[key] #实现梯度下降学习
############################################################################
loss = network.loss(x_batch,y_batch) # 计算损失值
if num % 100 ==0:
print("loss: ",loss)
#print(x_test.shape,y_test.shape)
print('准确率:',network.accuracy(x_test,y_test)*100,'%') #将10000张图片让其识别,看看正确率
"""
我们随机选一张图片让其识别
"""
x_train=train_dataset.train_data.numpy().reshape(-1,28*28) #将6万张28X28的图片,转换为一维数组
#print(x_train.shape) #输出;(60000, 784)
import random
imgIndex = random.randint(0,x_train.shape[0]) #在60000张图片中任选一张
#取其中的一个图片
x1 = x_train[imgIndex].reshape(28,28) #将一维数组转换为二阶矩阵 28X28,还原图片矩阵
#print(x1) #输出28X28二维矩阵
p = network.predict(x1.reshape(-1,28*28))
p = np.argmax(p,axis=1)
print("预测:",p)
y_train = train_dataset.train_labels.numpy() #转换为numpy数据
#print(y_train.shape) #输出torch.Size([60000]) ,有60000张图片的标签,正好与上面图片数量对应
y1 = y_train[imgIndex]
#print(y1) #输出:5
#图片显示
import matplotlib.pyplot as plt
plt.imshow(x1,cmap=plt.cm.binary) #显示图片设置
plt.title("predicted number:" + str(y1))
plt.show()
训练过程损失函数输出
current epoch is:0
loss: 2.266151231985748
loss: 0.3724026421914155
loss: 0.19832547560691383
loss: 0.22490945327141837
loss: 0.1661208009051106
loss: 0.258948805644127
current epoch is:1
loss: 0.13390206665995094
loss: 0.1320481015568629
loss: 0.07788363928512003
loss: 0.19471398981094826
loss: 0.06045146962828367
loss: 0.22834023219954858
current epoch is:2
loss: 0.08998278435494232
loss: 0.13953232891168038
loss: 0.05586382405036148
loss: 0.058314648911912174
loss: 0.09738683049424073
loss: 0.05205461861693841
current epoch is:3
loss: 0.045705761642539054
loss: 0.12238526156163801
loss: 0.07323083292990847
loss: 0.0800588072480463
loss: 0.06406958008082181
loss: 0.09598045459144477
current epoch is:4
loss: 0.08828214574587279
loss: 0.15144249360478873
loss: 0.08583687343851693
loss: 0.09221907715731381
loss: 0.03905677555959257
loss: 0.0632881118798391
准确率:96.23 %
最后预测正确。
参考
【2】《深度学习与图像识别原理与实践》 魏溪含等著
Original: https://blog.csdn.net/laoxue123456/article/details/121429507
Author: 维度攻城狮
Title: 神经网络实现手写数字识别(代码-训练-效果)- PyTorch框架
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/720379/
转载文章受原作者版权保护。转载请注明原作者出处!