从零开始机器学习——基于PyTorch构建你的第一个线性回归模型

随着人工智能技术的迅猛发展,机器学习成为了现代科技领域中最炙手可热的话题之一。然而,对于初学者来说,机器学习似乎总是充满了复杂的理论和难以理解的概念。本文将带你从零开始,使用PyTorch深度学习框架构建一个最简单的线性回归模型,一步步揭开机器学习的神秘面纱。无需预先的专业背景知识,只需跟随本文的指导,你就能亲手实现一个可以预测数据的机器学习模型!

一、什么是线性回归

线性回归是一种最基本的监督学习方法,其试图找到输入特征与输出结果之间的线性关系。通过训练模型,我们可以学习到一组参数,使得模型能够预测新的未知数据。

二、构建线性模型

在本文中,我们将使用 Python 的 PyTorch 库来构建一个简单的线性回归模型。PyTorch 是一个强大的深度学习框架,它不仅支持动态计算图,还提供了大量的预定义模块和工具,使得机器学习变得更加容易。

2.1 数据准备

首先,我们需要准备一些训练数据。假设我们有三个样本点,每个样本有一个输入特征一个对应的样本输出值

# 数据准备:x_data 和 y_data 是两个张量(Tensor),分别代表"输入数据"和对应的"标签数据"。
# x_data 包含了数值 [1.0, 2.0, 3.0],而 y_data 包含了 [2.0, 4.0, 6.0],这表明 y_data 中的每个值都是对应 x_data 值的两倍。
# 我们的目标是训练一个模型,使其能够学习到这种输入与输出之间的映射关系。
x_data = torch.Tensor([[1.0], [2.0], [3.0]])  # 输入数据
y_data = torch.Tensor([[2.0], [4.0], [6.0]])  # 标签数据

这里,x_data 是输入特征,y_data 是样本输出值。

2.2 定义模型

接下来,我们需要定义一个模型学习输入特征与输出值之间的关系。这里我们使用 PyTorch 提供的 torch.nn.Module 来定义一个简单的线性模型。

# 定义一个名为 LinearModel 的类,该类继承自 torch.nn.Module
class LinearModel(torch.nn.Module):# 在 __init__ 方法中,创建了一个线性层 self.linear = torch.nn.Linear(1, 1),接受一个输入特征并产生一个输出特征def __init__(self):super(LinearModel, self).__init__()# 实例化了一个具有单个输入和单个输出的线性层。# 这意味着该层会学习一个权重和一个偏差值,用于将输入标量转换成输出标量。self.linear = torch.nn.Linear(1, 1)# 定义了如何通过模型进行前向传播。对于输入 x,它返回经过线性变换后的结果 y_pred。def forward(self, x): y_pred = self.linear(x) return y_pred

在这个模型中,我们创建了一个线性层,它将输入的标量值转换为一个标量输出。

2.3 损失函数和优化器

为了训练模型,我们需要定义损失函数优化器

  • 损失函数衡量了模型预测值与实际值之间的差异
  • 优化器则负责根据损失函数的反馈来更新模型参数
# 创建一个 LinearModel 类的实例
model = LinearModel()
# 均方误差损失函数:torch.nn.MSELoss 计算预测值和真实值之间的均方误差
# size_average=False 控制损失值是否会被平均
criterion = torch.nn.MSELoss(size_average=False)
# 随机梯度下降优化器:torch.optim.SGD 随机梯度下降优化器,通过沿着梯度方向更新参数来最小化损失函数。
# model.parameters() 获取模型的所有可学习参数。LinearModel 中定义了一个线性层,其有两个参数"权重weight"、"偏置bias"。model.parameters()返回这两个参数。
# lr=0.01 学习率(Learning Rate),决定了每次参数更新的步长大小。
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

2.4 训练模型

现在,我们可以开始训练模型了,通过多次迭代来调整模型参数,使其能够更好地拟合数据。

# 训练模型:
# 在 for 循环中迭代执行 1000 次训练周期(epoch)。每一次迭代中:
for epoch in range(1000):# 计算模型对 x_data 的预测 y_predy_pred = model(x_data)# 计算损失 loss,即 y_pred 与实际标签 y_data 之间的差异loss = criterion(y_pred, y_data)# 打印当前的 epoch 数和损失值print(epoch, loss.item())# 清空梯度缓存:# 在PyTorch中,梯度是通过反向传播计算出来的。# 当我们调用 loss.backward() 时,PyTorch会自动计算损失函数关于模型参数的梯度,并将这些梯度存储在每个参数的.grad 属性中。# 如果不显式地清零梯度,那么每次调用loss.backward()都会将新计算出的梯度加上上次计算的结果,导致梯度不正确。optimizer.zero_grad()# 反向传播计算梯度loss.backward()# 在完成一次反向传播计算梯度之后,根据这些梯度更新模型的参数。利用优化器中定义的更新规则,来调整模型的权重和偏置,以期减少损失函数的值。optimizer.step()

在训练过程中,我们通过 loss.backward() 计算损失相对于模型参数的梯度,并通过 optimizer.step() 使用这些梯度来更新模型参数。

2.5 测试模型

训练完成后,我们可以查看模型学习到的权重和偏置,并用它来预测新的输入数据。

#
# 打印出模型的权重 model.linear.weight.item()
print('w = ', model.linear.weight.item())
# 打印出模型的偏置 model.linear.bias.item()
print('b = ', model.linear.bias.item())
#
# 使用训练好的模型预测新的输入 x_test = [[4.0]] 对应的输出值 y_test 并打印出来
x_test = torch.Tensor([[4.0]]) 
y_test = model(x_test) 
print('y_pred = ', y_test.data)

三、模型网络结构及源码

这个模型可以被视为最简单的线性回归模型,其结构可以用以下公式表示:

y = f ( w ∗ x + b ) y=f(w * x + b) y=f(wx+b)

其中:

  • x 是输入数据;
  • y 是预测输出;
  • w 是权重;
  • b 是偏置项;
  • f是激活函数:由于该模型为一个非常简单的线性回归模型,只包含一个线性层,代码实现中并没有使用激活函数,但还是有必要了解一下激活函数,所以这里将其写了出来。
    激活函数的作用是将那些无边界的输入转化成一组良好的,可预测的输出形式。一种常用的激活函数是Sigmoid函数,该激活函数仅输出范围(0,1)之间的数,你可以把它想象成将一组存在于(−∞,+∞)间的数字压缩到(0,1)之间,越大的负数(指绝对值越大)输出后会越接近0,越大的正数输出后会越接近1。

3.1 模型网络结构

模型网络结构也是非常简单,只有一个网络节点。

模型网络结构

3.2 完整源代码

在模型训练过程中,模型通过不断调整权重 w 和偏置 b 来最小化损失函数(均方误差),使得模型的预测值 y_pred 尽可能接近实际标签 y_data
最终完整的可执行源代码如下:

# 案例详细展示了如何使用 PyTorch 框架,从零开始构建一个单输入单输出的线性回归模型。
# 然后通过梯度下降法对模型进行训练,以预测输入值对应的输出值。
# 以下是详细的步骤解析说明:
import torch
# 数据准备:x_data 和 y_data 是两个张量(Tensor),分别代表"输入数据"和对应的"标签数据"。
# x_data 包含了数值 [1.0, 2.0, 3.0],而 y_data 包含了 [2.0, 4.0, 6.0],这表明 y_data 中的每个值都是对应 x_data 值的两倍。
# 因此,我们的目标是训练一个模型,使其能够学习到这种输入与输出之间的映射关系。
x_data = torch.Tensor([[1.0], [2.0], [3.0]])
y_data = torch.Tensor([[2.0], [4.0], [6.0]])# 定义一个名为 LinearModel 的类,该类继承自 torch.nn.Module
class LinearModel(torch.nn.Module):# 在 __init__ 方法中,创建了一个线性层 self.linear = torch.nn.Linear(1, 1),接受一个输入特征并产生一个输出特征def __init__(self):super(LinearModel, self).__init__()# 实例化了一个具有单个输入和单个输出的线性层。# 这意味着该层会学习一个权重和一个偏差值,用于将输入标量转换成输出标量。self.linear = torch.nn.Linear(1, 1)# 定义了如何通过模型进行前向传播。对于输入 x,它返回经过线性变换后的结果 y_pred。def forward(self, x): y_pred = self.linear(x) return y_pred# 创建一个 LinearModel 类的实例
model = LinearModel()
# 均方误差损失函数:torch.nn.MSELoss 计算预测值和真实值之间的均方误差
# size_average=False 控制损失值是否会被平均
criterion = torch.nn.MSELoss(size_average=False)
# 随机梯度下降优化器:torch.optim.SGD 随机梯度下降优化器,通过沿着梯度方向更新参数来最小化损失函数。
# model.parameters() 获取模型的所有可学习参数。LinearModel 中定义了一个线性层,其有两个参数"权重weight"、"偏置bias"。model.parameters()返回这两个参数。
# lr=0.01 学习率(Learning Rate),决定了每次参数更新的步长大小。
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
#
# 训练模型:
# 在 for 循环中迭代执行 1000 次训练周期(epoch)
for epoch in range(1000):# 计算模型对 x_data 的预测 y_predy_pred = model(x_data)# 计算损失 loss,即 y_pred 与实际标签 y_data 之间的差异loss = criterion(y_pred, y_data)# 打印当前的 epoch 数和损失值print(epoch, loss.item())# 清空梯度缓存:# 在PyTorch中,梯度是通过反向传播计算出来的。# 当我们调用 loss.backward() 时,PyTorch会自动计算损失函数关于模型参数的梯度,并将这些梯度存储在每个参数的.grad 属性中。# 如果不显式地清零梯度,那么每次调用loss.backward()都会将新计算出的梯度加上上次计算的结果,导致梯度不正确。optimizer.zero_grad()# 反向传播计算梯度loss.backward()# 在完成一次反向传播计算梯度之后,根据这些梯度更新模型的参数。利用优化器中定义的更新规则,来调整模型的权重和偏置,以期减少损失函数的值。optimizer.step()
#
# 打印出模型的权重 model.linear.weight.item()
print('w = ', model.linear.weight.item())
# 打印出模型的偏置 model.linear.bias.item()
print('b = ', model.linear.bias.item())
#
# 使用训练好的模型预测新的输入 x_test = [[4.0]] 对应的输出值 y_test 并打印出来
x_test = torch.Tensor([[4.0]]) 
y_test = model(x_test) 
print('y_pred = ', y_test.data)

3.3 训练参数及预测结果

模型的训练参数预测结果输出:

w =  1.9996986389160156
b =  0.0006850397912785411
y_pred =  tensor([[7.9995]])

这个模型是一个非常基础的单输入单输出线性回归模型,适用于解决简单的回归问题,例如预测输入标量与输出标量之间的线性关系。尽管模型结构简单,但它为我们提供了一个很好的起点,以了解如何使用 PyTorch 构建和训练模型

四、增加模型节点

增加模型的节点,即增加隐藏层增加隐藏层中的节点数,可以通过修改模型定义来实现。以下是增加隐藏层数增加隐藏层节点数的示例。

4.1 增加隐藏层数

如果我们想增加隐藏层数,可以在模型中添加隐藏层。例如,增加一个隐藏层。

# 定义带有隐藏层的线性模型  
class MultiLayerLinearModel(torch.nn.Module):  def __init__(self):  super(MultiLayerLinearModel, self).__init__()  # 添加一个隐藏层,输入1个特征,输出1个特征  self.hidden = torch.nn.Linear(1, 1)  # 添加一个输出层,输入1个特征,输出1个特征  self.output = torch.nn.Linear(1, 1)  def forward(self, x):  # 通过隐藏层,激活函数可以使用ReLU或其他激活函数  x = torch.relu(self.hidden(x))  # 通过输出层  y_pred = self.output(x)  return y_pred

4.2 增加隐藏层数

如果我们想增加隐藏层的节点数,可以修改隐藏层的输入和输出特征数。例如,将隐藏层的输出特征数从 1 增加到 3

# 定义一个名为 LinearModel 的类,该类继承自 torch.nn.Module  
class MultiLayerLinearModel(torch.nn.Module):  def __init__(self):  super(MultiLayerLinearModel, self).__init__()  # 添加一个隐藏层,输入1个特征,输出3个特征  self.hidden = torch.nn.Linear(1, 3)  # 添加一个输出层,输入3个特征,输出1个特征  self.output = torch.nn.Linear(3, 1)  def forward(self, x):  # 通过隐藏层,激活函数可以使用ReLU或其他激活函数  x = torch.relu(self.hidden(x))  # 通过输出层  y_pred = self.output(x)  return y_pred

4.3 完整代码

以下是完整的代码示例,包括增加隐藏层节点数和增加隐藏层数的情况:

import torch  # 数据准备:x_data 和 y_data 是两个张量(Tensor),分别代表"输入数据"和对应的"标签数据"。  
# x_data 包含了数值 [1.0, 2.0, 3.0],而 y_data 包含了 [2.0, 4.0, 6.0],这表明 y_data 中的每个值都是对应 x_data 值的两倍。  
# 因此,我们的目标是训练一个模型,使其能够学习到这种输入与输出之间的映射关系。  
x_data = torch.Tensor([[1.0], [2.0], [3.0]])  
y_data = torch.Tensor([[2.0], [4.0], [6.0]])  
#  
# 定义一个名为 LinearModel 的类,该类继承自 torch.nn.Module  
class MultiLayerLinearModel(torch.nn.Module):  def __init__(self):  super(MultiLayerLinearModel, self).__init__()  # 添加一个隐藏层,输入1个特征,输出3个特征  self.hidden = torch.nn.Linear(1, 3)  # 添加一个输出层,输入3个特征,输出1个特征  self.output = torch.nn.Linear(3, 1)  # 定义了如何通过模型进行前向传播。  def forward(self, x):  # 通过隐藏层,激活函数可以使用ReLU或其他激活函数  x = torch.relu(self.hidden(x))  # 通过输出层  y_pred = self.output(x)  return y_pred  #  
# 创建一个 MultiLayerLinearModel 类的实例  
model = MultiLayerLinearModel()  
# 均方误差损失函数:torch.nn.MSELoss 计算预测值和真实值之间的均方误差  
# size_average=False 控制损失值是否会被平均  
criterion = torch.nn.MSELoss(size_average=False)  
# 随机梯度下降优化器:torch.optim.SGD 随机梯度下降优化器,通过沿着梯度方向更新参数来最小化损失函数。  
# model.parameters() 获取模型的所有可学习参数。LinearModel 中定义了一个线性层,其有两个参数"权重weight"、"偏置bias"。model.parameters()返回这两个参数。  
# lr=0.01 学习率(Learning Rate),决定了每次参数更新的步长大小。  
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)  
#  
# 训练模型:  
# 在 for 循环中迭代执行 1000 次训练周期(epoch)  
for epoch in range(1000):  # 计算模型对 x_data 的预测 y_pred  y_pred = model(x_data)  # 计算损失 loss,即 y_pred 与实际标签 y_data 之间的差异  loss = criterion(y_pred, y_data)  # 打印当前的 epoch 数和损失值  print(epoch, loss.item())  # 清空梯度缓存:  # 在PyTorch中,梯度是通过反向传播计算出来的。    # 当我们调用 loss.backward() 时,PyTorch会自动计算损失函数关于模型参数的梯度,并将这些梯度存储在每个参数的.grad 属性中。    # 如果不显式地清零梯度,那么每次调用loss.backward()都会将新计算出的梯度加上上次计算的结果,导致梯度不正确。    optimizer.zero_grad()  # 反向传播计算梯度  loss.backward()  # 在完成一次反向传播计算梯度之后,根据这些梯度更新模型的参数。利用优化器中定义的更新规则,来调整模型的权重和偏置,以期减少损失函数的值。  optimizer.step()  
#  
# 打印模型参数  
print('Hidden layer:')  
print('w = ', model.hidden.weight)  
print('b = ', model.hidden.bias)  
print('Output layer:')  
print('w = ', model.output.weight)  
print('b = ', model.output.bias)  # 测试模型  
x_test = torch.Tensor([[4.0]])  
y_test = model(x_test)  
print('y_pred = ', y_test.data)

4.4 训练参数及预测结果

模型的训练参数预测结果输出:

Hidden layer:
w =  Parameter containing:tensor([[0.1732],[1.4368],[-0.9307]], requires_grad=True)
b =  Parameter containing:tensor([ 0.0400, -0.1946,  0.5237], requires_grad=True)
Output layer:
w =  Parameter containing:tensor([[0.0159, 1.3901, 0.5729]], requires_grad=True)
b =  Parameter containing:tensor([0.2699], requires_grad=True)
y_pred =  tensor([[8.0000]])

4.5 模型网络结构

增加隐藏层增加隐藏层中的节点数后的模型网络结构如下图所示。

网络模型

注:
f是激活函数,激活函数用来将那些无边界的输入转化成一组良好的,可预测的输出形式。一种常用的激活函数是Sigmoid函数,该激活函数仅输出范围(0,1)之间的数,你可以把它想象成将一组存在于(−∞,+∞)间的数字压缩到(0,1)之间,越大的负数(指绝对值越大)输出后会越接近0,越大的正数输出后会越接近1。

五、参考

An Introduction to Neural Networks
https://victorzhou.com/blog/intro-to-neural-networks/

PyTorch简单示例:
https://blog.csdn.net/yj13811596648/article/details/106886666

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/458459.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【设计模式系列】代理模式(八)

一、什么是代理模式 代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。代理模式在不直接访问实际对象的情况下,提供了对目标对象的间接访问。通过引入一个代理对象来间接操作实际对…

layui扩展组件之----右键菜单

源码:rightmenu.js layui.define([element], function (exports) {let element layui.element;const $ layui.jquery;let MOD_NAME rightmenu;let RIGHTMENUMOD function () {this.v 1.0.0;this.author raowenjing;};String.prototype.format function () {…

检索引擎Elasticsearch

一.为什么要用Elasticsearch 由于我们在运行我们的项目的时候通常都是将数据存到mysql或者sql serve等数据库中,在进行数据搜索时使用sql 语句 like进行模糊匹配查询,其一:虽然可以查到数据,但是它模糊匹配查询速度较慢&#xff0…

世优科技“AI+空间计算”推动消费行业向智能化升级

人工智能的演进正从初期的技术探索阶段,转向技术应用阶段,在此趋势下,融合了多模态大模型、虚拟现实、空间计算等前沿技术的人工智能应用新方向,展现出了巨大的潜力和商业价值。 10月19日,2024北京朝阳国际灯光节全新…

[C++11] 右值引⽤与移动语义

文章目录 左值和右值左值(Lvalue)右值(Rvalue)区别 左值引⽤和右值引⽤左值引用(Lvalue Reference)右值引用(Rvalue Reference)右值引用的特点 右值引用延长生命周期右值引⽤和移动语…

数据结构——树、二叉树和森林间的转换

前言 介绍 🍃数据结构专区:数据结构 参考 该部分知识参考于《数据结构(C语言版 第2版)》129~130页 🌈每一个清晨,都是世界对你说的最温柔的早安:ૢ(≧▽≦)و✨ 目录 前言 1、基础知识 2…

Matlab 车牌识别技术

1.1设计内容及要求: 课题研究的主要内容是对数码相机拍摄的车牌,进行基于数字图像处理技术的车牌定位技术和车牌字符分割技术的研究与开发,涉及到图像预处理、车牌定位、倾斜校正、字符分割等方面的知识,总流程图如图1-1所示。 图1-1系统总…

《手写Spring渐进式源码实践》实践笔记(第十一章 AOP-基于JDK、Cglib实现对象动态代理)

文章目录 第十一章 基于JDK、Cglib实现对象动态代理背景目标设计实现代码结构类图代理案例解析案例代码运行结果拆解案例 实现步骤 测试事先准备自定义拦截方法测试用例测试结果: 总结 第十一章 基于JDK、Cglib实现对象动态代理 背景 到本章节我们将要从 IOC 的实现…

今日头条APP移动手机端留痕脚本

这两个的脚本目的是什么呢? 很简单,就是批量访问指定用户的首页,在他人访客记录里面留下你的账户信息,可以让对方访问你的头条,概率下会关注你的头条,目的嘛,这个自己细想! 第1个是…

网页上的视频怎么下载下来?三种方法

分享三个简单好用的网页视频下载工具,值得使用! 1.IDM IDM 是一款可以提高下载速度达5倍的工具,同时具有恢复、调度和组织下载的功能。如果由于网络问题或意外的电源中断,程序将恢复未完成的下载。 IDM 还具有一个完全功能的站点…

张驰咨询:六西格玛培训费用,到底值不值得花?

六西格玛作为一种先进的管理理念和统计方法,已经在全球范围内得到了广泛的应用和认可。它旨在通过减少流程变异,提高产品质量和客户满意度,从而为企业带来持续的改进和盈利增长。随着六西格玛理念的普及,越来越多的人和企业开始寻…

spark on kubernetes运行测试

测试环境 ● kubernetes 1.20.15 ● default命名空间 ● spark 3.1.2 ● kubectl 运行架构 构建镜像 配置JAVA_HOME下载spark二进制包spark-3.1.2-bin-hadoop3.2.tgz并解压修改kubernetes/dockerfiles/spark/Dockerfile文件 ARG java_image_tag11-jre-slimFROM openjdk:${j…

HBuilder X 中Vue.js基础使用2(三)

一、条件渲染 1、条件判断 v-if : 表达式返回真值时才被渲染 v-else :表达式返回为假时不被渲染 2、 分支条件判断 v-else-if :使用v-if , v-else-if 和 v-else 来表示其他的条件分支 3、显示隐藏 v-show v-show true 把节点显示 …

持续深化信创布局,途普科技与统信软件完成产品兼容性互认证

近日,由北京途普科技有限公司(以下简称“途普科技”)自主研发的TopGraph图数据库及知识图谱构建平台已成功完成统信服务器操作系统V20的兼容性互认证,标志着途普科技在国产自控技术上又迈出了坚实的一步。 在各项严格的测试环节中…

技术成神之路:设计模式(二十一)外观模式

相关文章:技术成神之路:二十三种设计模式(导航页) 介绍 外观模式(Facade Pattern)是一种结构型设计模式,它为子系统中的一组接口提供一个统一的接口。外观模式定义了一个高层接口,使得子系统更容易使用。 …

XJ02、消费金融|消费金融业务模式中的主要主体

根据所持有牌照类型的不同,消费金融服务供给方主要分为商业银行、汽车金融公司、消费金融公司和小贷公司,不同类型机构定位不同、提供消费金融服务与产品类型也各不相同。此外,互联网金融平台也成为中国消费金融业务最重要的参与方之一,虽其并非持牌金融机构,但借助其流量…

D50【python 接口自动化学习】- python基础之类

day50 init方法 学习日期:20241027 学习目标:类 -- 64 init方法:如何为对象传递参数? 学习笔记: 魔术方法 init方法 class Klass(object):# 定义初始化方法,类实例化时自动进行初始化def __init__(self…

AGI 之 【Dify】 之 Dify 在 Windows 端本地部署调用 Ollama 本地下载的大模型,实现 API 形式进行聊天对话

AGI 之 【Dify】 之 Dify 在 Windows 端本地部署调用 Ollama 本地下载的大模型,实现 API 形式进行聊天对话 目录 AGI 之 【Dify】 之 Dify 在 Windows 端本地部署调用 Ollama 本地下载的大模型,实现 API 形式进行聊天对话 一、简单介绍 二、创建一个聊…

基于SSM+小程序的旅游社交登录管理系统(旅游4)

👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 ​ 本旅游社交小程序功能有管理员和用户。管理员有个人中心,用户管理,每日签到管理,景点推荐管理,景点分类管理,防疫查询管理&a…

洞察前沿趋势!2024深圳国际金融科技大赛——西丽湖金融科技大学生挑战赛技术公开课指南

在当前信息技术与“互联网”深度融合的背景下,金融行业的转型升级是热门话题,创新与发展成为金融科技主旋律。随着区块链技术、人工智能技术、5G通信技术、大数据技术等前沿科技的飞速发展,它们与金融领域的深度融合,正引领着新型…