The value of knowledge lies not in possession, but in share.

0%

PyTorch 快速教程

PyTorch是一个基于Torch的Python开源机器学习库,由Facebook的人工智能研究小组开发,可替代Numpy实现GPU加速的张量计算。

对比PyTorch和Tensorflow

没有好的框架,只有合适的框架, 这篇知乎文章有个简单的对比,所以这里就不详细再说了。 并且技术是发展的,知乎上的对比也不是绝对的,比如Tensorflow在1.5版的时候就引入了Eager Execution机制实现了动态图,PyTorch的可视化,windows支持,沿维翻转张量等问题都已经不是问题了。

一句话,PyTorch是一个相当简洁优雅且高效快速的框架!

快速入门:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import torch
from torch.nn import Linear, Module, MSELoss
from torch.optim import SGD
import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt

x = np.random.rand(256)
noise = np.random.randn(256) / 4
y = x * 5 + 7 + noise

# 模型:Linear
model = Linear(1, 1)

# 损失函数:MSELoss
loss_fn = MSELoss()

# 学习率
learning_rate = 1e-2

# 优化器: SGD
optimizer = SGD(model.parameters(), lr = learning_rate)

# 训练的次数
epochs = 3000

# 训练前,数据预处理
x_train = x.reshape(-1, 1).astype('float32')
y_train = y.reshape(-1, 1).astype('float32')

# 训练模型
for i in range(epochs):

# 整理输入和输出的数据,这里输入和输出一定要是torch的Tensor类型
inputs = torch.from_numpy(x_train)
labels = torch.from_numpy(y_train)

#使用模型进行预测
outputs = model(inputs)

# 计算损失
loss = loss_fn(outputs, labels)

#梯度置0,否则会累加
optimizer.zero_grad()

# 反向传播
loss.backward()

# 使用优化器默认方法优化
optimizer.step()

if (i%100==0):
#每 100次打印一下损失函数,看看效果
print('epoch {}, loss {:1.4f}'.format(i,loss.data.item()))

# 对数据进行预测
predicted = model.forward(torch.from_numpy(x_train)).data.numpy()

项目示例

经过一段时间的项目开发,关于深度学习的目录构建推荐如下:

1
2
3
4
5
6
7
8
9
10
.
├── datasets
│   └── xxxx //数据集
├── models
│   ├── model-weights.h5 //保存的模型
│   └── pretrain_model
│   └── keras.h5 //预训练模型
├── modle.py //神经网络结构
├── train.py //训练的脚本
└── test.py //测试的脚本

关于model.py脚本内容示例如下 (不保证运行,下同):

model.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# usr/bin/env python
# -*- coding:utf-8 -*-
import torch.nn as nn

class LeNet5(nn.Module):
def __init__(self):
super(LeNet5, self).__init__()
# 1 input image channel, 6 output channels, 5x5 square convolution
# kernel
self.conv1 = nn.Conv2d(1, 6, 5)
self.conv2 = nn.Conv2d(6, 16, 5)
# an affine operation: y = Wx + b
self.fc1 = nn.Linear(16 * 5 * 5, 120) # 这里论文上写的是conv,官方教程用了线性层
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)

def forward(self, x):
# Max pooling over a (2, 2) window
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
# If the size is a square you can only specify a single number
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
x = x.view(-1, self.num_flat_features(x))
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x

def num_flat_features(self, x):
size = x.size()[1:] # all dimensions except the batch dimension
num_features = 1
for s in size:
num_features *= s
return num_features

if __name__ == '__main__':
net = LeNet5()
print(net)

关于train.py脚本内容示例如下:

train.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# usr/bin/env python
#-*- coding:utf-8 -*-
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
# import the neural network
from . import model

class Train(model, device, train_loader, optimizer, epoch):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device)
# Forward pass
output = model(data)
loss = F.nll_loss(output, target)
optimizer.zero_grad()
# Backward and optimize
loss.backward()
optimizer.step()
if(batch_idx+1)%30 == 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()))

if __name__ == '__main__':
# batch size
BATCH_SIZE = 512
# 总共训练批次
EPOCHS = 20
# 让torch判断是否使用GPU,建议使用GPU环境,因为会快很多
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.LeNet5().to(DEVICE)
optimizer = optim.Adam(model.parameters())
# 加载训练数据
train_loader = torch.utils.data.DataLoader(
datasets.MNIST('data', train=True, download=True,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size=BATCH_SIZE, shuffle=True)

# Training
for epoch in range(1, EPOCHS + 1):
Train(model, DEVICE, train_loader, optimizer, epoch)

# Saving model
torch.save(model.state_dict(), 'model.ckpt')

test.py脚本内容示例如下:

test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# usr/bin/env python
#-*- coding:utf-8 -*-
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
# Import the neural network
from . import model

class 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() # 将一批的损失相加
pred = output.max(1, keepdim=True)[1] # 找到概率最大的下标
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)))

if __name__ == '__main__':
# 让torch判断是否使用GPU,建议使用GPU环境,因为会快很多
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.LeNet5().to(DEVICE)

# 加载测试函数
test_loader = torch.utils.data.DataLoader(
datasets.MNIST('data', train=False, transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size=BATCH_SIZE, shuffle=True)

# Load model
model.load_state_dict(torch.load('params.ckpt'))

# Testing
for epoch in range(1, EPOCHS + 1):
Test(model, DEVICE, test_loader)

🍭支持一根棒棒糖吧!