IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> pytorch学习笔记6 -> 正文阅读

[人工智能]pytorch学习笔记6

PyTorch的核心是两个主要特征:

  1. 一个n维张量,类似于numpy,但可以在GPU上运行
  2. 搭建和训练神经网络时的自动微分/求导机制
    本章节我们将使用全连接的ReLU网络作为运行示例。该网络将有一个单一的隐藏层,并将使用梯度下降训练,通过最小化网络输出和真正结果的欧几里得距离,来拟合随机生成的数据。
    张量
    在介绍PyTorch之前,本章节将首先使用numpy实现网络。 Numpy提供了一个n维数组对象,以及许多用于操作这些数组的 函数。Numpy是用于科学计算的通用框架;它对计算图、深度学习和梯度一无所知。然而,我们可以很容易地使用NumPy,手动实现网络的 前向和反向传播,来拟合随机数据:
import numpy as np
N,D_in,H,D_out=64,1000,100,10
x=np.random.randn(N,D_in)
y=np.random.randn(N,D_out)
w1=np.random.randn(D_in,H)
w2=np.random.randn(H,D_out)
learning_rate=1e-6
for t in range(500):
	h=x.dot(w1)
	h_relu=np.maximum(h,0)
	y_pred=h_relu.dot(w2)
	loss=np.square(y_pred-y).sum()
	print(t,loss)
	# 反向传播,计算w1和w2对loss的梯度
	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 -= learning_rate * grad_w1
	w2 -= learning_rate * grad_w2

PyTorch:张量
Numpy是一个很棒的框架,但它不能利用GPU来加速其数值计算。 对于现代深度神经网络,GPU通常提供50倍或更高的加速,所以,numpy不能满足当代深度学习的需求。在这里,先介绍最基本的PyTorch概念:
张量(Tensor):PyTorch的tensor在概念上与numpy的array相同: tensor是一个n维数组,
PyTorch提供了许多函数用于操作这些张量。任何希望使用NumPy执行的计算也可以使用PyTorch
的tensor来完成,可以认为它们是科学计算的通用工具。
与Numpy不同,PyTorch可以利用GPU加速其数值计算。要在GPU上运行Tensor,在构造张量使用
device 参数把tensor建立在GPU上。
在这里,本章使用tensors将随机数据上训练一个两层的网络。和前面NumPy的例子类似,我们使
用PyTorch的tensor,手动在网络中实现前向传播和反向传播:

import torch
dtype=torch.float
device=torch.device("cpu")
N, D_in, H, D_out = 64, 1000, 100, 10
x=torch.randn(N,D_in,device=device,dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)
# 随机初始化权重
w1 = torch.randn(D_in, H, device=device, dtype=dtype)
w2 = torch.randn(H, D_out, device=device, dtype=dtype)
learning_rate=1e-6
for t in range(500):
	h=x.mm(w1)
	h_relu=h.clamp(min=0)
	y_pred=h_relu.mm(w2)
	loss=(y_pred-y).pow(2).sum().item()
	print(t,loss)
	# Backprop计算w1和w2相对于损耗的梯度
	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 -= learning_rate * grad_w1
	w2 -= learning_rate * grad_w2

自动求导
PyTorch:张量和自动求导
在上面的例子中,需要手动实现神经网络的前向和后向 传递。手动实现反向传递对于小型双层网
络来说并不是什么大问 题,但对于大型复杂网络来说很快就会变得非常繁琐。
但是可以使用自动微分来自动计算神经网络中的后向传递。 PyTorch中的 autograd 包提供了这个
功能。当使用autograd时,网络前向传播将定义一个计算图;图中的节点是tensor,边是函数,这些函数是输出tensor到输入tensor的映射。这张计算图使得在网络中反向传播时梯度的计算十分
简单。

这听起来很复杂,在实践中使用起来非常简单。 如果我们想计算某些的tensor的梯度,我们只需
要在建立这个tensor时加入这么一句: requires_grad=True 。这个tensor上的任何PyTorch的操作
都将构造一个计算图,从而允许我们稍后在图中执行反向传播。如果这个tensor x 的
requires_grad=True ,那么反向传播之后x.grad 将会是另一个张量,其为x关于某个标量值的梯
度。
有时可能希望防止PyTorch在requires_grad=True 的张量执行某些操作时构建计算图;例如,在
训练神经网络时,我们通常不希望通过权重更新步骤进行反向传播。在这种情况下,我们可以使
用torch.no_grad() 上下文管理器来防止构造计算图。
下面我们使用PyTorch的Tensors和autograd来实现我们的两层的神经网络;我们不再需要手动执
行网络的反向传播:

# -*- coding: utf-8 -*-
import torch
dtype = torch.float
device = torch.device("cpu")
# device = torch.device(“cuda:0”)#取消注释以在GPU上运行
# N是批量大小; D_in是输入维度;
# H是隐藏的维度; D_out是输出维度。
N, D_in, H, D_out = 64, 1000, 100, 10
# 创建随机Tensors以保持输入和输出。
# 设置requires_grad = False表示我们不需要计算渐变
# 在向后传球期间对于这些Tensors。
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)
# 为权重创建随机Tensors。
# 设置requires_grad = True表示我们想要计算渐变
# 在向后传球期间尊重这些张贴。
w1 = torch.randn(D_in, H, device=device, dtype=dtype, requires_grad=True)
w2 = torch.randn(H, D_out, device=device, dtype=dtype, requires_grad=True)
learning_rate = 1e-6
for t in range(500):
# 前向传播:使用tensors上的操作计算预测值y;
# 由于w1和w2有requires_grad=True,涉及这些张量的操作将让PyTorch构建计算图,
# 从而允许自动计算梯度。由于我们不再手工实现反向传播,所以不需要保留中间值的引用。
	y_pred = x.mm(w1).clamp(min=0).mm(w2)
	# 使用Tensors上的操作计算和打印丢失。
	# loss是一个形状为()的张量
	# loss.item() 得到这个张量对应的python数值
	loss = (y_pred - y).pow(2).sum()
	print(t, loss.item())
	# 使用autograd计算反向传播。这个调用将计算loss对所有requires_grad=True的tensor的梯
	度。
	# 这次调用后,w1.grad和w2.grad将分别是loss对w1和w2的梯度张量。
	loss.backward()
	# 使用梯度下降更新权重。对于这一步,我们只想对w1和w2的值进行原地改变;不想为更新阶段构建
	计算图,
	# 所以我们使用torch.no_grad()上下文管理器防止PyTorch为更新构建计算图
	with torch.no_grad():
		w1 -= learning_rate * w1.grad
		w2 -= learning_rate * w2.grad
		# 反向传播后手动将梯度设置为零
		w1.grad.zero_()
		w2.grad.zero_()

定义新的自动求导函数
在底层,每一个原始的自动求导运算实际上是两个在Tensor上运行的函数。其中, forward 函数
计算从输入Tensors获得的输出Tensors。而backward 函数接收输出Tensors对于某个标量值的梯
度,并且计算输入Tensors相对于该相同标量值的梯度。
在PyTorch中,我们可以很容易地通过定义torch.autograd.Function 的子类并实现forward 和
backward函数,来定义自己的自动求导运算。之后我们就可以使用这个新的自动梯度运算符了。
然后,我们可以通过构造一个实例并像调用函数一样,传入包含输入数据的tensor调用它,这样来使用新的自动求导运算。这个例子中,我们自定义一个自动求导函数来展示ReLU的非线性。并用它实现我们的两层网络:

import torch
class MyReLU(torch.autograd.Function):
	@staticmethod
	def forward(ctx,x):
		ctx.save_for_backward(x)
		return x.clamp(min=0)
	@staticmethod
	def backward(ctx,grad_out_put):
		x, = ctx.saved_tensors
	grad_x = grad_output.clone()
	grad_x[x < 0] = 0
	return grad_x
device=torch.device('cuda' if torch.cuda.is_available() else 'cpu')
N, D_in, H, D_out = 64, 1000, 100, 10
# 产生输入和输出的随机张量
x = torch.randn(N, D_in, device=device)
y = torch.randn(N, D_out, device=device)
# 产生随机权重的张量
w1 = torch.randn(D_in, H, device=device, requires_grad=True)
w2 = torch.randn(H, D_out, device=device, requires_grad=True)
learning_rate = 1e-6
for t in range(500):
	y_pred = MyReLU.apply(x.mm(w1)).mm(w2)
	# 计算并输出loss
	loss = (y_pred - y).pow(2).sum()
	print(t, loss.item())
	loss.backward()
	with torch.no_grad():
		# 用梯度下降更新权重
		w1 -= learning_rate * w1.grad
		w2 -= learning_rate * w2.grad
		# 在反向传播之后手动清零梯度
		w1.grad.zero_()
		w2.grad.zero_()

PyTorch: nn
计算图和autograd是十分强大的工具,可以定义复杂的操作并自动求导;然而对于大规模的网
络,autograd太过于底层。 在构建神经网络时,我们经常考虑将计算安排成层,其中一些具有可
学习的参数,它们将在学习过程中进行优化。
TensorFlow里,有类似Keras,TensorFlow-Slim和TFLearn这种封装了底层计算图的高度抽象的接口,这使得构建网络十分方便。
在PyTorch中,包nn 完成了同样的功能。nn包中定义一组大致等价于层的模块。一个模块接受输
入的tesnor,计算输出的tensor,而且 还保存了一些内部状态比如需要学习的tensor的参数等。nn包中也定义了一组损失函数(loss functions),用来训练神经网络。
这个例子中,我们用nn包实现两层的网络:

import torch
N,D_in,H,D_out=64,1000,100,10
x=torch.randn(N,D_in)
y=torch.randn(N,D_out)

model=torch.nn.Sequential(
torch.nn.Linear(D_in,H),
torch.nn.ReLU(),
torch.nn.Linear(H,D_out),
)
loss_fn=torch.nn.MSEloss(REDUCTION='SUM')
learning_rate=1e-4
for t in range(500):
	y_pred=model(x)
	loss=loss_fn(y_pred,y)
	print(t,loss.item())
	model.zero_grad()
	loss.backward()
	with torch.no_grad():
		for param in model.parameters():
			param-=learning_rate*param.grad

PyTorch: optim
到目前为止,我们已经通过手动改变包含可学习参数的张量来更新模型的权重。对于随机梯度下
降(SGD/stochastic gradient descent)等简单的优化算法来说,这不是一个很大的负担,但在实践
中,我们经常使用AdaGrad、RMSProp、Adam等更复杂的优化器来训练神经网络。

import torch
N, D_in, H, D_out = 64, 1000, 100, 10
# 产生随机输入和输出张量
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
# 使用nn包定义模型和损失函数
model = torch.nn.Sequential(
torch.nn.Linear(D_in, H),
torch.nn.ReLU(),
torch.nn.Linear(H, D_out),
)
loss_fn = torch.nn.MSELoss(reduction='sum')
learning_rate = 1e-4
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
for t in range(500):
	y_pred = model(x)
	# 计算并打印loss
	loss = loss_fn(y_pred, y)
	print(t, loss.item())
	# 在反向传播之前,使用optimizer将它要更新的所有张量的梯度清零(这些张量是模型可学习的权)
	optimizer.zero_grad()
	# 反向传播:根据模型的参数计算loss的梯度
	loss.backward()
	# 调用Optimizer的step函数使它所有参数更新
	optimizer.step()

PyTorch:自定义nn 模块
有时候需要指定比现有模块序列更复杂的模型;对于这些情况,可以通过继承nn.Module 并定义
forward 函数,这个forward 函数可以 使用其他模块或者其他的自动求导运算来接收输入 tensor,产生输出tensor。在这个例子中,我们用自定义Module的子类构建两层网络:

import torch
class TwoLayerNet(torch.nn.Module):
	def __init__(self,D_in,H,D_out):
		super(TwoLayerNet,self).__init__()
		self.linear1=torch.nn.Linear(D_in,H)
		self.linear2=torch.nn.Linear(H,D_out)
	def forward(self,x):
		h_relu=self.linear1(x).clamp(min=0)
		y_pred=self.linear2(h_relu)
		return y_pred
N, D_in, H, D_out = 64, 1000, 100, 10
# 产生输入和输出的随机张量
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
# 通过实例化上面定义的类来构建我们的模型。
model = TwoLayerNet(D_in, H, D_out)
loss_fn = torch.nn.MSELoss(reduction='sum')
optimizer = torch.optim.SGD(model.parameters(), lr=1e-4)
for t in range(500):
	# 前向传播:通过向模型传递x计算预测值y
	y_pred = model(x)
	#计算并输出loss
	loss = loss_fn(y_pred, y)
	print(t, loss.item())
	# 清零梯度,反向传播,更新权重
	optimizer.zero_grad()
	loss.backward()
	optimizer.step()
  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-08-17 15:24:00  更:2021-08-17 15:25:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 21:06:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码