基础知识
- 创建tensor
import torch
# numpy转为tensor,t变了,a也会变
a = numpy.array([1, 2, 3])
t = torch.from_numpy(a)
# 创建[0,5)间隔为2
torch.arange(0, 5, 2)
# 创建[1,4]间隔为0.5
torch.range(1, 4,0.5)
# 一维[3,10],5个,等分
torch.linspace(3, 10, steps=5)
# 3*3的E
torch.eye(3)
# 按值初始化
torch.full((2, 3), 3.141592
# 构造5x3的矩阵,不初始化
result = torch.empty(3,3)
# 构造一个随机初始化的矩阵
x = torch.rand(5,3)
# 直接用数据构造一个张量
x = torch.tensor([5.5,3])
# 数据类型是int32的0矩阵
y = torch.zeros(3,3,dtype=torch.float)
# 默认返回一个与y有同样torch.dtype和torch.device的size为4x3的,值为1的tensor,记得要赋值
x = y.new_ones(3,3)
# 与y一样尺寸,创建随机值的tensor
y = torch.randn_like(y, dtype=torch.float)
# 获取x的维度信息
print(x.size())
- 张量的基本操作
# tensor可以进行加法
# 直接加
x+y
# 存放在存在的result中,大小需要一致
torch.add(x,y, out=result)
# 存放在y中
y.add_(x)
# 索引操作
print(y[:,1])
# 改变tensor的大小或者形状
x = torch.randn(6, 4)
y = x.view(24)
z = x.view(-1, 8) # -1意味着它的维度随着别的维度改变,输出结果为[3,8]
# 包含一个元素的tensor使用.item()来获得其value
x = torch.randn(1)
print(x.item())
# 返回数字个数
a = torch.randn(1, 2, 3, 4, 5) # 4行5列,3个一组,有两组,两组是一个tensor
print(torch.numel(a)
自动求梯度
#创建一个张量,设置requires_grad=True来跟踪与它相关的计算
x = torch.ones(2, 2, requires_grad=True)
print(x
可以使用in-place的方式.requires_grad_()
改变requires_grad属性。
y = x + 2
print(y) # grad_fn=<AddBackward0> 加操作得来
每个Tensor都有一个.grad_fn
属性,该属性即创建该Tensor的Function, 就是说该Tensor是不是通过某些运算得到的,若是,则grad_fn返回一个与这些运算相关的对象,否则是None(说明该tensor是直接创建的,称为叶子节点,可以用.is_leaf
验证)。
叶子节点的原地操作,不记录在.grad_fn
属性中。
import torch
x = torch.ones(2, 2, requires_grad=True)
print(x)
print(x.grad_fn)
x.data += 1
print(x)
print(x.grad_fn)
【重点】叶子节点和tensor的requires_grad:https://zhuanlan.zhihu.com/p/85506092
z = y*y*3
out = z.mean()
# 反向传播,应用链式法则计算梯度
out.backward()
注意在out.backward()
时,如果out是标量,则不需要为backward()
传入任何参数;否则,需要传入一个与out同形的Tensor。解释
# 上述梯度将累计到grad属性中,打印梯度 d(out)/dx
print(x.grad)
#将代码包裹在with torch.no_grad(),来停止对从跟踪历史中的.requires_grad=True的张量自动求导
with torch.no_grad():
print((x ** 2).requires_grad)
如果不想要被继续追踪,可以调用x.detach()
将其从追踪记录中分离出来,这样就可以防止将来的计算被追踪,这样梯度就传不过去了。
参考:
https://www.cnblogs.com/cocode/p/10746347.html
http://tangshusen.me/Dive-into-DL-PyTorch/#/chapter02_prerequisite/2.3_autograd
神经网络
# 一个模型可训练的参数可以通过调用 net.parameters()
params = list(net.parameters())
print(len(params))
print(params[0].size()) # conv1's .weight
# 把所有参数梯度缓存器置零,用随机的梯度来反向传播
net.zero_grad()
out.backward(torch.randn(1, 10))
# 计算损失
loss_function = nn.CrossEntropyLoss() # 交叉熵计算
loss = loss_function(output, target) # output训练结果,target真实值
print(loss)
# 更新权重
import torch.optim as optim
# create your optimizer
optimizer = optim.SGD(net.parameters(), lr=0.01)
# in your training loop:
optimizer.zero_grad() # zero the gradient buffers
loss.backward() # 求梯度
optimizer.step() # 更新
pytorch使用cuda
在GPU上训练 就像你怎么把一个张量转移到GPU上一样。
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# 模型放入GPU
net.to(device)
# 复制张量到GPU
mytensor = my_tensor.to(device)
# 多GPU并行
model = nn.DataParallel(model)
数据并行自动拆分了你的数据并且将任务单发送到多个 GPU 上。当每一个模型都完成自己的任务之后,DataParallel 收集并且合并这些结果,然后再返回给你。(如果用mapreduce做,这是的思路)
包
totchvision包,该包含有支持加载类似Imagenet,CIFAR10,MNIST 等公共数据集的数据加载模块 torchvision.datasets
和支持加载图像数据数据转换模块 torch.utils.data.DataLoader
。
1. torchvision.datasets # 包含公开的数据集
2. torchvision.models # 包含预训练的模型结构
3. torchvision.transforms # 常用的图片变换
4. torchvision.utils # 其他常用方法,例如读取小批次数据
5. torch.nn # 包含神经网络模型的架构,如卷积核,激活函数等
6. torch.optim # 包含各种优化算法