PyTorch基础

PyTorch基础

0.前提

什么是 PyTorch

PyTorch 是一个 Python 优先的深度学习框架,动态计算图让它比静态图更灵活、更容易调试

⚠️说明:PyTorch更推荐在Linux上学习和使用,并且如果想要结合显卡操作,强烈不推荐在虚拟机上使用。有能力的同学可以给自己的电脑安装双系统。本笔记只记录在Windows上的操作

在此之前需要学会的知识或者环境

  • Python编程基础:PyTorch 主要是用 Python 编写的, 虽然目前也支持C++和JAVA语言,但是现在市面上能以这两个语言编写Torch的教程还很少。

  • 数学基础:了解线性代数、微积分等基础数学知识。本教程不需要精通,如果已经忘记,强烈推荐观看 3Blue1Brown 的课程。

  • 机器学习基础:了解机器学习的基本概念。这些知识点即使不了解,我也会在本笔记中简单介绍。如果想学习比较扎实的基础,推荐周志华的《机器学习》这本书(大家亲切的称他为西瓜书,因为整本书都在教你用机器学习算法如何挑到好吃的西瓜,,,)。

安装pytorch

❗前提:你需要安装python,建议python3

访问 PyTorch 的官方网站,网站提供了一个方便的工具,可以根据你的系统配置(操作系统、包管理器、Python版本以及CUDA版本)推荐安装命令。

PyTorch官方网站工具

❗在这里你能看到CUDA的版本选择,如果你的显卡支持CUDA,那么请选择CUDA版本,否则请选择CPU版本。
# 安装pytorch,torchvision和torchaudio
pip3 install torch torchvision torchaudio

安装cuda

CUDA是英伟达是NVIDIA推出的通用并行计算平台和编程模型,支持多种编程语言。

CUDA Toolkit是NVIDIA提供的一个用于GPU开发的工具包。它可以帮助开发人员使用GPU进行深度学习、机器学习、图像处理等等任务。

CUDA版本与PyTorch版本是有严格的对应关系的,同时根据我本人安装经历,CUDA版本和英伟达显卡驱动版本也是有严格对应关系。

访问 NVIDIA CUDA Toolkit 下载界面,同PyTorch一样,NVIDIA也提供了工具,根据你的系统配置推荐下载的安装包。

NVIDIA CUDA Toolkit 下载界面

下载好之后点击安装包,开始安装。

✔️安装好后,在命令行中运行以下命令,即可查看英伟达的版本。
nvidia-smi.exe

CUDA下载验证

其他

除此之外,还推荐使用PyCharm作为Python的开发IDE

验证基础环境

我们创建一个简单的Python文件,用来检查PyTorch的运行以及对GPU的支持

这个代码你暂时不需要了解他在做什么,不需要做任何修改,可以直接运行


## 在这里引用PyTorch
import torch

## 如果支持CUDA,则使用GPU,否则使用CPU
DEV = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"设备: {DEV}")


print("\n" + "=" * 55)
print("GPU 支持")
print("=" * 55)
if DEV.type == "cuda":
    print(f"GPU: {torch.cuda.get_device_name(0)}")

    wx = torch.randn(100, 200, device="cuda")
    wy = torch.randn(200, 100, device="cuda")
    # 矩阵乘法
    _ = wx @ wy; torch.cuda.synchronize()
else:
    print("未检测到 GPU, CPU 模式运行")
    x = torch.tensor([[1.0, 2.0], [3.0, 4.0]])
    y = torch.tensor([[5.0, 6.0], [7.0, 8.0]])
    print(f"x:\n{x}\ny:\n{y}")
    print(f"x + y:\n{x + y}")

如果你是NVIDIA显卡用户,并且正确安装了CUDA,那么运行结果如下:

设备: cuda
GPU: NVIDIA GeForce RTX 5070 Ti Laptop GPU
tensor([[  5.2766,  11.5421,  -5.2882,  ..., -15.2835, -12.4100,  -9.0720],
        [ 18.3162, -23.5693,  24.4115,  ...,  -6.1360,  24.1747,   3.2343],
        [  0.4944,  21.7948,   2.2534,  ..., -16.5061,  22.3207,  -8.2079],
        ...,
        [ 13.0756,   8.9047, -10.7848,  ..., -11.7192,  -1.8161, -17.7984],
        [-10.8788,  -1.6606,   2.6119,  ...,  22.6208, -27.0059,   8.9193],
        [  1.0328,  -4.5920,  -6.0699,  ..., -14.9712,  -2.0496,   3.2142]],
       device='cuda:0')

如果只使用了CPU计算,那么运行结果如下:

设备: cpu
未检测到 GPU, CPU 模式运行
x:
tensor([[1., 2.],
        [3., 4.]])
y:
tensor([[5., 6.],
        [7., 8.]])
x + y:
tensor([[ 6.,  8.],
        [10., 12.]])

如果正确打印出了以上结果,那么恭喜大家可以继续学习PyTorch了。

1.Pytorch到底可以做什么

或者说深度学习到底可以做什么。简单来说,深度学习可以让电脑像人一样,通过大量例子自己学会做某件事,而不是程序员一条条写死规则。

而PyTorch就是一个深度学习框架,可以快速实现深度学习模型。让你不用从零开始造轮子,直接用现成的零件快速搭出能学习的模型。

传统编程像是给电脑写一本极其详细的操作手册,每一步都规定死。而深度学习更像是给电脑看海量例子,让它自己领悟规律。这个对比的关键在于“规则”和“数据”的角色互换。

我们举个简单的例子:外卖员送餐

北京某区域某时刻的路况信息

这是北京某区域某时刻的路况信息

传统编程是这样的:你给外卖员画了一张地图,上面标好了每一条路,告诉他“从商家出门左拐,走到第二个红绿灯右转,直走三百米看到小区大门进去”。(蓝色路线)

深度学习就不一样了。你没给他画路线,但你给了他过去半年这个区域所有外卖订单的记录:每一单是从哪个店送到哪个小区、走了哪条路、花了多长时间。他拿着这些数据自己研究,慢慢就明白了:“哦,中午十二点这条路特别堵不能走”。以后你给他一个新订单,他没有现成的路线,但他能根据自己从数据里学到的东西,当场判断出一条最优路线。(橙色路线)

基础代码

我们首先使用PyTorch做一个简单的事情

result = a + b

这个看起来很简单,代码写起来也很简单,如果你刚才在上一个章节中阅读了代码,那么你很快就能发现你已经使用过了

import torch

x = torch.tensor(1.0)
y = torch.tensor(2.0)
print(x)
print(y)

print("=====")
result = x + y
print(result)

结果很明显

tensor(1.)
tensor(2.)
=====
tensor(3.)

经过上面的计算,可以将两个张量相加,得到结果。

等等,什么是张量?

2.张量

张量(Tensor)是深度学习中的基础数据结构,你暂时不需要了解他代表什么,你最多只需要了解,他算是一个多维数组,并且Python和PyTorch都提供了相应的API,可以方便的进行张量的创建、运算、保存、加载等等。

如果你对线性代数还有些了解,那么二维张量就可以看作是一个矩阵。

# 创建一个二维张量(矩阵)
# [1.0, 2.0]
# [3.0, 4.0]
x = torch.tensor([[1.0, 2.0], [3.0, 4.0]])

如果你对线性代数有更多的记忆,那么你肯定还记得向量,标量,矩阵乘法这种知识点。

而我们第一张使用的tensor(1.)其实就是一个标量,也就是一个数字。

# 标量
x = torch.tensor(1.0)

# 向量
y = torch.tensor([1.0, 2.0])

i = torch.tensor([[1.0, 2.0], [3.0, 4.0]])
j = torch.tensor([[5.0, 6.0], [7.0, 8.0]])
# 矩阵乘法
print(i@j)

创建张量的方式有很多,可以直接指定值,也可以只指定形状,然后随机生成值。

你甚至可以根据一个张量的形状,来创建另一个张量。

## 大家可以自己运行一下,看看这些创建出来的张量都是什么样子
a = torch.tensor([1, 2, 3, 4, 5])
b = torch.zeros(3, 4)
c = torch.ones(2, 3)
d = torch.randn(2, 3)
e = torch.arange(0, 10, 2)
f = torch.linspace(0, 1, steps=5)
print(f"从列表:   {a}")
print(f"全零 3x4:\n{b}")
print(f"全一 2x3:\n{c}")
print(f"正态随机:\n{d}")
print(f"arange:    {e}")
print(f"linspace:  {f}")
print(f"\n形状: {d.shape}, 类型: {d.dtype}, 设备: {d.device}, 维度数: {d.ndim}")

t = torch.randn(2, 3)
print(f"\nfloat32 -> int32: {t.to(torch.int32).dtype}")
print(f"float32 -> float64: {t.to(torch.float64).dtype}")
⏸️ 如果看到这里累了,可以直接看下一章,等有需求再回来看

张量的其他属性

在上面的例子中,我们可以看到张量的形状,类型,设备,维度数。
这些其实都很好理解

  • 形状:张量的形状大小
  • 类型:张量的数据类型
  • 设备:张量存储的设备
  • 维度数:张量的维数

需要说明的是设备:

  1. CPU:CPU设备,默认设备
  2. GPU:GPU设备

创建张量的时候,可以指定设备,但是默认是CPU设备。

x = torch.tensor([1, 2, 3], device='cpu')
# 如果运行接下来的代码,没有GPU设备,那么会报错
y = torch.tensor([1, 2, 3], device='cuda:0')
print(x.device)
print(y.device)

以下是其他的属性,简单看看就好

tensor = torch.tensor(
    data=[[1, 2, 3], [4, 5, 6]],
    dtype=torch.float32,
    device=torch.device('cuda:0'),
    requires_grad=True
)

# 查看所有主要属性
print("data:", tensor)                     # 张量本身的值
print("shape:", tensor.shape)              # 形状 (2, 3)
print("ndim:", tensor.ndim)                # 维度数 2
print("dtype:", tensor.dtype)              # torch.float32
print("device:", tensor.device)            # cuda:0 或 cpu
print("requires_grad:", tensor.requires_grad)  # 是否需要梯度(用于自动微分)True
print("is_cuda:", tensor.is_cuda)          # 是否在GPU上
print("layout:", tensor.layout)            # torch.strided(默认密集布局)
print("itemsize:", tensor.itemsize)        # 每个元素字节数(float32为4)
print("nbytes:", tensor.nbytes)            # 总字节数 = shape[0]*shape[1]*itemsize = 2 * 3 * 4=24
print("numel:", tensor.numel())            # 元素总数 6
print("stride:", tensor.stride())          # 步长,访问下一个行/列时需要跳过的元素数 (3, 1)
print("grad:", tensor.grad)                # 梯度(目前为None,因为还没反向传播)
print("grad_fn:", tensor.grad_fn)          # 梯度函数(叶子节点为None)
print("T:", tensor.T)                      # 转置后的张量(视图)
print("H:", tensor.H)                      # Hermitian转置(共轭转置,复数才有效)
print("mH:", tensor.mH)                    # 同上
print("real:", tensor.real)                # 实部(实数张量就是自身)
print("imag:", tensor.imag)                # 虚部(实数张量为0)

张量的计算

张量的计算很方便,我们只需要使用Python自带的运算符即可

x = torch.tensor([[1.0, 2.0], [3.0, 4.0]])
y = torch.tensor([[5.0, 6.0], [7.0, 8.0]])
print(f"x:\n{x}\ny:\n{y}")
print(f"x + y:\n{x + y}")
print(f"x + y:\n{x.sum(y)}")
print(f"x * y (逐元素!):\n{x * y}")
print(f"x @ y (矩阵乘法!):\n{x @ y}")
print(f"求和: {x.sum()}, 沿行求和: {x.sum(dim=0)}, 沿列求和: {x.sum(dim=1)}")
print(f"均值: {x.mean()}, 最大值: {x.max()}, 最大值索引: {x.argmax()}")
print(f"\n广播: x + 10 =\n{x + 10}")
print(f"广播: x + [10, 100] =\n{x + torch.tensor([10.0, 100.0])}")
❗注意:张量进行运算时要保证设备同在CPU或者GPU上,否则会报错

在上述的运算代码中,我们可以看到加法是有多种计算方式的,其实还有更多
我们以加法为例,如果想了解其他计算方式,可以自行查询

a = torch.tensor([[1,2,3]])
b = torch.tensor([[10],[20]]) 

# 以加法为例
c = a + b
c = torch.add(a, b)
c = a.add(b)
a.add_(b) 

# 广播
a = torch.tensor([[1,2,3]])      # shape (1,3)
b = torch.tensor([[10],[20]])    # shape (2,1)
c = a + b                        # 结果 shape (2,3)

上述代码中有两点需要说明:

  1. 原地加法:
    这些加法操作中有一个特殊的方法:add_。这个加法与其他的写法不同处在于:add_方法会改变原张量的值,而其他方法不会。比如刚才的a.add_(b)运算,他会直接将计算的结果赋给a,a的值会改变。

    ScreenShot_2026-06-24_211608_748

  2. 广播:
    当两个张量形状不同但在运算时满足广播条件,那么允许这两个向量进行运算。刚才举的例子中,a的形状是(1,3),b的形状是(2,1),虽然两个张量的形状不同,但是a的第一个维度是1,b的维度是2,那么a的维度1会自动扩展为(2,1),两个张量形状相同,那么两个张量就会进行运算。
    ScreenShot_2026-06-24_214419_115

3. 训练一个模型从开始到结束的流程

在谈论模型训练之前,我们先举一个例子:还是外卖员送货:

(接下来是吴恩达的PyTorch课程中的例子)

假设你是一个资深外卖员,本月送货已经迟到了4次,如果再迟到一次,那么这个外卖员就要被裁员了。
现在有一个新的单子派发过来:客户要求30分钟内送往7公里(原例为英里)的位置。那么如果你接了这个单子,会迟到吗?

image-1782308020486

(AI生成的图片)

既然你已经是个资深的外卖员了,那你肯定也经历过不同的外卖配送单,假设你拥有一些历史交付数据:

距离(公里) 时间(分钟)
2.0 11.9
3.0 15.3
4.0 18.8
5.0 22.2
6.0 25.6

具体在坐标轴上,是这样展示出来的:

ScreenShot_2026-06-24_221052_919

很明显,根据公里的变化,时间也程线性变化。那你现在想象一下,7公里大致可以多长时间到达?
我们可以很简单的推测出来,7公里大致耗时在28-30分钟之间
我们也可以预测这几个点的最佳拟合直线,并查看他在x=7上y的位置

image-1782308890986

其中红色为预测直线,i点为x=7在预测直线上的位置,他很明显没有超过30分钟。

⚠️说明:其实这个预测直线是有很大的问题的,因为x坐标代表的是距离,y代表时间,但是在这里明显x和y都走向了负数,而且当公里数为0时也需要花费5分钟,这样也是不合理的。总的来说这个直线很不值得推敲。

现在我们通过简单的猜测以及图示,已经能够预测出我们可以在规定时间内完成这个配送单。

但是

我们这是个PyTorch教程,并不是智力开发教程。接下来,我们开始训练一个模型,来预测这个结果。

了解神经网络

什么?这么快?已经开始学习神经网络了?

其实神经网络并没有我们想的那么复杂,我们简单的通过一个图来看一下一个神经网络的架构:

image-1782310224611

大家可以看到,这是一个简单的神经网络,其中的圆形我们称之为神经元。
神经元分为线性和非线性两种。我们暂时忽略非线性神经元,只考虑线性神经元。

线性神经元

线性神经元,就是我们最基础的计算单元,他内部仅仅是一个具有两组参数的函数:权重w和偏置b

image-1782310633161

再简单一点说,如果我们只有一个输入x,那么这个神经元的输出为:output = wx + b

那么我使用训练数据时,即使用正确的x和output这两个值,并提供给模型,深度学习的训练过程,就是通过不断调整权重w和偏置b,使得预测值和真实值之间的误差最小化。在这个阶段,实际上就是机器学习在“学习”。

image-1782310887589

哇 这样很直观吧

也就是说,权重w和偏置b就是模型的参数

那问题就从如何预测出来这个output值,变成了如何判断哪个w和b是最佳的(哪条线是最佳的)

我们先瞎猜一个:假设权重为1,偏置为10,那么这个神经元的输出为:output = x + 10

image-1782311291564

黄色则是第一次猜出的直线,可以发现当距离为5的时候,这个直线的输出为15,这个输出值与真实值之间的误差为7.2,所以我们可以认为这个直线并不是最佳的,或者说还有优化的空间。

我们再猜一个:假设权重为3.4,偏置为5,那么这个神经元的输出为:output = 3.4x + 5

image-1782311497011

天哪,那是接近的

这两条线已经接近重合了,当距离为5的时候,这个直线的输出为22,这个输出值与真实值之间的误差仅为0.2,所以我们可以认为这个直线快要达到最佳了。

那么我们总结一下, 刚才我们为了让神经元学习,调整了权重w和偏置b,使得预测值和真实值之间的误差最小化。
然而我们是通过直觉来调整的,PyTorch则不一样。

神经元则是以随机的权重和偏置开始,每次参数调整结束后将预测值与结果值进行比较,与结果越远,整体的误差也就越大,随后通过算法(微积分)来不断调整权重和偏置的方向。

这就好像是,我第一次预测结束后获得了一个误差值,那么我条整理一下参数,误差值是增大了还是减小了?发现误差值减小了,我们就确定了调整的方向,从而向正确的方向调整更细微的参数,最终可能会找到最接近最佳的参数(误差值最小的参数)。

训练一个神经网络

即使一个神经网络中仅存在一个线性神经元,也叫一个神经网络。

好,我们来开始训练一个神经网络。

等等,在这之前,我们需要了解,训练神经网络都需要哪些步骤

训练步骤

  • 步骤1:数据获取

训练神经网络,需要一个数据集,数据集一般分为训练集和测试集,训练集用于训练模型,测试集用于评估模型。

假设说我们需要训练一个模型来认识手写的字,那么你就需要获取多组训练图片以及它的对应的字。

image-1782312436690

在上面的例子中,图片就是我们的训练数据,而他对应的数字就是我们的训练标签。这一个照片和一个标签,我们就称为一组数据,多组数据合并起来就是一个数据集。

训练集和测试集的划分,一般使用80%和20%的比例。

但是需要说明的是,有些数据属于脏数据,如果使用脏数据进行训练,那么训练的模型就会有较大的误判率。假设说刚才例子中的外卖员,获取到一个数据组为:距离为5公里,时间为-10分钟。拿着很明显是一个脏数据。类似于这种脏数据需要在这个阶段筛选掉。

  • 步骤2:数据预处理

数据预处理,就是将数据进行清洗、转换、归一化等操作,使得数据符合神经网络的要求。

假设说我们获取到的数据为: 从a地址到b地址,需要20分钟。 很明显这不是脏数据,但是他没有达到训练要求,因为我们希望训练的模型输入的数据为距离,所以需要将“从a地址到b地址”这样的数据进行转换。

  • 步骤3:模型定义

模型定义,就是定义一个神经网络,这个神经网络由多个神经元组成。

在我们现在这个例子中,我们只需要设计单个线性神经元即可

  • 步骤4:模型训练

模型训练,就是将训练集的数据进行训练,并让模型参数(权重w和偏置b)得到最接近训练集的参数。

  • 步骤5:模型评估和调试

模型评估和调试,就是将测试集的数据进行评估,并查看模型的预测结果与真实结果之间的误差。

  • 步骤6:模型部署

多次训练,多次评估,最终得到一个最接近训练集的模型。此时我们就可以将这个模型部署到实际使用中。

代码实现

好的!我们终于可以开始写代码了!

import torch
import torch.nn as nn
import torch.optim as optim

# ====== 数据:距离(公里) → 时间(分钟) ======
x_data = torch.tensor([[2.0], [3.0], [4.0], [5.0], [6.0]])  # 距离
y_data = torch.tensor([[11.9], [15.3], [18.8], [22.2], [25.6]])  # 时间

# ====== 模型:单个线性神经元 y = wx + b ======
model = nn.Sequential(nn.Linear(1, 1))  # 1个输入 → 1个输出(无激活函数 → 线性)
loss_fn = nn.MSELoss()  # 均方误差损失
optimizer = optim.SGD(model.parameters(), lr=0.05)  # SGD 优化器

print("初始参数:")
print(f"  w = {model[0].weight.item():.4f}, b = {model[0].bias.item():.4f}\n")

# ====== 训练 500 次 ======
for epoch in range(500):
    y_pred = model(x_data)  # 前向传播
    loss = loss_fn(y_pred, y_data)  # 计算损失

    optimizer.zero_grad()  # 梯度清零
    loss.backward()  # 反向传播
    optimizer.step()  # 更新参数

    if (epoch + 1) % 50 == 0:
        print(f"Epoch {epoch+1:3d}  loss = {loss.item():.6f}")

# ====== 结果 ======
w, b = model[0].weight.item(), model[0].bias.item()
print(f"\n训练完成 → w = {w:.4f}, b = {b:.4f}")
print(f"公式:时间 = {w:.4f} × 距离 + {b:.4f}")

# 预测一个值试试
test_dist = torch.tensor([[7.0]])
pred = model(test_dist)
print(f"\n预测:距离 7.0 公里 → 时间 {pred.item():.2f} 分钟")

好的,我们目前可以复制上面的代码来运行,但是下面我会一步一步拆开来解释这些操作。

我们来讲解一下:首先我们要了解我们引用了哪些东西

  • torch: 提供pytorch的核心功能
  • nn: 提供神经网络相关的功能
  • optim: 提供优化器的功能(训练神经网络的工具)
数据获取/数据预处理

首先,我们观察上一个章的操作步骤,会发现我们已经省略了 步骤1:数据获取 和 步骤2:数据预处理 。这是因为数据本身已经达到了可以训练的程度,后续可以学习数据的相关操作,但是在这里,我们可以暂时忽略。

那么张量,就成为了我们存储数据集的容器

# ====== 数据:距离(公里) → 时间(分钟) ======
# 需要说明的是,如果张量的数值为小数,则默认dtype为torch.float32
x_data = torch.tensor([[2.0], [3.0], [4.0], [5.0], [6.0]])  # 距离
y_data = torch.tensor([[11.9], [15.3], [18.8], [22.2], [25.6]])  # 时间

在这个例子中,x始终为一个,如果出现多个,比如天气情况,时间段等,可能会出现多个参数。

x_data = torch.tensor([[2.0, 1], [3.0, 0], [4.0, 0], [5.0, 1], [6.0, 1]])  # 距离,是否白天

但是在这个例子中我们暂时用不到

模型定义

接下来,我们开始定义这个模型,我们需要创建神经网络

# ====== 模型:单个线性神经元 y = wx + b ======
model = nn.Sequential(nn.Linear(1, 1))  # 1个输入 → 1个输出(无激活函数 → 线性)
loss_fn = nn.MSELoss()  # 均方误差损失
optimizer = torch.optim.SGD(model.parameters(), lr=0.05)  # SGD 优化器

其中model就是我们定义的神经网络,内部包裹着一个神经元。

下面两个分别为损失函数和优化器:
损失函数具体来说就是计算每次预测和实际的标签之间的损失值的,损失值越大代表预测的参数越不准确。
优化器简单来说就是提供给下一次模型预测参数的算法。

这两部分我们后期会单独讲

模型训练

开始训练!

# ====== 训练 500 次 ======
for epoch in range(500):
    optimizer.zero_grad()  # 梯度清零

    y_pred = model(x_data)  # 前向传播
    loss = loss_fn(y_pred, y_data)  # 计算损失

    loss.backward()  # 反向传播
    optimizer.step()  # 更新参数

    if (epoch + 1) % 50 == 0:
        print(f"Epoch {epoch+1:3d}  loss = {loss.item():.6f}")

好的 这里面就比较复杂了,这里一共循环500次,很明显每次循环共经历了五步,但是实际这五步在上面讲解神经元的时候都已经走过了。我们这次再走一遍:

  1. 梯度清零
    这一步实际上是清理掉上次所有计算的值,防止上次的数据会影响到本次的计算。

  2. 前向传播
    这一步其实就是根据已经存在的权重和偏置,传入x_data,来输出预测的output(y_pred)

  3. 计算损失
    可以看到这个计算损失就是使用了损失函数。通过损失函数可以给当前模型"打分",分数越高则代表损失越大

  4. 反向传播
    这一步就是根据上一步打出的"分数",思考如何调整权重和偏差以减少分数

  5. 更新参数
    上一步偏向于思考,而这一步更偏向于实践。将调整的策略应用于参数上以便于下一次训练。

模型评估和调试

经过500次循环的五步走,后我们得到了最终的模型结果,现在我们来评估一下

# ====== 结果 ======
w, b = model[0].weight.item(), model[0].bias.item()
print(f"\n训练完成 → w = {w:.4f}, b = {b:.4f}")
print(f"公式:时间 = {w:.4f} × 距离 + {b:.4f}")

# 预测一个值试试
test_dist = torch.tensor([[7.0]])
pred = model(test_dist)
print(f"\n预测:距离 7.0 公里 → 时间 {pred.item():.2f} 分钟")

这个时候我们就已经可以打印出来权重w和偏置b了,并且输入7.0,我们可以预测出所需要的时间

那么到此,我们就已经训练出人生中的第一个神经网络了,接下来是我自己训练后的结果输出

初始参数:
  w = 0.2463, b = -0.0089
Epoch  50  loss = 0.672430
Epoch 100  loss = 0.231203
Epoch 150  loss = 0.080161
Epoch 200  loss = 0.028050
Epoch 250  loss = 0.010071
Epoch 300  loss = 0.003867
Epoch 350  loss = 0.001727
Epoch 400  loss = 0.000989
Epoch 450  loss = 0.000734
Epoch 500  loss = 0.000646

训练完成 → w = 3.4345, b = 5.0198
公式:时间 = 3.4345 × 距离 + 5.0198

预测:距离 7.0 公里 → 时间 29.06 分钟

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×