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


Posted in Python onAugust 20, 2019

线性模型

线性模型介绍

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

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

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

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

线性模型例子

下面通过一个例子可以观察不同权重(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变化图:

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

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

梯度下降法

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

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

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

#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:

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

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

#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: 梯度下降及反向传播的实例详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python列出一个文件夹及其子目录的所有文件
Jun 30 Python
Python3使用PyQt5制作简单的画板/手写板实例
Oct 19 Python
python实现数独游戏 java简单实现数独游戏
Mar 30 Python
Python检查ping终端的方法
Jan 26 Python
python+logging+yaml实现日志分割
Jul 22 Python
Python使用matplotlib 模块scatter方法画散点图示例
Sep 27 Python
numpy ndarray 取出满足特定条件的某些行实例
Dec 05 Python
pytorch中获取模型input/output shape实例
Dec 30 Python
Python实现搜索算法的实例代码
Jan 02 Python
Python实现RabbitMQ6种消息模型的示例代码
Mar 30 Python
Python中三维坐标空间绘制的实现
Sep 22 Python
Django程序的优化技巧
Apr 29 Python
python爬虫 urllib模块发起post请求过程解析
Aug 20 #Python
pytorch 加载(.pth)格式的模型实例
Aug 20 #Python
python multiprocessing模块用法及原理介绍
Aug 20 #Python
python 并发编程 阻塞IO模型原理解析
Aug 20 #Python
PyTorch中常用的激活函数的方法示例
Aug 20 #Python
Pytorch抽取网络层的Feature Map(Vgg)实例
Aug 20 #Python
python批量解压zip文件的方法
Aug 20 #Python
You might like
一些星际专用术语解释
2020/03/04 星际争霸
PHP 遍历文件实现代码
2011/05/04 PHP
php+iframe 实现上传文件功能示例
2020/03/04 PHP
Javascript在IE或Firefox下获取鼠标位置的代码
2009/12/18 Javascript
jQuery源码解读之hasClass()方法分析
2015/02/20 Javascript
浅谈被jQuery抛弃的函数及替代函数
2015/05/03 Javascript
jQuery实现模拟marquee标签效果
2015/07/14 Javascript
jQuery实现响应鼠标滚动的动感菜单效果
2015/09/21 Javascript
jQuery实现横向带缓冲的水平运动效果(附demo源码下载)
2016/01/29 Javascript
jQuery常用的一些技巧汇总
2016/03/26 Javascript
微信小程序 页面跳转传递值几种方法详解
2017/01/12 Javascript
jQuery层级选择器实例代码
2017/02/06 Javascript
js实现简易垂直滚动条
2017/02/22 Javascript
jQuery插件HighCharts绘制2D半圆环图效果示例【附demo源码下载】
2017/03/09 Javascript
详解nodejs模板引擎制作
2017/06/14 NodeJs
使用D3.js创建物流地图的示例代码
2018/01/27 Javascript
浅谈Webpack 是如何加载模块的
2018/05/24 Javascript
vue插件mescroll.js实现移动端上拉加载和下拉刷新
2019/03/07 Javascript
jQuery实现简单弹幕效果
2019/11/28 jQuery
[03:07]2015国际邀请赛选手档案EHOME.rOtK 是什么让他落泪?
2015/07/31 DOTA
python时间整形转标准格式的示例分享
2014/02/14 Python
使用Python中的greenlet包实现并发编程的入门教程
2015/04/16 Python
python使用PIL模块实现给图片打水印的方法
2015/05/22 Python
基于Python检测动态物体颜色过程解析
2019/12/04 Python
class类在python中获取金融数据的实例方法
2020/12/10 Python
python爬虫scrapy框架的梨视频案例解析
2021/02/20 Python
复古服装:RetroStage
2019/05/10 全球购物
J2EE面试题
2016/03/14 面试题
大学生求职推荐信
2013/11/27 职场文书
2014年领导班子工作总结
2014/12/11 职场文书
穆斯林的葬礼读书笔记
2015/06/26 职场文书
2016年世界人口日宣传活动总结
2016/04/05 职场文书
django如何自定义manage.py管理命令
2021/04/27 Python
pandas提升计算效率的一些方法汇总
2021/05/30 Python
python基础之文件操作
2021/10/24 Python
MYSQL中文乱码问题的解决方案
2022/06/14 MySQL