pytorch常用函数

Tensor基本操作

Tensor的基本数据类型

torch.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 N/A 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
import torch
import numpy as np

t = torch.FloatTensor([[1, 2, 3], [4, 5, 6]])
print(t.dtype)
print(t)

Tensor数据类型的转化

import torch
import numpy as np

# 默认数据类型为float32
t = torch.Tensor(3, 5)
print(t.dtype, "\n")


# t.double()将该tensor投射为double类型
double_t = t.double()
print(double_t.dtype)

# t.float()将该tensor投射为float类型
float_t = t.float()
print(float_t.dtype)


# t.half()将tensor投射为半精度浮点类型
half_t = t.half()
print(half_t.dtype)

# t.long() 将tensor投射为long类型
long_t = t.long()
print(long_t.dtype)

# t.int()将该tensor投射为int类型
int_t = t.int()
print(int_t.dtype)

# t.short()将该tensor投射为short类型
short_t = t.short()
print(short_t.dtype)


# t.char()将该tensor投射为char类型
char_t = t.char()
print(char_t.dtype)

# t.byte()将该tensor投射为byte类型
byte_t = t.byte()
print(byte_t.dtype)

# t.cuda()将tensor投射为gputensor
gpu_t = t.cuda()
print(gpu_t.dtype)

Tensor与numpy的相互转换

import torch
import numpy as np

a = np.array([1, 2, 3])
t = torch.from_numpy(a)
print(t)
t[0] = -1
a = t.numpy()
print(a)

Tensor拼接操作

import torch
import numpy as np

x = torch.randn(2, 3)
print(x)

x0 = torch.cat((x, x, x), 0)
print(x0)

x1 = torch.cat((x, x, x), 1)
print(x1)

Tensor进行分块

import torch
import numpy as np

x = torch.randn(2, 3)
print(x)

x = torch.chunk(x, 2, 0)
print(x)

Tensor进行挤压

import torch
import numpy as np

x = torch.zeros(2, 1, 2, 1, 2)
print(x.size())

y = torch.squeeze(x)
print(y.size())

y = torch.squeeze(x, 0)
print(y.size())

y = torch.squeeze(x, 1)
print(y.size())

Tensor进行扩增

import torch
import numpy as np

x = torch.zeros(2, 2, 2)
print(x.size())

y = torch.unsqueeze(x, 0)
print(y.size())

y = torch.unsqueeze(x, 1)
print(y.size())

Tensor进行转置

import torch
import numpy as np

x = torch.randn(2, 3)
print(x)

x = torch.transpose(x, 0, 1)
print(x)

Tensor进行view操作

相当于numpy中resize()的功能,但是用法可能不太一样。

把原先tensor中的数据按照行优先的顺序排成一个一维的数据(这里应该是因为要求地址是连续存储的),然后按照参数组合成其他维度的tensor。比如说是不管你原先的数据是[[[1,2,3],[4,5,6]]]还是[1,2,3,4,5,6],因为它们排成一维向量都是6个元素,所以只要view后面的参数一致,得到的结果都是一样的。比如,

a=torch.Tensor([[[1,2,3],[4,5,6]]])
b=torch.Tensor([1,2,3,4,5,6])

print(a.view(1,6))
print(b.view(1,6))

得到的结果都是tensor([[1., 2., 3., 4., 5., 6.]])

a=torch.Tensor([[[1,2,3],[4,5,6]]])
print(a.view(3,2))

'''
tensor([[1., 2.],
        [3., 4.],
        [5., 6.]])'''

随机种子

import torch
import numpy as np

torch.manual_seed(0)

x = torch.randn(2, 3)
print(x)

torch.manual_seed(0)

x = torch.randn(2, 3)
print(x)

序列化

当提到保存和加载模型时,有三个核心功能需要熟悉:
1.torch.save:将序列化的对象保存到disk。这个函数使用Python的pickle实用程序进行序列化。使用这个函数可以保存各种对象的模型、张量和字典。
2.torch.load:使用pickle unpickle工具将pickle的对象文件反序列化为内存。
3.torch.nn.Module.load_state_dict:使用反序列化状态字典加载model’s参数字典。

什么是state_dict

import torch
import torch.nn as nn
import torch.nn.functional as F
# Define model


class TheModelClass(nn.Module):
def __init__(self):
super(TheModelClass, 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 farward(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 = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x


# Initialize model
model = TheModelClass()
# Initialize optimizer
optimizer = torch.optim.SGD(model.parameters(), lr=1e-4, momentum=0.9)

print("Model's state_dict:")
# Print model's state_dict
for param_tensor in model.state_dict():
print(param_tensor, "\t", model.state_dict()[param_tensor].size())
print("optimizer's state_dict:")
# Print optimizer's state_dict
for var_name in optimizer.state_dict():
print(var_name, "\t", optimizer.state_dict()[var_name])

保存读取模型

# 只保存模型的学习参数
torch.save(model.state_dict(), PATH)

# 读取模型的可学习参数
model = TheModelClass(*args, **kwargs)
model.load_state_dict(torch.load(PATH))
model.eval()
# 保存整个模型
torch.save(the_model, PATH)

# 读取整个模型
the_model = torch.load(PATH)
model.eval()
# 序列化字典

# save
torch.save({
'epoch': epoch,
'model_state_dict': model.state_dict(),
'optimizer_state_dict': optimizer.state_dict(),
'loss': loss,
...
}, PATH)

# load
model = TheModelClass(*args, **kwargs)
optimizer = TheOptimizerClass(*args, **kwargs)
checkpoint = torch.load(PATH)
model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
epoch = checkpoint['epoch']
loss = checkpoint['loss']

model.eval()
# - or -
model.train()

数学操作

夹紧操作

import torch
import numpy as np

a = torch.randn(4)
print(a)

a = torch.clamp(a, min=-0.5, max=0.5)
print(a)

沿维度计算和

import torch
import numpy as np

a = torch.randn(10)
print(a)

a = torch.cumsum(a, dim=0)
print(a)
print(a[-1])

计算元素均值

import torch
import numpy as np

a = torch.randn(2, 2)
print(a)

b = torch.mean(a)
print(b)

b = torch.mean(a, 1)
print(b)

计算元素标准差

import torch
import numpy as np

a = torch.randn(2, 2)
print(a)

b = torch.std(a)
print(b)

b = torch.std(a, dim=1)
print(b)

计算所有元素和

import torch
import numpy as np

a = torch.randn(2, 2)
print(a)

b = torch.sum(a)
print(b)

b = torch.sum(a, dim=0)
print(b)

torch.nn

容器

torch.nn.Module是所有网络的基类。你的模型也应该继承这个类。
Modules也可以包含其它Modules,允许使用树结构嵌入他们。
你可以将子模块赋值给模型属性。

import torch.nn as nn
import torch.nn.functional as F


class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.conv1 = nn.Conv2d(1, 20, 5) # submodule: Conv2d
self.conv2 = nn.Conv2d(20, 20, 5)

def forward(self, x):
x = F.relu(self.conv1(x))
return F.relu(self.conv2(x))

时序容器

# Example of using Sequential
model = nn.Sequential(
nn.Conv2d(1,20,5),
nn.ReLU(),
nn.Conv2d(20,64,5),
nn.ReLU()
)

# Example of using Sequential with OrderedDict
model = nn.Sequential(OrderedDict([
('conv1', nn.Conv2d(1,20,5)),
('relu1', nn.ReLU()),
('conv2', nn.Conv2d(20,64,5)),
('relu2', nn.ReLU())
]))

卷积层

Conv2d

class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)

参数kernel_size,stride,padding,dilation也可以是一个int的数据,此时卷积height和width值相同;也可以是一个tuple数组,tuple的第一维度表示height的数值,tuple的第二维度表示width的数值。

  • in_channels(int) – 输入信号的通道
  • out_channels(int) – 卷积产生的通道
  • kerner_size(int or tuple) - 卷积核的尺寸
  • stride(int or tuple, optional) - 卷积步长
  • padding(int or tuple, optional) - 输入的每一条边补充0的层数
  • dilation(int or tuple, optional) – 卷积核元素之间的间距
  • groups(int, optional) – 从输入通道到输出通道的阻塞连接数
  • bias(bool, optional) - 如果bias=True,添加偏置
    import torch.nn as nn
    import torch

    m = nn.Conv2d(16, 33, 3, stride=2)

    m = nn.Conv2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2))

    m = nn.Conv2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2), dilation=(3, 1))

    input = torch.Tensor(torch.randn(20, 16, 50, 100))

    output = m(input)

    print(output)
# 空洞卷积
import torch.nn as nn
import torch

m = nn.Conv2d(16, 33, kernel_size=3, stride=1, padding=2, dilation=2)

input = torch.Tensor(torch.randn(20, 16, 100, 100))
print(input.size())

output = m(input)

print(output.size())

ConvTranspose2d

class torch.nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True)

注意,这上面的stride、padding是争对于与原始卷积上的stride和padding
2维的转置卷积操作(transposed convolution operator,注意改视作操作可视作解卷积操作,但并不是真正的解卷积操作) 该模块可以看作是Conv2d相对于其输入的梯度,有时(但不正确地)被称为解卷积操作。

由于内核的大小,输入的最后的一些列的数据可能会丢失。因为输入和输出是不是完全的互相关。因此,用户可以进行适当的填充(padding操作)。

  • in_channels(int) – 输入信号的通道数
  • out_channels(int) – 卷积产生的通道数
  • kerner_size(int or tuple) - 卷积核的大小
  • stride(int or tuple,optional) - 卷积步长
  • padding(int or tuple, optional) - 输入的每一条边补充0的层数
  • output_padding(int or tuple, optional) - 输出的每一条边补充0的层数
  • dilation(int or tuple, optional) – 卷积核元素之间的间距
  • groups(int, optional) – 从输入通道到输出通道的阻塞连接数
  • bias(bool, optional) - 如果bias=True,添加偏置
    import torch.nn as nn
    import torch

    input = torch.Tensor(torch.randn(20, 16, 64, 64))
    print(input.size())

    m = nn.ConvTranspose2d(16, 33, 3, stride=2, padding=1, output_padding=1)
    output = m(input)
    print(output.size())

池化层

Maxpool2d

class torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)

  • kernel_size(int or tuple) - max pooling的窗口大小
  • stride(int or tuple, optional) - max pooling的窗口移动的步长。默认值是kernel_size
  • padding(int or tuple, optional) - 输入的每一条边补充0的层数
  • dilation(int or tuple, optional) – 一个控制窗口中元素步幅的参数
  • return_indices - 如果等于True,会返回输出最大值的序号,对于上采样操作会有帮助
  • ceil_mode - 如果等于True,计算输出信号大小的时候,会使用向上取整,代替默认的向下取整的操作
    import torch.nn as nn
    import torch

    input = torch.Tensor(torch.randn(20, 16, 64, 64))
    print(input.size())

    m = nn.MaxPool2d(3, stride=2)
    output = m(input)
    print(output.size())

    input = torch.Tensor(torch.randn(1, 3, 4, 4))
    print(input)

    m = nn.MaxPool2d(2, stride=2, return_indices=True)
    output, indices = m(input)
    print(indices)

MaxUnpool2d

class torch.nn.MaxUnpool2d(kernel_size, stride=None, padding=0)

Maxpool2d的逆过程,不过并不是完全的逆过程,因为在maxpool2d的过程中,一些最大值的已经丢失。 MaxUnpool2d的输入是MaxPool2d的输出,包括最大值的索引,并计算所有maxpool2d过程中非最大值被设置为零的部分的反向。

  • kernel_size(int or tuple) - max pooling的窗口大小
  • stride(int or tuple, optional) - max pooling的窗口移动的步长。默认值是kernel_size
  • padding(int or tuple, optional) - 输入的每一条边补充0的层数
    import torch.nn as nn
    import torch


    pool = nn.MaxPool2d(2, stride=2, return_indices=True)
    unpool = nn.MaxUnpool2d(2, stride=2)

    input = torch.Tensor([[[[1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
    [13, 14, 15, 16]]]])

    output, indices = pool(input)
    result = unpool(output, indices)
    print(result)

AvgPool2d

class torch.nn.AvgPool2d(kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True)

  • kernel_size(int or tuple) - 池化窗口大小
  • stride(int or tuple, optional) - max pooling的窗口移动的步长。默认值是kernel_size
  • padding(int or tuple, optional) - 输入的每一条边补充0的层数
  • dilation(int or tuple, optional) – 一个控制窗口中元素步幅的参数
  • ceil_mode - 如果等于True,计算输出信号大小的时候,会使用向上取整,代替默认的向下取整的操作
  • count_include_pad - 如果等于True,计算平均池化时,将包括padding填充的0
    import torch.nn as nn
    import torch

    input = torch.Tensor(torch.randn(1, 3, 9, 9))

    m = nn.AvgPool2d(3, stride=2)
    output = m(input)
    print(output.size())

AdaptiveMaxPool2d

class torch.nn.AdaptiveMaxPool2d(output_size, return_indices=False)

对输入信号,提供2维的自适应最大池化操作 对于任何输入大小的输入,可以将输出尺寸指定为H*W,但是输入和输出特征的数目不会变化。

import torch.nn as nn
import torch

input = torch.Tensor(torch.randn(1, 3, 9, 9))

m = nn.AdaptiveMaxPool2d((3, 3))

output = m(input)

print(output.size())

非线性激活函数

ReLU

class torch.nn.ReLU(inplace=False)

对输入运用修正线性单元函数
{ReLU}(x)= max(0, x)

import torch.nn as nn
import torch

input = torch.Tensor(torch.randn(1, 3, 3, 3))
print(input)

m = nn.ReLU(inplace=True)

output = m(input)

print(input)
print(output)

ELU

class torch.nn.ELU(alpha=1.0, inplace=False)

对输入的每一个元素运用函数
f(x) = max(0,x) + min(0, alpha * (e^x - 1))

import torch.nn as nn
import torch

input = torch.Tensor(torch.randn(1, 3, 3, 3))
print(input)

m = nn.ELU(inplace=False)

output = m(input)

print(output)

PReLU

class torch.nn.PReLU(num_parameters=1, init=0.25)
对输入的每一个元素运用函数
PReLU(x) = max(0,x) + a * min(0,x)
a是一个可学习参数。当没有声明时,nn.PReLU()在所有的输入中只有一个参数a;如果是nn.PReLU(nChannels),a将应用到每个输入。

import torch.nn as nn
import torch

input = torch.Tensor(torch.randn(1, 3, 3, 3))
print(input)

m = nn.PReLU()

output = m(input)

print(output)

LeakyReLU

class torch.nn.LeakyReLU(negative_slope=0.01, inplace=False)

对输入的每一个元素运用
f(x) = max(0, x) + {negative_slope} * min(0, x)

import torch.nn as nn
import torch

input = torch.Tensor(torch.randn(1, 3, 3, 3))
print(input)

m = nn.LeakyReLU()

output = m(input)

print(output)

Threshold

class torch.nn.Threshold(threshold, value, inplace=False)

y=x,if x>=threshold y=value,if x<threshold

import torch.nn as nn
import torch

input = torch.Tensor(torch.randn(1, 3, 3, 3))
print(input)

m = nn.Threshold(0.1, 20)

output = m(input)

print(output)

Sigmoid

class torch.nn.Sigmoid

import torch.nn as nn
import torch

input = torch.Tensor(torch.randn(1, 3, 3, 3))
print(input)

m = nn.Sigmoid()

output = m(input)

print(output)

Tanh

class torch.nn.Tanh

import torch.nn as nn
import torch

input = torch.Tensor(torch.randn(1, 3, 3, 3))
print(input)

m = nn.Tanh()

output = m(input)

print(output)

Softmax

class torch.nn.Softmax
对n维输入张量运用Softmax函数,将张量的每个元素缩放到(0,1)区间且和为1。

import torch.nn as nn
import torch

input = torch.Tensor(torch.randn(1, 7))
print(input)

m = nn.Softmax(dim=1)

output = m(input)

print(output)

标准化层

BatchNorm2d

class torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True)

对小批量(mini-batch)3d数据组成的4d输入进行批标准化(Batch Normalization)操作
在每一个小批量(mini-batch)数据中,计算输入各个维度的均值和标准差。gamma与beta是可学习的大小为C的参数向量(C为输入大小)
在训练时,该层计算每次输入的均值与方差,并进行移动平均。移动平均默认的动量值为0.1。
在验证时,训练求得的均值/方差将用于标准化验证数据。

  • num_features: 来自期望输入的特征数,该期望输入的大小为’batch_size x num_features x height x width’
  • eps: 为保证数值稳定性(分母不能趋近或取0),给分母加上的值。默认为1e-5。
  • momentum: 动态均值和动态方差所使用的动量。默认为0.1。
  • affine: 一个布尔值,当设为true,给该层添加可学习的仿射变换参数。
    import torch.nn as nn
    import torch

    input = torch.Tensor(torch.randn(20, 100, 3, 3))
    print(input)

    m = nn.BatchNorm2d(100)

    output = m(input)

    print(output)

线性层

Linear

class torch.nn.Linear(in_features, out_features, bias=True)
对输入数据做线性变换:y=Ax+b

  • in_features - 每个输入样本的大小
  • out_features - 每个输出样本的大小
  • bias - 若设置为False,这层不会学习偏置。默认值:True
    import torch.nn as nn
    import torch

    input = torch.Tensor(torch.randn(20, 20))
    print(input.size())

    m = nn.Linear(20, 30)

    output = m(input)

    print(output.size())

Dropout层

Dropout

class torch.nn.Dropout(p=0.5, inplace=False)

随机将输入张量中部分元素设置为0。对于每次前向调用,被置0的元素都是随机的。

  • p - 将元素置0的概率。默认值:0.5
  • in-place - 若设置为True,会在原地执行操作。默认值:False
    import torch.nn as nn
    import torch

    input = torch.Tensor(torch.randn(3, 6))
    print(input)

    m = nn.Dropout(p=0.5)

    output = m(input)

    print(output)

Droupout2d

class torch.nn.Dropout2d(p=0.5, inplace=False)

随机将输入张量中整个通道设置为0。对于每次前向调用,被置0的通道都是随机的。

import torch.nn as nn
import torch

input = torch.Tensor(torch.randn(1, 3, 3, 3))
print(input)

m = nn.Dropout2d(p=0.5)

output = m(input)

print(output)

损失函数

基本用法:

criterion = LossCriterion() #构造函数有自己的参数
loss = criterion(x, y) #调用标准时也有参数

计算出来的结果已经对mini-batch取了平均。

MSELoss

class torch.nn.MSELoss(size_average=True)
创建一个衡量输入x(模型预测输出)和目标y之间均方误差标准。

import torch.nn as nn
import torch

input1 = torch.Tensor(torch.randn(1, 8))
print(input1)

input2 = torch.Tensor(torch.rand(1, 8))
print(input2)

criterion = nn.MSELoss()

loss = criterion(input1, input2)
print(loss)

CrossEntropyLoss

class torch.nn.CrossEntropyLoss(weight=None, size_average=True)

此标准将LogSoftMax和NLLLoss集成到一个类中。不需要再使用softmax。

  • weight(tensor): 1-D tensor,n个元素,分别代表n类的权重,如果你的训练样本很不均衡的话,是非常有用的。默认值为None。

  • input : 包含每个类的得分,3-D tensor,shape为 batchn样例数

  • target: 大小为 n 的 2-D tensor,包含类别的索引(0到 n-1),long型。
    import torch.nn as nn
    import torch

    # batchsize=3, 二分类, 8个样例
    input = torch.Tensor(torch.randn(2, 3, 3, 3))
    print(input)

    # target为long型
    target = torch.Tensor(torch.zeros(2, 3, 3)).long()
    target[0, 0, 0] = 2
    target[1, 1, 1] = 1
    target[1, 2, 2] = 1
    print(target)

    criterion = nn.CrossEntropyLoss()

    loss = criterion(input, target)
    print(loss)

BCELoss

class torch.nn.BCELoss(weight=None, size_average=True)

计算 target 与 output 之间的二进制交叉熵。

import torch.nn as nn
import torch

# 二进制交叉商,用0和1来表示类别
criterion = nn.BCELoss(reduction="none")

input = torch.Tensor(torch.randn(2, 3, 3))
m = nn.Sigmoid()
input = m(input)
print(input)

target = torch.Tensor(torch.ones(2, 3, 3))
target[0, 0, 0] = 0
target[1, 1, 1] = 0
target[1, 2, 2] = 0
print(target)

loss = criterion(input, target)
print(loss.mean())

视觉函数

PixelShuffle

class torch.nn.PixelShuffle(upscale_factor)

将shape为$[N, Cr^2, H, W]$的Tensor重新排列为shape为$[N, C, Hr, W*r]$的Tensor。 当使用stride=1/r 的sub-pixel卷积的时候,这个方法是非常有用的。

import torch.nn as nn
import torch

ps = nn.PixelShuffle(3)

input = torch.Tensor(torch.randn(1, 9, 4, 4))
print(input.size())

output = ps(input)
print(output.size())

UpsamplingNearest2d

class torch.nn.UpsamplingNearest2d(size=None, scale_factor=None)

对于多channel 输入 进行 2-D 最近邻上采样。
可以通过size或者scale_factor来指定上采样后的图片大小。
当给定size时,size的值将会是输出图片的大小。

  • size (tuple, optional) – 一个包含两个整数的元组 (H_out, W_out)指定了输出的长宽
  • scale_factor (int, optional) – 长和宽的一个乘子
    import torch.nn as nn
    import torch

    m = nn.UpsamplingNearest2d(scale_factor=2)

    input = torch.Tensor(torch.randn(1, 1, 2, 2))
    print(input)

    output = m(input)
    print(output)

UpsamplingBilinear2d

class torch.nn.UpsamplingBilinear2d(size=None, scale_factor=None)

import torch.nn as nn
import torch

m = nn.UpsamplingBilinear2d(scale_factor=2)

input = torch.Tensor(torch.randn(1, 1, 2, 2))
print(input)

output = m(input)
print(output)

多GPU模块并行

DataParallel

class torch.nn.DataParallel(module, device_ids=None, output_device=None, dim=0)

在模块级别上实现数据并行。
此容器通过将mini-batch划分到不同的设备上来实现给定module的并行。在forward过程中,module会在每个设备上都复制一遍,每个副本都会处理部分输入。在backward过程中,副本上的梯度会累加到原始module上。
batch的大小应该大于所使用的GPU的数量。还应当是GPU个数的整数倍,这样划分出来的每一块都会有相同的样本数量。

  • module – 要被并行的module
  • device_ids – CUDA设备,默认为所有设备。
  • output_device – 输出设备(默认为device_ids[0])
    net = torch.nn.DataParallel(model, device_ids=[0, 1, 2])
    output = net(input_var)

优化器

为了构建一个Optimizer,你需要给它一个包含了需要优化的参数(必须都是Variable对象)的iterable。然后,你可以设置optimizer的参 数选项,比如学习率,权重衰减,等等。

optimizer = optim.SGD(model.parameters(), lr = 0.01, momentum=0.9)
optimizer = optim.Adam([var1, var2], lr = 0.0001)

当我们想指定每一层的学习率时

optim.SGD([
{'params': model.base.parameters()},
{'params': model.classifier.parameters(), 'lr': 1e-3}
], lr=1e-2, momentum=0.9)

这意味着model.base的参数将会使用1e-2的学习率,model.classifier的参数将会使用1e-3的学习率,并且0.9的momentum将会被用于所有的参数。

所有的optimizer都实现了step()方法,这个方法会更新所有的参数。

optimizer.step()
这是大多数optimizer所支持的简化版本。一旦梯度被如backward()之类的函数计算好后,我们就可以调用这个函数。

for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()

Optimizer

class torch.optim.Optimizer(params, defaults) [source]

Base class for all optimizers.

  • params (iterable) —— Variable 或者 dict的iterable。指定了什么参数应当被优化。
  • defaults —— (dict):包含了优化选项默认值的字典(一个参数组没有指定的参数选项将会使用默认值)。

    Adam

    class torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)[source]

  • params (iterable) – 待优化参数的iterable或者是定义了参数组的dict

  • lr (float, 可选) – 学习率(默认:1e-3)
  • betas (Tuple[float, float], 可选) – 用于计算梯度以及梯度平方的运行平均值的系数(默认:0.9,0.999)
  • eps (float, 可选) – 为了增加数值计算的稳定性而加到分母里的项(默认:1e-8)
  • weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认: 0)

    SGD

    class torch.optim.SGD(params, lr=, momentum=0, dampening=0, weight_decay=0, nesterov=False)[source]

实现随机梯度下降算法(momentum可选)

  • params (iterable) – 待优化参数的iterable或者是定义了参数组的dict
  • lr (float) – 学习率
  • momentum (float, 可选) – 动量因子(默认:0)
  • weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认:0)
  • dampening (float, 可选) – 动量的抑制因子(默认:0)
  • nesterov (bool, 可选) – 使用Nesterov动量(默认:False)
    import torch.optim as optim

    optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
    optimizer.zero_grad()
    loss_fn(model(input), target).backward()
    optimizer.step()

数据集抽象类

torch.utils.data

class torch.utils.data.Dataset
表示Dataset的抽象类。
所有其他数据集都应该进行子类化。所有子类应该overridelengetitem,前者提供了数据集的大小,后者支持整数索引,范围从0到len(self)。

DataLoader

class torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, num_workers=0, collate_fn=, pin_memory=False, drop_last=False)

数据加载器。组合数据集和采样器,并在数据集上提供单进程或多进程迭代器。

  • dataset (Dataset) – 加载数据的数据集。
  • batch_size (int, optional) – 每个batch加载多少个样本(默认: 1)。
  • shuffle (bool, optional) – 设置为True时会在每个epoch重新打乱数据(默认: False).
  • sampler (Sampler, optional) – 定义从数据集中提取样本的策略。如果指定,则忽略shuffle参数。
  • num_workers (int, optional) – 用多少个子进程加载数据。0表示数据将在主进程中加载(默认: 0)
  • collate_fn (callable, optional) –
  • pin_memory (bool, optional) –
  • drop_last (bool, optional) – 如果数据集大小不能被batch size整除,则设置为True后可删除最后一个不完整的batch。如果设为False并且数据集的大小不能被batch size整除,则最后一个batch将更小。(默认: False)

    torchvision

    torchvision.datasets

    torchvision.datasets中包含了以下数据集
  • MNIST
  • COCO(用于图像标注和目标检测)(Captioning and Detection)
  • LSUN Classification
  • ImageFolder
  • Imagenet-12
  • CIFAR10 and CIFAR100
  • STL10

Datasets 拥有以下API:
getitem len
由于以上Datasets都是 torch.utils.data.Dataset的子类,所以,他们也可以通过torch.utils.data.DataLoader使用多线程(python的多进程)。

MNIST

from torchvision import datasets

root = "/home/ltb/MNIST"
datasets.MNIST(root, train=True, transform=None, target_transform=None, download=True)

参数说明:

  • root : processed/training.pt 和 processed/test.pt 的主目录

  • train : True = 训练集, False = 测试集

  • download : True = 从互联网上下载数据集,并把数据集放在root目录下. 如果数据集之前下载过,将处理过的数据(minist.py中有相关函数)放在processed文件夹下。

COCO

需要安装COCO API

# 图像标注
dset.CocoCaptions(root="dir where images are", annFile="json annotation file", [transform, target_transform])

from torchvision import datasets
import torchvision.transforms as transforms
cap = datasets.CocoCaptions(root='dir where images are',
annFile='json annotation file',
transform=transforms.ToTensor())

print('Number of samples: ', len(cap))
img, target = cap[3] # load 4th sample

print("Image Size: ", img.size())
print(target)
# 检测
dset.CocoDetection(root="dir where images are", annFile="json annotation file", [transform, target_transform])

ImageFolder

一个通用的数据加载器,数据集中的数据以以下方式组织。

root/dog/xxx.png
root/dog/xxy.png
root/dog/xxz.png

root/cat/123.png
root/cat/nsdf3.png
root/cat/asd932_.png

既其默认你的数据集已经自觉按照要分配的类型分成了不同的文件夹,一种类型的文件夹下面只存放一种类型的图片

import torchvision.datasets as dset
dset.ImageFolder(root="root folder path", [transform, target_transform])

# root : 指定图片存储的路径,在下面的例子中是'./data/dogcat_2'
# transform: 一个函数,原始图片作为输入,返回一个转换后的图片。
# target_transform - 一个函数,输入为target,输出对其的转换。例子,输入的是图片标注的string,输出为word的索引。

import torchvision.datasets as dset
dataset = dset.ImageFolder('./data/dogcat_2') #没有transform,先看看取得的原始图像数据
print(dataset.classes) #根据分的文件夹的名字来确定的类别
print(dataset.class_to_idx) #按顺序为这些类别定义索引为0,1...
print(dataset.imgs) #返回从所有文件夹中得到的图片的路径以及其类别

'''
['cat', 'dog']
{'cat': 0, 'dog': 1}
[('./data/dogcat_2/cat/cat.12484.jpg', 0), ('./data/dogcat_2/cat/cat.12485.jpg', 0), ('./data/dogcat_2/cat/cat.12486.jpg', 0), ('./data/dogcat_2/cat/cat.12487.jpg', 0), ('./data/dogcat_2/dog/dog.12496.jpg', 1), ('./data/dogcat_2/dog/dog.12497.jpg', 1), ('./data/dogcat_2/dog/dog.12498.jpg', 1), ('./data/dogcat_2/dog/dog.12499.jpg', 1
'''

torchvision.models

torchvision.models模块的 子模块中包含以下模型结构。

  • AlexNet
  • VGG
  • ResNet
  • SqueezeNet
  • DenseNet

你可以使用随机初始化的权重来创建这些模型。

from torchvision import models
resnet18 = models.resnet18()
alexnet = models.alexnet()
squeezenet = models.squeezenet1_0()
densenet = models.densenet161()

对于ResNet variants和AlexNet,我们也提供了预训练(pre-trained)的模型。

import torchvision.models as models
# pretrained=True就可以使用预训练的模型
resnet18 = models.resnet18(pretrained=True)
alexnet = models.alexnet(pretrained=True)

tansform

Compose

将多个transform组合起来使用。
transforms: 由transform构成的列表. 例子:

from PIL import Image
from torchvision import transforms

transforms.Compose([
transforms.CenterCrop(10),
transforms.ToTensor(),
])


'''
### class torchvision.transforms.Scale(size, interpolation=2)

将输入的`PIL.Image`重新改变大小成给定的`size`,`size`是最小边的边长。举个例子,如果原图的`height>width`,那么改变大小后的图片大小是`(size*height/width, size)`。
**用例:**
​```python
'''

crop = transforms.Scale(12)
img = Image.open('/home/ltb/图片/cv2-tutorial/000001.jpg')

print(type(img))
print(img.size)

croped_img = crop(img)
print(type(croped_img))
print(croped_img.size)

CenterCrop

class torchvision.transforms.CenterCrop(size)
将给定的PIL.Image进行中心切割,得到给定的size,size可以是tuple,(target_height, target_width)。size也可以是一个Integer,在这种情况下,切出来的图片的形状是正方形。

RandomCrop

class torchvision.transforms.RandomCrop(size, padding=0)
切割中心点的位置随机选取。size可以是tuple也可以是Integer。

RandomHorizantalFlip

class torchvision.transforms.RandomHorizontalFlip
随机水平翻转给定的PIL.Image,概率为0.5。即:一半的概率翻转,一半的概率不翻转。

RandomSizeCrop

class torchvision.transforms.RandomSizedCrop(size, interpolation=2)
先将给定的PIL.Image随机切,然后再resize成给定的size大小。

Pad

class torchvision.transforms.Pad(padding, fill=0)
将给定的PIL.Image的所有边用给定的pad value填充。 padding:要填充多少像素 fill:用什么值填充 例子:

from torchvision import transforms
from PIL import Image
padding_img = transforms.Pad(padding=10, fill=0)
img = Image.open('/home/ltb/图片/cv2-tutorial/000001.jpg')

print(type(img))
print(img.size)

padded_img = padding_img(img)
print(type(padded_img))
print(padded_img.size)

Normalize

class torchvision.transforms.Normalize(mean, std)
给定均值:(R,G,B) 方差:(R,G,B),将会把Tensor正则化。即:Normalized_image=(image-mean)/std。

ToTensor与ToPILImage

把一个取值范围是[0,255]的PIL.Image或者shape为(H,W,C)的numpy.ndarray,转换成形状为[C,H,W],取值范围是[0,1.0]的torch.FloadTensor

import numpy as np
from PIL import Image
import cv2
import torch
from torchvision import transforms

# opencv和PIL读取图片
img1 = Image.open("/home/ltb/图片/cv2-tutorial/000001.jpg")
img2 = cv2.imread("/home/ltb/图片/cv2-tutorial/000001.jpg")


img1.show()
cv2.imshow("img2", img2)
cv2.waitKey(0)

print(img1)
print(img2)


img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)

# ToTensor,转化为tensor,[C, H, W],RGB,[0,1.0]
t = transforms.ToTensor()

img1_tensor = t(img1)
img2_tensor = t(img2)

print(img1_tensor)
print("\n"*10)
print(img2_tensor)

# tensor转化为PILImage
t = transforms.ToPILImage()

img1 = t(img1_tensor)
img2 = t(img2_tensor)

img1.show()
img2.show()

Author: pangzibo243
Link: https://litianbo243.github.io/2019/08/05/pytorch常用函数/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
支付宝打赏
微信打赏