Pytorch学习
Tensor张量
tensor是pytorch里面的数据类型
标量,向量和矩阵三个其实都是张量,标量是零维的张量,向量是一维的张量,矩阵是二维的张量
tensor的成员
- ==tensor.data==:张量的数据值是什么
- ==tensor.grad==:该张量的梯度(如果没有就显示NONE)
- ==tensor.grad_fn==:指向该张量处的函数计算(计算图中的计算节点),进行梯度反向传播的时候会用到。如果是由用户创建的tensor,则该值 为 NONE
- ==tensor.grad_fn.next_function==: 上一级节点的grad_fn
- ==tensor.requires_grad==: 是否需要梯度,如果需要pytorch会在图中跟踪该张量然后在反向传播的时候计算梯度
创建tensor
==torch.eye(n)==, ==torch.ones((n,m))==,== torch.zeros((n,m))==和numpy建立矩阵的方法差不多
==torch.t(x)== 对x进行转置
直接==torch.tensor(x)==
常用操作
把numpy数组装成tensor:==torch.from_numpy(array)==
展开为特定的大小:==tensor.view(x,y)==
- 若x,y中任意一个的维度为-1,则另外一个自动计算(就是可以少打一个,改成-1)
- tensor.view(-1)则直接展开为1*n的张量
==tensor,squeeze(n)==表示若tensor的n维度是1,则去掉该维度(例如(3,1,3)的squeeze(1)就会变成(3,3))
==tensor.unsqueeze(n)==: squeeze的逆向操作,参数含义相同
==torch.max(tensor, axis)==和numpy的max差不多
==torch.randn(x,y)==生成随机的二维tensor
==x.mm(y)==:x与y矩阵乘法
自动求导Autograd
设置一个张量的==requires_grad=True==,只要调用tensor.backward()即可方向计算所有点的梯度,但是注意,图里面的tensor要是一个浮点数
还要注意的是,在直接==tensor.backward()==的时候,这个tensor要是一个标量
但是我们可以也可以对任意张量求导,==tensor.backward(torch.tensor([[1.0,1.0]])==,设置张量每个值的权重,在backward的时候,每一步得到的关于这个向量的梯度,然后按照这个权重加起来
计算图会自动销毁
- 一个计算图在进行反向求导之后,为了节省内存,这个计算图就销毁了,如果这时候还想求导就会报错。
不想追踪张量
- ==tensor.detach()==,把该张量从计算图中分离
- 使用==with torch.no_grad():==包装可以直接分离多个点
torch.nn
containers—>torch.nn.Module
1 | class Model(nn.Module): |
你的类可以继承这个类
- 注意,在所有的子类中都要重写forward函数,定义了每次执行的计算步骤
卷积层
- 传给==nn.Conv2d()==的张量size应当为
$$
batchSizechannelsheight*width
$$
- ==nn.Conv2d==的输入输出的图像尺寸关系为:
$$
output=\frac{input-kernerSize+2*paddings}{stride}+1
$$- 以上为CNN中的参数
- in_channels(
int
) – 输入信号的通道 - out_channels(
int
) – 卷积产生的通道 - kerner_size(
int
ortuple
) - 卷积核的尺寸 - stride(
int
ortuple
,optional
) - 卷积步长 - padding(
int
ortuple
,optional
) - 输入的每一条边补充0的层数 - dilation(
int
ortuple
,optional
) – 卷积核元素之间的间距 - groups(
int
,optional
) – 从输入通道到输出通道的阻塞连接数 - bias(
bool
,optional
) - 如果bias=True
,添加偏置
网络层
- ==nn.Linear(m,n)== 线性全连接层。接受一个张量,输出一个张量,输入的size必须为(
,m),输出的size必须为(,n),即只对最后一个维度进行全连接计算,再将各个维度拼接起来。这是为了保证在网络中进行随机梯度下降的时候(假设batchSize=b),最后传到全连接层的张量size为(b,m),这样设计可以保证全连接层的输出size为(b,n),即只对每个样本进行计算,而不会把不同样本的数据放在一起计算。
Sequentail与add_module
Sequential是一个时序容器
model = nn.Sequential(OrderedDict([ ('conv1', nn.Conv2d(1,20,5)), ('relu1', nn.ReLU()), ('conv2', nn.Conv2d(20,64,5)), ('relu2', nn.ReLU()) ]))
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
如上,就相当于model是一个模型,可以像内置模型那样出结果,如`model(x)`
再加上`add_module(name, layer)`可以自己重构一个模型,name是一个字符串表示名字,layer是一个模型的内容像conv,relu之类的
### MSELoss
有两个参数,模型预测输出x和目标y。能计算这之间的均方误差。
## cuda加速运算
- cuda可以使用显卡的gpu计算tensor的运算(前提是要有一个支持cuda的显卡)
- 1、==torch.cuda.is_available==来判断cuda是否可用
- 2、把tensor或模型放到gpu中计算:==x=x.cuda()==
- 3、然后计算的时候就能快速运算了
- ==torch.device("设备名")==可以定义计算时所用的设备,例如例如==torch.device("cuda")==表示使用cuda,==torch.device("cpu"==)表示使用cpu。使用==x.to(torch.device("设备名"))==可以将模型/张量放到相应的设备上。
## 数据加载
### dataset
- 重写torch.utils.data.dataset类
- `__init__():`初始化数据集,一般传入数据存放位置,储存标签信息文件路径等
- `__getitem__():`定义给定一个索引,加载相应样本的方法。传入参的索引i,返回数据集中第i个样本文件(tensor、PIL.image等)
- `__len__():`返回数据集中样本的个数
### dataloader
- 将dataset加载为dataloader:==torch.utils.data.dataloader.Dataloader(dataset,batch_size=n,shuufle=True,drop_last=True,num_worker)==
- batch_size表示每个batch的大小
- shuffle表示是否在训练时打乱数据
- drop_last表示当前最后剩下的数据不足一个batch时,是否丢弃
- num_worker表示加载数据所用的线程数
## 图像操作
### torchvision.transforms
- Resize(h,w)将图片缩放为指定尺寸。只传入一个参数x的时候,将图像缩放使得其中一条边大小为x
- Centercrop(h,w)从图片的中心裁剪下(h,w)的大小,当只有一个参数x的时候为正方形
- Randomcrop(h,w)从图片随机裁剪下(h,w)的大小,当只有一个参数x的时候,裁剪正方形
- ToTesor()把PIL_Image或numpy数组变为tensor,同时进行归一化操作
- Normaliuze()进行归一化操作
- ToPILImage(tensor)把tensor变为PIL格式
- tensor.numpy()变为numpy数组
- 使用matplotlib显示图片:plt.imshow(np.transpose(img,(1,2,0))),img是由tensor转化来的数组,之所以要转置,是因为torch和numpy中表示图片的格式不同
- torchvision.utils.save_image(img, path)
## models
```python
import torchvision.models as models
VGG = models.vgg16(pretrained=True)pretrained为True表示要训练模型,为False表示只保留网络结构