×

PyTorch教程3.5之线性回归的简洁实现

消耗积分:0 | 格式:pdf | 大小:0.22 MB | 2023-06-05

分享资料个

在过去的十年中,深度学习见证了某种形式的寒武纪大爆发。技术、应用和算法的绝对数量远远超过了前几十年的进步。这是由于多种因素的偶然组合,其中之一是许多开源深度学习框架提供的强大的免费工具。Theano Bergstra等人,2010 年、DistBelief Dean等人,2012 年和 Caffe Jia等人,2014 年可以说代表了被广泛采用的第一代此类模型。与 SN2 (Simulateur Neuristique) 等早期(开创性)作品相比 Bottou 和 Le Cun,1988,它提供了类似 Lisp 的编程体验,现代框架提供了自动微分和 Python 的便利性。这些框架使我们能够自动化和模块化实现基于梯度的学习算法的重复性工作。

3.4 节中,我们仅依靠 (i) 张量进行数据存储和线性代数;(ii) 计算梯度的自动微分。在实践中,由于数据迭代器、损失函数、优化器和神经网络层非常普遍,现代图书馆也为我们实现了这些组件。在本节中,我们将向您展示如何 使用深度学习框架的高级 API 简洁地实现3.4 节中的线性回归模型。

import numpy as np
import torch
from torch import nn
from d2l import torch as d2l
from mxnet import autograd, gluon, init, np, npx
from mxnet.gluon import nn
from d2l import mxnet as d2l

npx.set_np()
import jax
import optax
from flax import linen as nn
from jax import numpy as jnp
from d2l import jax as d2l
No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)
import numpy as np
import tensorflow as tf
from d2l import tensorflow as d2l

3.5.1. 定义模型

当我们在第 3.4 节中从头开始实现线性回归时 ,我们明确定义了我们的模型参数并编写了计算代码以使用基本线性代数运算生成输出。应该知道如何做到这一点。但是一旦您的模型变得更加复杂,并且一旦您几乎每天都必须这样做,您就会很高兴获得帮助。这种情况类似于从头开始编写自己的博客。做一两次是有益和有益的,但如果你花一个月重新发明轮子,你将成为一个糟糕的 Web 开发人员。

对于标准操作,我们可以使用框架的预定义层,这使我们能够专注于用于构建模型的层,而不用担心它们的实现。回想一下图 3.1.2中描述的单层网络的架构该层称为全连接层,因为它的每个输入都通过矩阵向量乘法连接到它的每个输出。

在 PyTorch 中,全连接层定义在LinearLazyLinear(自版本 1.8.0 起可用)类中。后者允许用户指定输出维度,而前者额外询问有多少输入进入该层。指定输入形状很不方便,这可能需要大量的计算(例如在卷积层中)。因此,为简单起见,我们将尽可能使用此类“惰性”层。

class LinearRegression(d2l.Module): #@save
  """The linear regression model implemented with high-level APIs."""
  def __init__(self, lr):
    super().__init__()
    self.save_hyperparameters()
    self.net = nn.LazyLinear(1)
    self.net.weight.data.normal_(0, 0.01)
    self.net.bias.data.fill_(0)

In Gluon, the fully connected layer is defined in the Dense class. Since we only want to generate a single scalar output, we set that number to 1. It is worth noting that, for convenience, Gluon does not require us to specify the input shape for each layer. Hence we do not need to tell Gluon how many inputs go into this linear layer. When we first pass data through our model, e.g., when we execute net(X) later, Gluon will automatically infer the number of inputs to each layer and thus instantiate the correct model. We will describe how this works in more detail later.

class LinearRegression(d2l.Module): #@save
  """The linear regression model implemented with high-level APIs."""
  def __init__(self, lr):
    super().__init__()
    self.save_hyperparameters()
    self.net = nn.Dense(1)
    self.net.initialize(init.Normal(sigma=0.01))
class LinearRegression(d2l.Module): #@save
  """The linear regression model implemented with high-level APIs."""
  lr: float

  def setup(self):
    self.net = nn.Dense(1, kernel_init=nn.initializers.normal(0.01))

In Keras, the fully connected layer is defined in the Dense class. Since we only want to generate a single scalar output, we set that number to 1. It is worth noting that, for convenience, Keras does not require us to specify the input shape for each layer. We do not need to tell Keras how many inputs go into this linear layer. When we first try to pass data through our model, e.g., when we execute net(X) later, Keras will automatically infer the number of inputs to each layer. We will describe how this works in more detail later.

class LinearRegression(d2l.Module): #@save
  """The linear regression model implemented with high-level APIs."""
  def __init__(self, lr):
    super().__init__()
    self.save_hyperparameters()
    initializer = tf.initializers.RandomNormal(stddev=0.01)
    self.net = tf.keras.layers.Dense(1, kernel_initializer=initializer)

forward方法中,我们只调用预定义层的内置__call__ 方法来计算输出。

@d2l.add_to_class(LinearRegression) #@save
def forward(self, X):
  return self.net(X)
@d2l.add_to_class(LinearRegression) #@save
def forward(self, X):
  return self.net(X)
@d2l.add_to_class(LinearRegression) #@save
def forward(self, X):
  return self.net(X)
@d2l.add_to_class(LinearRegression) #@save
def forward(self, X):
  return self.net(X)

3.5.2. 定义损失函数

该类MSELoss计算均方误差(没有 1/2(3.1.5)中的因素)。默认情况下,MSELoss 返回示例的平均损失。它比我们自己实现更快(也更容易使用)。

@d2l.add_to_class(LinearRegression) #@save
def loss(self, y_hat, y):
  fn = nn.MSELoss()
  return fn(y_hat, y)

The loss module defines many useful loss functions. For speed and convenience, we forgo implementing our own and choose the built-in loss.L2Loss instead. Because the loss that it returns is the squared error for each example, we use meanto average the loss across over the minibatch.

@d2l.add_to_class(LinearRegression) #@save
def loss(self, y_hat, y):
  fn = gluon.loss.L2Loss()
  return fn(y_hat, y).mean()
@d2l.add_to_class(LinearRegression) #@save
def loss(self, params, X, y, state):
  y_hat = state.apply_fn({'params': params}, *X)
  return optax.l2_loss(y_hat, y).mean()

The MeanSquaredError class computes the mean squared error (without the 1/2 factor in (3.1.5)). By default, it returns the average loss over examples.

@d2l.add_to_class(LinearRegression) #@save
def loss(self, y_hat, y):
  fn = tf.keras.losses.MeanSquaredError()
  return fn(y, y_hat)

3.5.3. 定义优化算法

Minibatch SGD 是用于优化神经网络的标准工具,因此 PyTorch 支持它以及模块中该算法的许多变体optim当我们实例化一个SGD实例时,我们指定要优化的参数,可通过 和我们的优化算法所需的self.parameters()学习率 ( ) 从我们的模型中获得。self.lr


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.obk20.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'PyTorch教程3.5之线性回归的简洁实现',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.obk20.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);