PyTorch_Task1_诗旋
1、什么是Pytorch,为什么选择Pytroch?
根据Pytorch中文官网,PyTorch是使用GPU和CPU优化的深度学习张量库。PyTorch既可以看作加入了GPU支持的numpy,同时也可以看成一个拥有自动求导功能的强大的深度神经网络。除了Facebook外,它已经被Twitter、CMU和Salesforce等机构采用。
简而言之,是一个神经网络Python库。
2、Pytroch的安装
根据官网 https://pytorch.org/get-started/locally/ :
选择与自己相匹配的环境:
conda install pytorch-cpu torchvision-cpu -c pytorch
显示安装成功
3、配置Python环境
由于之前已经安装过Anaconda和Python,并已经添加环境变量。
当然,可以在base之外再添加一个新的环境。
4、准备Python管理器
已经安装过Anaconda
5、通过命令行安装PyTorch
conda install pytorch-cpu torchvision-cpu -c pytorch
6、PyTorch基础概念
待完善
7、通用代码实现流程(实现一个深度学习的代码流程)
受限于个人水平,这里参考 https://github.com/BI4O/ML_git_repos/blob/master/pytorch_learning/pytorch手写数字识别.ipynb 实例进行了复现
// Example of PyTorch
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
import matplotlib.pyplot as plt
import torch
import torch.nn.functional as F
from torch import nn
from torchvision import datasets, transforms
# images 2 Vectors 定义转换器
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize([0.5], [0.5])
])
# 下载数据并转换
trainset = datasets.MNIST('MNIST_data/',
download=True,
train=True,
transform=transform)
# 定义数据加载器(可迭代对象,每次取出64个样本)
trainloader = torch.utils.data.DataLoader(trainset,
batch_size=64,
shuffle=True)
# 查看转换后的数据
dataiter = iter(trainloader)
images, labels = dataiter.next()
print(type(images)) # torch.Tensor
print(images.shape) # 64个,1厚度,28宽,28高
print(labels.shape) # 64 表示只包含64个元素的向量
plt.imshow(images[60].numpy().squeeze(),cmap='Greys_r')
print(labels[60])
class Num_Identify(nn.Module):
def __init__(self):
super().__init__()
self.h1 = nn.Linear(784,128) # 输入层有784单元,即28x28
self.h2 = nn.Linear(128, 64)
self.output = nn.Linear(64, 10)
def forward(self, x):
x = x.view(x.shape[0],784) # images 2 vector 不知道为啥输入(64,-1)会报错
x = F.relu(self.h1(x))
x = F.relu(self.h2(x))
x = F.softmax(self.output(x), dim=1) # 注意,dim=1是指跨列方向求softmax,因为一行是一个样本
return x
# 从迭代器中拿出一份(64个)样本数据
images_test, labels_test = next(iter(trainloader))
# 运行模型
my_model = Num_Identify()
output_test = my_model(images_test)
# 得到一个64x10的概率分布,注意最后一层中softmax函数输出的是一个概率分布
print(output_test.shape,images_test.shape[0])
# 取第一个样本看,实际值为7
# 预测的概率分布0-9的概率都接近却不严格等于0.1,这是因为模型自动初始化了w和b,但可认为此时模型没有偏向选择
print("第一个样本的标签:",labels_test[0],"\n第一个样本的模型预测概率分布:\n",output_test[0])
# 输出取对数,要去玩对数才可以放进NLLLoss中
log_output_test = torch.log(output_test)
# 定义损失函数
loss_function = nn.NLLLoss() # nn.CrossEntropyLoss()一样的结果,但交叉熵会在前面多一步softmax,我们模型里已经有了
loss = loss_function(log_output_test,labels_test) # 注意输入时候的顺序,前面是模型结果,后面是真实值,他们的维度是不一样的
loss,output_test.shape,labels_test.shape,images_test.shape # 可以看到初始误差为2.3227
from torch import optim
# 优化器需要传入模型的参数(记得加括号)和学习率,这里用批量梯度batch gradient decent下降
optimizer = optim.Adam(my_model.parameters(), lr=0.003)
# 程序运行时间
import time
start = time.time()
# 进行损失函数的优化
epochs = 5 # 遍历整个数据集5次
for e in range(epochs):
# 损失函数容器
running_loss = 0
for images, labels in trainloader: # 批次:每次取64个
# 梯度清零
optimizer.zero_grad()
# 向前传播
output = my_model(images)
log_output = torch.log(output)
# 计算损失
loss = loss_function(log_output, labels)
# 反向传播
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f'Training loss:{running_loss/len(trainloader)}')
stop = time.time()
execution_time = stop - start
execution_time
import random
n = random.randint(1,64)
images3,labels3 = next(iter(trainloader))
print('batch_shape\n',images3.shape,'label_shape\n',labels3.shape)
# 打印其中一个样本的shape和图形
print('batch中取第%d个样本' %n,images3[n].shape)
plt.imshow(images3[n].numpy().squeeze(),cmap='Greys_r')
# 打印真实值
print('\n真实值:',labels3[n])
# 打印预测值
predict_ps = my_model(images3) # 32x10
# dim=1 也就是跨列比较,取每行最大的值top_p,以及最大的值对应的列索引top_class
top_p, top_class = predict_ps.topk(1, dim=1)
print('\n预测值:',top_class[n])
print('\n该值预测概率:',top_p[n])