总结 | 深度学习之Pytorch入门教程
目录
2.2.2 TensorFlow可视化:TensorBoard
(本文笔记pdf版本可在【人工智能算法与Python大数据】后台回复8003 获取)
一、整体学习的建议
1.1 如何成为Pytorch大神?
-
打好深度学习基础
-
学习Pytorch的官方tutorial
-
打开Github,多看看教程
-
使用 https://discuss.pytorch.org, 阅读文档
-
跑代码,项目,论文代码
-
复现,实现模型,自己创造
1.2 如何读Github代码?
2.1 什么是Pytorch?
-
Facebook开源,2017年,论文《PyTorch 中的自动微分》,地址:https://openreview.net/pdf?id=BJJsrmfCZ
-
类似于Numpy,可以使用GPU,运行在CUDA上
-
PyTorch框架和Python语言的整合更加紧密
-
Pytorch动态图内置,可以定义深度学习模型,可灵活的进行训练和应用
-
分布式训练并行化时,利用Python对异步执行的本地支持
2.1.1 Pytorch两个核心模块
优点:
-
类似Python的代码
-
动态图
-
轻松编辑
-
良好的文档和社区支持
-
开源
-
很多项目都在使用
缺点:
-
可视化需要第三方
-
生产部署需要使用API服务器
2.2 什么是TensorFlow
-
谷歌开源,2015年,论文《TensorFlow:异构分布式系统上的大规模机器学习》,地址:http://download.tensorflow.org/paper/whitepaper2015.pdf
-
使用GPU增强训练,使用的是内置的GPU进行加速
-
分布式训练并行化时,必须手动编写代码,并微调每个操作
-
使用TensorFlow Fold库实现动态图
-
可实现并行化或依赖驱动式调度,训练更快更有效率
2.2.1 TensorFlow两个核心模块
-
一个用于定义计算图以及在各种不同硬件上执行这些图的运行时间的软件库
-
一个计算图,计算图是以静态方式定义。与外部通信通过tf.Sessionobject和tf.Placeholder
2.2.2 TensorFlow可视化:TensorBoard
优点:
-
简单的内置高级API
-
使用TensorBoard可视化训练
-
通过TensorFlow serving容易实现生产部署
-
很容易的移动平台支持
-
开源
-
良好的文档和社区支持
缺点:
1.学术界PyTorch已经全面超越TensorFlow,上手快,容易实现,验证想法
2.工业界TensorFlow仍然广泛应用,GPU部署方便
三、Pytorch的一些简单命令
第一步,导入torch:
import torch
构造一个未被初始化的3x5的矩阵
-
x = torch.empty(3,5)
-
x
生成一个随机初始化的3x5矩阵
-
x = torch.rand(3,5)
-
x
生成一个全部为0的矩阵
-
x = torch.zeros(3,5)
-
x
-
x.dtype
-
torch.float32
生成一个全部为0的矩阵,long的矩阵
-
x = torch.zeros(3,5,dtype = torch.long)
-
x
-
x.dtype
-
torch.int64
-
# 或者 x = torch.zeros(3,5).long()
直接通过数据构建tensor
-
x = torch.tensor([1.2,4])
-
x
-
tensor([1.2000,4.0000])
也可以通过已有tensor构建一个新的tensor
-
x = x.new_ones(3,5)
-
# 或者改变类型 x = x.new_ones(3,5,dtype=torch.double)
构建一个和上一个形状相同的tensor
-
x = torch.randn_like(x, dtype=torch.float)
-
x
得到tensor的形状
-
x.shape
-
torch.Size([3,5])
加法准则:
-
x + y
-
torch.add(x,y)
-
result = torch.empty(3,5)
-
torch.add(x,y, out = result)
-
result
-
# 效果与下面类似 result = x + y
in-place加法
注意,任何in-place的运算都会以结尾,比如x.copy(y) , x.t_() ,这些都会改变x
y.add_(x) y # 注意,这里加了下划线,就把y直接进行更改了,效果等价于 y=y+x类似于Numpy的索引在Pytorch 的 tensor上面都可以使用,类比matlab
x[1:,1:]
Resizing,想要resize、reshape一个tensor,可以使用torch.view
-
x = torch.randn(4,4)
-
y = x.view(16)
-
y = x.view(2,8)
-
# 也可以用-1代表其中一个,它会自动计算 y = x.view(2,-1)和 x.view(2,8)功能类似
dir(x)可以看看x包含哪些功能
-
data
-
grad
怎么使用?
-
x.data
-
x.grad
-
x.item 把tensor变成数字
Numpy和tensor之间的相互转换
-
a = tensor([1,1,1,1,1])
-
b = a.numpy()
-
b
-
array([1.,1.,1.,1.,1.], dtype=float32)
注意,这里a和b是共享空间的,其中一个变,整体都会变
把Numpy array 转换成 Torch Tensor
-
import numpy as np
-
a = np.ones(5)
-
b = torch.from_numpy(a)
-
b
如果我们有GPU,可以转换为 CUDA Tensors
if torch.cuda.is_available()
device = torch.device("cuda")
y = torch.ones_like(x, device=device)
x = x.to(device)
z = x + y
# 注意,这里是GPU的
print(z)
# 转换成CPU进行输出的话
print(z.to("cpu", torch.double))
注意,如果是GPU的tensor,是没办法直接用.data这类操作,必须先转换再操作
y.cpu().data.numpy()
numpy是CPU的库,并没有GPU的库,所以如果想使用numpy,但是你默认GPU产生的是tensor
四、实现两层神经网络
4.1 如何用numpy实现两层神经网络
一个全连接ReLU神经网络,一个隐藏层,没有bias。用来从x预测y,使用L2 Loss。
# 定义一些基本的信息,64个输入,每个输入是1000维,hidden是100维,输出是10维 N, D_in, H, D_out = 64, 1000, 100, 10 # 随机创建一些训练数据 # x是64个1000维,x是64x1000矩阵 # y是64个10维,y是64x10矩阵 x = np.random.randn(N, D_in)
y = np.random.randn(N, D_out)
# 随机初始化权重 # w1是1000个100维,w1是1000x100矩阵 # w2是100个10维,w2是100x10矩阵 w1 = np.random.randn(D_in, H)
w2 = np.random.randn(H, D_out)
learning_rate = 1e-6
for t in range(500):
# 前向传播,h是64x1000x1000x100=64x100
# h_relu是看哪个激活了,还是64x100
# y_pred是64x100x100x10=64x10
h = x.dot(w1) # N * H
h_relu = np.maximum(h, 0) # N * H
y_pred = h_relu.dot(w2) # N * D_out
# compute loss
loss = np.square(y_pred - y).sum()
print(it, loss)
# Backward pass
# 计算梯度,链式法则,挨个求导相乘
grad_y_pred = 2.0 * (y_pred - y)
grad_w2 = h_relu.T.dot(grad_y_pred)
grad_h_relu = grad_y_pred.dot(w2.T)
grad_h = grad_h_relu.copy()
grad_h[h<0] = 0
grad_w1 = x.T.dot(grad_h)
# 更新w1和w2的权重
w1 -=learning_rate * grad_w1
w2 -=learning_rate * grad_w2
4.2 如何用torch实现两层神经网络
这里将numpy修改为pytorch做这件事
pytorch用的是tensors
# 定义一些基本的信息,64个输入,每个输入是1000维,hidden是100维,输出是10维 N, D_in, H, D_out = 64, 1000, 100, 10 # 随机创建一些训练数据 # x是64个1000维,x是64x1000矩阵 # y是64个10维,y是64x10矩阵 # np.random要改为torch x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
# 随机初始化权重 # w1是1000个100维,w1是1000x100矩阵 # w2是100个10维,w2是100x10矩阵 w1 = torch.randn(D_in, H)
w2 = torch.randn(H, D_out)
learning_rate = 1e-6
for t in range(500):
# 前向传播,h是64x1000x1000x100=64x100
# h_relu是看哪个激活了,还是64x100
# y_pred是64x100x100x10=64x10
# .dot改为mm
h = x.mm(w1) # N * H
# maximum改为clamp,夹住
h_relu = h.clamp(min=0) # N * H
y_pred = h_relu.mm(w2) # N * D_out
# compute loss
# 求平方在这里也要改
# loss = np.square(y_pred - y).sum()
loss = (y_pred - y).pow(2).sum().item()
print(it, loss)
# Backward pass
# 计算梯度,链式法则,挨个求导相乘
grad_y_pred = 2.0 * (y_pred - y)
grad_w2 = h_relu.t().mm(grad_y_pred)
grad_h_relu = grad_y_pred.mm(w2.t())
grad_h = grad_h_relu.clone()
grad_h[h<0] = 0
grad_w1 = x.t().mm(grad_h)
# 更新w1和w2的权重
w1 -=learning_rate * grad_w1
w2 -=learning_rate * grad_w2
4.3 简单的autograd
x = torch.tensor(1., requires_grad=True)
w = torch.tensor(2., requires_grad=True)
b = torch.tensor(3., requires_grad=True)
y = w*x + b # y = 2*1 + 3
y.backward()
# dy/dw=x
print(w.grad)
print(x.grad)
print(b.grad)
# 结果
tensor(1.)
tensor(2.)
tensor(1 . )
如何使用autograd简化上面的两层神经网络?
# 定义一些基本的信息,64个输入,每个输入是1000维,hidden是100维,输出是10维 N, D_in, H, D_out = 64, 1000, 100, 10 # 随机创建一些训练数据 # x是64个1000维,x是64x1000矩阵 # y是64个10维,y是64x10矩阵 # np.random要改为torch x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
# 随机初始化权重 # w1是1000个100维,w1是1000x100矩阵 # w2是100个10维,w2是100x10矩阵 w1 = torch.randn(D_in, H, requires_grad=True)
w2 = torch.randn(H, D_out, requires_grad=True)
learning_rate = 1e-6
for t in range(500):
# 前向传播,h是64x1000x1000x100=64x100
# h_relu是看哪个激活了,还是64x100
# y_pred是64x100x100x10=64x10
# .dot改为mm
# h = x.mm(w1) # N * H
# h_relu = h.clamp(min=0) # N * H
# y_pred = h_relu.mm(w2) # N * D_out
# 把上面三行合并为1行
y_pred =x.mm(w1).clamp(min=0).mm(w2)
# compute loss
# 求平方在这里也要改
loss = (y_pred - y).pow(2).sum() # 这是计算图
print(it, loss.item())
# Backward pass
# 计算梯度,链式法则,挨个求导相乘
# grad_y_pred = 2.0 * (y_pred - y)
# grad_w2 = h_relu.t().mm(grad_y_pred)
# grad_h_relu = grad_y_pred.mm(w2.t())
# grad_h = grad_h_relu.clone()
# grad_h[h<0] = 0
# grad_w1 = x.t().mm(grad_h)
# 这些求梯度的全部不要
loss.backward()
# 更新w1和w2的权重
# 为了减少内存,取消计算图的储存
with torch.no_grad():
w1 -=learning_rate * w1.grad
w2 -=learning_rate * w2.grad
# 每次清零
w1.grad.zero_()
w2.grad.zero_()
最后pytorch的简单代码
# 定义一些基本的信息,64个输入,每个输入是1000维,hidden是100维,输出是10维 N, D_in, H, D_out = 64, 1000, 100, 10 x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
w1 = torch.randn(D_in, H, requires_grad=True)
w2 = torch.randn(H, D_out, requires_grad=True)
learning_rate = 1e-6
for t in range(500):
y_pred =x.mm(w1).clamp(min=0).mm(w2)
loss = (y_pred - y).pow(2).sum() # 这是计算图
print(it, loss.item())
loss.backward()
# 更新w1和w2的权重
with torch.no_grad():
w1 -=learning_rate * w1.grad
w2 -=learning_rate * w2.grad
# 每次清零
w1.grad.zero_()
w2.grad.zero_()
五、Pytorch常用库
5.1 Pytorch:nn
使用pytorch:nn库来构建网络
使用Pytorch autograd 来构建计算图和计算梯度
import torch.nn as nn
# 定义一些基本的信息,64个输入,每个输入是1000维,hidden是100维,输出是10维 N, D_in, H, D_out = 64, 1000, 100, 10 x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
# 不用这么繁琐顶定义这个w1,w2 # w1 = torch.randn(D_in, H, requires_grad=True) # w2 = torch.randn(H, D_out, requires_grad=True) model = torch.nn.Sequential(
torch.nn.Linear(D_in,H), #w_1 * x +b_1
torch.nn.ReLU();
torch.nn.Linear(H, D_out)
)
# model = model.cuda() loss_fn = nn.MSELoss(reduction='sum')
learning_rate = 1e-6
for t in range(500):
# y_pred =x.mm(w1).clamp(min=0).mm(w2)
y_pred = model(x) # model.forward()
loss = loss_fn(y_pred,y)
print(it, loss.item())
model.zero_grad
loss.backward()
# 更新w1和w2的权重
with torch.no_grad():
for param in model.parameters():
param -= learning_rate * param.grad
初始化数据,可能影响训练效果 ,这里可对weight进行初始化
model
model[0].weight
可能初始化问题会影响训练效果
可在model和loss_fn中间加:
torch.nn.init.normal_(model[0].weight) #第一层 torch.nn.init.normal_(model[2].weight) #第二层
5.2 Pytorch:optim
不用手动更新模型的weights,而是使用optim这个包来帮助我们更新参数
optim这个包提供了各种不同的模型优化方法,包括SGD+momentum,RMSProp,Adam等等
import torch.nn as nn
# 定义一些基本的信息,64个输入,每个输入是1000维,hidden是100维,输出是10维 N, D_in, H, D_out = 64, 1000, 100, 10 x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
# 不用这么繁琐顶定义这个w1,w2 # w1 = torch.randn(D_in, H, requires_grad=True) # w2 = torch.randn(H, D_out, requires_grad=True) model = torch.nn.Sequential(
torch.nn.Linear(D_in,H), #w_1 * x +b_1
torch.nn.ReLU();
torch.nn.Linear(H, D_out)
)
# model = model.cuda() loss_fn = nn.MSELoss(reduction='sum')
learning_rate = 1e-4 optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
# 或者优化方法 # learning_rate = 1e-6 # optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) learning_rate = 1e-6
for t in range(500):
y_pred = model(x) # model.forward()
loss = loss_fn(y_pred,y)
print(it, loss.item())
# 求导之前把数据清空
optimizer.zero_grad()
loss.backward()
# 更新w1和w2的权重
optimizer.step()
5.3 Pytorch:nn Module
import torch.nn as nn
定义一些基本的信息,64个输入,每个输入是1000维,hidden是100维,输出是10维
N, Din, H, D_out = 64, 1000, 100, 10
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
class TwoLayerNet(torch.nn.Module):
def _init(self, Din, H, D_out):
super(TwoLayerNet, self)._init()
# 定义模型框架
self.linear1 = torch.nn.Linear(D_in, H, bias=False)
self.linear2 = torch.nn.Linear(H, D_out, bias=False)
def forward(self, x)
# 定义前向传播
y_pred = self.linear2(self.linear1(x).clamp(min=0))
return y_pred
model = TwoLayerNet(D_in, H, D_out))
loss_fn = nn.MSELoss(reduction=’sum’)
learning_rate = 1e-4
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
learning_rate = 1e-6
for t in range(500):
y_pred = model(x) # model.forward()
loss = loss_fn(y_pred,y)
print(it, loss.item())
# 求导之前把数据清空
optimizer.zero_grad()
loss.backward()
# 更新w1和w2的权重
optimizer.step()
文章来源: kings.blog.csdn.net,作者:人工智能博士,版权归原作者所有,如需转载,请联系作者。
原文链接:kings.blog.csdn.net/article/details/107866287
- 点赞
- 收藏
- 关注作者
评论(0)