《Pytorch中文手册》第一章知识

pytorch是NumPy的替代品,可以使用GPU的强大计算能力,作为深度学习的一个研究平台。包含自动求导系统的的深度神经网络

Tensors(张量)

所有的 Tensor 类型默认都是基于CPU

#定义张量torch.tensor

import torch x = torch.tensor([5.5, 3],[4,3],[5,2])

根据现有的张量$x$ 创建新的张量
y = torch.randn_like(x, dtype=torch.float)

tensor.size方法可以打印尺度大小
print(x.size())

使用索引方式来进行对张量的操作print(x[:, 1])返回tensor([3,3,2])

torch.view: 可以改变张量的维度和大小 y = x.view(2,3)

Numpy转换

b = a.numpy() a是tensor, b为numpy

a = torch.from_numpy(b) b为numpy, a是tensor

cuda

直接从GPU创建张量y = torch.ones_like(x, device=torch.device("cuda"))

使用.to方法 可以将Tensor移动到任何设备中x = x.to(torch.device("cuda"))

Autograd: 自动求导机制

torch.Tensor是这个包的核心类。如果设置 .requires_gradTrue,那么将会追踪所有对于该张量的操作。 当完成计算后通过调用.backward(),自动计算所有的梯度, 这个张量的所有梯度将会自动积累到.grad属性。

x = torch.ones(2, 2, requires_grad=True) 会得到grad_fn = AddBackward

要阻止张量跟踪历史记录,可以调用.detach()方法将其与计算历史记录分离,并禁止跟踪它将来的计算记录fake_AB.detach()。可以将代码块包装在with torch.no_grad():比如
with torch.no_grad(): y = x ** 2 #不会添加到计算图中

计算导数,你可以在Tensor上调用.backward()。 如果Tensor是一个标量(即它包含一个元素数据)则不需要为backward()指定任何参数。但是如果它有更多的元素,需要指定一个gradient参数来匹配张量的形状

y = torch.tensor([-920.6895, -115.7301, -867.6995]) gradients = torch.tensor([0.1, 0.01, 0.001], dtype=torch.float) y.backward(gradients)

神经网络

import torch import torch.nn as nn import torch.nn.functional as f import torch.optim as optim

定义网络

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
class ysq_net(nn.Module):
#定义卷积和全连接层
def __init__(self):
super(ysq_net,self).__init__()
self.conv1 = nn.Conv2d(in_channels=1,out_channels=6,kernel_size=5)
self.conv2 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5)
self.fc_1 = nn.Linear(16*5*5,120)
self.fc_2 = nn.Linear(120,84)
self.fc_3 = nn.Linear(84,10)
#定义简单的前馈
def forward(self,x):
x1 = f.max_pool2d(f.relu(self.conv1(x)),(2,2))
x2 = f.max_pool2d(f.relu(self.conv2(x1)),(2,2))
x3 = x2.view(-1,self.sum_flat_features(x2))
x4 = f.relu(self.fc_1(x3))
x5 = f.relu(self.fc_2(x4))
x6 = self.fc_3(x5)
return x6
#特征展开
def sum_flat_features(self,x):
size = x.size()[1:]
num_feature = 1
for s in size:
num_feature *= s
return num_feature
net = ysq_net() #网络实例化
print(net)

for i in range(10):
#随机输入,得到输出
input =torch.randn(1,1,32,32)
out = net(input)
print(out)
#所有参数的梯度缓存清零
net.zero_grad()
print('conv1.bias.grad')
print(net.conv1.bias.grad)
#out.backward(torch.randn(1, 10))
#定义优化器为随机梯度下降
optimizer = optim.SGD(net.parameters(), lr=0.01)
optimizer.zero_grad()
#与真实值MSE损失
target = torch.randn(10)
target = target.view(1,-1)
criterion = nn.MSELoss()
loss = criterion(out,target)
#损失反向传播
loss.backward()
print(loss)


print('conv1.bias.grad')
print(net.conv1.bias.grad)
#更新权重
optimizer.step()

bb
bb

训练一个分类器
下载数据集
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import torch
import torchvision
from torchvision.transforms import transforms

#图像为[0,1]的PIL格式  要转为[-1,1]的tensor形式
transform = transforms.Compose(
[
transforms.ToTensor(),
transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))
]
)

trainset = torchvision.datasets.CIFAR10(root='./data', train=True,download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=False, num_workers=2)
定义标签
1
classes= ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
显示输入图片
1
2
3
4
def imshow(img):
img = img /2 +0.5 #[0,1]
npimg = img.numpy()#tensor转为numpy
plt.imshow(np.transpose(npimg,(1,2,0)))
迭代读图片
1
2
3
4
5
6
dataiter = iter(trainloader)#创建迭代器
images, label = dataiter.next()

imshow(torchvision.utils.make_grid(images))
#torchvision.utils.make_grid(images)将多张图拼在一起
print(''.join('%5s' %classes[label[j]] for j in range(4)))
定义网络并实例化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class net(nn.module):
def __init__(self):
super(net,self).__init__()
self.conv1 = nn.Conv2d(3,6,5)
self.pool = nn.MaxPool2d(2,2)
self.conv2 = nn.Conv2d(6,16,5)
self.fc1= nn.Linear(16*5*5, 120)
self.fc2 = nn.Linear(120,84)
self.fc3 = nn.Linear(84,10)

def forward(self,x):
x = self.pool(f.relu(self.conv1(x)))
x = self.pool(f.relu(self.conv2(x)))
x = x.view(-1,16*5*5)
x = nn.relu(self.fc1(x))
x = nn.relu(self.fc2(x))
x = self.fc3(x)
return x
net = net()
定义优化器
1
2
3
from torch.optim import optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
训练
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for epoch in range(2):
running_loss=0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs,labels)
loss.backward()
optimizer.step()

running_loss +=loss.item()
if i%2000 == 0:
print('[%d,%5d] loss:%3f' %(epoch+1,i+1,running_loss/2000))
running_loss = 0.0
print('finish')
测试
1
2
3
4
5
6
dataiter = iter(testloader)
images, labels = dataiter.next()
imshow(torchvision.utils.make_grid(images))
outputs = net(images)
_, predicted = torch.max(outputs,1)
print('predicted', ''.join('%5s' %classes[predicted[j]] for j in range(4)))