pytorch(1)

torch.nn包里的Functional包含convolution函数,pooling函数,非线性函数、激活函数等函数,torch.nn.optim包含各种优化算法,Momentum、RMSProp等。

Tensor

torch.Tensor是一种包含单一数据类型元素的多维矩阵。

Torch定义了七种CPU tensor类型和八种 tensor类型:

torch.Tensor是默认的tensor类型(torch.FloatTensor)的简称。

一个张量tensor可以从Python的list或序列构建:

>>>torch.FloatTensor([[1,2,3],[4,5,6]])
tensor([[1., 2., 3.],
[4., 5., 6.]])

>>>torch.Tensor([[3,2,1],[6,5,4]])
tensor([[3., 2., 1.],
[6., 5., 4.]])

空张量tensor可以通过规定其大小来构建:

>>>torch.IntTensor(2,4).zero_()
tensor([[0, 0, 0, 0],
[0, 0, 0, 0]], dtype=torch.int32)

可以用python的索引和切片来获取和修改一个张量tensor中的内容:

>>>x=torch.FloatTensor([[1,2,3],[4,5,6]])
>>>print(x[1][2])
tensor(6.)
>>>print(x[0][1])
tensor(2.)
>>>x[0][1]=8
>>>print(x)
tensor([[1., 8., 3.],
[4., 5., 6.]])

每一个张量tensor都有一个相应的tourch.Storage用来保存其数据。

注意:会改变tensor的函数操作会用一个下划线后缀来表示。比如,torch.FloatTensor.abs_()会在原地计算绝对值,并返回改变后的tensor,而torch.FloatTensor.abs()将会在一个新的tensor中计算结果。

创建张量时有个参数是requires_grad,如果设置 requires_grad为 True,那么将会追踪所有对于该张量的操作吗,默认False。 当完成计算后通过调用 .backward(),自动计算所有的梯度, 这个张量的所有梯度将会自动积累到 .grad属性。

torch.squeeze

torch.squeeze(input,dim=None,out=None):将输入张量形状中的1去除并返回。当给定dim时,那么挤压操作只在给定维度上。

>>>x=torch.zeros(2,1)
>>>x
tensor([[0.],
[0.]])
>>>y=torch.squeeze(x)
>>>y
tensor([0., 0.])

torch.abs

torch.abs(input,out=None):计算输入张量的每个元素的绝对值

>>>torch.abs(torch.Tensor([-1,-2,-3]),out=z)
tensor([1., 2., 3.])
>>>z
tensor([1., 2., 3.])

torch.add

torch.add(input,value,out=None),对输入张量input逐元素加上标量值value,并返回结果得到一个新的张量out。

>>>a=torch.rand(4)
>>>a
tensor([0.0694, 0.6366, 0.6938, 0.8872])
>>>torch.add(a,20)
tensor([20.0694, 20.6366, 20.6938, 20.8872])

torch.mean

torch.mean(input,dim,out=None):返回输入张量给定维度dim上每行的均值。0是列,1是行。

>>>a=torch.rand(4,4)
>>>a
tensor([[0.7413, 0.5828, 0.0070, 0.0146],
[0.1668, 0.6566, 0.1865, 0.0700],
[0.7603, 0.8017, 0.3065, 0.8772],
[0.7918, 0.8798, 0.7355, 0.1142]])
>>>torch.mean(a,1)
tensor([0.3364, 0.2700, 0.6864, 0.6303])

比较运算符

torch.eq

torch.eq(input,other,out=None):比较元素相等性。第二个参数可以为一个数或与第一个参数同类型形状的张量。

>>>torch.eq(torch.Tensor([[1,2],[3,4]]),torch.Tensor([[1,1],[4,4]]))
tensor([[ True, False],
[False, True]])

如果两个张量有相同的形状和元素值,则返回True,否则返回False。

>>>torch.equal(torch.Tensor([[1,2],[3,4]]),torch.Tensor([[1,1],[4,4]]))
False

>>>torch.equal(torch.Tensor([[1,2],[3,4]]),torch.Tensor([[1,2],[3,4]]))
True

torch.ge

torch.ge(input,other,out=None):逐元素比较input和other。即是否 input>=otherinput>=other。如果两个张量有相同的形状和元素值,则返回True。否则返回False。第二个参数可以为一个数或与第一个参数相同形状和类型的张量。

>>>torch.ge(torch.Tensor([[1,2],[3,4]]),torch.Tensor([[1,1],[4,4]]))
tensor([[ True, True],
[False, True]])

torch.gt

torch.gt(input,other,out=None):逐元素比较input和other。即input>otherinput>other。如果两个张量有相同的形状和元素值,则返回True。否则返回False。第二个参数可以为一个数或与第一个参数相同形状和类型的张量。PS:这个和ge有什么区别?

>>>torch.gt(torch.Tensor([[1,2],[3,4]]),torch.Tensor([[1,1],[4,4]]))
tensor([[False, True],
[False, False]])

torch.le

torch.le(input, other, out=None):逐元素比较input和other , 即是否input<=otherinput<=other 第二个参数可以为一个数或与第一个参数相同形状和类型的张量

>>>torch.le(torch.Tensor([[1,2],[3,4]]),torch.Tensor([[1,1],[4,4]]))
tensor([[ True, False],
[ True, True]])

torch.lt

torch.lt(input, other, out=None):逐元素比较input和other , 即是否 input<otherinput<other。第二个参数可以为一个数或与第一个参数相同形状和类型的张量

>>>torch.lt(torch.Tensor([[1,2],[3,4]]),torch.Tensor([[1,1],[4,4]]))
tensor([[False, False],
[ True, False]])

Variable

Variable和Tensor本质上没有区别,不过Variable会被放入一个计算图中,然后进行前向传播、反向传播、自动求导。

首先Variable是在torch.autograd.Variable中,要将tensor变成Variable,只需要Variable(a)就可以了。Variable有三个比较重要的组成属性:data、grad、grad_fn。data可以取出variable里面的tensor值,grad_fn表示的是得到这个Variable的操作(op),grad是这个Variable的反向传播梯度。

>>>from torch.autograd import Variable
>>>x=Variable(torch.Tensor([1]),requires_grad=True)
>>>w=Variable(torch.Tensor([2]),requires_grad=True)
>>>b=Variable(torch.Tensor([3]),requires_grad=True)
>>>y=w*x+b
>>>y
tensor([5.], grad_fn=)
>>>print(y.backward())
None
>>>print(x.grad)
tensor([2.])
>>>print(w.grad)
tensor([1.])
>>>print(b.grad)
tensor([1.])
>>>print(x.grad_fn)
None
>>>print(y.grad_fn)

构建Variable,我们传入了一个参数requires_grad=True,这个参数表示是否对这个变量求梯度,默认的是False,也就是不对这个变量求梯度。

parameters

paramerters(memo=None):返回一个包含模型所有参数的迭代器。一般用来当作optimizer的参数。

backward

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

zero_grad

zero_grad():清空所有被优化过的Variable的梯度

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
60
61
62
63
64
65
66
67

## view

返回一个有相同数据但大小不同的tensor。 返回的tensor必须有与原tensor相同的数据和相同数目的元素,但可以有不同的大小。一个tensor必须是连续的`contiguous()`才能被查看。

> \>>>import torch
> \>>>x=torch.randn(4,4)
> \>>>x.size()
> torch.Size([4, 4])
> \>>>y=x.view(16)
> \>>>y.size()
> torch.Size([16])
> \>>>z=x.view(-1,8)
> \>>>z.size()
> torch.Size([2, 8])

## zero_

zero_(tensor):用0填充一个tensor

> \>>>torch.zero_(x)
> tensor([[0., 0., 0., 0.],
> [0., 0., 0., 0.],
> [0., 0., 0., 0.],
> [0., 0., 0., 0.]])

## 模型的保存和加载

在pytorch里面使用torch.save来保存模型的结构和参数,有两种保存方式,当然加载模型有两种方式对应于保存模型的方式:

(1)保存这个模型的结构信息和参数信息,保存的对象是模型model。加载完整的模型结构和参数信息,在网络较大的时候加载的时间比较长,同时存储空间也比较大。

torch.save(the_model,path)

the_model=torch.load("path")

(2)保存模型的参数,保存的对象是模型的状态model.state_dict()。加载模型时加载的是参数信息。

torch.save(the_model.state_dict(),path)

the_model=TheModeClass(\*args,\**kwargs)

the.model.load_state_dict(path)

## 优化算法

优化算法分两类:

### 一阶优化算法

这种算法使用各个参数的梯度值来更新参数,最常用的一阶优化算法是梯度下降。所谓的梯度就是导数的多变量表达式,同时也是一个方向,这个方向上方向导数最大,且等于梯度。梯度下降的功能是通过寻找最小值,控制方差,更新模型参数,最终使模型收敛。

### 二阶优化算法

二阶优化算法使用了二阶导数来最小化或最大化损失函数,主要基于牛顿法。但是由于二阶导数的计算成本很高,所以这种方法并没有广泛使用。torch.optim是一个实现各种优化算法的包,大多数常见的算法都能通过这个包调用。

### torch.optim

为了使用torch.optim,我们需要构建一个optimizer对象。这个对象能够保持当前参数状态并基于计算得到的梯度进行参数更新。

#### 构建optimizer

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

举个例子:

```optimizer = optim.SGD(model.parameters(), lr = 0.01, momentum=0.9)

单独设置参数

我们还可以为每个参数单独设置选项。Optimizer也支持为每个参数单独设置选项。若想这么做,不要直接传入Variable的iterable,而是传入dict的iterable。每一个dict都分别定 义了一组参数,并且包含一个param键,这个键对应参数的列表。其他的键应该optimizer所接受的其他参数的关键字相匹配,并且会被用于对这组参数的优化。

你仍然能够传递选项作为关键字参数。在未重写这些选项的组中,它们会被用作默认值。当你只想改动一个参数组的选项,但其他参数组的选项不变时,这是非常有用的。

例如,当我们想指定每一层的学习率时,这是非常有用的:

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

单次优化

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

for input, target in dataset:

​ optimizer.zero_grad()

​ output = model(input)

​ loss = loss_fn(output, target)

​ loss.backward()

​ optimizer.step()

补充

我看到优化算法时,发现中文文档好像没有调整学习率的函数。补充一下。torch.optim.lr_scheduler提供了几种方法来根据epoches的数量调整学习速率。 两种机制:LambdaLR机制和StepLR机制;

LambdaLR机制:

class torch.optim.lr_scheduler.LambdaLR(optimizer,lr_lambda,last_epoch=-1)

将每一个参数组的学习率设置为初始学习率lr的某个函数倍.当last_epoch=-1时,设置初始学习率为lr.

参数:

​ optimizer(Optimizer对象)—优化器

​ lr_lambda(是一个函数,或者列表(list))— 当是一个函数时,需要给其一个整数参数,使其计算出一个乘数因子,用于调整学习率,通常该输入参数是epoch数目或者是一组上面的函数组成的列表,

​ last_epoch(int类型):最后一次epoch的索引,默认为-1.

StepLR机制

class torch.optim.lr_scheduler.StepLR(optimizer,step_size,gamma=0.1,last_epoch=-1)

设置每个参数组的学习率为 lr*λn, n=epoch/step_size。当last_epoch=-1时,令lr=lr

参数:

​ optimizer(Optimizer对象)—优化器

​ step_size(整数类型): 调整学习率的步长,每过step_size次,更新一次学习率

​ gamma(float 类型):学习率下降的乘数因子

​ last_epoch(int类型):最后一次epoch的索引,默认为-1.

其它API

其它的API不想做搬运工了,上网址。pytorch中文文档

看文档我发现torch.nn包里面和nn.functional都有卷积等一些函数。其实nn.functional中的函数仅仅定义了一些具体的基本操作,不能构成pytorch中的一个Layer。当我们需要自定义一些非标准Layer时,可以在其中调用nn.functional中的操作。例如,relu仅仅是一个函数,参数包括输入和计算需要的参数,返回计算的结果,它不能存储任何上下文的信息。

torch.nn包里面只是包装好了神经网络架构的类,nn.functional 与torch.nn包相比,nn.functional是可以直接调用函数的。

----本文结束,感谢您的阅读。如有错,请指正。----
大哥大嫂过年好!支持我一下呗
0%