文章目录
1、pytorch基本语法
1.1认识pytorch
什么是pytorch
- pytorch是一个基于numpy的科学计算包,向它的使用者提供两大功能
- 向用户提供使用GPU强大功能的能力
- 作为一款深度学习的平台,向用户提供最大的灵活性与速度
pytorch的基本元素操作
- tensors张量:张量的概念类似于numpy中的ndarray数据结构,最大的区别在于tensor可以利用GPU的加速功能
- 我们使用pytorch的时候,常规操作是将torch 引入
import torch
- 创建矩阵的操作
- 创建一个没有初始化的矩阵
x=torch.empty(5,3) x
- 输出结果
tensor([[9.9184e-39, 9.0000e-39, 1.0561e-38], [1.0653e-38, 4.1327e-39, 8.9082e-39], [9.8265e-39, 9.4592e-39, 1.0561e-38], [6.7041e-39, 1.1112e-38, 9.5511e-39], [1.0102e-38, 9.0918e-39, 1.0469e-38]])
- 创建一个有初始化的矩阵
x=torch.rand(5,3) x
- 输出结果
tensor([[0.6362, 0.8270, 0.9099], [0.6367, 0.3966, 0.7022], [0.6347, 0.6491, 0.7345], [0.4258, 0.7607, 0.5514], [0.8695, 0.7048, 0.7198]])
- 对比有无初始化的矩阵:当声明一个未初始化的矩阵时,它本身不包含任何确切的值,当创建一个未初始化的矩阵时,分配给矩阵的内存中有什么数值就赋值给了这个矩阵,本质上是毫无意义的数据
- 创建一个全零矩阵并可指定数据元素的类型为long
x=torch.zeros(5,3,dtype=torch.long) x
- 输出结果
tensor([[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]])
- 直接通过数据创建张量
x=torch.tensor([2.5,3.5]) x
- 输出结果
tensor([2.5000, 3.5000])
- 通过已有的张量创建相同尺寸的新张量
#利用news_methods方法得到一个张量 x=x.new_ones(5,3,dtype=torch.double) print(x) #利用randn_like方法得到相同张量尺寸的一个新张量,并采用随机初始化来对其赋值 y=torch.rand_like(x,dtype=torch.float) y
- 输出结果
tensor([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.], [1., 1., 1.], [1., 1., 1.]], dtype=torch.float64) tensor([[0.7829, 0.0101, 0.0631], [0.2268, 0.9584, 0.2150], [0.0471, 0.2468, 0.4159], [0.1639, 0.6118, 0.8197], [0.8424, 0.4187, 0.1257]])
- 得到张量的尺寸
print(x.size()) print(y.size())
- 输出结果
torch.Size([5, 3]) torch.Size([5, 3])
📌注意
torch.Size函数本质上是返回的一个tuple,因此它支持一切元组的操作
a,b=x.size() print("a=",a) print("b=",b)
- 输出结果
a= 5 b= 3
pytorch的基本运算操作
- 加法操作
x=torch.rand(5,3) y=torch.rand(5,3) x+y
- 输出结果
tensor([[1.4247, 1.0858, 0.9374], [1.6952, 0.6679, 1.7217], [0.8453, 1.5807, 0.7486], [0.5964, 0.6290, 1.5933], [1.7306, 0.9639, 1.3272]])
- 第二种加法方式
#调用add方法 print(torch.add(x,y))
- 输出结果
tensor([[0.3530, 1.1992, 1.3401], [1.1715, 1.0932, 0.7382], [0.2289, 0.4667, 0.1676], [0.7239, 1.1013, 1.0996], [0.8246, 0.6548, 1.3755]])
- 第三种加法方式
#提前设定一个空的张量 result=torch.empty(5,3) #将空的张量作为加法的结果存储张量 torch.add(x,y,out=result) result
- 输出结果
tensor([[0.3530, 1.1992, 1.3401], [1.1715, 1.0932, 0.7382], [0.2289, 0.4667, 0.1676], [0.7239, 1.1013, 1.0996], [0.8246, 0.6548, 1.3755]])
- 第四种加法方式:in-place(原地置换)
y.add_(x) y
- 输出结果
tensor([[0.3530, 1.1992, 1.3401], [1.1715, 1.0932, 0.7382], [0.2289, 0.4667, 0.1676], [0.7239, 1.1013, 1.0996], [0.8246, 0.6548, 1.3755]])
📌注意
- 所有in-place的操作函数都有一个下划线的后缀
- 比如x.copy (y),x.add(y),都会直接改变x的值
- 用类似于Numpy的方式对张量进行操作
# 切片操作 # 取所有的行,第二列的数据 x[:,1]
- 输出结果
tensor([0.7256, 0.1973, 0.1387, 0.9497, 0.0471])
- 改变张量的形状:torch.view()
x=torch.randn(4,4) # tensor.view()操作需要保证数据元素的总数量不变 y=x.view(16) # -1代表自动匹配个数 # 用-1 去匹配行,固定死列数为8 z=x.view(-1,8) print(x.size(),y.size(),z.size())
- 输出结果
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])
- 如果张量中只有一个元素,可以用.item()将值取出,作为一个python类型的number
# 只有一个的时候才可以直接取出该数值 x=torch.randn(1) print(x) print(x.item())
- 输出结果
tensor([-2.0162]) -2.0162177085876465
关于Torch Tensor和Numpy array之间的相互转换
- Torch Tensor和Numpy array共享底层的内存空间,因此改变其中一个值,另一个也会随之被改变
a=torch.ones(5) a
- 输出结果
tensor([1., 1., 1., 1., 1.])
- 将Torch Tensor 转换为Numpy array
b=a.numpy() b
- 输出结果
array([1., 1., 1., 1., 1.], dtype=float32)
- 对其中一个进行加法操作,另一个也随之被改变
a.add_(1) print(a) print(b)
- 输出结果
tensor([2., 2., 2., 2., 2.]) [2. 2. 2. 2. 2.]
- 将Numpy array 转换为Torch Tensor
import numpy as np a=np.ones(5) b=torch.from_numpy(a) print(a) print(b) np.add(a,1,out=a) print(a) print(b)
- 输出结果
[1. 1. 1. 1. 1.] tensor([1., 1., 1., 1., 1.], dtype=torch.float64) [2. 2. 2. 2. 2.] tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
📌注意
- 所有在CPU上的Tensors,除了CharTensor,都可以转换为Numpy array 并可以反向转换
- 关于Cuda Tensor :Tensors可以用.to()方法来将其移到到任意设备上
#判断服务器上是否安装了GPU和CUDA if torch.cuda.is_available(): #定义一个设备对象,这里指定成CUDA,即使用GPU device=torch.device("cuda") #直接在GPU上创建y,在CPU上创建张量x x=torch.randn(1) #直接在GPU上创建一个Tensor y=torch.ones_like(x,device=device) #将在CPU上面的x张量移到GPU上面 x=x.to(device) #此时x和y都在GPU上面,才可以进行加法运算 z=x+y #此处的张量z在GPU上 print(z) #在将z转移到CPU上面进行打印 print(z.to("cpu",torch.double))
- 输出结果
tensor([0.8107], device='cuda:0') tensor([0.8107], dtype=torch.float64)
1.1小节总结
- 什么是pytorch
- pytorch是一个基于numpy的科学计算包
- 向用户提供使用GPU强大功能的能力
- 作为一款深度学习的平台,向用户提供最大的灵活性与速度
- pytorch是一个基于numpy的科学计算包
- pytorch基本元素操作
- 矩阵的初始化
- torch.enpty()
- torch.rand(n,m)
- torch.zeros(n,m,dtype=torch.long)
- 其他操作
- x.new_ones(n,m,dtype=torch.doubl)
- torch.randn_like(x,dtype=torch.float)
- x.size()
- 矩阵的初始化
- pytorch 基本运算操作
- 加法操作
- x+y
- torch.add(x,y)
- torch.add(x,y,out=result)
- y.add _(x)
- 其他操作
- x.view()
- x.item()
- 加法操作
- Torch Tensor 和Numpy Array 之间的相互转化
- Torch Tensor 转化为Numpy Array
- b=a.numpy()
- Numpy Array 转化为Torch Tensor
- b=torch.from_numpy(a)
- 注意 只有在CPU上的Tensor,除了charTensor,都可以转化为NumpyArray 并可以反向转化
- Torch Tensor 转化为Numpy Array
- 任意Tensors可以使用.to()方法将其移到到任意设备上
- x=x.to(device)
1.2 pytorch 中的autograd
学习目标
- 掌握自动求导中的tensor概念和操作
- 掌握自动求导中的梯度Gradients概念和操作
- 在整个pytorch框架中,所有的神经网络本质上都是一个autograd package(自动求导工具包)
- autograd package 提供了一个对 Tensors上所有的操作进行自动微分的功能
关于torch.tensor
- torch.tensor 是整个package中的核心类,如果属性requires_grad设置为True,它将追踪在这个类上定义的所有操作。当代码要进行反向传播时,直接调用.backward()就可以自动计算所有的梯度。在这个tensor上的所有梯度将被累加进属性.gard中
- 如果想终止一个tensor在计算图中的追踪回溯,只需要执行.detach()就可以将该tensor从计算图中撤下,在未来的回溯计算中也不会再计算该tensor。
- 除了.detach(),如果要终止对计算图的回溯,也就是不再进行方向传播求导数的过程;也可以采用代码块方式with.torch.no_gard(),这种方法非常适合于对模型进行预测的时候,因为预测阶段不再需要对梯度进行计算。
- 关于torch.function
- function类和tensor类同等重要的一个核心类,它和tensor共同构建了一个完整的类,每一个tensor拥有一个.grad_fn属性,代表引用了那个具体的function创建了该tensor
- 如果某个张量tensor是用户自定义的,则对应的grad_fn is None
关于tensor的操作
x1=torch.ones(3,3)
print(x1)
x=torch.ones(2,2,requires_grad=True)
print(x)
- 结果
tensor([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]]) tensor([[1., 1.], [1., 1.]], requires_grad=True)
- 在具有requires_grad=True 的tensor上进行一个加法操作
y=x+2
print(y)
- 结果
tensor([[3., 3.], [3., 3.]], grad_fn=<AddBackward0>)
- 打印tensor的grad_fn 属性
print(x.grad_fn)
print(y.grad_fn)
- 结果
None <AddBackward0 object at 0x000002185AE06BE0>
- 在tensor上执行更复杂的操作
z=y*y*3
out=z.mean()
print(z,out)
- 结果
tensor([[27., 27.], [27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)
- 关于方法.requires_grad_() 该方法可以原地改变tensor的属性 requires_grad的值 如果没有主动设定默认为False
a=torch.randn(2,2)
a=((a*3)/(a-1))
print(a.requires_grad)
a.requires_grad_(True)
print(a.requires_grad)
b=(a*a).sum()
print()
print(b.grad_fn)
- 结果
False True <SumBackward0 object at 0x000002185AE066A0>
关于梯度gradients
- 在pytorch中,反向传播是依靠.backward()实现的
out.backward()
print(x.grad)
- 结果
tensor([[4.5000, 4.5000], [4.5000, 4.5000]])
- 关于自动求导的属性设置 可以通过设置.requires_grad=True 来执行自动求导,也可以通过代码块的限制来停止自动求导
print(x.requires_grad)
print((x**2).requires_grad)
#终止自动求导
with torch.no_grad():
print((x**2).requires_grad)
- 结果
True
True
False
- 可以通过.detach()获得一个新的tensor,拥有相同的内容但不需要自动求导
#通过.detach()方法获得新的tensor
print(x.requires_grad)
y=x.detach()
print(y.requires_grad)
print(x.eq(y).all())# eq()是数值上的比较
- 结果
True
False
tensor(True)
1.2 小节总结
- torch.tensor类的相关概念
- torch.tensor 是整个package中的核心类,如果属性requires_grad设置为True,它将追踪在这个类上定义的所有操作。当代码要进行反向传播时,直接调用.backward()就可以自动计算所有的梯度。在这个tensor上的所有梯度将被累加进属性.gard中
- 执行.detach()命令,就可以将该tensor从计算图中撤下,在未来的回溯计算中也不会再计算该tensor。
- 采用代码块的方式也可以终止对计算图的回溯
- with.torch.no_grad():
- 关于tensor 的若干操作
- torch.ones(n,n,requires_grad=True)
- x.grad_fn
- a.requires_grad_(True)
- 关于gradients的属性
- x.grad
- 通过.detach()获得一个新的tensor,拥有相同的内容但不需要自动求导