PyTorch 框架使用教程

本教程系统介绍 PyTorch 的基础用法,涵盖框架简介、张量创建与各类操作、自动微分模块,以及利用 PyTorch 构建线性回归模型的完整流程,适合机器学习和深度学习初学者学习与实战。


一、PyTorch 框架简介

1.1 什么是 PyTorch

PyTorch 是一个基于 Python 的开源科学计算与深度学习框架。它将数据封装为张量(Tensor)进行处理,并提供构建、训练和部署机器学习和深度学习模型的灵活、高效工具。

安装

pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple

核心特点

  • 基于 Python 语言的深度学习框架,将数据封装成张量(Tensor)来处理。
  • 提供灵活、高效的工具,用于构建、训练和部署机器学习和深度学习模型。
  • 广泛应用于学术研究和工业界,尤其在计算机视觉、自然语言处理、强化学习等领域表现突出。

1.2 PyTorch 的特点

PyTorch 与 TensorFlow 的区别

  • PyTorch 基于动态计算图,而 TensorFlow 1.x 基于静态计算图(TensorFlow 2.x 已支持动态图)。这使得 PyTorch 在灵活性和调试体验上优于 TensorFlow,尤其是在研究和原型设计中。
  • TensorFlow 2.x(引入 Eager Execution)与 PyTorch 都支持动态图,但 PyTorch 因更直观的编程模式和更好的调试支持,在学术界和部分工业界应用中更流行。

PyTorch 的主要特性:

  • 类似 NumPy 的张量计算:基本数据结构是张量(Tensor),与 NumPy 数组类似,但支持 GPU 加速(CUDA),使模型能在 GPU 上高效运行。
  • 自动微分系统:提供强大的自动微分功能(autograd 模块),可自动计算每个参数的梯度,使梯度计算简洁高效,支持复杂模型和动态计算图。
  • 深度学习库:子模块 torch.nn 用于构建神经网络,内置大量预构建层(全连接层、卷积层、循环神经网络层等)、损失函数(如交叉熵、均方误差)以及优化算法(如 SGD、Adam)。torch.nn.Module 是构建神经网络的基础类。
  • 动态计算图:可在运行时构建和修改模型结构,灵活性高,适合实验和调试。
  • GPU 加速(CUDA 支持):对 NVIDIA CUDA 设备支持良好,通过 tensor.to(device) 可轻松迁移数据和模型。
  • 跨平台支持:支持 CPU、GPU、TPU 等硬件平台及 Linux、Windows、macOS 等系统,支持多 GPU、分布式训练。

1.3 PyTorch 发展历史

  • Torch:由 Ronan Collobert、Clement Farabet 等人开发的早期科学计算框架,提供多维张量操作和科学计算工具。
  • Torch7:Torch 的后续版本,引入 Lua 语言,取得一定成功。随着 PyTorch 普及,Torch 停止维护,Torch7 成为最后一个版本。
  • PyTorch 0.1.0:2016 年 Facebook 人工智能研究院(FAIR)在 Torch 基础上发布 PyTorch 首版,引入更具 Python 风格的设计。
  • PyTorch 0.2.0:首次引入动态图机制,使构建神经网络更灵活,是后期战胜 TensorFlow 的关键机制。
  • PyTorch 1.0.0:2018 年发布的首个稳定版本,引入 Eager 模式,简化模型构建和训练。
  • PyTorch 2.0:引入 torch.compile 加速训练,同时引入 TorchDynamo 取代 torch.jit.tracetorch.jit.script,编译器性能大幅提升,并优化了分布式运行。

在这里插入图片描述


二、张量创建

2.1 什么是张量

张量是 PyTorch 中的核心数据抽象。

  • 张量是元素为同一数据类型的多维矩阵,与 NumPy 数组类似。
  • 张量以"类"的形式封装,运算和处理方法(数值计算、矩阵操作、自动求导)被封装在类中。

在这里插入图片描述

多个二维张量组成三维张量:

在这里插入图片描述

多个三维张量组成四维张量,多个四维张量组成五维张量:

在这里插入图片描述

2.2 基本创建方式

张量数据类型:

在这里插入图片描述

张量默认数据类型是 float32(torch.FloatTensor)

  • torch.tensor(data=, dtype=):根据指定数据创建张量。
import torch                     # 需先安装 torch 模块
import numpy as np


# 1. 创建标量张量
data = torch.tensor(10)
print(data)

# 2. numpy 数组,由于 data 为 float64,张量元素类型也为 float64
data = np.random.randn(2, 3)
data = torch.tensor(data)
print(data)

# 3. 列表,浮点类型默认 float32
data = [[10., 20., 30.], [40., 50., 60.]]
data = torch.tensor(data)
print(data)
  • torch.Tensor(size=):根据形状创建张量,也可创建指定数据的张量。
# 1. 创建 2 行 3 列的张量,默认 dtype 为 float32
data = torch.Tensor(2, 3)
print(data)

# 2. 注意:如果传列表,则创建包含指定元素的张量
data = torch.Tensor([10])
print(data)
data = torch.Tensor([10, 20])
print(data)
  • torch.IntTensor() / torch.FloatTensor():创建指定类型的张量。
# 1. 创建 2 行 3 列、dtype 为 int32 的张量
data = torch.IntTensor(2, 3)
print(data)

# 2. 注意:如果传入元素类型不正确,会自动进行类型转换
data = torch.IntTensor([2.5, 3.3])
print(data)

# 3. 其他类型
data = torch.ShortTensor()   # int16
data = torch.LongTensor()    # int64
data = torch.FloatTensor()   # float32
data = torch.DoubleTensor()  # float64

2.3 线性和随机张量

  • torch.arange(start=, end=, step=):按固定步长生成线性张量。
  • torch.linspace(start=, end=, steps=):按固定元素数量生成线性张量。
# 1. 在指定区间按步长生成 [start, end, step),左闭右开
data = torch.arange(0, 10, 2)
print(data)

# 2. 在指定区间按元素个数生成 [start, end, steps],左闭右闭
# step = (end - start) / (steps - 1)
data = torch.linspace(0, 9, 10)
print(data)
  • torch.randn / rand(size=):创建随机浮点类型张量。
  • torch.randint(low=, high=, size=):创建随机整数类型张量,左闭右开。
  • torch.initial_seed()torch.manual_seed(seed=):随机种子的读取与设置。
# 1. 创建随机张量
data = torch.randn(2, 3)  # 创建 2 行 3 列张量
print(data)
# 查看随机数种子
print('随机数种子:', torch.initial_seed())

# 2. 设置随机数种子
torch.manual_seed(100)
data = torch.randn(2, 3)
print(data)
print('随机数种子:', torch.initial_seed())

2.4 指定值张量

  • torch.zeros(size=)torch.zeros_like(input=):创建全 0 张量。
# 1. 创建指定形状的全 0 张量
data = torch.zeros(2, 3)
print(data)

# 2. 根据张量形状创建全 0 张量
data = torch.zeros_like(data)
print(data)
  • torch.ones(size=)torch.ones_like(input=):创建全 1 张量。
# 1. 创建指定形状的全 1 张量
data = torch.ones(2, 3)
print(data)

# 2. 根据张量形状创建全 1 张量
data = torch.ones_like(data)
print(data)
  • torch.full(size=, fill_value=)torch.full_like(input=, fill_value=):创建全为指定值的张量。
# 1. 创建指定形状、指定值的张量
data = torch.full([2, 3], 10)
print(data)

# 2. 根据张量形状创建指定值的张量
data = torch.full_like(data, 20)
print(data)

2.5 指定元素类型张量

  • data.type(dtype=):转换元素类型。
data = torch.full([2, 3], 10)
print(data.dtype)
# 将 data 元素类型转换为 float64
data = data.type(torch.DoubleTensor)
print(data.dtype)
# 转换为其他类型
# data = data.type(torch.ShortTensor)
# data = data.type(torch.IntTensor)
# data = data.type(torch.LongTensor)
# data = data.type(torch.FloatTensor)
  • data.half / float / double / short / int / long():快捷转换方法。
data = torch.full([2, 3], 10)
print(data.dtype)
# 将 data 元素类型转换为 float64
data = data.double()
print(data.dtype)
# 转换为其他类型
# data = data.short()
# data = data.int()
# data = data.long()
# data = data.float()
```---

## 三、张量类型转换

### 3.1 张量转换为 NumPy 数组

- 使用 `t.numpy()` 可将张量转换为 `ndarray` 数组,但两者**共享内存**,可通过 `copy()` 函数避免共享。

```python
# 1. 将张量转换为 numpy 数组
data_tensor = torch.tensor([2, 3, 4])
data_numpy = data_tensor.numpy()
print(type(data_tensor))
print(type(data_numpy))
# 注意: data_tensor 和 data_numpy 共享内存,修改其一,另一个也会变化
data_numpy[0] = 100
print(data_tensor)
print(data_numpy)

# 2. 拷贝对象避免共享内存
data_tensor = torch.tensor([2, 3, 4])
data_numpy = data_tensor.numpy().copy()
print(type(data_tensor))
print(type(data_numpy))
# 此时不再共享内存,修改其一,另一个不会变化
data_numpy[0] = 100
print(data_tensor)
print(data_numpy)

3.2 NumPy 数组转换为张量

  • torch.from_numpy(ndarray=) 将 ndarray 数组转为张量,默认共享内存,可用 copy() 避免共享。
  • torch.tensor(data=) 将 ndarray 数组转为张量,默认不共享内存。
data_numpy = np.array([2, 3, 4])
# 1. torch.from_numpy(ndarray):numpy 和 tensor 共享内存
data_tensor = torch.from_numpy(data_numpy)
data_tensor[0] = 100
print(data_tensor)
print(data_numpy)

# 2. torch.tensor(ndarray):numpy 和 tensor 不共享内存
data_numpy = np.array([2, 3, 4])
data_tensor = torch.tensor(data_numpy)
data_tensor[0] = 100
print(data_tensor)
print(data_numpy)

3.3 提取标量张量的数值

  • 只有一个元素的张量,可用 item() 函数提取该值。
# 当张量只含一个元素时,可通过 item() 提取出该值
data = torch.tensor([30,])
print(data.item())
data = torch.tensor(30)
print(data.item())

四、张量数值计算

4.1 基本运算

加减乘除取负号:

  • 运算符:+ - * /
  • 方法:add(other=)submuldivneg
  • 原地版本:add_(other=) 等(带下划线的版本会直接修改原数据)
data = torch.randint(0, 10, [2, 3])
print(data)
# 1. 不修改原数据
new_data = data.add(10)  # 等价于 new_data = data + 10
print(new_data)
# 2. 直接修改原数据(带下划线的函数修改原数据本身)
data.add_(10)  # 等价于 data += 10
print(data)
# 3. 其他函数
print(data.sub(100))
print(data.mul(100))
print(data.div(100))
print(data.neg())

4.2 点乘(哈达玛积)

点乘(Hadamard)也称元素级乘积,指相同形状张量对应位置的元素相乘,用 mul 和运算符 * 实现。

在这里插入图片描述

data1 = torch.tensor([[1, 2], [3, 4]])
data2 = torch.tensor([[5, 6], [7, 8]])
# 方式一
data = torch.mul(data1, data2)
print(data)
# 方式二
data = data1 * data2
print(data)

4.3 矩阵乘法

矩阵乘法要求第一个矩阵 shape 为 (n, m),第二个为 (m, p),乘积 shape 为 (n, p)。

  • 运算符 @ 用于两个矩阵相乘。
  • torch.matmul(input=, other=) 对两矩阵形状无严格限定:对 shape 不同的张量,最后几个维度必须符合矩阵乘法规则。
data1 = torch.tensor([[1, 2], [3, 4], [5, 6]])
data2 = torch.tensor([[5, 6], [7, 8]])
# 方式一
data3 = data1 @ data2
print("data3-->", data3)
# 方式二
data4 = torch.matmul(data1, data2)
print("data4-->", data4)

五、张量运算函数

  • tensor.mean(dim=):平均值
  • tensor.sum(dim=):求和
  • tensor.min / max(dim=):最小值 / 最大值
  • tensor.pow(exponent=):幂次方 x^n
  • tensor.sqrt():平方根
  • tensor.exp():指数 e^x
  • tensor.log(dim=):以 e 为底的对数

dim=0 按列计算,dim=1 按行计算。

import torch


data = torch.randint(0, 10, [2, 3], dtype=torch.float64)
print(data)
# 1. 均值(tensor 必须为 Float 或 Double 类型)
print(data.mean())
print(data.mean(dim=0))  # 按列计算均值
print(data.mean(dim=1))  # 按行计算均值
# 2. 总和
print(data.sum())
print(data.sum(dim=0))
print(data.sum(dim=1))
# 3. 平方
print(torch.pow(data, 2))
# 4. 平方根
print(data.sqrt())
# 5. 指数 e^n 次方
print(data.exp())
# 6. 对数
print(data.log())   # 以 e 为底
print(data.log2())
print(data.log10())

六、张量索引操作

操作张量时,经常需要获取或修改某些元素,这里介绍 torch 中的索引操作。

import torch


# 随机生成数据
data = torch.randint(0, 10, [4, 5])
print(data)

# 1. 简单行、列索引
print(data[0])      # 第 0 行
print(data[:, 0])   # 第 0 列

# 2. 列表索引(整数索引)
# 返回 (0, 1)、(1, 2) 两个位置的元素
print(data[[0, 1], [1, 2]])
# 返回 0、1 行的 1、2 列(共 4 个元素)
print(data[[[0], [1]], [1, 2]])

# 3. 范围索引
print(data[:3, :2])  # 前 3 行的前 2 列
print(data[2:, :2])  # 第 2 行到末尾的前 2 列

# 4. 布尔索引
print(data[data[:, 2] > 5])  # 第三列大于 5 的行
print(data[:, data[1] > 5])  # 第二行大于 5 的列

# 5. 多维索引
data = torch.randint(0, 10, [3, 4, 5])
print(data)
print(data[0, :, :])  # 取第 0 个二维矩阵
print(data[:, 0, :])  # 取每个矩阵的第 0 行
print(data[:, :, 0])  # 取每个矩阵的第 0 列
```---

## 七、张量形状操作

> 张量形状操作是对张量维度进行变换的一系列操作。张量的形状描述了每个维度上元素的数量。

### 7.1 reshape

> 在保证张量数据不变的前提下,改变数据的维度。

```python
import torch

data = torch.tensor([[10, 20, 30], [40, 50, 60]])
# 1. 使用 shape 属性或 size 方法获取张量形状
print(data.shape, data.shape[0], data.shape[1])
print(data.size(), data.size(0), data.size(1))

# 2. 用 reshape 修改张量形状
new_data = data.reshape(1, 6)
print(new_data.shape)

7.2 squeeze 和 unsqueeze

squeeze:删除指定位置形状为 1 的维度,不指定位置则删除所有形状为 1 的维度,实现降维

unsqueeze:在指定位置添加形状为 1 的维度,实现升维

mydata1 = torch.tensor([1, 2, 3, 4, 5])
print('mydata1--->', mydata1.shape, mydata1)
mydata2 = mydata1.unsqueeze(dim=0)
print('在 0 维度上扩展维度:', mydata2, mydata2.shape)  # 1*5
mydata3 = mydata1.unsqueeze(dim=1)
print('在 1 维度上扩展维度:', mydata3, mydata3.shape)  # 5*1
mydata4 = mydata1.unsqueeze(dim=-1)
print('在 -1 维度上扩展维度:', mydata4, mydata4.shape) # 5*1
mydata5 = mydata4.squeeze()
print('压缩维度:', mydata5, mydata5.shape)  # 5

7.3 transpose 和 permute

transpose 用于交换两个指定维度;permute 可按任意顺序重新排列维度。

import numpy as np
data = torch.tensor(np.random.randint(0, 10, [3, 4, 5]))
print('data shape:', data.size())
# 1. 交换 1 和 2 维度
mydata2 = torch.transpose(data, 1, 2)
print('mydata2.shape--->', mydata2.shape)
# 2. 将 data 改为 (4, 5, 3),需多次变换
mydata3 = torch.transpose(data, 0, 1)
mydata4 = torch.transpose(mydata3, 1, 2)
print('mydata4.shape--->', mydata4.shape)
# 3. 用 permute 直接改为 (4, 5, 3)
mydata5 = torch.permute(data, [1, 2, 0])
print('mydata5.shape--->', mydata5.shape)
mydata6 = data.permute([1, 2, 0])
print('mydata6.shape--->', mydata6.shape)

7.4 view 和 contiguous

view 也可修改张量形状,但只能用于连续张量。当张量底层数据在内存中的存储顺序与其逻辑顺序不一致(如经过 transpose 或 permute 处理后),就不能用 view,需先调用 contiguous() 转为连续张量。

data = torch.tensor([[10, 20, 30], [40, 50, 60]])
print('data--->', data, data.shape)
# 1. 判断张量是否连续
print(data.is_contiguous())  # True
# 2. view
mydata2 = data.view(3, 2)
print('mydata2--->', mydata2, mydata2.shape)
print('mydata2.is_contiguous()--->', mydata2.is_contiguous())
# 3. transpose 后 —— 不连续
mydata3 = torch.transpose(data, 0, 1)
print('mydata3--->', mydata3, mydata3.shape)
print('mydata3.is_contiguous()--->', mydata3.is_contiguous())
# 4. 先 contiguous 再 view
print(mydata3.contiguous().is_contiguous())
mydata4 = mydata3.contiguous().view(2, 3)
print('mydata4--->', mydata4.shape, mydata4)
```## 八、张量拼接操作

> 张量拼接操作用于组合来自不同来源或经过不同处理的数据。

### 8.1 cat / concat

> 沿现有维度连接一系列张量。所有输入张量除指定拼接维度外,其他维度必须匹配。

```python
import torch

data1 = torch.randint(0, 10, [1, 2, 3])
data2 = torch.randint(0, 10, [1, 2, 3])
print(data1)
print(data2)
# 1. 按 0 维度拼接
new_data = torch.cat([data1, data2], dim=0)
print(new_data)
print(new_data.shape)
# 2. 按 1 维度拼接
new_data = torch.cat([data1, data2], dim=1)
print(new_data)
print(new_data.shape)
# 3. 按 2 维度拼接
new_data = torch.cat([data1, data2], dim=2)
print(new_data)
print(new_data.shape)

8.2 stack

在一个新维度上连接一系列张量,会新增一个维度,且所有输入张量的形状必须完全相同。

import torch

data1 = torch.randint(0, 10, [2, 3])
data2 = torch.randint(0, 10, [2, 3])
print(data1)
print(data2)
# 1. 在 0 维度上拼接
new_data = torch.stack([data1, data2], dim=0)
print(new_data, new_data.shape)  # (2, 2, 3)
# 2. 在 1 维度上拼接
new_data = torch.stack([data1, data2], dim=1)
print(new_data, new_data.shape)  # (2, 2, 3)
# 3. 在 2 维度上拼接
new_data = torch.stack([data1, data2], dim=2)
print(new_data, new_data.shape)  # (2, 3, 2)

九、自动微分模块

自动微分就是自动计算梯度值,即计算导数。

  • 什么是梯度:对函数求导得到的值就是梯度。
  • 梯度下降法:一种求最优梯度值的方法,使损失函数的值最小。
  • 梯度相关概念
    • 对函数求导得到的值就是梯度(数值理解)。
    • 梯度就是上山下山最快的方向(方向理解)。
    • 在平面内,梯度就是某一点的斜率。
    • 反向传播传播的是梯度。反向传播利用链式法则不断从后向前求导,求出的值就是梯度。
    • 链式法则中,梯度相乘,就是梯度传播。

训练神经网络时最常用的算法是反向传播。PyTorch 内置了 torch.autograd 微分模块,支持任意计算图的自动梯度计算。

在这里插入图片描述

9.1 梯度基本计算

  • PyTorch 不支持向量张量对向量张量的求导,只支持标量张量对向量张量的求导。
  • 计算梯度:y.backward(),y 需要是标量。
  • 获取 x 点的梯度值:x.grad,会累加上一次的梯度值。
  • 标量张量梯度计算
x = torch.tensor(10, requires_grad=True, dtype=torch.float32)
print("x-->", x)

y = 2 * x ** 2
print("y-->", y)
print(y.grad_fn)

# y 是标量,可直接用 backward,无需 sum()
# y'|(x=10) = (2*x**2)'|(x=10) = 4x|(x=10) = 40
y.sum().backward()
print("x 的梯度值是:", x.grad)
  • 向量张量梯度计算
x = torch.tensor([10, 20], requires_grad=True, dtype=torch.float32)
print("x-->", x)

y = 2 * x ** 2
print("y-->", y)

# x 和 y 都是向量,不能直接求导,需将 y 先转换成标量:y.sum()
# y'|(x=10) = 40, y'|(x=20) = 80
y.sum().backward()
print("x.grad-->", x.grad)
```### 9.2 梯度下降法求最优解

- 梯度下降法公式:`w = w - r * grad`(r 是学习率,grad 是梯度值)
- 清空上一次的梯度值:`x.grad.zero_()`

```python
# 求 y = x**2 + 20 的极小值点,并输出 y 取最小值时 x 的值
x = torch.tensor(10, requires_grad=True, dtype=torch.float32)

y = x ** 2 + 20
print('开始 权重 x 初始值:%.6f  y:%.6f' % (x, y))

for i in range(1, 1001):
    # 正向计算
    y = x ** 2 + 20
    # 梯度清零(grad 属性会累加历史梯度值)
    if x.grad is not None:
        x.grad.zero_()
    # 反向传播
    y.sum().backward()
    # 梯度更新(x.data 修改原内存数据,前后内存空间一致)
    x.data = x.data - 0.01 * x.grad

    if i % 100 == 0:
        print('次数:%d 权重 x: %.6f, 0.01*x.grad:%.6f y:%.6f' % (i, x, 0.01 * x.grad, y))

print('x:', x, x.grad, 'y 最小值:', y)

9.3 梯度计算注意点

  • 不能将需要自动微分的张量直接转换成 numpy 数组,会报错。可通过 detach() 方法解决。
x1 = torch.tensor([10, 20], requires_grad=True, dtype=torch.float64)
# 以下代码会报错:RuntimeError: Can't call numpy() on Tensor that requires grad.
# print(x1.numpy())

# 通过 detach() 产生新张量,作为叶子结点
x2 = x1.detach()
# x1 和 x2 共享数据,但 x2 不会自动微分
print(x1.requires_grad)  # True
print(x2.requires_grad)  # False
print(x1.data)
print(x2.data)
print(id(x1.data))
print(id(x2.data))

# 将 x2 转换为 numpy 数组
print(x2.numpy())

9.4 自动微分模块应用

import torch

# 输入张量 2*5
x = torch.ones(2, 5)
# 目标值 2*3
y = torch.zeros(2, 3)
# 设置权重和偏置的初始值
w = torch.randn(5, 3, requires_grad=True)
b = torch.randn(3, requires_grad=True)
# 设置网络输出值
z = torch.matmul(x, w) + b  # 矩阵乘法
# 设置损失函数并计算损失
loss = torch.nn.MSELoss()
loss = loss(z, y)
# 自动微分
loss.backward()
# 打印 w, b 的梯度
print("W 的梯度:", w.grad)
print("b 的梯度:", b.grad)

十、PyTorch 构建线性回归模型

使用 PyTorch 构建线性回归模型,一般分为四个步骤:

  1. 准备训练集数据
  2. 构建要使用的模型
  3. 设置损失函数和优化器
  4. 模型训练

在这里插入图片描述

使用的 API:

  • nn.MSELoss():平方损失函数
  • data.DataLoader:数据加载器
  • optim.SGD:优化器
  • nn.Linear:假设函数(线性层)
import torch
from torch.utils.data import TensorDataset
from torch.utils.data import DataLoader
from torch import nn
from torch import optim
from sklearn.datasets import make_regression
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False


def create_dataset():
    x, y, coef = make_regression(
        n_samples=100, n_features=1, noise=10,
        coef=True, bias=14.5, random_state=0
    )
    x = torch.tensor(x)
    y = torch.tensor(y)
    return x, y, coef


def train():
    x, y, coef = create_dataset()
    dataset = TensorDataset(x, y)
    dataloader = DataLoader(dataset=dataset, batch_size=16, shuffle=True)
    model = nn.Linear(in_features=1, out_features=1)
    criterion = nn.MSELoss()
    print("w 和 b-->", list(model.parameters()))
    print("w-->", model.weight)
    print("b-->", model.bias)
    optimizer = optim.SGD(params=model.parameters(), lr=1e-2)

    epochs = 100
    epoch_loss = []
    total_loss = 0.0
    train_sample = 0

    for _ in range(epochs):
        for train_x, train_y in dataloader:
            y_pred = model(train_x.type(torch.float32))
            loss = criterion(y_pred, train_y.reshape(-1, 1).type(torch.float32))
            total_loss += loss.item()
            train_sample += 1
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        epoch_loss.append(total_loss / train_sample)

    print(model.weight)
    print(model.bias)

    # 绘制损失变化曲线
    plt.plot(range(epochs), epoch_loss)
    plt.title('损失变化曲线')
    plt.grid()
    plt.show()

    # 绘制拟合直线
    plt.scatter(x, y)
    x_line = torch.linspace(x.min(), x.max(), 1000)
    y1 = torch.tensor([v * model.weight + model.bias for v in x_line])
    y2 = torch.tensor([v * coef + 14.5 for v in x_line])
    plt.plot(x_line, y1, label='训练')
    plt.plot(x_line, y2, label='真实')
    plt.grid()
    plt.legend()
    plt.show()


if __name__ == '__main__':
    train()

在这里插入图片描述

在这里插入图片描述


以上就是 PyTorch 框架的基础使用教程,包含张量创建、类型转换、数值计算、索引与形状操作、拼接、自动微分以及线性回归实战。希望这份教程能帮助你快速上手 PyTorch!

更多推荐