目录
2.1.3 torch.nn与torch.nn.functional的区别
课代表的文章:PyTorch 深度学习实践 第9讲_错错莫的博客-CSDN博客
全连接网络 :
1. 手写数字识别的多分类问题
1.1 Softmax
1.2 交叉熵损失
1.2.1 numpy计算交叉熵
import numpy as np
y = np.array([1,0,0])
z = np.array([0.2,0.1,-0.1])
y_pred = np.exp(z) / np.exp(z).sum() #softmax原理
loss = (-y * np.log(y_pred)).sum()
print(loss)
1.2.2 PyTorch计算交叉熵(其中有存疑)
勘误代码:
import torch
y = torch.LongTensor([0]) #将y做成长整型张量 # target: [1]
z = torch.Tensor([0.2,0.1,-0.1]) #上下两行数据的维度不等,所以会报错
criterion = torch.nn.CrossEntropyLoss() # input: [3]
loss = criterion(z,y)
print(loss)
修正:
import torch
#y = torch.LongTensor([0]) #输出:tensor(0.9729) #将y做成长整型张量 # target维度:[1]
y = torch.LongTensor([1]) # 输出: tensor(1.0729)
z = torch.Tensor([[0.2,0.1,-0.1]]) #上下两行数据的维度不等,所以会报错
criterion = torch.nn.CrossEntropyLoss() # input维度:[3]
loss = criterion(z,y)
print(loss)
存疑的理解:
以上理解可能有误,看见的大佬可以指点一下:如下一个奇怪的规律:
1.2.3 Mini-Batch 交叉熵计算
import torch
criterion = torch.nn.CrossEntropyLoss()
Y = torch.LongTensor([2,0,1])
Y_pred1 = torch.Tensor(
[[0.1,0.2,0.9],[1.1,0.1,0.2],[0.2,2.1,0.1]]
)
Y_pred2 = torch.Tensor(
[[0.8,0.2,0.3],[0.2,0.3,0.5],[0.2,0.2,0.5]]
)
l1 = criterion(Y_pred1,Y)
l2 = criterion(Y_pred2,Y)
print('Batch Loss1 =',l1.data,"\nBatch Loss2 =",l2.data)
输出:
Batch Loss1 = tensor(0.4966)
Batch Loss2 = tensor(1.2389)
2. 手写数字识别实战
2.1 导入库
import torch
from torchvision import transforms,datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
2.1.1 torchvision库
Pytorch torchvision库使用详情 - 知乎 (zhihu.com)
tochvision主要处理图像数据,包含一些常用的数据集、模型、转换函数等。torchvision主要包含以下四部分:
(1)torchvision.models: 提供深度学习中各种经典的网络结构、预训练好的模型,如:Alex-Net、VGG、ResNet、Inception等。
(2)torchvision.datasets:提供常用的数据集,设计上继承 torch.utils.data.Dataset,主要包括:MNIST、CIFAR10/100、ImageNet、COCO等。torchvision.datasets是从torch.utils.data.Dataset的子类,可以使用torch.utils.data.DataLoader进行多线程处理。
示例:加载MNIST:
from torchvision import datasets
dataset = datasets.MNIST('data/', download=True, train=False, transform=None)
(3)torchvision.transforms:提供常用的数据预处理操作,主要包括对Tensor及PIL Image对象的操作。
(4)torchvision.utils:工具类,如保存张量作为图像到磁盘,给一个小批量创建一个图像网格。
2.1.2 torch.utils.data
这个package包含数据读取预处理的一些类,其中两个最常用的类:class torch.utils.data.Dataset 和 class torch.utils.data.DataLoader。
(1)生成数据集:class torch.utils.data.Dataset
(2)加载数据集: torch.utils.data.DataLoader
torch.utils.data_爱钻研的小铭的博客-CSDN博客_torch.utils.data
torch.utils.data - PyTorch中文文档 (pytorch-cn.readthedocs.io)
2.1.3 torch.nn与torch.nn.functional的区别
参考文献:
【pytorch】torch.nn 与 torch.nn.functional 的区别_One__Way的博客-CSDN博客_torch.nn.functional torch.nn库和torch.nn.functional库_jk英菲尼迪的博客-CSDN博客_torch.nn.functional
类型:
(1) torch.nn中包含的是封装好的类,继承自nn.Module,调用时先实例化,然后在__init__()中初始化,再在forward()中进行操作。
(2) torch.nn.functional中包含的是实现好的函数,直接通过接口调用。
2.1.4 torch.optim
torch.optim - PyTorch中文文档 (pytorch-cn.readthedocs.io)
PyTorch学习之 torch.optim 的6种优化器及优化算法介绍_Line_Walker的博客-CSDN博客_lr_decay
PyTorch中的optimizer几种优化方法:
其中的6种方法分为2大类:一大类方法是SGD及其改进(加Momentum);另外一大类是Per-parameter adaptive learning rate methods(逐参数适应学习率方法),包括AdaGrad、RMSProp、Adam等。
2.2 准备数据集
2.2.1 transforms.Compose()函数
transforms.Compose()函数_马鹏森的博客-CSDN博客_transforms.compose
torchvision.transforms是pytorch中的图像预处理包。一般用Compose把多个步骤整合到一起:
transforms.Compose([
transforms.CenterCrop(10),
transforms.ToTensor(),
])
这样就把两个步骤整合到了一起。
介绍transforms中的函数:
2.3 构建网络模型
2.4 计算损失,选择优化器
2.5 训练
3.完整代码
import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
# step1:准备数据集
batch_size = 64
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]) # 归一化,均值和方差
#准备并加载训练集
train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
#准备并加载测试集
test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform)
test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
# step2:构建网络模型:继承torch.nn.Module类
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.l1 = torch.nn.Linear(784, 512)
self.l2 = torch.nn.Linear(512, 256)
self.l3 = torch.nn.Linear(256, 128)
self.l4 = torch.nn.Linear(128, 64)
self.l5 = torch.nn.Linear(64, 10)
def forward(self, x):
x = x.view(-1, 784) # -1其实就是自动获取mini_batch
x = F.relu(self.l1(x))
x = F.relu(self.l2(x))
x = F.relu(self.l3(x))
x = F.relu(self.l4(x))
return self.l5(x) # 最后一层不做激活,不进行非线性变换
model = Net()
# step3:construct loss and optimizer
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
# step4:training cycle forward, backward, update
def train(epoch):
running_loss = 0.0
for batch_idx, data in enumerate(train_loader, 0):
# 获得一个批次的数据和标签
inputs, target = data
optimizer.zero_grad()
# 获得模型预测结果(64, 10)
outputs = model(inputs)
# 交叉熵代价函数outputs(64,10),target(64)
loss = criterion(outputs, target)
loss.backward()
optimizer.step()
running_loss += loss.item()
if batch_idx % 300 == 299:
print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
running_loss = 0.0
def test():
correct = 0
total = 0
with torch.no_grad():
for data in test_loader:
images, labels = data
outputs = model(images)
_, predicted = torch.max(outputs.data, dim=1) # dim = 1 列是第0个维度,行是第1个维度
total += labels.size(0)
correct += (predicted == labels).sum().item() # 张量之间的比较运算
print('accuracy on test set: %d %% ' % (100 * correct / total))
if __name__ == '__main__':
for epoch in range(10):
train(epoch)
test()