今日疯言疯语:
搭好环境,成功写完demo就成功了一半!作者:司南牧
什么是PyTorch?
它是一个搭建深度学习神经网络python包,里面封装了很多函数和类。使用它我们可以不怎么懂神经网络参数调整细节就可以设计一个神经网络。因为它自带了自动调节参数的功能。并且它的使用模式和python非常像,比tensorflow更直观。所以很多论文会提供用pytorch写的神经网络代码。除了用于搭建神经网络外,由于它能充分利用GPU所以在你有GPU的情况下它是可以代替numpy当做高性能的矩阵运算库。
如何安装pytorch?
注意1:在安装pytorch之前一定要先安装python,然后再安装numpy。 如果你想快速学习下pytorch并且没有安装CUDA那可以直接安装CPU版本的pytorch。这个不用安装额外的软件。 请参考这个pytorch官方指导安装(注意一定要选对正确的python版本,如果你没有安装CUDA那就选None。如果安装了那就需要选择正确的版本号。后面有讲怎么看python版本,和怎么看CUDA版本).
- 小建议:用conda这种方式安装非常慢(真的是很慢,翻了墙也很慢,应该是它提供的源在国外的原因而且还不让在国内弄镜像源),如果你等不了或者你没法用conda安装那就用pip安装吧。
- CUDA是一个软件它的作用是可以让你用GPU加速pytorch里面的计算(不用它也可以只不过计算会慢一些,如果你没有安装cuda我认为初学者不建议先折腾这些,直接用CPU版本的pytorch就可以)。如果你安装了CUDA那就需要判断CUDA的版本号。)
怎么看python是哪个版本?
你在命令行输入python
,下面这个是命令行截图Python 3.7.3
就是python版本。
怎么看安装的cuda是哪个版本?
打开NVIDA的控制面板
然后点击“系统信息”->“组件”,NVCUDA那栏就可以看到cuda的版本
怎么看Pytorch安装好了没有?
你如果在python中能运行import torch
这段代码基本上已经安装好了。
PyTorch使用
我觉得你想使用pytorch大概率是想快速入门搭建一个神经网络。所以我觉得一开始给你讲怎么用pytorch定义变量这种细节,你一定会很不爽。所以我先介绍下深度学习常用经典数据处理流程是什么,再介绍下怎么用pytorch搭建一个神经网络,最后用这个神经网络进行手写数字识别项目实战。
使用神经网络来解决问题,你需要做的6件事
- 加载数据和标签(如手写数字识别中的数据就是一张图片,而一张图片在计算机里面是一个由整数组成的矩阵,它的标签是当前这个图片到底是数字几)
- 设计网络结构(如是共有几层神经网络,每层输入输出的矩阵格式,每层的激活函数是怎样的,当前层到底是卷积层还是循环神经网络层等等),初学者一定要关注输入数据矩阵形状是几乘几,输出数据是几乘几。但是不用关注它具体怎么优化参数。
- 设计损失(误差)函数(以手写数字识别为例,神经网络会输出一个值表明当前这个图片到底是几,但是一开始肯定不准确。所以我们需要计算神经网络输出值与标签之间的误差。而误差计算有很多种我们需要告诉pytorch怎么计算误差。然后pytorch就会自动根据我们设定的误差计算方法去自动调整神经网络的参数)
- 设置用于自动调整神经网络参数的优化器(在上一步我们提到了pytorch会自动帮我们自动调整神经网络的参数,但是具体用哪种优化器去调整参数呢?这需要我们告诉pytorch,因此我们需要用代码设置具体用哪个优化器调整参数)
- 使用数据和标签训练神经网络
- 这个神经网络已经训练好可以用于解决你的问题了。(你只用输入数据,然后用神经网络输出结果即可)
怎么使用pytorch实践上面那7件事?
为了简化数据加载部分,我用伪代码代替数据加载部分。(下面代码不可运行,稍后会给出可以运行的代码)
import torch
# 1. 加载数据和标签
data,label = 加载数据()
# 2. 设计网络结构
model = torch.nn.Sequential(
torch.nn.Linear(第1层输入向量维数, 第1层输出的向量维数), # 输入向量维数其实就是当前这层的“神经元”的个数,输出向量维数和下一层输入向量维数要一样
torch.nn.ReLU(), # 设置前面那一层的激活函数
....
torch.nn.Linear(第n层输入向量维数, 第n层输出向量维数),
torch.nn.ReLU(), # 设置前面那一层的激活函数
)
# 3. 设计损失函数,就是最简单的两点间距离(model_output-lable)^2
loss_fn = torch.nn.MSELoss(reduction='sum')
# 4. 设置用于自动调节神经网络参数的优化器
learning_rate = 1e-4
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
# 5. 训练神经网络
# 5. 训练神经网络(重复训练10次)
for t in range(10):
model_output = model(data)
# 5.1 用所设计算损失(误差)函数计算误差
loss = loss_fn(model_output, label)
# 5.2 每次训练前清零之前计算的梯度(导数)
optimizer.zero_grad()
# 5.3 根据误差反向传播计算误差对各个权重的导数
loss.backward()
# 5.4 根据优化器里面的算法自动调整神经网络权重
optimizer.step()
##########现在你已经训练好了#################
# 6. 用这个神经网络解决你的问题,比如手写数字识别,输入一个图片矩阵,然后模型返回一个数字
result_digit = model(img_mattrix)
完整的PyTorch代码识别手写数字
# -*- coding: utf-8 -*-
import torch
import torchvision
from torchvision import datasets, transforms
# 1. 加载MNIST手写数字数据集数据和标签
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5, ), (0.5, ))])
trainset = datasets.MNIST(root='./data', train=True,
download=True, transform=transform)
trainsetloader = torch.utils.data.DataLoader(trainset, batch_size=20000, shuffle=True)
testset = datasets.MNIST(root='./data', train=True,
download=True, transform=transform)
testsetloader = torch.utils.data.DataLoader(testset, batch_size=20000, shuffle=True)
#######如果你不放心数据有没有加载出可以将图片显示出来看下#######
# dataiter = iter(trainsetloader)
# images, labels = dataiter.next()
# import numpy as np
# import matplotlib.pyplot as plt
# plt.imshow(images[0].numpy().squeeze())
# plt.show()
# print(images.shape)
# print(labels.shape)
##########上面这段是显示图片的代码#############
# 2. 设计网络结构
first_in, first_out, second_out = 28*28, 128, 10
model = torch.nn.Sequential(
torch.nn.Linear(first_in, first_out),
torch.nn.ReLU(),
torch.nn.Linear(first_out, second_out),
)
# 3. 设计损失函数
loss_fn = torch.nn.CrossEntropyLoss()
# 4. 设置用于自动调节神经网络参数的优化器
learning_rate = 1e-4
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
# 5. 训练神经网络(重复训练10次)
for t in range(10):
for i, one_batch in enumerate(trainsetloader,0):
data,label = one_batch
data[0].view(1,784)# 将28x28的图片变成784的向量
data = data.view(data.shape[0],-1)
# 让神经网络根据现有的参数,根据当前的输入计算一个输出
model_output = model(data)
# 5.1 用所设计算损失(误差)函数计算误差
loss = loss_fn(model_output , label)
if i%500 == 0:
print(loss)
# 5.2 每次训练前清零之前计算的梯度(导数)
optimizer.zero_grad()
# 5.3 根据误差反向传播计算误差对各个权重的导数
loss.backward()
# 5.4 根据优化器里面的算法自动调整神经网络权重
optimizer.step()
# 保存下训练好的模型,省得下次再重新训练
torch.save(model,'./my_handwrite_recognize_model.pt')
##########现在你已经训练好了#################
# 6. 用这个神经网络解决你的问题,比如手写数字识别,输入一个图片矩阵,然后模型返回一个数字
testdataiter = iter(testsetloader)
testimages, testlabels = testdataiter.next()
img_vector = testimages[0].squeeze().view(1,-1)
# 模型返回的是一个1x10的矩阵,第几个元素值最大那就是表示模型认为当前图片是数字几
result_digit = model(img_vector)
print("该手写数字图片识别结果为:", result_digit.max(1)[1],"标签为:",testlabels[0])
欢迎关注我的知乎专栏适合初学者的机器学习神经网络理论到实践。
推荐阅读: