学习资料汇总
总结一下这段时间学习 pytorch 用到的东西,以下为主要参考的资料:
- [深度学习框架] PyTorch 常用代码段总结 _ 极市高质量视觉算法开发者社区
- PyTorch 的入门与实战(七月在线,褚老师),结合实战代码,很适合我这种好吃懒做的
- 深度学习与 PyTorch 入门实战教程(人工智能 101 学院,龙良曲),理论+代码讲的特别仔细
- PyTorch 模型训练实用教程 (很全面)
一些常识
-
构建 tensor
-
torch.rand(5,3)
torch.zeros(5,3,dtype=torch.long)
与np不太一样
或 torch.zeros(5,3).long() -
从已有数据构建 tensor,会使用原有 tensor 的特征 x = torch.tensor([5.5,3])
x.new_ones(5,3)
torch.randn_like(x,dtype=torch.float)
-
-
x.shape 、x.size() 返回 x 的大小
-
in-place 运算(以_结尾),会直接改变变量
-
reshape一个 tensor: x.view()
-
将一个元素的 tensor 变成数值,x.item()
-
tensor 与 array 的相互转换
b = a.numpy() <–> a = torch.from_numpy(b) 此处 a,b 共享内存
-
加法:a = a+1 和 np.add(a,1,out=a)不同,前者分配了新内存空间,后者直接改变
-
CUDA
- if torch.cuda.is_available():
device = torch.device(“cuda”)
y = torch.ones_like(x, device=device)
x = x.to(device)
z=x+y
z.to(“cpu”, torch.double)
- if torch.cuda.is_available():
-
GPU 上的 tensor 不能直接转 numpy,y.to(“cpu”).data.numpy() 或 y.cpu().data.numpy()
- 也可使用.cuda()
数据增强
PyTorch 学习笔记(三):transforms 的二十二个方法
自定义数据集的读取
PyTorch 学习笔记(一):让 PyTorch 读取你的数据集
自定义 Module 类
Module 类中的 forward 方法
模型的保存与加载
parameters()和 state_dict()的区别
优化器选择
pytorch 中使用 torch.optim 优化神经网络以及优化器的选择
- momentum,动量因子,计算本次梯度时结合上一次梯度的方向,相当于惯性,可以避免陷入局部最小值
- Adam 优化器会自动计算 momentum,因此设置时没有这个参数
- 正则化
- 能够降低网络复杂度,没有过拟合时不应该加,会降低网络的表达能力
- 二范数:在 torch 的优化器中设置 weight_decay 参数即可
- 一范数:torch 中暂无 API 实现
学习率调整策略
PyTorch 学习笔记(八):PyTorch 的六个学习率调整方法
Pytorch 提供了六种学习率调整方法,可分为三大类,分别是
-
有序调整;
-
自适应调整;
-
自定义调整。
第一类,依一定规律有序进行调整,这一类是最常用的,分别是等间隔下降(Step),按需设定下降间隔(MultiStep),指数下降(Exponential)和 CosineAnnealing。这四种方法的调整时机都是人为可控的,也是训练时常用到的。
第二类,依训练状况伺机调整,这就是 ReduceLROnPlateau 方法。该法通过监测某一指标的变化情况,当该指标不再怎么变化的时候,就是调整学习率的时机,因而属于自适应的调整。
第三类,自定义调整,Lambda。Lambda 方法提供的调整策略十分灵活,我们可以为不同的层设定不同的学习率调整方法,这在 fine-tune 中十分有用,我们不仅可为不同的层设定不同的学习率,还可以为其设定不同的学习率调整策略。
BN 层的使用
- BN 原理
- 实际使用时,BN 层更新的是
β
\beta
β 和
γ
\gamma
γ,而不是均值和方差
可视化
visdom
- 安装:
- pip install visdom
- 或者从 source 安装,据说能避免一些莫名错误(进入 visdom-master 目录后运行 pip install -e)
- 使用:
- 命令行输入 python -m visdom.server
- 按提示打开网页 http://localhost:8097
- 添加下列代码 + 一条曲线
+ 多条曲线
+ 图片和文本
实战:手撕两层感知机
numpy 实现
N, D_in, H, D_out = 64, 1000, 100, 10
# 随机创建一些训练数据
x = np.random.randn(N, D_in)
y = np.random.randn(N, D_out)
w1 = np.random.randn(D_in, H)
w2 = np.random.randn(H, D_out)
learning_rate = 1e-6
for it in range(500):
# Forward pass
h = x.dot(w1) # N * H
h_relu = np.maximum(h, 0) # N * H
y_pred = h_relu.dot(w2) # N * D_out
# compute loss
loss = np.square(y_pred - y).sum()
print(it, loss)
# Backward pass
# compute the gradient
grad_y_pred = 2.0 * (y_pred - y)
grad_w2 = h_relu.T.dot(grad_y_pred)
grad_h_relu = grad_y_pred.dot(w2.T)
grad_h = grad_h_relu.copy()
grad_h[h<0] = 0
grad_w1 = x.T.dot(grad_h)
# update weights of w1 and w2
w1 -= learning_rate * grad_w1
w2 -= learning_rate * grad_w2
自定义 nn.Modules 实现
class TwoLayerNet(torch.nn.Module):
def __init__(self, D_in, H, D_out):
super(TwoLayerNet, self).__init__()
# define the model architecture
self.linear1 = torch.nn.Linear(D_in, H, bias=False)
self.linear2 = torch.nn.Linear(H, D_out, bias=False)
def forward(self, x):
y_pred = self.linear2(self.linear1(x).clamp(min=0))
return y_pred
model = TwoLayerNet(D_in, H, D_out)
# N is batch size; D_in is input dimension;
# H is hidden dimension; D_out is output dimension.
N, D_in, H, D_out = 64, 1000, 100, 10
# Create random Tensors to hold inputs and outputs
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
# Construct our model by instantiating the class defined above
model = TwoLayerNet(D_in, H, D_out)
# Construct our loss function and an Optimizer. The call to model.parameters()
# in the SGD constructor will contain the learnable parameters of the two
# nn.Linear modules which are members of the model.
criterion = torch.nn.MSELoss(reduction='sum')
optimizer = torch.optim.SGD(model.parameters(), lr=1e-4)
for t in range(500):
# Forward pass: Compute predicted y by passing x to the model
y_pred = model(x)
# Compute and print loss
loss = criterion(y_pred, y)
print(t, loss.item())
# Zero gradients, perform a backward pass, and update the weights.
optimizer.zero_grad()
loss.backward()
optimizer.step()
实战:简单的 CNN 网络(验证集)
定义训练集
def train(model, device, train_loader, optimizer, epoch, log_interval=100):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = F.nll_loss(output, target)
loss.backward()
optimizer.step()
if batch_idx % log_interval == 0:
print("Train Epoch: {} [{}/{} ({:0f}%)]\tLoss: {:.6f}".format(
epoch, batch_idx * len(data), len(train_loader.dataset),
100. * batch_idx / len(train_loader), loss.item()
定义验证集
def test(model, device, test_loader):
model.eval()
test_loss = 0
correct = 0
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)
output = model(data)
test_loss += F.nll_loss(output, target, reduction='sum').item() # sum up batch loss
pred = output.argmax(dim=1, keepdim=True) # get the index of the max log-probability
correct += pred.eq(target.view_as(pred)).sum().item()
test_loss /= len(test_loader.dataset)
print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
test_loss, correct, len(test_loader.dataset),
100. * correct / len(test_loader.dataset)))
训练+验证
torch.manual_seed(53113)
use_cuda = torch.cuda.is_available()
device = torch.device("cuda" if use_cuda else "cpu")
batch_size = test_batch_size = 32
kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {}
train_loader = torch.utils.data.DataLoader(
datasets.MNIST('./mnist_data', train=True, download=True,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size=batch_size, shuffle=True, **kwargs)
test_loader = torch.utils.data.DataLoader(
datasets.MNIST('./mnist_data', train=False, transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size=test_batch_size, shuffle=True, **kwargs)
lr = 0.01
momentum = 0.5
model = Net().to(device)
optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum)
epochs = 2
for epoch in range(1, epochs + 1):
train(model, device, train_loader, optimizer, epoch)
test(model, device, test_loader)
save_model = True
if (save_model):
torch.save(model.state_dict(),"mnist_cnn.pt")