百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Pytorch学习记录-使用Pytorch进行深度学习,使用案例学习Pytorch

toyiye 2024-06-21 12:39 10 浏览 0 评论

首页.jpg

注意确定已经安装了torch和torchvision

使用案例学习Pytorch

在完成60分钟入门之后,接下来有六节tutorials和五节关于文本处理的tutorials。争取一天一节。不过重点是关注神经网络构建和数据处理部分。

教程通过下面的几个例子介绍了Pytorch的基本概念。Pytorch的核心是以下两个特性:

  • n维张量,和numpy类似但可以在GPU上运行
  • 构建和训练神经网络的自动微分功能

接下来教程会使用全连接Relu网络作为运行案例,这个网络有一个隐藏层hy,使用梯度下降进行训练拟合随即数据。

下面是教程目录。

1.Tensors(张量)

1.1 Warm-up:numpy

1.2 PyTorch:Tensors

2.Autograd(自动梯度)

2.1 PyTorch:Variables and autograd (变量和自动梯度)

2.2 PyTorch : Defining new autograd functions(定义新的自动梯度函数)

2.3 TensorFlow: Static Graphs (静态图)

3.nn module

3.1 PyTorch: nn

3.2 PyTorch: optim

3.3 PyTorch: Custom nn Modules (定制nn模块)

3.4 PyTorch: Control Flow + Weight Sharing (控制流+权重分享)

1. Tensor

1.1 热身

介绍Pytorch之前使用numpy实现一个网络。numpy提供的是一个n维数组对象,以及操作这些数组的函数。但是numpy不是为计算图、深度学习、梯度计算而生,在这里生成一个两层的网络,然后使用随即数据拟合,前向、后向传播均使用numpy操作。

# -*- coding:utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
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)
 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

我们输出一下损失函数

image.png

1.2 PyTorch:Tensors

Pytorch的基本概念Tensor,Tensor与numpy的array类似,是一个n维的array。

Pytorch提供多种进行Tensor运算,教程中还提到,Pytorch同样也不是专门进行深度学习、计算图、计算梯度的。但是优势在于能在GPU上运行。

在这里使用Pytorch Tensor来拟合一个2层的网络,需要手动执行前向和反向操作。

import torch
import matplotlib.pyplot as plt
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
loss_list = []
t_list = []
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)
 loss_list.append(loss)
 t_list.append(t)
 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

image.png

2.Autograd(自动梯度)

2.1 PyTorch:Tensors and autograd

实际操作中肯定不能像上面那样手动操作,这样,就需要有一个自动求梯度,自动反向传递。

在之前60分钟已经做了介绍,那就是autograd包,在使用autograd时,前向通道定义一个计算图(computational graph),图中的节点是Tensor,边是依据输入Tensor产生的输出Tensro的函数,这样图的反向传播就可以计算梯度了。

操作历程如下

  • 将Tensors打包到Variable对象中(一个Variable代表一个计算图中的节点。如果x是一个Variable,那么x. data 就是一个Tensor),x.grad是另一个Tensor,这个Tensor通过对某个标量保持x的梯度
  • 这里使用Tensor和autograd来实现上面的那个两层网络,不再需要手动实现反向传播了!
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)
# 在这里设置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):
 y_pred = x.mm(w1).clamp(min=0).mm(w2)
 #计算损失,这时损失已经是一个Tensor,shape为(1,),loss.item()获取的就是损失的标量值
 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大大降低了手工操作的负担,只需要在设定的时候增加requires_grad=True,在最后对权重进行归零即可。

2.2 PyTorch : Defining new autograd functions(定义新的自动梯度函数)

在底层,每次原始的autograd操作都是对Tensor的两个方法的操作。

  • forward方法用于计算输入Tensor
  • backward方法获取输出的梯度,并且计算输入Tensors相对于该相同标量值的梯度
  • 在Pytorch中,可以容易定义自己的autograd操作,通过定义子类torch.autograd.Function来实现forward和backward函数,然后就可以通过构建实例并进行调用来使用新的autograd运算符。传递包含输入数据的Variables。

这个例子就是定制一个autograd函数来执行Relu非线性,进一步执行两层神经网络。

import torch
class MyRelu(torch.autograd.Function):
 @staticmethod
 def forward(ctx, input):
 '''
 ctx是一个上下文对象,可用于存储信息以进行反向计算。
 :param ctx: 
 :param input: 
 :return: 
 '''
 ctx.save_for_backward(input)
 return input.clamp(min=0)
 @staticmethod
 def backward(ctx, grad_output):
 '''
 在backwward中,获取一个含有损失的梯度的Tensor,并且计算相对于输入的损失的梯度。
 :param ctx: 
 :param grad_output: 
 :return: 
 '''
 input, = ctx.saved_tensors
 grad_input = grad_output.clone()
 grad_input[input < 0] = 0
 return grad_input
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, 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):
 relu = MyRelu.apply
 y_pred = relu(x.mm(w1)).mm(w2)
 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_()

2.3 TensorFlow: Static Graphs (静态图)

这一节空出来,主要内容是为了对比Tensorflow和Pytorch在动态图和静态图之间的区别,不用说,肯定Pytorch更好一些。

3.nn module(神经网络模块)

3.1 PyTorch: nn

计算图和autograd时很有用的范式,可以用来定义复杂运算符和自动求导。这时对于大型网络而言,原始的autograd就有些低级。

在构建神经网络时,会经常需要把计算安排在层(layers)中。某些层有可学习的参数,将会在学习中进行优化。

Pytorch提供的nn包就是类似Keras的高级抽象,其中定义了一系列Modules,相当于神经网络中的层,一个Module接收输入Variables,计算输出Variables,但是也可以保持一个内部状态,例如包含了可学习参数的Variables。nn 包还定义了一系列在训练神经网络时常用的损失函数。

接下来就是使用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(size_average=False)
learning_rate = 1e-6
for t in range(500):
 y_pred = model(x)
 loss = loss_fn(y_pred, y)
 print(t, loss.data[0])
 model.zero_grad()
 loss.backward()
 with torch.no_grad():
 for param in model.parameters():
 param -= learning_rate * param.grad

3.2 PyTorch: optim(优化)

在前面更新权重,使用的是手动改变学习参数,这对于使用简单的优化算法(SGD)是可以的,但是在使用更加复杂的优化算法(ADAGrad,RMSProp,Adam)训练神经网络。

Pytorch提供了optim包对优化算法进行抽象。

同样是刚才的那个2层神经网络,这里使用optim来进行优化。

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(size_average=False)
learning_rate=1e-4
optimizer=torch.optim.Adam(model.parameters(), lr=learning_rate)
for t in range(500):
 y_pred=model(x)
 loss=loss_fn(y_pred,y)
 print(t,loss.item())
 optimizer.zero_grad()
 loss.backward()
 optimizer.step()

对比前面的,你会发现越来越简化,就能生成一个神经网络。

3.3 PyTorch: Custom nn Modules (定制nn模块)

有时候,需要设定比现有模块序列更加复杂的模型。这时,你可以通过生成一个nn.Module的子类来定义一个forward。该forward可以使用其他的modules或者其他的自动梯度运算来接收输入Variables,产生输出Variables。

在这个例子中,我们实现两层神经网络作为一个定制的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)
criterion=torch.nn.MSELoss(size_average=False)
optimizer=torch.optim.SGD(model.parameters(),lr=1e-4)
for t in range(500):
 y_pred=model(x)
 loss=criterion(y_pred,y)
 print(t,loss.item())
 optimizer.zero_grad()
 loss.backward()
 optimizer.step()

3.4 PyTorch: Control Flow + Weight Sharing (控制流+权重分享)

我们实现一个非常奇怪的模型来作为动态图和权重分享的例子。这个模型是一个全连接的ReLU网络。每一个前向通道选择一个1至4之间的随机数,在很多隐含层中使用。多次使用相同的权重来计算最内层的隐含层。

这个模型我们使用正常的Python流控制来实现循环。在定义前向通道时,通过多次重复使用相同的Module来实现权重分享。

我们实现这个模型作为一个Module的子类。

# -*- coding: utf-8 -*-
import random
import torch
class DynamicNet(torch.nn.Module):
 def __init__(self, D_in, H, D_out):
 super(DynamicNet, self).__init__()
 self.input_linear = torch.nn.Linear(D_in, H)
 self.middle_linear = torch.nn.Linear(H, H)
 self.output_linear = torch.nn.Linear(H, D_out)
 def forward(self, x):
 h_relu = self.input_linear(x).clamp(min=0)
 for _ in range(random.randint(0, 3)):
 h_relu = self.middle_linear(h_relu).clamp(min=0)
 y_pred = self.output_linear(h_relu)
 return y_pred
# N is batch size; D_in is input dimension;
# H is hidden dimension; D_out is output dimension.
N, D_in, H, D_out = 64, 1000, 100, 10
# Create random Tensors to hold inputs and outputs
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
# Construct our model by instantiating the class defined above
model = DynamicNet(D_in, H, D_out)
# Construct our loss function and an Optimizer. Training this strange model with
# vanilla stochastic gradient descent is tough, so we use momentum
criterion = torch.nn.MSELoss(reduction='sum')
optimizer = torch.optim.SGD(model.parameters(), lr=1e-4, momentum=0.9)
for t in range(500):
 # Forward pass: Compute predicted y by passing x to the model
 y_pred = model(x)
 # Compute and print loss
 loss = criterion(y_pred, y)
 print(t, loss.item())
 # Zero gradients, perform a backward pass, and update the weights.
 optimizer.zero_grad()
 loss.backward()
 optimizer.step()

最后这个例子我没实现,照抄的。

这算是基本上的模型构建,主要包括模型、损失函数计算、优化、最后的迭代。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码