最近学习深度学习框架Pytorch。发现了一篇很好的博客,通俗易懂。这个博客作为新手学习Pytorch有很多帮助。本文对该博客进行重写(主要是丰富内容)。
学习顺序。首先,翻阅该博客,让你对Pytorch有一个大体的了解;然后,进一步查看中文版官网教程;其次,在你遇到问题时,查看中文文档内容,最后,在英文官网中跟进时代步伐。(学习顺序:该博客->中文版官网教程->中文文档->英文官网。)
博客: https://blog.csdn.net/zzulp/article/details/80573331
中文版官网教程: http://pytorch123.com/
中文文档: https://pytorch-cn.readthedocs.io/zh/latest/
英文官网: https://pytorch.org/
Pytorch简介。Python是torch的python版本,是由Facebook开源的神经网络框架。与Tensorflow的静态计算图不同(Tensorflow2.0以后也是动态计算),Python的计算图是动态的,可以根据计算需要实时改变计算图。
其他学习资源:
b站(莫烦python): https://www.bilibili.com/video/av15997678?from=search&seid=11420017031775931605
一.安装
如果已经安装了cuda8,则使用pip来安装pytorch会十分简单。若使用其他版本的cuda,则需要下载官方释放出来对应的安装包。具体安装地址参见官网的首页。
pip install torch torchvision # for python2.7
pip3 install torch torchvision # for python3
二.概述
理解pytorch的基础主要从以下三个方面:
- Numpy风格的Tensor操作。pytorch中tensor提供的API参考了Numpy的设计,因此熟悉Numpy的用户基本上可以无缝理解,并创建和操作tensor,同时torch中的数组和Numpy数组对象可以无缝的对接。
- 变量自动求导。在一序列计算过程形成的计算图中,参与的变量可以方便的计算自己对目标函数的梯度。这样就可以方便的实现神经网络的后向传播过程。
- 神经网络层与损失函数优化等高层封装。网络层的封装存在于torch.nn模块,损失函数由torch.nn.functional模块提供,优化函数由torch.optim模块提供。
因此下面的内容也主要围绕这三个方面来介绍。第3节介绍张量的操作,第4节介绍自动求导,第5节介绍神经网络层等的封装,第6节简单介绍损失函数与优化方法。这三部分相对重要。后续的第7节介绍介绍数据集及torchvision,第8节介绍训练过程可视的工具,第9节介绍GPU及并行处理,第10节通过相对完整的示例代码展示pytorch中如何解决MNIST分类。
三.Tensor(张量)
Tensor是神经网络框架中重要的基础数据类型,可以简单理解为N维数组的容器对象。tensor之间的通过运算进行连接,从而形成计算图。
1.Tensor类型
Torch 定义了八种 CPU tensor 类型和八种 GPU tensor 类型:
Data type | CPU tensor | GPU tensor |
---|---|---|
32-bit floating point | torch.FloatTensor | torch.cuda.FloatTensor |
64-bit floating point | torch.DoubleTensor | torch.cuda.DoubleTensor |
16-bit floating point | torch.HalfTensor | torch.cuda.HalfTensor |
8-bit integer (unsigned) | torch.ByteTensor | torch.cuda.ByteTensor |
8-bit integer (signed) | torch.CharTensor | torch.cuda.CharTensor |
16-bit integer (signed) | torch.ShortTensor | torch.cuda.ShortTensor |
32-bit integer (signed) | torch.IntTensor | torch.cuda.IntTensor |
64-bit integer (signed) | torch.LongTensor | torch.cuda.LongTensor |
通常情况下使用Tensor类的构造函数返回的是FloatTensor类型对象,可通过在对象上调用cuda()返回一个新的cuda.FloatTensor类型的对象。
torch模块内提供了操作tensor的接口,而Tensor类型的对象上也设计了对应了接口。例如torch.add()与tensor.add()等价。需要注意的是这些接口都采用创建一个新对象返回的形式。如果想就地修改一个tensor对象,需要使用加后缀下划线的方法。例如x.add_(y),将修改x。Tensor类的构建函数支持从列表或ndarray等类型进行构建。默认tensor为FloatTensor。
2.Tensor的常见创建接口
方法名 | 说明 |
---|---|
Tensor() | 直接从参数构造一个的张量,参数支持list,numpy数组 |
eye(row, column) | 创建指定行数,列数的二维单位tensor |
linspace(start,end,count) | 在区间[s,e]上创建c个tensor |
logspace(s,e,c) | 在区间[10^s, 10^e]上创建c个tensor |
ones(*size) | 返回指定shape的张量,元素初始为1 |
zeros(*size) | 返回指定shape的张量,元素初始为0 |
ones_like(t) | 返回与t的shape相同的张量,且元素初始为1 |
zeros_like(t) | 返回与t的shape相同的张量,且元素初始为0 |
arange(s,e,sep) | 在区间[s,e)上以间隔sep生成一个序列张量 |
3.随机采样
方法名 | 说明 |
---|---|
rand(*size) | 在区间[0,1)返回一个均匀分布的随机数张量 |
uniform(s,e) | 在指定区间[s,e]上生成一个均匀分布的张量 |
randn(*size) | 返回正态分布N(0,1)取样的随机数张量 |
normal(means, std) | 返回一个正态分布N(means, std) |
4.序列化
方法名 | 说明 |
---|---|
save(obj, path) | 张量对象的保存,通过pickle进行 |
load(path) | 从文件中反序列化一个张量对象 |
5.数学操作
这些方法均为逐元素处理方法。
方法名 | 说明 |
---|---|
abs | 绝对值 |
add | 加法 |
addcdiv(t, v, t1, t2) | t1与t2的按元素除后,乘v加t |
addcmul(t, v, t1, t2) | t1与t2的按元素乘后,乘v加t |
ceil | 向上取整 |
floor | 向下取整 |
clamp(t, min, max) | 将张量元素限制在指定区间 |
exp | 指数 |
log | 对数 |
pow | 幂 |
mul | 逐元素乘法 |
neg | 取反 |
sigmoid | Sigmoid激活层 |
sign | 取符号 |
sqrt | 开根号 |
tanh | Tanh激活层 |
注:这些操作均创建新的tensor,如果需要就地操作,可以使用这些方法的下划线版本,例如abs_。
6.规约方法
cumprod(t, axis) | 在指定维度对t进行累积 |
---|---|
cumsum | 在指定维度对t进行累加 |
dist(a,b,p=2) | 返回a,b之间的p阶范数 |
mean | 均值 |
median | 中位数 |
std | 标准差 |
var | 方差 |
norm(t,p=2) | 返回t的p阶范数 |
prod(t) | 返回t所有元素的积 |
sum(t) | 返回t所有元素的和 |
6.1 cumprod(t, axis)
#实例
#结果打印
6.2 cumsum
#实例
#结果打印
6.3 dist(a,b,p=2)
#实例
#结果打印
6.4 mean
#实例
#结果打印
6.5 median
#实例
#结果打印
6.6 std
#实例
#结果打印
6.7 var
#实例
#结果打印
6.8 norm(t,p=2)
#实例
#结果打印
6.9 sum(t)
#实例
#结果打印
6.10附加
计算pytorch标准化(Normalize)所需要数据集的均值和方差。
7.比较方法
方法名 | 说明 |
---|---|
eq | 比较tensor是否相等,支持broadcast |
equal | 比较tensor是否有相同的shape与值 |
ge/le | 大于/小于比较 |
gt/lt | 大于等于/小于等于比较 |
max/min(t,axis) | 返回最值,若指定axis,则额外返回下标 |
topk(t,k,axis) | 在指定的axis维上取最高的K个值 |
8.其他操作
方法名 | 说明 |
---|---|
cat(inputs, dimension=0) → Tensor | 在指定的维度上拼接序列 |
chunk(tensor, c, axis) | 在指定的维度上分割tensor |
index_select(input, dim, index, out=None) | 返回一个包含输入input中非零元素索引的张量 |
masked_select(input, mask, out=None) | 根据掩码张量mask中的二元值,取输入张量中的指定项( mask为一个 ByteTensor),将取值返回到一个新的1D张量 |
nonzero(input, out=None) | |
split(tensor, split_size, dim=0) | 将输入张量分割成相等形状的chunks(如果可分) |
Joining | |
squeeze(input,dim) | 将张量维度为1的dim进行压缩,不指定dim则压缩所有维度为1的维 |
unsqueeze(dim) | squeeze操作的逆操作 |
permute(t) | 计算矩阵的转置(任意维度) |
transpose(t) | 计算矩阵的转置(2D矩阵) |
cross(a, b, axis) | 在指定维度上计算向量积 |
diag | 返回对角线元素 |
hist(t, bins) | 计算直方图 |
trace | 返回迹 |
one_hot() | 分散操作 |
scatter_(input, dim, index, src) → Tensor | 分散操作 |
gather(dim, index) → Tensor | 聚集操作 |
torch.Tensor() | 是Python类,更明确的说,是默认张量类型torch.FloatTensor()的别名 |
torch.tensor() | 仅仅是Python的函数 |
8.1 cat( inputs, dimension=0) → Tensor
- 在给定维度上对输入的张量序列进行连接操作。
- torch.cat()可以看做 torch.split() 和 torch.chunk()的反操作。
参数:
- inputs (sequence of Tensors) – 可以是任意相同Tensor 类型的python 序列
- dimension (int, optional) – 沿着此维连接张量序列。
例子:
#实例
import torch
#dim=0(行):表示的就是接下来的操作是对于第一维度进行的,也就是行(使行发生变化)
a=torch.randn(2,3)
print(a)
cat1=torch.cat((a,a,a),0)
print(cat1)
#dim=1(列):表示接下来的操作是对于第二维度进行的,也就是列(使列发生变化)
cat2=torch.cat((a,a,a),1)
print(cat2)
#打印结果
tensor([[-0.0063, -1.3362, 0.7948],
[ 0.6496, 0.3608, 0.7559]])
tensor([[-0.0063, -1.3362, 0.7948],
[ 0.6496, 0.3608, 0.7559],
[-0.0063, -1.3362, 0.7948],
[ 0.6496, 0.3608, 0.7559],
[-0.0063, -1.3362, 0.7948],
[ 0.6496, 0.3608, 0.7559]])
tensor([[-0.0063, -1.3362, 0.7948, -0.0063, -1.3362, 0.7948, -0.0063, -1.3362, 0.7948],
[ 0.6496, 0.3608, 0.7559, 0.6496, 0.3608, 0.7559, 0.6496, 0.3608, 0.7559]])
8.2 chunk(tensor, c, axis)
- 在给定维度(轴)上将输入张量进行分块儿。
参数:
- tensor (Tensor) – 待分块的输入张量
- chunks (int) – 分块的个数
- dim (int) – 沿着此维度进行分块
#实例
import torch
#dim=0(列)
a=torch.randn(2,3)
print(a)
cat1=torch.chunk(a,3,0)
print(cat1)
#dim=1(行)
cat2=torch.chunk(a,3,1)
print(cat2)
#结果打印
tensor([[-0.1469, -1.3852, 0.4884],
[-0.2091, -0.9021, -1.0245]])
(tensor([[-0.1469, -1.3852, 0.4884]]), tensor([[-0.2091, -0.9021, -1.0245]]))
(tensor([[-0.1469],
[-0.2091]]), tensor([[-1.3852],
[-0.9021]]), tensor([[ 0.4884],
[-1.0245]]))
8.3 index_select()
index_select(input, dim, index, out=None)
-
沿着指定维度对输入进行切片,取index中指定的相应项(index为一个LongTensor),然后返回到一个新的张量, 返回的张量与原始张量_Tensor_有相同的维度(在指定轴上)。
注意: 返回的张量不与原始张量共享内存空间。
参数:
- input (Tensor) – 输入张量
- dim (int) – 索引的轴
- index (LongTensor) – 包含索引下标的一维张量
- out (Tensor, optional) – 目标张量
例子:
#实例
import torch
a=torch.randn(3,4)
print(a)
indices=torch.LongTensor([0,2])
print(indices)
s=torch.index_select(a, 1, indices)
print(s)
#打印结果
tensor([[-0.3832, -0.5268, -0.1379, 0.2479],
[ 1.2284, -0.3913, -0.0408, -1.1721],
[ 0.4044, 0.4127, 1.3877, 0.0443]])
tensor([0, 2])
tensor([[-0.3832, -0.1379],
[ 1.2284, -0.0408],
[ 0.4044, 1.3877]])
8.4 masked_select()
masked_select(input, mask, out=None)
- 根据掩码张量mask中的二元值,取输入张量中的指定项( mask为一个 ByteTensor),将取值返回到一个新的1D张量,
- 张量 mask须跟input张量有相同数量的元素数目,但形状或维度不需要相同。 注意: 返回的张量不与原始张量共享内存空间。
参数:
- input (Tensor) – 输入张量
- mask (ByteTensor) – 掩码张量,包含了二元索引值
- out (Tensor, optional) – 目标张量
例子:
#实例
import torch
a=torch.randn(3,4)
print(a)
mask=a.ge(0.5)
print(mask)
s=torch.masked_select(a,mask)
print(s)
#打印结果
tensor([[-0.7987, -1.6043, 0.8072, 0.9651],
[ 1.5802, -1.2261, 0.2911, -1.8187],
[ 1.0078, 0.1547, 0.2759, -0.6589]])
tensor([[False, False, True, True],
[ True, False, False, False],
[ True, False, False, False]])
tensor([0.8072, 0.9651, 1.5802, 1.0078])
8.5 nonzero()
nonzero(input, out=None)
- 返回一个包含输入input中非零元素索引的张量。输出张量中的每行包含输入中非零元素的索引。
- 如果输入input有n维,则输出的索引张量output的形状为 z x n, 这里 z 是输入张量input中所有非零元素的个数。
参数:
- input (Tensor) – 源张量
- out (LongTensor, optional) – 包含索引值的结果张量
例子:
#实例
import torch
a = torch.nonzero(torch.Tensor([1, 1, 1, 0, 1]))
print(a)
b = torch.nonzero(torch.Tensor([[0.6, 0.0, 0.0, 0.0],
[0.0, 0.4, 0.0, 0.0],
[0.0, 0.0, 1.2, 0.0],
[0.0, 0.0, 0.0, -0.4]
]))
print(b)
#打印结果
tensor([[0],
[1],
[2],
[4]])
tensor([[0, 0],
[1, 1],
[2, 2],
[3, 3]])
8.6 split()
split(tensor, split_size, dim=0)
- 将输入张量分割成相等形状的chunks(如果可分)。 如果沿指定维的张量形状大小不能被split_size 整分, 则最后一个分块会小于其它分块。
参数:
- tensor (Tensor) – 待分割张量
- split_size (int) – 单个分块的形状大小
- dim (int) – 沿着此维进行分割
#实例
import torch
a=torch.randn(3,4)
print(a)
s=torch.split(a,3,1)
print(s)
#打印结果
tensor([[ 1.6925, 1.7529, -1.1991, 0.3190],
[ 0.7297, 0.1151, -1.1397, -0.1572],
[ 0.4931, -1.0127, -0.5640, -0.0530]])
(tensor([[ 1.6925, 1.7529, -1.1991],
[ 0.7297, 0.1151, -1.1397],
[ 0.4931, -1.0127, -0.5640]]), tensor([[ 0.3190],
[-0.1572],
[-0.0530]]))
8.7 squeeze(input,dim)
原文链接: https://blog.csdn.net/xiexu911/article/details/80820028
对数据的维度进行压缩。去掉维数为1的维度,比如是一行或者一列。例如:一行三列(1,3)的数去掉第一个维数为1的维度之后变成(3)行。
- squeeze(a):将a中所有为1的维度去掉,不为1的维度没有影响。
- a.squeeze(N):去掉a中指定的维数为1的维度。
- b=torch.squeeze(a,N):a中去掉指定的维数为1的维度。
#实例:先看8.4unsqueeze(dim),再看8.3squeeze(input,dim)。
import torch
#加轴
a=torch.randn(1,3)
print(a)
print(a.shape)
b=torch.unsqueeze(a,1)
print(b)
print(b.shape)
c=a.unsqueeze(0)
print(c)
print(c.shape)
#减轴
d=torch.squeeze(c)
print(d)
print(d.shape)
#打印结果
tensor([[1.1275, 0.3616, 0.9084]])
torch.Size([1, 3])
tensor([[[1.1275, 0.3616, 0.9084]]])
torch.Size([1, 1, 3])
tensor([[[1.1275, 0.3616, 0.9084]]])
torch.Size([1, 1, 3])
tensor([1.1275, 0.3616, 0.9084])
torch.Size([3])
8.8 unsqueeze(dim)
原文链接: https://blog.csdn.net/xiexu911/article/details/80820028
对数据维度进行扩充。给指定位置加上维数为1的维度。例如:原本有个3行的数据(3),在0的位置上加了1维就变成一行三列(1,3)。
- a.unsqueeze(N):在a中指定位置N加上一个维数为1的维度。
- b=torch.unsqueeze(a,N):a就是在a中指定位置N加上一个维数1的维度。
#实例
import torch
#举例1
a=torch.randn(1,3)
print(a)
print(a.shape)
b=torch.unsqueeze(a,1)
print(b)
print(b.shape)
c=a.unsqueeze(0)
print(c)
print(c.shape)
#举例2
f=torch.randn(3)
print(f)
print(f.shape)
g=f.unsqueeze(0)
print(g)
print(g.shape)
#打印结果
tensor([[ 0.2710, -0.6628, -1.0097]])
torch.Size([1, 3])
tensor([[[ 0.2710, -0.6628, -1.0097]]])
torch.Size([1, 1, 3])
tensor([[[ 0.2710, -0.6628, -1.0097]]])
torch.Size([1, 1, 3])
tensor([-1.9598, 0.2997, -0.9772])
torch.Size([3])
tensor([[-1.9598, 0.2997, -0.9772]])
torch.Size([1, 3])
8.9 permute(t)
原文链接: http://www.studyai.com/article/bba734ff
- permute可以对任意高维矩阵进行转置。
- 但没有 torch.permute() 这个调用方式, 只能 Tensor.permute()。
#实例
import torch
a=torch.rand(2,3,4,5)
print(a)
print(a.shape)
t=a.permute(3,2,0,1)
print(t)
print(t.shape)
#打印结果
tensor([[[[0.8990, 0.5257, 0.4056, 0.3442, 0.4227],
[0.4314, 0.7968, 0.1702, 0.4386, 0.3200],
[0.2228, 0.0835, 0.8115, 0.1287, 0.1376],
[0.3401, 0.9858, 0.0772, 0.7046, 0.7150]],
[[0.7911, 0.7294, 0.4788, 0.3178, 0.3548],
[0.6023, 0.5171, 0.4468, 0.6843, 0.7368],
[0.8288, 0.3849, 0.7249, 0.3588, 0.4122],
[0.8533, 0.4637, 0.4655, 0.9747, 0.5392]],
[[0.1040, 0.0630, 0.7595, 0.4268, 0.8369],
[0.4327, 0.4381, 0.1207, 0.0395, 0.7422],
[0.1375, 0.9428, 0.2811, 0.2074, 0.6422],
[0.0453, 0.1161, 0.1819, 0.7607, 0.5973]]],
[[[0.0396, 0.5103, 0.3517, 0.0987, 0.5590],
[0.8538, 0.1142, 0.5996, 0.0995, 0.5748],
[0.2435, 0.8972, 0.9531, 0.3976, 0.6509],
[0.8004, 0.0790, 0.5753, 0.6184, 0.6776]],
[[0.6232, 0.2009, 0.0095, 0.1793, 0.7148],
[0.6807, 0.8827, 0.6945, 0.3416, 0.0655],
[0.6823, 0.1163, 0.4287, 0.2652, 0.9910],
[0.3454, 0.2654, 0.2190, 0.7379, 0.2384]],
[[0.1513, 0.3303, 0.9560, 0.1060, 0.0692],
[0.6487, 0.4870, 0.3306, 0.3174, 0.9725],
[0.2740, 0.6013, 0.6560, 0.4343, 0.6577],
[0.6590, 0.0249, 0.4299, 0.4182, 0.2684]]]])
torch.Size([2, 3, 4, 5])
tensor([[[[0.8990, 0.7911, 0.1040],
[0.0396, 0.6232, 0.1513]],
[[0.4314, 0.6023, 0.4327],
[0.8538, 0.6807, 0.6487]],
[[0.2228, 0.8288, 0.1375],
[0.2435, 0.6823, 0.2740]],
[[0.3401, 0.8533, 0.0453],
[0.8004, 0.3454, 0.6590]]],
[[[0.5257, 0.7294, 0.0630],
[0.5103, 0.2009, 0.3303]],
[[0.7968, 0.5171, 0.4381],
[0.1142, 0.8827, 0.4870]],
[[0.0835, 0.3849, 0.9428],
[0.8972, 0.1163, 0.6013]],
[[0.9858, 0.4637, 0.1161],
[0.0790, 0.2654, 0.0249]]],
[[[0.4056, 0.4788, 0.7595],
[0.3517, 0.0095, 0.9560]],
[[0.1702, 0.4468, 0.1207],
[0.5996, 0.6945, 0.3306]],
[[0.8115, 0.7249, 0.2811],
[0.9531, 0.4287, 0.6560]],
[[0.0772, 0.4655, 0.1819],
[0.5753, 0.2190, 0.4299]]],
[[[0.3442, 0.3178, 0.4268],
[0.0987, 0.1793, 0.1060]],
[[0.4386, 0.6843, 0.0395],
[0.0995, 0.3416, 0.3174]],
[[0.1287, 0.3588, 0.2074],
[0.3976, 0.2652, 0.4343]],
[[0.7046, 0.9747, 0.7607],
[0.6184, 0.7379, 0.4182]]],
[[[0.4227, 0.3548, 0.8369],
[0.5590, 0.7148, 0.0692]],
[[0.3200, 0.7368, 0.7422],
[0.5748, 0.0655, 0.9725]],
[[0.1376, 0.4122, 0.6422],
[0.6509, 0.9910, 0.6577]],
[[0.7150, 0.5392, 0.5973],
[0.6776, 0.2384, 0.2684]]]])
torch.Size([5, 4, 2, 3])
8.10 transpose(t)
原文链接: http://www.studyai.com/article/bba734ff
- transpose只能操作2D矩阵的转置。有两种调用方式。
- 连续使用transpose也可实现permute的效果。
#实例1:单独使用
import torch
a=torch.rand(2,3,4,5)
print(a)
print(a.shape)
t1=torch.transpose(a,3,0)
print(t1)
print(t1.shape)
#打印结果
tensor([[[[1.8886e-01, 9.1154e-01, 3.1995e-01, 3.9562e-01, 5.8923e-01],
[4.6089e-01, 1.6451e-01, 8.2870e-01, 8.3913e-01, 4.9235e-01],
[4.3370e-01, 8.4900e-01, 6.6459e-04, 1.1571e-01, 8.2184e-01],
[8.4245e-01, 4.1580e-01, 1.0864e-01, 2.4843e-02, 3.9513e-01]],
[[9.4327e-01, 5.2818e-01, 7.6342e-01, 8.3515e-01, 5.2758e-02],
[1.4774e-02, 8.0928e-01, 3.1887e-01, 1.6237e-01, 8.9653e-01],
[1.6837e-01, 1.4563e-01, 6.4972e-01, 3.1336e-01, 9.0515e-01],
[9.3290e-01, 7.8390e-01, 7.0800e-01, 8.3910e-01, 7.7378e-01]],
[[4.3617e-01, 2.7500e-01, 5.6161e-01, 3.1444e-01, 3.4530e-01],
[4.0011e-01, 1.9616e-01, 2.9006e-01, 5.5288e-01, 4.5468e-01],
[4.0885e-01, 4.6007e-01, 3.6832e-01, 1.4268e-01, 7.2884e-01],
[2.9190e-01, 6.7845e-01, 8.7304e-01, 4.8186e-01, 2.2290e-01]]],
[[[3.3204e-02, 8.9005e-02, 9.4937e-01, 6.1268e-01, 5.3787e-01],
[7.1518e-01, 5.7354e-01, 9.1108e-01, 1.3833e-01, 4.8504e-01],
[1.1717e-01, 1.8180e-01, 9.2203e-01, 9.9294e-01, 4.4336e-01],
[8.7715e-01, 2.6028e-01, 1.0137e-01, 1.6556e-01, 6.5634e-01]],
[[5.9997e-01, 9.5615e-01, 3.0710e-02, 9.3653e-01, 6.6751e-01],
[3.0322e-01, 2.6505e-01, 3.0881e-01, 9.1510e-02, 1.8432e-01],
[3.3284e-01, 5.6368e-02, 9.6277e-01, 1.3569e-01, 8.8944e-01],
[8.5775e-02, 5.3068e-01, 1.1948e-01, 5.0761e-01, 2.4392e-01]],
[[1.8847e-01, 5.9933e-01, 2.3334e-01, 7.4749e-01, 6.8980e-01],
[5.8939e-01, 7.9963e-01, 5.4763e-01, 7.6409e-01, 5.5838e-01],
[2.9860e-01, 1.8813e-01, 8.1701e-01, 6.9333e-01, 4.0103e-02],
[8.8619e-01, 7.6062e-01, 9.8575e-01, 5.0231e-01, 3.5003e-01]]]])
torch.Size([2, 3, 4, 5])
tensor([[[[1.8886e-01, 3.3204e-02],
[4.6089e-01, 7.1518e-01],
[4.3370e-01, 1.1717e-01],
[8.4245e-01, 8.7715e-01]],
[[9.4327e-01, 5.9997e-01],
[1.4774e-02, 3.0322e-01],
[1.6837e-01, 3.3284e-01],
[9.3290e-01, 8.5775e-02]],
[[4.3617e-01, 1.8847e-01],
[4.0011e-01, 5.8939e-01],
[4.0885e-01, 2.9860e-01],
[2.9190e-01, 8.8619e-01]]],
[[[9.1154e-01, 8.9005e-02],
[1.6451e-01, 5.7354e-01],
[8.4900e-01, 1.8180e-01],
[4.1580e-01, 2.6028e-01]],
[[5.2818e-01, 9.5615e-01],
[8.0928e-01, 2.6505e-01],
[1.4563e-01, 5.6368e-02],
[7.8390e-01, 5.3068e-01]],
[[2.7500e-01, 5.9933e-01],
[1.9616e-01, 7.9963e-01],
[4.6007e-01, 1.8813e-01],
[6.7845e-01, 7.6062e-01]]],
[[[3.1995e-01, 9.4937e-01],
[8.2870e-01, 9.1108e-01],
[6.6459e-04, 9.2203e-01],
[1.0864e-01, 1.0137e-01]],
[[7.6342e-01, 3.0710e-02],
[3.1887e-01, 3.0881e-01],
[6.4972e-01, 9.6277e-01],
[7.0800e-01, 1.1948e-01]],
[[5.6161e-01, 2.3334e-01],
[2.9006e-01, 5.4763e-01],
[3.6832e-01, 8.1701e-01],
[8.7304e-01, 9.8575e-01]]],
[[[3.9562e-01, 6.1268e-01],
[8.3913e-01, 1.3833e-01],
[1.1571e-01, 9.9294e-01],
[2.4843e-02, 1.6556e-01]],
[[8.3515e-01, 9.3653e-01],
[1.6237e-01, 9.1510e-02],
[3.1336e-01, 1.3569e-01],
[8.3910e-01, 5.0761e-01]],
[[3.1444e-01, 7.4749e-01],
[5.5288e-01, 7.6409e-01],
[1.4268e-01, 6.9333e-01],
[4.8186e-01, 5.0231e-01]]],
[[[5.8923e-01, 5.3787e-01],
[4.9235e-01, 4.8504e-01],
[8.2184e-01, 4.4336e-01],
[3.9513e-01, 6.5634e-01]],
[[5.2758e-02, 6.6751e-01],
[8.9653e-01, 1.8432e-01],
[9.0515e-01, 8.8944e-01],
[7.7378e-01, 2.4392e-01]],
[[3.4530e-01, 6.8980e-01],
[4.5468e-01, 5.5838e-01],
[7.2884e-01, 4.0103e-02],
[2.2290e-01, 3.5003e-01]]]])
torch.Size([5, 3, 4, 2])
#实例:第二连续使用,达到permute效果
import torch
a=torch.rand(2,3,4,5)
print(a)
print(a.shape)
t1=torch.transpose(a,3,0).transpose(2,1)
print(t1)
print(t1.shape)
#打印结果
tensor([[[[0.6145, 0.0217, 0.6302, 0.7685, 0.6366],
[0.5061, 0.6048, 0.4834, 0.4790, 0.7047],
[0.8830, 0.1933, 0.1915, 0.6766, 0.8500],
[0.2529, 0.1014, 0.9574, 0.8797, 0.3859]],
[[0.2312, 0.4686, 0.6397, 0.3307, 0.0647],
[0.6365, 0.0661, 0.8347, 0.2134, 0.3537],
[0.5092, 0.3454, 0.9779, 0.7042, 0.7014],
[0.2687, 0.9292, 0.0176, 0.9149, 0.0463]],
[[0.2066, 0.6487, 0.5045, 0.8170, 0.5224],
[0.3861, 0.6353, 0.4143, 0.3179, 0.9907],
[0.6222, 0.8247, 0.3584, 0.5044, 0.5356],
[0.7609, 0.0730, 0.3194, 0.7531, 0.8807]]],
[[[0.9681, 0.2559, 0.7613, 0.7709, 0.2788],
[0.9170, 0.6462, 0.3086, 0.5657, 0.3025],
[0.1831, 0.1238, 0.4580, 0.5863, 0.4381],
[0.2495, 0.0836, 0.7207, 0.2461, 0.7073]],
[[0.0582, 0.6320, 0.6108, 0.8980, 0.6512],
[0.4229, 0.7929, 0.1370, 0.6749, 0.9821],
[0.7613, 0.2799, 0.7962, 0.9832, 0.2901],
[0.6457, 0.7345, 0.9339, 0.2956, 0.6101]],
[[0.5216, 0.8806, 0.8637, 0.0034, 0.0702],
[0.2733, 0.3293, 0.2936, 0.2549, 0.7152],
[0.2157, 0.7046, 0.1385, 0.7045, 0.0263],
[0.4234, 0.0611, 0.2030, 0.5957, 0.4047]]]])
torch.Size([2, 3, 4, 5])
tensor([[[[0.6145, 0.9681],
[0.2312, 0.0582],
[0.2066, 0.5216]],
[[0.5061, 0.9170],
[0.6365, 0.4229],
[0.3861, 0.2733]],
[[0.8830, 0.1831],
[0.5092, 0.7613],
[0.6222, 0.2157]],
[[0.2529, 0.2495],
[0.2687, 0.6457],
[0.7609, 0.4234]]],
[[[0.0217, 0.2559],
[0.4686, 0.6320],
[0.6487, 0.8806]],
[[0.6048, 0.6462],
[0.0661, 0.7929],
[0.6353, 0.3293]],
[[0.1933, 0.1238],
[0.3454, 0.2799],
[0.8247, 0.7046]],
[[0.1014, 0.0836],
[0.9292, 0.7345],
[0.0730, 0.0611]]],
[[[0.6302, 0.7613],
[0.6397, 0.6108],
[0.5045, 0.8637]],
[[0.4834, 0.3086],
[0.8347, 0.1370],
[0.4143, 0.2936]],
[[0.1915, 0.4580],
[0.9779, 0.7962],
[0.3584, 0.1385]],
[[0.9574, 0.7207],
[0.0176, 0.9339],
[0.3194, 0.2030]]],
[[[0.7685, 0.7709],
[0.3307, 0.8980],
[0.8170, 0.0034]],
[[0.4790, 0.5657],
[0.2134, 0.6749],
[0.3179, 0.2549]],
[[0.6766, 0.5863],
[0.7042, 0.9832],
[0.5044, 0.7045]],
[[0.8797, 0.2461],
[0.9149, 0.2956],
[0.7531, 0.5957]]],
[[[0.6366, 0.2788],
[0.0647, 0.6512],
[0.5224, 0.0702]],
[[0.7047, 0.3025],
[0.3537, 0.9821],
[0.9907, 0.7152]],
[[0.8500, 0.4381],
[0.7014, 0.2901],
[0.5356, 0.0263]],
[[0.3859, 0.7073],
[0.0463, 0.6101],
[0.8807, 0.4047]]]])
torch.Size([5, 4, 3, 2])
8.11 cross(a, b, axis)
8.12 diag
8.13 hist(t, bins)
8.14 trace
8.15 one_hot()
参数必须是LongTensor
#实例
import torch
a=torch.empty(5).random_(10)
print(a)
b=a.byte().long()
print(b)
t=torch.nn.functional.one_hot(b)
print(t)
#打印结果
tensor([7., 5., 3., 3., 7.])
tensor([7, 5, 3, 3, 7])
tensor([[0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1]])
8.16 scatter_(input, dim, index, src) → Tensor 分散操作
原文链接(加修改): https://blog.csdn.net/qq_16234613/article/details/79827006
将src中数据根据index中的索引按照dim的方向填进input中。
#实例:按列填充
import torch
x=torch.rand(2,5)
print(x)
#LongTensor的shape刚好与x的shape对应,也就是LongTensor每个index指定x中一个数据的填充位置。
# dim=0,表示按列填充,主要理解按列填充。
# 举例LongTensor中的第0行第2列index=2,表示在第2行(从0开始)进行填充,对应到zeros(3, 5)中就是位置(2,2)。
# 所以此处要求zeros(3, 5)的列数要与x列数相同,而LongTensor中的index最大值应与zeros(3, 5)行数相一致。
k=torch.LongTensor([[0, 1, 2, 0, 0], [2, 0, 0, 1, 2]])
print(k)
z=torch.zeros(3, 5)
print(z)
y=torch.zeros(3, 5).scatter_(0, torch.LongTensor([[0, 1, 2, 0, 0], [2, 0, 0, 1, 2]]), x)
print(y)
#打印结果
tensor([[0.3934, 0.2420, 0.2617, 0.2116, 0.2538],
[0.4061, 0.8673, 0.2282, 0.2894, 0.2330]])
tensor([[0, 1, 2, 0, 0],
[2, 0, 0, 1, 2]])
tensor([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
tensor([[0.3934, 0.8673, 0.2282, 0.2116, 0.2538],
[0.0000, 0.2420, 0.0000, 0.2894, 0.0000],
[0.4061, 0.0000, 0.2617, 0.0000, 0.2330]])
#实例:按行填充
import torch
x=torch.LongTensor([[2], [3]])
print(x)
y=torch.zeros(2, 4)
print(y)
z = torch.zeros(2, 4).scatter_(1, torch.LongTensor([[2], [3]]), 1.23)
print(z)
#打印结果
tensor([[2],
[3]])
tensor([[0., 0., 0., 0.],
[0., 0., 0., 0.]])
tensor([[0.0000, 0.0000, 1.2300, 0.0000],
[0.0000, 0.0000, 0.0000, 1.2300]])
附加:scatter_(*input, dim, index, src*)与scatter(*input, dim, index, src*)功能相同
8.17gather(dim, index) → Tensor 聚集操作
原文链接: https://www.jianshu.com/p/5d1f8cd5fe31
- 沿给定轴 dim ,将输入索引张量 index 指定位置的值进行聚合。
- 对一个 3 维张量,输出可以定义为:
out[i][j][k] = input[index[i][j][k]][j][k] # if dim == 0
out[i][j][k] = input[i][index[i][j][k]][k] # if dim == 1
out[i][j][k] = input[i][j][index[i][j][k]] # if dim == 2
Parameters:
- input (Tensor) – 源张量
- dim (int) – 索引的轴
- index (LongTensor) – 聚合元素的下标(index需要是torch.longTensor类型)
- out (Tensor, optional) – 目标张量
使用说明举例:
(1) dim = 1
#实例:
import torch
a = torch.randint(0, 30, (2, 3, 5))
print(a)
index = torch.LongTensor([[[0,1,2,0,2],
[0,0,0,0,0],
[1,1,1,1,1]],
[[1,2,2,2,2],
[0,0,0,0,0],
[2,2,2,2,2]]])
print(a.size()==index.size())
b = torch.gather(a, 1,index)
print(b)
#打印结果
tensor([[[14, 0, 11, 3, 8],
[12, 7, 12, 7, 25],
[24, 5, 22, 19, 10]],
[[ 2, 16, 4, 0, 17],
[ 6, 22, 16, 21, 21],
[16, 19, 18, 11, 18]]])
True
tensor([[[14, 7, 22, 3, 10],
[14, 0, 11, 3, 8],
[12, 7, 12, 7, 25]],
[[ 6, 19, 18, 11, 18],
[ 2, 16, 4, 0, 17],
[16, 19, 18, 11, 18]]])
#解释
"""
可以看到沿着dim=1,也就是列的时候。输出tensor第一页内容,
第一行分别是 按照index指定的,
input tensor的第一页
第一列的下标为0的元素 第二列的下标为1元素 第三列的下标为2的元素,第四列下标为0元素,第五列下标为2元素
index-->0,1,2,0,2 output--> 18., 26., 22., 1., 0.
"""
(2) dim =2
#实例:
a = torch.randint(0, 30, (2, 3, 5))
print(a)
index = torch.LongTensor([[[0,1,2,0,2],
[0,0,0,0,0],
[1,1,1,1,1]],
[[1,2,2,2,2],
[0,0,0,0,0],
[2,2,2,2,2]]])
print(a.size()==index.size())
c = torch.gather(a, 2,index)
print(c)
#打印结果
tensor([[[ 5, 2, 1, 16, 19],
[12, 20, 4, 9, 16],
[29, 23, 26, 23, 27]],
[[12, 2, 11, 15, 13],
[ 4, 28, 24, 5, 28],
[ 9, 9, 12, 0, 11]]])
True
tensor([[[ 5, 2, 1, 5, 1],
[12, 12, 12, 12, 12],
[23, 23, 23, 23, 23]],
[[ 2, 11, 11, 11, 11],
[ 4, 4, 4, 4, 4],
[12, 12, 12, 12, 12]]])
#解释
"""
dim = 2的时候就安装 行 聚合了。参照上面的举一反三。
"""
(3) dim = 0
#实例:
import torch
a = torch.randint(0, 30, (2, 3, 5))
print(a)
index2 = torch.LongTensor([[[0,1,1,0,1],
[0,1,1,1,1],
[1,1,1,1,1]],
[[1,0,0,0,0],
[0,0,0,0,0],
[1,1,0,0,0]]])
d = torch.gather(a, 0,index2)
print(d)
#打印结果
tensor([[[17, 29, 19, 9, 9],
[19, 9, 1, 11, 21],
[22, 15, 23, 9, 18]],
[[ 3, 4, 14, 14, 18],
[11, 8, 29, 5, 12],
[12, 1, 1, 23, 9]]])
tensor([[[17, 4, 14, 9, 18],
[19, 8, 29, 5, 12],
[12, 1, 1, 23, 9]],
[[ 3, 29, 19, 9, 9],
[19, 9, 1, 11, 21],
[12, 1, 23, 9, 18]]])
#解释
"""
这个有点特殊,dim = 0的时候(三维情况下),是从不同的页收集元素的。
这里举的例子只有两页。所有index在0,1两个之间选择。
输出的矩阵元素也是按照index的指定。分别在第一页和第二页之间跳着选的。
index [0,1,1,0,1]的意思就是。
在第一页选这个位置的元素,在第二页选这个位置的元素,在第二页选,第一页选,第二页选。
作者:逆鳞L
链接:https://www.jianshu.com/p/5d1f8cd5fe31
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
"""
8.18 torch.Tensor()
torch.Tensor()是Python类,更明确的说,是默认张量类型torch.FloatTensor()的别名,torch.Tensor([1,2]) 会调用Tensor类的构造函数__init__,生成单精度浮点类型的张量。
#实例
import torch
a=torch.Tensor([1,2])
print(a.type())
#打印结果
torch.FloatTensor
8.19 torch.tensor()
torch.tensor()仅仅是Python的函数,函数原型是:
torch.tensor(data, dtype=None, device=None, requires_grad=False)
其中data可以是:list, tuple, array, scalar等类型。
torch.tensor()可以从data中的数据部分做拷贝(而不是直接引用),根据原始数据类型生成相应的torch.LongTensor,torch.FloatTensor,torch.DoubleTensor。
#实例
import torch
import numpy as np
a = torch.tensor([1, 2])
print(a.type())
a = torch.tensor([1., 2.])
print(a.type())
a = np.zeros(2, dtype=np.float64)
a = torch.tensor(a)
print(a.type())
#结果打印
torch.LongTensor
torch.FloatTensor
torch.DoubleTensor
9.矩阵操作
方法名 | 说明 |
---|---|
dot(t1, t2) | 计算张量的内积 |
mm(t1, t2) | 计算矩阵乘法 |
mv(t1, v1) | 计算矩阵与向量乘法 |
qr(t) | 计算t的QR分解 |
svd(t) | 计算t的SVD分解 |
10.Tensor对象的方法
方法名 | 作用 |
---|---|
size() | 返回张量的shape属性值 |
numel(input) | 计算tensor的元素个数 |
view(*shape) | 修改tensor的shape,与np.reshape类似,view返回的对象共享内存 |
resize | 类似于view,但在size超出时会重新分配内存空间 |
item | 若为单元素tensor,则返回pyton的scalar |
from_numpy | 从numpy数据填充 |
numpy | 返回ndarray类型 |
11.Tensor内部
tensor对象由两部分组成,tensor的信息与存储,storage封装了真正的data,可以由多个tensor共享。大多数操作只是修改tensor的信息,而不修改storage部分。这样达到效率与性能的提升。
12.使用Pytorch进行线性回归
四.自动求导
tensor对象通过一系列的运算可以组成动态图,对于每个tensor对象,有下面几个变量控制求导的属性。
变量 | 作用 |
---|---|
requirs_grad | 默认为False,表示变量是否需要计算导数 |
grad_fn | 变量的梯度函数 |
grad | 变量对应的梯度 |
五.创建神经网络
1.神经网络层
torch.nn模块提供了创建神经网络的基础构件,这些层都继承自Module类。下面我们简单看下如何实现Liner层。
下面表格中列出了比较重要的神经网络层组件。对应的在nn.functional模块中,提供这些层对应的函数实现。通常对于可训练参数的层使用module,而对于不需要训练参数的层如softmax这些,可以使用functional中的函数。
Layer对应的类 | 功能说明 |
---|---|
Linear(in_dim, out_dim, bias=True) | 提供了进行线性变换操作的功能 |
Dropout§ | Dropout层,有2D,3D的类型 |
Conv2d(in_c, out_c, filter_size, stride, padding) | 二维卷积层,类似的有Conv1d,Conv3d |
ConvTranspose2d() | |
MaxPool2d(filter_size, stride, padding) | 二维最大池化层 |
MaxUnpool2d(filter, stride, padding) | 逆过程 |
AvgPool2d(filter_size, stride, padding) | 二维平均池化层 |
FractionalMaxPool2d | 分数最大池化 |
AdaptiveMaxPool2d([h,w]) | 自适应最大池化 |
AdaptiveAvgPool2d([h,w]) | 自自应平均池化 |
ZeroPad2d(padding_size) | 零填充边界 |
ConstantPad2d(padding_size,const) | 常量填充边界 |
ReplicationPad2d(ps) | 复制填充边界 |
BatchNorm1d() | 对2维或3维小批量数据进行标准化操作 |
RNN(in_dim, hidden_dim, num_layers, activation, dropout, bidi, bias) | 构建RNN层 |
RNNCell(in_dim, hidden_dim, bias, activation) | RNN单元 |
LSTM(in_dim, hidden_dim, num_layers, activation, dropout, bidi, bias) | 构建LSTM层 |
LSTMCell(in_dim, hidden_dim, bias, activation) | LSTM单元 |
GRU(in_dim, hidden_dim, num_layers, activation, dropout, bidi, bias) | 构建GRU层 |
GRUCell(in_dim, hidden_dim, bias, activation) | GRU单元 |
2.非线性激活层
激活层类名 | 作用 |
---|---|
ReLU(inplace=False) | Relu激活层 |
Sigmoid | Sigmoid激活层 |
Tanh | Tanh激活层 |
Softmax | Softmax激活层 |
Softmax2d | |
LogSoftmax | LogSoftmax激活层 |
2.1 ReLU(inplace=False)
2.2 Sigmoid
2.3 Tanh
2.4 Softmax
2.5 Softmax2d
2.6 LogSoftmax
3.容器类型
容器类型 | 功能 |
---|---|
Module | 神经网络模块的基类 |
Sequential | 序列模型,类似于keras,用于构建序列型神经网络 |
ModuleList | 用于存储层,不接受输入 |
Parameters(t) | 模块的属性,用于保存其训练参数 |
ParameterList | 参数列表 |
4.其他层
容器类型 | 功能 |
---|---|
Embedding(vocab_size, feature_dim) | 词向量层 |
Embeddingbag |
5.模型的保存
前面我们知道tensor可以通过save与load方法实现序列化与反序列化。由tensor组成的网络同样也可以方便的保存。不过通常没有必要完全保存网络模块对象,只需要保存各层的权重数据即可,这些数据保存在模块的state_dict字典中,因此只需要序列化这个词典。
6.实现LeNet神经网络
六.损失函数与优化方法
1.损失函数
torch.nn模块中提供了许多损失函数类,这里列出几种相对常见的。
类名 | 功能 |
---|---|
MSELoss | 均方差损失 |
CrossEntropyLoss | 交叉熵损失 |
NLLLoss | 负对数似然损失 |
PoissonNLLLoss | 带泊松分布的负对数似然损失 |
1.1 MSELoss
1.2 CrossEntropyLoss
1.3 NLLLoss
1.4 PoissonNLLLoss
2.优化方法
由torch.optim模块提供支持 。
类名 | 功能 |
---|---|
SGD(params, lr=0.1, momentum=0, dampening=0, weight_decay=0, nesterov=False) | 随机梯度下降法 |
Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False) | Adam |
RMSprop(params, lr=0.01, alpha=0.99, eps=1e-08, weight_decay=0, momentum=0, centered=False) | RMSprop |
Adadelta(params, lr=1.0, rho=0.9, eps=1e-06, weight_decay=0) | Adadelta |
Adagrad(params, lr=0.01, lr_decay=0, weight_decay=0, initial_accumulator_value=0) | Adagrad |
lr_scheduler.ReduceLROnPlateau(optimizer, mode=’min’, factor=0.1, patience=10, verbose=False, threshold=0.0001, threshold_mode=’rel’, cooldown=0, min_lr=0, eps=1e-08) | 学习率的控制 |
2.1 SGD()
2.2 Adam()
2.3 RMSprop()
2.4 Adadelta()
2.5 Adagrad()
2.6 lr_scheduler.ReduceLROnPlateau()
在神经网络的性能调优中,常见的作法是对不对层的网络设置不同的学习率。
3.参数初始化
良好的初始化可以让模型快速收敛,有时甚至可以决定模型是否能训练成功。Pytorch中的参数通常有默认的初始化策略,不需要我们自己指定,但框架仍然留有相应的接口供我们来调整初始化方法。
初始化方法 | 说明 |
---|---|
xavier_uniform_ | |
xavier_normal_ | |
kaiming_uniform_ |
七.数据集与数据加载器
1.DataSet与DataLoader
torch.util.data模块提供了DataSet类用于描述一个数据集。定义自己的数据集需要继承自DataSet类,且实现__getitem__()与__len__()方法。__getitem__方法返回指定索引处的tensor与其对应的label。
为了支持数据的批量及随机化操作,可以使用data模块下的DataLoader类型来返回一个加载器:
DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, batch_sampler=None, num_workers=0)
2.torchvision简介
torchvision是配合pytorch的独立计算机视觉数据集的工具库,下面介绍其中常用的数据集类型。
-
torchvision.datasets.ImageFolder(dir, transform, label_map,loader)
提供了从一个目录初始化出来一个图片数据集的便捷方法。
要求目录下的图片分类存放,每一类的图片存储在以类名为目录名的目录下,方法会将每个类名映射到唯一的数字上,如果你对数字有要求,可以用label_map来定义目录名到数字的映射。 -
torchvision.datasets.DatasetFolder(dir,transform, label_map, loader, extensions)
提供了从一个目录初始化一般数据集的便捷方法。目录下的数据分类存放,每类数据存储在class_xxx命名的目录下。 -
此外torchvision.datasets下实现了常用的数据集,如CIFAR-10/100, ImageNet, COCO, MNIST, LSUN等。
-
除了数据集,torchvision的model模块提供了常见的模型实现,如Alex-Net, VGG,Inception, Resnet等。
3.torchvision提供的图像变换工具
torchvision的transforms模块提供了对PIL.Image对象和Tensor对象的常见操作。如果需要连续应用多个变换,可以使用Compose对象组装多个变换。
转换操作 | 说明 |
---|---|
Scale | PIL图片进行缩放 |
CenterCrop | PIL图片从中心位置剪切 |
Pad | PIL图片填充 |
ToTensor | PIL图片转换为Tensor且归一化到[0,1] |
Normalize | Tensor标准化 |
ToPILImage | 将Tensor转为PIL表示 |
八.训练过程可视化
1.使用Tensorboard
通过使用第三方库tensorboard_logger,将训练过程中的数据保存为日志,然后便可以通过Tensorboard来查看这些数据了。其功能支持相对有限,这里不做过多介绍。
2.使用visdom
visdom是facebook开源的一个可视工具,可以用来完成pytorch训练过程的可视化。
- 安装可以使用pip install visdom
- 启动类似于tb,在命令行上执行:python -m visdom.server
- 服务启动后可以使用浏览器打开http://127.0.0.1:8097/即可看到主面板。
visdom的绘图API类似于plot,通过API将绘图数据发送到基于tornado的web服务器上并显示在浏览器中。更详细内容参见visdom的github主页。
九.GPU及并行处理
为了能在GPU上运行,Tensor与Module都需要转换到cuda模式下。
如果有多块显卡,可以通过cuda(device_id)来将tensor分到不同的GPU上以达到负载的均衡。
另一种比较省事的做法是调用torch.set_default_tensor_type使程序默认使用某种cuda的tensor。或者使用torch.cuda.set_device(id)指定使用某个GPU。
十.示例
4.enumerate()
5.均值和方差的计算
以torch中MNIST书数据集为例,计算数据*****************************的均值和方差。
6.优化
from torch.optim import optimizer
self.op=torch.optim.Adam(self.net.parameters())
7.损失
8.GPU及并行支持