Time: 2019-08-04
链接:https://youtu.be/0VCOG8IeVf8?list=PLZbbT5o_s2xrfNyHZsM6ufI0iZENK9xgG
训练神经网络的7个步骤
- 从训练集中获取batch
- 将batch传递到网络
- 计算损失函数(网络输出值与真实值之间差异) -- Loss
- 计算损失函数相对于权重的梯度 -- BP算法
- 使用梯度更新权重降低损失 -- Optimizer
- 重复1-5,直到该epoch完成
- 重复1-6,用尽可能多的epoch直到比较好的准确度达成
Epoch:一次完全遍历训练样本的过程。
完整的网络以及数据加载代码
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
torch.set_printoptions(linewidth=120)
torch.set_grad_enabled(True) # 默认值,参数可更新
def get_num_correct(preds, labels):
return preds.argmax(dim=1).eq(labels).sum()
# 构建网络
class Network(nn.Module):
def __init__(self):
super(Network, self).__init__()
self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)
self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5)
self.fc1 = nn.Linear(in_features=12*4*4, out_features=120)
self.fc2 = nn.Linear(in_features=120, out_features=60)
self.out = nn.Linear(in_features=60, out_features=10)
def forward(self, t):
t = F.relu(self.conv1(t))
t = F.max_pool2d(t, kernel_size=2, stride=2)
t = F.relu(self.conv2 (t))
t = F.max_pool2d(t, kernel_size=2, stride=2)
t = F.relu(self.fc1(t.reshape(-1, 12*4*4)))
t = F.relu(self.fc2(t))
t = self.out(t)
return t
# 准备数据集
train_set = torchvision.datasets.FashionMNIST(
root='./data/FashionMNIST',
download=True,
train=True,
transform=transforms.Compose([
transforms.ToTensor()
])
)
# 实例化网络
network = Network()
# 数据加载器,准备batch
train_data_loader = torch.utils.data.DataLoader(train_set, batch_size=100)
batch = next(iter(train_data_loader))
images, labels = batch
images.shape # torch.Size([100, 1, 28, 28])
计算损失函数,梯度,更新参数的过程
# Loss:
preds = network(images)
loss = F.cross_entropy(preds, labels)
# Gradients
loss.backward() # 计算梯度
print(network.conv1.weight.grad) # 打印梯度
print(network.conv1.weight.grad.shape) # 梯度形状
# Optimizer用于更新参数,决定了更新的方式
optimizer = optim.Adam(network.parameters(), lr=0.01)
loss.item() # 2.308018684387207
# 更新参数
optimizer.step()
preds = network(images)
loss = F.cross_entropy(preds, labels)
loss.item() # 2.277029275894165
一个完整的batch训练样例
network = Network()
train_loader = torch.utils.data.DataLoader(train_set, batch_size=100)
optimizer = optim.Adam(network.parameters(), lr=0.01)
batch = next(iter(train_loader)) # 获取batch
images, labels = batch
preds = network(images) # 传入一个batch
loss = F.cross_entropy(preds, labels) # 计算损失函数
loss.backward() # 计算梯度
optimizer.step() # 一个批次更新参数
#------------------
print("loss1: ", loss.item()) # loss是个标量
preds = network(images) # 用新的参数再计算一下网络输出
loss = F.cross_entropy(preds, labels)
print("loss2: ", loss.item())
总结
PyTorch的流程设计是我用过的几个框架中最Pythonic的,也是最清晰,最好用的。
每个阶段要做的事情极为清晰,使得每个概念的落地也非常自然,多写几遍demo就能感受到整个深度学习流程。
torch.nn
和torch.nn.functional
的分离,前者是用于设定可更新参数的函数,后者则是不含参数更新的功能性的函数,乍一看不是很清晰为啥还分了两个,用起来才发现,这个设计真的好极了。
优化器的设定中,第一个参数是网络的参数,这个很自然,因为优化的目标就是网络的可学习参数,其次还可以设定关于优化器的超参数,还有优化器本身就有很多类别,这是更高一层的超参数选择问题。
END.
网友评论