03_利用pytorch解决线性回归问题

一、引言

上一篇文章我们利用numpy解决了线性回归问题,我们能感觉到他的麻烦之处,很多数学性的方法都需要我们自己亲手去实现,这对于数学不好的同学来说,简直就是灾难,让你数学又好并且码代码能力又强,臣妾做不到呀!因此我们说到,可以利用torch这个框架简化其中的很多操作,接下来就让我们提前体验下torch的强大,由于直接上代码,有些代码可能你可能看不懂,但没关系,能看懂torch的强大就行。

由于上一篇已经详细的介绍了线性回归模型的流程,我们这里就不再次罗嗦了,直接把线性回归的5个步骤贴过来:

  1. 初始化未知变量\(w=b=0\)
  2. 得到损失函数\(loss = \frac{1}{N}\sum_{i=1}^N{(\hat{y_i}-y_i)}^2\)
  3. 利用梯度下降算法更新得到\(w', b'\)
  4. 重复步骤3,利用\(w', b'\)得到新的更优的\(w', b'\),直至\(w', b'\)收敛
  5. 最后得到函数模型\(f=w'*x+b'\)

但是这里为了体现torch的强大,我们使用了神经网络全连接层的概念,但是用的是一层网络,相信不会难倒你。有人很好奇,为什么我这样做,我想说:如果不使用神经网络,我为什么不用sklearn框架做个线性回归给你体验下框架的强大呢?三行代码一套搞定。而且一层神经网络可以看做是感知机模型,而感知机模型无非就是在线性回归模型的基础上加了一个sgn函数。

二、利用torch解决线性回归问题

2.1 定义x和y

在下面的代码中,我们定义的x和y都是ndarray数据的格式,所以在之后的处理之中需要通过torch的from_numpy()方法把ndarray格式的数据转成tensor类型。

其中x为一维数组,例如:[1,2,3,4,5,……]

其中y假设\(y=2*x+3\)

import numpy as np

# torch里要求数据类型必须是float
x = np.arange(1, 12, dtype=np.float32).reshape(-1, 1)
y = 2 * x + 3

2.2 自定制线性回归模型类

由于torch内部封装了线性回归算法,我们只需要继承它给我们提供的模型类即可,然后通过Python中类的继承做出一些灵活的改动。(如果你对继承不熟悉,强烈推荐回炉重造Python)下面给出代码:

import torch
import torch.nn as nn # 继承nn.module,实现前向传播,线性回归直接可以看做是全连接层
class LinearRegressionModel(nn.Module):
def __init__(self, input_dim, output_dim):
super().__init__() # 继承父类方法
self.linear = nn.Linear(input_dim, output_dim) # 定义全连接层,其中input_dim和output_dim是输入和输出数据的维数 # 定义前向传播算法
def forward(self, inp):
out = self.linear(inp) # 输入x后,通过全连接层得到输入出结果out
return out # 返回被全连接层处理后的结果 # 定义线性回归模型
regression_model = LinearRegressionModel(1, 1) # x和y都是一维的

2.3 指定gpu或者cpu

# 可以通过to()或者cuda()使用GPU进行模型的训练,需要将模型和数据都转换到GPU上,也可以指定具体的GPU,如.cuda(1)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
regression_model.to(device)

2.4 设置参数

epochs = 1000  # 训练次数
learning_rate = 0.01 # 学习速率
optimizer = torch.optim.SGD(regression_model.parameters(), learning_rate) # 优化器(未来会详细介绍),这里使用随机梯度下降算法(SGD)
criterion = nn.MSELoss() # 使用均方误差定义损失函数

2.5 训练

for epoch in range(epochs):
# 数据类型转换
inputs = torch.from_numpy(x).to(device) # 由于x是ndarray数组,需要转换成tensor类型,如果用gpu训练,则会通过to函数把数据传入gpu
labels = torch.from_numpy(y).to(device) # 训练
optimizer.zero_grad() # 每次求偏导都会清零,否则会进行叠加
outputs = regression_model(inputs) # 把输入传入定义的线性回归模型中,进行前向传播,得到预测结果
loss = criterion(outputs, labels) # 通过均方误差评估预测误差
loss.backward() # 反向传播
optimizer.step() # 更新权重参数 # 每50次循环打印一次结果
if epoch % 50 == 0:
print("epoch:", epoch, "loss:", loss.item()) predict = regression_model(torch.from_numpy(x).requires_grad_()).data.numpy() # 通过训练好的模型预测结果

2.6 保存模型

torch.save(regression_model.state_dict(), "model.pk1")  # 保存模型
result = regression_model.load_state_dict(torch.load("model.pk1")) # 加载模型

三、代码汇总

# author : 'nickchen121';
# date: 14/4/2021 20:11 import numpy as np # torch里要求数据类型必须是float
x = np.arange(1, 12, dtype=np.float32).reshape(-1, 1)
y = 2 * x + 3 import torch
import torch.nn as nn # 继承nn.module,实现前向传播,线性回归直接可以看做是全连接层
class LinearRegressionModel(nn.Module):
def __init__(self, input_dim, output_dim):
super().__init__() # 继承父类方法
self.linear = nn.Linear(input_dim, output_dim) # 定义全连接层,其中input_dim和output_dim是输入和输出数据的维数 # 定义前向传播算法
def forward(self, inp):
out = self.linear(inp) # 输入x后,通过全连接层得到输入出结果out
return out # 返回被全连接层处理后的结果 # 定义线性回归模型
regression_model = LinearRegressionModel(1, 1) # x和y都是一维的 # 可以通过to()或者cuda()使用GPU进行模型的训练,需要将模型和数据都转换到GPU上,也可以指定具体的GPU,如.cuda(1)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
regression_model.to(device) epochs = 1000 # 训练次数
learning_rate = 0.01 # 学习速率
optimizer = torch.optim.SGD(regression_model.parameters(), learning_rate) # 优化器,这里使用随机梯度下降算法(SGD)
criterion = nn.MSELoss() # 使用均方误差定义损失函数 for epoch in range(epochs):
# 数据类型转换
inputs = torch.from_numpy(x).to(device) # 由于x是ndarray数组,需要转换成tensor类型,如果用gpu训练,则会通过to函数把数据传入gpu
labels = torch.from_numpy(y).to(device) # 训练
optimizer.zero_grad() # 每次求偏导都会清零,否则会进行叠加
outputs = regression_model(inputs) # 把输入传入定义的线性回归模型中,进行前向传播
loss = criterion(outputs, labels) # 通过均方误差评估预测误差
loss.backward() # 反向传播
optimizer.step() # 更新权重参数 # 每50次循环打印一次结果
if epoch % 50 == 0:
print("epoch:", epoch, "loss:", loss.item()) predict = regression_model(torch.from_numpy(x).requires_grad_()).data.numpy() # 通过训练好的模型预测结果 # torch.save(regression_model.state_dict(), "model.pk1") # 保存模型
# result = regression_model.load_state_dict(torch.load("model.pk1")) # 加载模型

四、总结

本篇文章从torch的角度去解决了线性回归问题,细节你可能不懂,但也可以发现它是非常简单的,全程没有让你去实现优化器、去实现全连接层、去实现反向传播,在这里你就不需要去实现一个数学公式。你需要做的仅仅是成为一个优秀的调包侠,并且努力成为一个伟大的调参师即可。

至于为什么直接上代码,而不是先讲解torch的基础,一定是有深意的。站得高看得远,先带你领略下torch的用途及其强大,然后我们再慢慢的一步一步筑基。

03_利用pytorch解决线性回归问题的更多相关文章

  1. 02_利用numpy解决线性回归问题

    02_利用numpy解决线性回归问题 目录 一.引言 二.线性回归简单介绍 2.1 线性回归三要素 2.2 损失函数 2.3 梯度下降 三.解决线性回归问题的五个步骤 四.利用Numpy实战解决线性回 ...

  2. 机器学习中梯度下降法原理及用其解决线性回归问题的C语言实现

    本文讲梯度下降(Gradient Descent)前先看看利用梯度下降法进行监督学习(例如分类.回归等)的一般步骤: 1, 定义损失函数(Loss Function) 2, 信息流forward pr ...

  3. 利用闭包解决for循环里onclick事件不能捕捉实时i值问题

    问题描述 我们都知道,如果我们对于一组元素(相同的标签)同时进行onclick事件处理的时候(在需要获取到索引的时候),一般是写一个for循环,但是onclick是一个异步调用的,所以会带来一个问题, ...

  4. 利用Readability解决网页正文提取问题

    分享: 利用Readability解决网页正文提取问题   做数据抓取和分析的各位亲们, 有没有遇到下面的难题呢? - 如何从各式各样的网页中提取正文!? 虽然可以用SS为各种网站写脚本做解析, 但是 ...

  5. 利用gulp解决微信浏览器缓存问题

    做了好多项目,这次终于要解决微信浏览器缓存这个令人头疼的问题了.每次上传新的文件,在微信浏览器中访问时,总要先清除微信的缓存,实在麻烦,在网上搜罗了很多解决办法,终于找到了方法:利用gulp解决缓存问 ...

  6. 利用Json_encode解决中文问题

    利用Json_encode解决中文问题       public function return_json($data=array()){         echo json_encode($data ...

  7. 利用Filter解决跨域请求的问题

    1.为什么出现跨域. 很简单的一句解释,A系统中使用ajax调用B系统中的接口,此时就是一个典型的跨域问题,此时浏览器会出现以下错误信息,此处使用的是chrome浏览器. 错误信息如下: jquery ...

  8. 利用NSProxy解决NSTimer内存泄漏问题

    之前写过一篇利用RunTime解决由NSTimer导致的内存泄漏的文章,最近和同事讨论觉得这样写有点复杂,然后发现有NSProxy这么好用的根类,根类,根类,没错NSProxy与NSObject一样是 ...

  9. 利用dynamic解决匿名对象不能赋值的问题

    原文:利用dynamic解决匿名对象不能赋值的问题 关于匿名对象 匿名对象是.Net Framework 3.0提供的新类型,例如: }; 就是一个匿名类,搭配Linq,可以很灵活的在代码中组合数据, ...

随机推荐

  1. js 使用socket-io发送文件

    更多 前端 import { Component, OnInit, ViewChild, ElementRef } from '@angular/core'; import { MediaDevice ...

  2. 百万SPC即将空投,3.0公链NGK有多“豪横”?

    在1月2日晚间,比特币强势突破3万美金,随后还在一路上涨,现在价格33431.64美金.仅用了不到一个月的时间,比特币就从2万美金涨到了3万美金,这充分展示了市场对于数字货币的强烈信心.没有了天花板的 ...

  3. yaml配置和ini配置的数据源配置和数据获取

    1.前言 关于yaml和ini的相关理论暂不做记录,不影响代码编写,百度即可. 2.关于配置文件的选择 yaml 和 ini 都使用过, 但是yaml更符合人类使用,已要弃用ini,后期各项目均采用y ...

  4. js中国标准时间转换成datetime格式

    var format = function (time, format) { var t = new Date(time); var tf = function (i) { return (i < ...

  5. Java基础语法:static修饰符

    一.静态变量 描述: 在类中,使用'static'修饰的成员变量,就是静态变量,反之为非静态变量. 区别: 静态变量属于类的,可以使用类名来访问:非静态变量是属于对象的,必须使用对象来访问. 静态变量 ...

  6. 微信小程序滚动条设置

    隐藏滚动条 ::-webkit-scrollbar { width: 0rpx; height: 0rpx; background-color: transparent; } 其实设置为宽高为 0 或 ...

  7. Shiro反序列化漏洞检测、dnslog

    目录 信息收集 poc 参考 信息收集 poc # pip install pycrypto import sys import base64 import uuid from random impo ...

  8. 实现Hi3559板载自启动网卡、NFS及Telnet服务

    实现Hi3559板载开机自启动网卡.NFS及Telnet服务通过直接在home目录下,编辑.bashrc,vi ~/.bashrc 1 ifconfig eth0 up 2 ifconfig eth0 ...

  9. 一个把数据转化成Excel导出的程序 python Django

    把从数据库查询出来数据导出 源码下载!!!!! 效果图 登入界面 主页面 查询到数据 导出 打开得到文件 项目地址,源码下载

  10. Python开发环境从零搭建-02-代码编辑器Sublime

    想要从零开始搭建一个Python的开发环境说容易也容易 说难也能难倒一片开发人员,在接下来的一系列视频中,会详细的讲解如何一步步搭建python的开发环境 本文章是搭建环境的第2篇 讲解的内容是:安装 ...