李宏毅机器学习——pytorch
什么是pytorch
python机器学习框架,Facebook提出,主要有一下两个特点
-
使用GPU加速高维矩阵的运算
torch.cuda.is_available() x = x.to('cuda')
-
可以很方便的实现梯度的计算
requires_grad=True
指定需要对变量x计算梯度z是x的函数,调用
z.backward()
反向传播计算梯度x.grad
属性存放z对x的梯度
如何使用pytorch训练和测试神经网络
-
加载数据
训练数据 & 测试数据
使用pytorch提供的Dataset和DataLoader
-
定义网络模型
pytorch提供torch.nn.Model,可以很方便的实现全连接层、卷积层、池化层等
-
定义损失函数
pytorch提供MSELoss(均方误差),CrossEntropyLoss(交叉熵损失)等损失函数
-
选择优化器
选择优化算法,SGD
-
开始训练
-
测试
Dataset & DataLoader
from torch.utils.data import Dataset, DataLoader
class MyDataset(Dataset): # 重写Dataset三个函数inti, getitem, len
def __init__(self, file): # 读取数据 + 预处理
self.data = xxx
def __getitem__(self, index): # 根据索引返回一个样本
return self.data[index]
def __len__(self): # 返回数据集的总量
return len(self.data)
Tensor
高维矩阵 —— 张量(tensor),pytorch中处理数据的类型
通过.shape()
检查数据的维度
Define Model
定义网络模型
-
Linear Layer(Fully-connected Layer)
线性层/全连接层
nn.Linear(in_features, out_features)
-
Non-Linear Activation Functions
非线性激活函数
- nn.Sigmoid()
- nn.ReLU()
-
完整创建神经网络
- 自定义模型类重写
nn.Model
- 初始化模型,定义各层
- 重写前向传播方法
forward
import torch.nn as nn class MyModel(nn.Model): def __init__(self): super(MyModel, self).__init__() self.net = nn.Sequential( nn.Linear(10, 32), nn.Sigmoid(), nn.Linear(32, 1) ) def forward(self, x): return self.net(x) # 上面使用了nn.Sequential方法,和下方的方式等价 class MyModel(nn.Model): def __init__(self): super(MyModel, self).__init__() self.layer1 = nn.Linear(10, 32), self.layer2 = nn.Sigmoid(), self.layer3 = nn.Linear(32, 1) def forward(self, x): out = self.layer1(x) out = self.layer2(out) out = self.layer3(out) return out
- 自定义模型类重写
Loss Functions
损失函数
-
Mean Square Error
适用于回归问题的损失函数
criterion = nn.MSELoss()
-
Cross Entropy
criterion = nn.CrossEntropyLoss()
# 计算损失函数
# model_output:模型的预测结果;expected_value:训练数据的真实值
loss = criterion(model_output, expected_value)
torch.optim
优化算法
Stochastic Gradient Descent(SGD)
optimizer = torch.nn.SGD(model.parameters(), lr, momentum=0)
对于每一批训练数据
- 调用
optimizer.zero_grad()
,将上一批计算的梯度归零 - 调用
loss.backward()
反向传播计算梯度 - 调用
optimizer.step()
根据梯度调整模型参数
训练 & 验证 & 测试
# ---------------------------- 准备工作 -----------------------------------
dataset = MyDataset(file) # 通过MyDataset读取数据
tr_set = DataLoader(dataset, 16, shuffle=True) # 使用DataLoader给数据分批
model = MyModel.to(device) # 将模型放在相应的device上进行训练(cpu/cuda)
criterion = nn.MSELoss() # 定义均方误差损失函数
optimizer = nn.optim.SGD(model.parameters(), lr=0.1) # 设置优化器
# ---------------------------- 训练过程 -----------------------------------
for epoch in range(n_epochs): # 训练n_epochs轮
model.train() # 将模型设置为训练模式
for x, y in tr_set: # 对于一个batch中的所有训练样本
oprimizer.zero_grad() # 梯度清零(随机梯度下降)
x, y = x.to(device), y.to(device) # 将数据放到相应device上进行运算
pred = model(x) # 前向传播,求预测值pred
loss = criterion(pred, y) # 计算损失
loss.backward() # 反向传播计算梯度
optimizer.step() # 根据梯度更新模型参数
# ---------------------------- 验证过程 -----------------------------------
model.eval() # 将模型设置为验证模式
total_loss = 0.0
for x, y in dv_set:
x, y = x.to(device), y.to(device)
with torch.no_grad(): # 设置模型不进行梯度的计算
pred = model(x)
loss = criterion(pred, y)
total_loss += loss.cpu().item() * len(x)
avg_loss = total_loss / len(dv_set.dataset)
# ---------------------------- 测试过程 -----------------------------------
model.eval()
preds = []
for x in tt_set:
x = x.to(device)
with torch.no_grad():
pred = model(x)
preds.append(pred.cpu())
注意:
-
model.train() & model.eval()
模型中的一些层在训练和测试的表现并不相同,如:dropout、batch-normalization,在训练时需要指定
model.train
,在验证和测试时需要指定model.eval()
,以确保这样的层分别在训练和测试时按照不同的方式运行 -
with torch.no_grad()
在验证和测试时,不应该计算梯度和更新参数,只因该观察训练过的模型在此的表现。如果不关掉这个的话,相当于”泄题“
保存/加载模型参数
-
Save
torch.save(model.state_dict(), path)
-
Load
ckpt = torch.load(path) model.load_state_dick(ckpt)
参考:李宏毅机器学习课程