PyTorch: 梯度下降及反向传播的实例详解

线性模型

线性模型介绍

线性模型是很常见的机器学习模型,通常通过线性的公式来拟合训练数据集。训练集包括(x,y),x为特征,y为目标。如下图:

将真实值和预测值用于构建损失函数,训练的目标是最小化这个函数,从而更新w。当损失函数达到最小时(理想上,实际情况可能会陷入局部最优),此时的模型为最优模型,线性模型常见的的损失函数:

线性模型例子

下面通过一个例子可以观察不同权重(w)对模型损失函数的影响。

#author:yuquanle
#data:2018.2.5
#Study of Linear Model
import numpy as np
import matplotlib.pyplot as plt

x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]

def forward(x):
  return x * w

def loss(x, y):
  y_pred = forward(x)
  return (y_pred - y)*(y_pred - y)

w_list = []
mse_list = []

for w in np.arange(0.0, 4.1, 0.1):
  print("w=", w)
  l_sum = 0
  for x_val, y_val in zip(x_data, y_data):
    # error
    l = loss(x_val, y_val)
    l_sum += l
  print("MSE=", l_sum/3)
  w_list.append(w)
  mse_list.append(l_sum/3)

plt.plot(w_list, mse_list)
plt.ylabel("Loss")
plt.xlabel("w")
plt.show()

输出结果:
w= 0.0
MSE= 18.6666666667
w= 0.1
MSE= 16.8466666667
w= 0.2
MSE= 15.12
w= 0.3
MSE= 13.4866666667
w= 0.4
MSE= 11.9466666667
w= 0.5
MSE= 10.5
w= 0.6
MSE= 9.14666666667

调整w,loss变化图:

可以发现当w=2时,loss最小。但是现实中最常见的情况是,我们知道数据集,定义好损失函数之后(loss),我们并不会从0到n去设置w的值,然后求loss,最后选取使得loss最小的w作为最佳模型的参数。更常见的做法是,首先随机初始化w的值,然后根据loss函数定义对w求梯度,然后通过w的梯度来更新w的值,这就是经典的梯度下降法思想。

梯度下降法

梯度的本意是一个向量,表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模)。

梯度下降是迭代法的一种,可以用于求解最小二乘问题(线性和非线性都可以)。在求解机器学习算法的模型参数,即无约束优化问题时,梯度下降(Gradient Descent)是最常采用的方法之一,另一种常用的方法是最小二乘法。在求解损失函数的最小值时,可以通过梯度下降法来一步步的迭代求解,得到最小化的损失函数和模型参数值。即每次更新参数w减去其梯度(通常会乘以学习率)。

#author:yuquanle
#data:2018.2.5
#Study of SGD

x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]

# any random value
w = 1.0

# forward pass
def forward(x):
  return x * w

def loss(x, y):
  y_pred = forward(x)
  return (y_pred - y)*(y_pred - y)

# compute gradient (loss对w求导)
def gradient(x, y):
  return 2*x*(x*w - y)

# Before training
print("predict (before training)", 4, forward(4))

# Training loop
for epoch in range(20):
  for x, y in zip(x_data, y_data):
    grad = gradient(x, y)
    w = w - 0.01 * grad
    print("\t grad: ",x, y, grad)
    l = loss(x, y)
  print("progress:", epoch, l)

# After training
print("predict (after training)", 4, forward(4))

输出结果:
predict (before training) 4 4.0
   grad: 1.0 2.0 -2.0
   grad: 2.0 4.0 -7.84
   grad: 3.0 6.0 -16.2288
progress: 0 4.919240100095999
   grad: 1.0 2.0 -1.478624
   grad: 2.0 4.0 -5.796206079999999
   grad: 3.0 6.0 -11.998146585599997
progress: 1 2.688769240265834
   grad: 1.0 2.0 -1.093164466688
   grad: 2.0 4.0 -4.285204709416961
   grad: 3.0 6.0 -8.87037374849311
progress: 2 1.4696334962911515
   grad: 1.0 2.0 -0.8081896081960389
   grad: 2.0 4.0 -3.1681032641284723
   grad: 3.0 6.0 -6.557973756745939
progress: 3 0.8032755585999681
   grad: 1.0 2.0 -0.59750427561463
   grad: 2.0 4.0 -2.3422167604093502
   grad: 3.0 6.0 -4.848388694047353
progress: 4 0.43905614881022015
   grad: 1.0 2.0 -0.44174208101320334
   grad: 2.0 4.0 -1.7316289575717576
   grad: 3.0 6.0 -3.584471942173538
progress: 5 0.2399802903801062
   grad: 1.0 2.0 -0.3265852213980338
   grad: 2.0 4.0 -1.2802140678802925
   grad: 3.0 6.0 -2.650043120512205
progress: 6 0.1311689630744999
   grad: 1.0 2.0 -0.241448373202223
   grad: 2.0 4.0 -0.946477622952715
   grad: 3.0 6.0 -1.9592086795121197
progress: 7 0.07169462478267678
   grad: 1.0 2.0 -0.17850567968888198
   grad: 2.0 4.0 -0.6997422643804168
   grad: 3.0 6.0 -1.4484664872674653
progress: 8 0.03918700813247573
   grad: 1.0 2.0 -0.13197139106214673
   grad: 2.0 4.0 -0.5173278529636143
   grad: 3.0 6.0 -1.0708686556346834
progress: 9 0.021418922423117836
predict (after training) 4 7.804863933862125

反向传播

但是在定义好模型之后,使用pytorch框架不需要我们手动的求导,我们可以通过反向传播将梯度往回传播。通常有二个过程,forward和backward:

#author:yuquanle
#data:2018.2.6
#Study of BackPagation

import torch
from torch import nn
from torch.autograd import Variable

x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]

# Any random value
w = Variable(torch.Tensor([1.0]), requires_grad=True)

# forward pass
def forward(x):
  return x*w

# Before training
print("predict (before training)", 4, forward(4))

def loss(x, y):
  y_pred = forward(x)
  return (y_pred-y)*(y_pred-y)

# Training: forward, backward and update weight
# Training loop
for epoch in range(10):
  for x, y in zip(x_data, y_data):
    l = loss(x, y)
    l.backward()
    print("\t grad:", x, y, w.grad.data[0])
    w.data = w.data - 0.01 * w.grad.data
    # Manually zero the gradients after running the backward pass and update w
    w.grad.data.zero_()
  print("progress:", epoch, l.data[0])

# After training
print("predict (after training)", 4, forward(4))

输出结果:
predict (before training) 4 Variable containing:
 4
[torch.FloatTensor of size 1]
   grad: 1.0 2.0 -2.0
   grad: 2.0 4.0 -7.840000152587891
   grad: 3.0 6.0 -16.228801727294922
progress: 0 7.315943717956543
   grad: 1.0 2.0 -1.478623867034912
   grad: 2.0 4.0 -5.796205520629883
   grad: 3.0 6.0 -11.998146057128906
progress: 1 3.9987640380859375
   grad: 1.0 2.0 -1.0931644439697266
   grad: 2.0 4.0 -4.285204887390137
   grad: 3.0 6.0 -8.870372772216797
progress: 2 2.1856532096862793
   grad: 1.0 2.0 -0.8081896305084229
   grad: 2.0 4.0 -3.1681032180786133
   grad: 3.0 6.0 -6.557973861694336
progress: 3 1.1946394443511963
   grad: 1.0 2.0 -0.5975041389465332
   grad: 2.0 4.0 -2.3422164916992188
   grad: 3.0 6.0 -4.848389625549316
progress: 4 0.6529689431190491
   grad: 1.0 2.0 -0.4417421817779541
   grad: 2.0 4.0 -1.7316293716430664
   grad: 3.0 6.0 -3.58447265625
progress: 5 0.35690122842788696
   grad: 1.0 2.0 -0.3265852928161621
   grad: 2.0 4.0 -1.2802143096923828
   grad: 3.0 6.0 -2.650045394897461
progress: 6 0.195076122879982
   grad: 1.0 2.0 -0.24144840240478516
   grad: 2.0 4.0 -0.9464778900146484
   grad: 3.0 6.0 -1.9592113494873047
progress: 7 0.10662525147199631
   grad: 1.0 2.0 -0.17850565910339355
   grad: 2.0 4.0 -0.699742317199707
   grad: 3.0 6.0 -1.4484672546386719
progress: 8 0.0582793727517128
   grad: 1.0 2.0 -0.1319713592529297
   grad: 2.0 4.0 -0.5173273086547852
   grad: 3.0 6.0 -1.070866584777832
progress: 9 0.03185431286692619
predict (after training) 4 Variable containing:
 7.8049
[torch.FloatTensor of size 1]
Process finished with exit code 0

以上这篇PyTorch: 梯度下降及反向传播的实例详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Pytorch反向求导更新网络参数的方法

    方法一:手动计算变量的梯度,然后更新梯度 import torch from torch.autograd import Variable # 定义参数 w1 = Variable(torch.FloatTensor([1,2,3]),requires_grad = True) # 定义输出 d = torch.mean(w1) # 反向求导 d.backward() # 定义学习率等参数 lr = 0.001 # 手动更新参数 w1.data.zero_() # BP求导更新参数之前,需先对导

  • 详解Pytorch 使用Pytorch拟合多项式(多项式回归)

    使用Pytorch来编写神经网络具有很多优势,比起Tensorflow,我认为Pytorch更加简单,结构更加清晰. 希望通过实战几个Pytorch的例子,让大家熟悉Pytorch的使用方法,包括数据集创建,各种网络层结构的定义,以及前向传播与权重更新方式. 比如这里给出 很显然,这里我们只需要假定 这里我们只需要设置一个合适尺寸的全连接网络,根据不断迭代,求出最接近的参数即可. 但是这里需要思考一个问题,使用全连接网络结构是毫无疑问的,但是我们的输入与输出格式是什么样的呢? 只将一个x作为输入

  • PyTorch: 梯度下降及反向传播的实例详解

    线性模型 线性模型介绍 线性模型是很常见的机器学习模型,通常通过线性的公式来拟合训练数据集.训练集包括(x,y),x为特征,y为目标.如下图: 将真实值和预测值用于构建损失函数,训练的目标是最小化这个函数,从而更新w.当损失函数达到最小时(理想上,实际情况可能会陷入局部最优),此时的模型为最优模型,线性模型常见的的损失函数: 线性模型例子 下面通过一个例子可以观察不同权重(w)对模型损失函数的影响. #author:yuquanle #data:2018.2.5 #Study of Linear

  • Django 反向生成url实例详解

    Django中提供了一个关于URL的映射的解决方案, 1.客户端的浏览器发起一个url请求,Django根据URL解析,把url中的参数捕获,调用相应的试图,获取相应的数据,然后返回给客户端显示 2.通过一个视图的名字,再加上一些参数和值,逆向获取相应的URL 第一个就是平常的请求有URLconf来解析的过程, 第二个叫做,url的逆向解析,url逆向匹配,url的逆向查阅,等 Django提供了不同的层级的url逆向处理工具: 1.在模板templates中,使用url标记,如:{% url

  • pytorch中的自定义反向传播,求导实例

    pytorch中自定义backward()函数.在图像处理过程中,我们有时候会使用自己定义的算法处理图像,这些算法多是基于numpy或者scipy等包. 那么如何将自定义算法的梯度加入到pytorch的计算图中,能使用Loss.backward()操作自动求导并优化呢.下面的代码展示了这个功能` import torch import numpy as np from PIL import Image from torch.autograd import gradcheck class Bicu

  • 人工智能学习Pytorch梯度下降优化示例详解

    目录 一.激活函数 1.Sigmoid函数 2.Tanh函数 3.ReLU函数 二.损失函数及求导 1.autograd.grad 2.loss.backward() 3.softmax及其求导 三.链式法则 1.单层感知机梯度 2. 多输出感知机梯度 3. 中间有隐藏层的求导 4.多层感知机的反向传播 四.优化举例 一.激活函数 1.Sigmoid函数 函数图像以及表达式如下: 通过该函数,可以将输入的负无穷到正无穷的输入压缩到0-1之间.在x=0的时候,输出0.5 通过PyTorch实现方式

  • python实现梯度下降算法的实例详解

    python版本选择 这里选的python版本是2.7,因为我之前用python3试了几次,发现在画3d图的时候会报错,所以改用了2.7. 数据集选择 数据集我选了一个包含两个变量,三个参数的数据集,这样可以画出3d图形对结果进行验证. 部分函数总结 symbols()函数:首先要安装sympy库才可以使用.用法: >>> x1 = symbols('x2') >>> x1 + 1 x2 + 1 在这个例子中,x1和x2是不一样的,x2代表的是一个函数的变量,而x1代表

  • pytorch中的transforms模块实例详解

    pytorch中的transforms模块中包含了很多种对图像数据进行变换的函数,这些都是在我们进行图像数据读入步骤中必不可少的,下面我们讲解几种最常用的函数,详细的内容还请参考pytorch官方文档(放在文末). data_transforms = transforms.Compose([ transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms

  • opencv python图像梯度实例详解

    这篇文章主要介绍了opencv python图像梯度实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一阶导数与Soble算子 二阶导数与拉普拉斯算子 图像边缘: Soble算子: 二阶导数: 拉普拉斯算子: import cv2 as cv import numpy as np # 图像梯度(由x,y方向上的偏导数和偏移构成),有一阶导数(sobel算子)和二阶导数(Laplace算子) # 用于求解图像边缘,一阶的极大值,二阶的零点

  • PyTorch加载自己的数据集实例详解

    数据预处理在解决深度学习问题的过程中,往往需要花费大量的时间和精力. 数据处理的质量对训练神经网络来说十分重要,良好的数据处理不仅会加速模型训练, 更会提高模型性能.为解决这一问题,PyTorch提供了几个高效便捷的工具, 以便使用者进行数据处理或增强等操作,同时可通过并行化加速数据加载. 数据集存放大致有以下两种方式: (1)所有数据集放在一个目录下,文件名上附有标签名,数据集存放格式如下: root/cat_dog/cat.01.jpg root/cat_dog/cat.02.jpg ...

  • Nginx的反向代理实例详解

    一.反向代理实例 1 1.实现效果 (1)打开浏览器,在浏览器中输入www.123.com,跳转到linux系统tomcat主页面. 2.具体配置 (1)在windows系统的host文件进行域名和ip对应关系 (2)在Nginx进行请求 注意: 端口乤对外开放.  二.反向代理实例 2 1.实现效果 (1)使用Nginx反向代理,根据访问的路径跳转到不同端口的服务中,Nginx监听端口为8001. 访问 http://127.0.0.1:9001/deu/ 直接跳转到127.0.0.1:801

  • pytorch中的nn.ZeroPad2d()零填充函数实例详解

    在卷积神经网络中,有使用设置padding的参数,配合卷积步长,可以使得卷积后的特征图尺寸大小不发生改变,那么在手动实现图片或特征图的边界零填充时,常用的函数是nn.ZeroPad2d(),可以指定tensor的四个方向上的填充,比如左边添加1dim.右边添加2dim.上边添加3dim.下边添加4dim,即指定paddin参数为(1,2,3,4),本文中代码设置的是(3,4,5,6)如下: import torch.nn as nn import cv2 import torchvision f

随机推荐