目录

PyTorch-入门学习

PyTorch 入门学习


PyTorch 定义

PyTorch 是一个基于 Python 深度学习框架 ,由 Facebook(现 Meta)的 AI 研究团队开发并维护。它专注于 深度学习张量计算 , 它将数据封装成张量(Tensor)来进行处理。PyTorch 中的张量就是元素为同一种数据

类型的多维矩阵。在 PyTorch 中,张量以 “类” 的形式封装起来,对张量的一些运算、处理的方法被封装在类中。

Pytorch的安装:

清华镜像

pip install torch==2.0.1 -i

其他的镜像源:

阿里云镜像

豆瓣镜像

中科大镜像


核心作用

  1. 张量计算(Tensor Computations)

    PyTorch 提供高效的 Tensor 库(类似 NumPy),支持 GPU 加速,能够处理高维数组的数学运算(如矩阵乘法、卷积等),是构建神经网络的数学基础。

  2. 自动微分(Autograd)

    通过 autograd 模块,PyTorch 可以自动计算张量的梯度(导数),这是训练神经网络的核心功能(如反向传播)。

  3. 动态计算图(Dynamic Computation Graph)

    与 TensorFlow 的静态图不同,PyTorch 使用 动态图机制 (即 “Define-by-Run”),允许在代码运行时动态构建计算图。这使得调试更直观,灵活性更高,尤其适合研究场景。

  4. 深度学习模型构建

    提供 torch.nn 模块,包含预定义的神经网络层(如全连接层、卷积层、RNN 等),简化了复杂模型的搭建过程。

  5. 部署与生产化

    支持通过 TorchScriptONNX 格式将模型导出到生产环境(如移动端、服务器端),并与 C++ 无缝集成。


应用场景

  • 学术研究 :PyTorch 的灵活性和易用性使其成为学术界的主流工具,大量论文代码基于 PyTorch 实现。
  • 自然语言处理(NLP) :如 Transformer、BERT 等模型的实现。
  • 计算机视觉(CV) :图像分类、目标检测、生成对抗网络(GAN)等。
  • 强化学习 :与 OpenAI Gym 等工具结合,训练智能体。
  • 工业原型开发 :快速迭代和部署模型。

Pytorch 基本语法

1. 张量的创建
import torch
import numpy as np

"""
创建张量的方式
• torch.tensor 根据指定数据创建张量
• torch.Tensor 根据形状创建张量, 其也可用来创建指定数据的张量
"""
# 1.torch.tensor() 根据指定数据创建张量
# 0维张量:标量(scalar)
print(torch.tensor(10))
# 1维张量:向量(vector)
print(torch.tensor([10,10]))
# 2维张量:矩阵(matrix)
print(torch.tensor([[10,10],[10,10],[10,10]]))
# 多维张量
print(torch.tensor([[[10,10],[10,10],[10,10]]]))

# numpy 数组, 由于 data 为 float64, 下面代码也使用该类型
data_np=np.random.rand(2,3)
print(data_np)
print(torch.tensor(data_np))

data =[[10.,20,30],[20,30,40]]
print(data)
print(torch.tensor(data))

#2.torch.Tensor() 根据指定形状创建张量,也可以用来创建指定数据的张量
#创建2行3列的张量, 默认 dtype 为 float32
data = torch.Tensor(2, 3)
print(data)
# 注意: 如果传递列表, 则创建包含指定元素的张量
print(torch.Tensor([2]))
print(torch.Tensor([[2, 3, 4], [5, 6, 7]]))

"""
创建线性和随机张量
• torch.arrange() 和 torch.linspace() 创建线性张量
• torch.randn() 创建随机张量
"""
#创建线性
# 1. 在指定区间按照步长生成元素 [start, end, step)
data = torch.arange(0, 10, 2)
print(data)
# 2. 在指定区间按照元素个数生成 [start, end, num]
data = torch.linspace(0, 11, 10)
print(data)

#torch.randn() 创建随机张量
# 1. 创建随机张量
data = torch.randn(2, 3) # 创建2行3列张量
print(data)

"""
创建01张量
• torch.zeros() 创建全0张量
• torch.ones() 创建全1张量
• torch.full() 创建全为指定值张量
"""
#创建0、1、指定值张量
# 1. 创建指定形状全0张量
data = torch.zeros(2, 3)
print(data)
# 2. 创建指定形状全1张量
# torch.ones()创建全1张量
data = torch.ones(2, 3)
print(data)
# 3. 创建指定形状指定值的张量
# torch.full()创建全为指定值张量
data = torch.full([2, 3], 10)
print(data)

"""
张量元素类型转换
data.type(torch.DoubleTensor) 
• data.double()
"""
#张量的类型转换
#data.type(torch.DoubleTensor)
data = torch.full([2, 3], 10)
print(data.dtype)
# 将 data 元素类型转换为 float64 类型
data = data.type(torch.DoubleTensor)
print(data.dtype)
# 转换为其他类型
data = data.type(torch.IntTensor)
data = data.type(torch.LongTensor)
data = data.type(torch.FloatTensor)

# data.double()
data = torch.full([2, 3], 10)
print(data.dtype)
# 将 data 元素类型转换为 float64 类型
data = data.double()
print(data.dtype)
# 转换为其他类型
data = data.int()
data = data.long()
data = data.float()
2. 张量的类型转换
import numpy as np
import torch

"""
张量转换为NumPy数组
• data_tensor.numpy()
"""
#使用Tensor.numpy()函数可以将张量转换为ndarray数组
# 1. 将张量转换为 numpy 数组
data_tensor = torch.tensor([2, 3, 4])
# 使用张量对象中的 numpy 函数进行转换
data_numpy = data_tensor.numpy()
print(type(data_tensor))
print(type(data_numpy))
print(data_numpy)

"""
NumPy数组转换为张量
• 使用 from_numpy 可以将 ndarray 数组转换为 Tensor。torch.from_numpy(data_numpy)
• 使用 torch.tensor 可以将 ndarray 数组转换为 Tensor。torch.tensor(data_numpy)
"""
#使用from_numpy()可以将ndarray数组转换为Tensor
data_numpy = np.array([2, 3, 4])
# 将 numpy 数组转换为张量类型
# 1. from_numpy
# 2. torch.tensor(ndarray)
data_tensor = torch.from_numpy(data_numpy)
print(data_tensor)
print(data_numpy)

# 使用torch.tensor()可以将ndarray数组转换为Tensor。
data_numpy = np.array([2, 3, 4])
data_tensor = torch.tensor(data_numpy)
print(data_tensor)
print(data_numpy)

"""
标量张量和数字转换
• data.item()
"""
# 当张量只包含一个元素时, 可以通过 item() 函数提取出该值
data = torch.tensor([30,])
print(data.item())
data = torch.tensor(30)
print(data.item())
3. 张量数值计算

张量基本运算

import torch

"""
张量基本运算
加减乘除取负号:
• add、sub、mul、div、neg等函数
• add_、sub_、mul_、div_、neg_等函数(其中带下划线的版本会修改原数据)
"""
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())

点乘运算

点乘指(Hadamard)的是两个同维数组对应位置的元素相乘,使用

mul 和运算符 * 实现。

https://i-blog.csdnimg.cn/direct/119fbe6557e848fb8ef93085c7e8a372.png

"""
张量的点乘运算
• 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)

乘法运算

数组乘法运算要求第一个数组 shape: (n, m),第二个数组 shape: (m, p), 两个数组乘法运算 shape 为: (n, p)。

  1. 运算符 @ 用于进行两个矩阵的乘积运算

  2. torch.matmul 中输入的 shape 不同的张量, 对应的维度必须符合数组乘法的运算规则

"""
矩阵乘法运算
• 运算符@用于进行两个矩阵的乘法运算
• torch.matmul 对应的维度必须符合矩阵运算规则
"""
# 乘法运算
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)
4. 张量运算函数
import torch

"""
张量运算函数
Sum,mean,sqrt,pow,exp,log等
"""

data = torch.randint(0, 10, [2, 3], dtype=torch.float64)
print(data)
# 1. 计算均值
# 注意: tensor 必须为 Float 或者 Double 类型
print(data.mean())
# 2. 计算总和
print(data.sum())
# 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())
5. 张量索引操作

索引操作

在操作张量时,经常需要去获取某些元素就进行处理或者修改操作,我们需要了解在torch中的索引操作。

import torch

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

"""
• 简单行列索引的使用
"""
print(data[0])
print(data[:, 0])

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

"""
• 范围索引的使用
"""
# 前3行的前2列数据
print(data[:3, :2])
# 第2行到最后的前2列数据
print(data[2:, :2])

"""
• 多维索引的使用
"""
data = torch.randint(0, 10, [3, 4, 5])
print(data)
# 获取0轴上的第一个数据
print(data[0, :, :])
# 获取1轴上的第一个数据
print(data[:, 0, :])
# 获取2轴上的第一个数据
print(data[:, :, 0])
6. 张量形状操作

reshape()函数

reshape 函数可以在保证张量数据不变的前提下改变数据的维度,将其转换成指定的形状。

"""
1.reshape 函数可以在保证张量数据不变的前提下改变数
据的维度
"""
data = torch.tensor([[10, 20, 30], [40, 50, 60]])
# 1. 使用 shape 属性或者 size 方法都可以获得张量的形状
print(data.shape)
print(data.size)
# 2. 使用 reshape 函数修改张量形状
new_data = data.reshape(1, 6)
print(new_data)
print(new_data.shape)

squeeze()和unsqueeze()函数

squeeze 函数删除形状为 1 的维度(降维),unsqueeze 函数添加形状为1的维度(升维)。

"""
2.squeeze 和 unsqueeze 函数可以用来减少或者增加维
"""
mydata1 = torch.tensor([1, 2, 3, 4, 5])
print('mydata1--->', mydata1.shape, mydata1) # 一个普通的数组 1维数据
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) #1*5

transpose()和permute()函数

transpose 函数可以实现交换张量形状的指定维度, 例如: 一个张量的形状为 (2, 3, 4) 可以通过 transpose 函数把 3 和4 进行交换, 将张量的形状变为 (2, 4, 3) 。 permute 函数可以一次交换更多的维度。

"""
3.transpose 函数可以实现交换张量形状的指定维度, 
permute 可以一次交换更多的维度
"""
data = torch.tensor(np.random.randint(0, 10, [3, 4, 5]))
print(data)
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)
# 3-1 方法1
mydata5 = torch.permute(data, [1, 2, 0])
print('mydata5.shape--->', mydata5.shape)
# 3-2 方法2
mydata6 = data.permute([1, 2, 0])
print('mydata6.shape--->', mydata6.shape)

view()和contiguous()函数

view 函数也可以用于修改张量的形状,只能用于存储在整块内存中的张量。在 PyTorch 中,有些张量是由不同的数据块组成的,它们并没有存储在整块的内存中,view 函数无法对这样的张量进行变形处理。

"""
4.view 函数也可以用于修改张量的形状, 但是它要求被转
换的张量内存必须连续,所以一般配合 contiguous 函数使
"""
# 1 若要使用view函数, 需要使用contiguous() 变成连续以后再使用view函数
# 2 判断张量是否使用整块内存
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)
7. 张量拼接操作

torch.cat()

torch.cat()函数可以将两个张量根据指定的维度拼接起来,不改变维度数

import torch
"""
1.cat()函数可以将张量按照指定的维度拼接起来
"""
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.shape)
# 2. 按1维度拼接
new_data = torch.cat([data1, data2], dim=1)
print(new_data.shape)
# 3. 按2维度拼接
new_data = torch.cat([data1, data2], dim=2)
print(new_data.shape)
8. 自动微分模块

训练神经网络时,最常用的算法就是反向传播。在该算法中,参数(模型权重)会根据损失函数关于对应

参数的梯度进行调整。为了计算这些梯度,PyTorch内置了名为 torch.autograd 的微分引擎。它支持任

意计算图的自动梯度计算。

https://i-blog.csdnimg.cn/direct/54739e319eb8475ca03855f3fd58b2dc.png

使用 backward 方法、grad 属性来实现梯度的计算和访问。

import torch


"""
1. 当X为标量时梯度的计算
"""
def test01():
    x = torch.tensor(5)
    # 目标值
    y = torch.tensor(0.)
    # 设置要更新的权重和偏置的初始值
    w = torch.tensor(1., requires_grad=True, dtype=torch.float32)
    b = torch.tensor(3., requires_grad=True, dtype=torch.float32)
    # 设置网络的输出值
    z = x * w + b  # 矩阵乘法
    # 设置损失函数,并进行损失的计算
    loss = torch.nn.MSELoss()
    loss = loss(z, y)
    # 自动微分
    loss.backward()
    # 打印 w,b 变量的梯度
    # backward 函数计算的梯度值会存储在张量的 grad 变量中
    print("W的梯度:", w.grad)
    print("b的梯度", b.grad)
test01()

"""
2. 当X为矩阵时梯度的计算
"""
def test02():
    # 输入张量 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 变量的梯度
    # backward 函数计算的梯度值会存储在张量的 grad 变量中
    print("W的梯度:", w.grad)
    print("b的梯度", b.grad)
test02()
9. 案例-线性回归案例

线性回归 :一种用于建立输入特征(X)与连续型输出(y)之间线性关系的监督学习模型。

模型公式

https://i-blog.csdnimg.cn/direct/83f5fb61906a4992bd904259b7d981c6.png

  • w:权重(斜率),控制每个特征的影响力
  • b:偏置(截距),调整整体偏移

目标 :找到最佳的 w 和 b,使预测值最接近真实值。


损失函数: 用于衡量模型预测值与真实值之间的差异。

在线性回归中,常用的损失函数是均方误差(MSE),即所有样本预测值与真实值差的平方的平均值。

均方误差(MSE)公式

https://i-blog.csdnimg.cn/direct/36fb621e3f5943bf91678c07d4eb1b56.png


梯度下降: 是一种优化算法,用于找到损失函数的最小值。通过计算损失函数关于参数的梯度(导数),然后沿着梯度的反方向更新参数,逐步逼近最小值。

参数更新公式

https://i-blog.csdnimg.cn/direct/240f098d1c884e1fb1dc9ba943e4d12a.png

梯度计算(以MSE为例)

https://i-blog.csdnimg.cn/direct/6dc2cee29e2544958c0144f51817f1a1.png

  • 关键参数

    • 学习率(ηη) :控制步长,过大易震荡,过小收敛慢
    • 迭代次数 :决定更新轮次

线性回归,损失函数和梯度下降,三者的协同工作流程

  1. 初始化参数 :随机设置 ww 和 bb 的初始值
  2. 前向传播 :计算预测值 y^=wX+by^​=wX+b
  3. 损失计算 :通过MSE评估预测误差
  4. 梯度计算 :求损失对 ww 和 bb 的偏导数
  5. 参数更新 :沿负梯度方向调整 ww 和 bb
  6. 重复2-5步 :直到损失收敛或达到最大迭代次数

实例演示(房价预测)

场景 :用房屋面积(xx)预测房价(yy)

  • 数据
    面积(㎡)房价(万元)
    80320
    100400
    120480

步骤

  1. 假设模型: https://i-blog.csdnimg.cn/direct/a7503d409bc24135ba7d26ec93ec64e2.png

  2. 初始化:设 w=3, b=50

  3. 预测值:

    • 第一样本: https://i-blog.csdnimg.cn/direct/5660296e36ec424495130eeb0765a0be.png
  4. 计算损失:

    https://i-blog.csdnimg.cn/direct/1340478123af4e5aa9789d7528ce01ad.png

  5. 计算梯度:

    https://i-blog.csdnimg.cn/direct/9d2fdeaa1640406b843245ff7da5b3e7.png

  6. 更新参数(设 η=0.0001η=0.0001):

    https://i-blog.csdnimg.cn/direct/4c93b42149c348c2a7c919dd9dd3e5ff.png


在pytorch中进行模型构建的整个流程一般分为四个步骤:

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

代码案例

import torch
from torch.utils.data import TensorDataset # 构造数据集对象
from torch.utils.data import DataLoader # 数据加载器
from torch import nn # nn模块中有平方损失函数和假设函数
from torch import optim # 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=1.5,random_state=0)
    x = torch.tensor(x)
    y = torch.tensor(y)
    return x,y,coef

# 构造数据集
x, y, coef = create_dataset()
# 构造数据集对象
dataset = TensorDataset(x, y)
# 构造数据加载器
# dataset=:数据集对象
# batch_size=:批量训练样本数据
# shuffle=:样本数据是否进行乱序
dataloader = DataLoader(dataset=dataset, batch_size=16, shuffle=True)
# 构造模型
# in_features指的是输入张量的大小size
# out_features指的是输出张量的大小size
model = nn.Linear(in_features=1, out_features=1)

# 损失和优化器
# 构造平方损失函数
criterion = nn.MSELoss()
# 构造优化函数
optimizer = optim.SGD(params=model.parameters(), lr=1e-2)

epochs = 100
# 损失的变化
loss_epoch = []
total_loss=0.0
train_sample=0.0
for _ in range(epochs):
    for train_x, train_y in dataloader:
        # 将一个batch的训练数据送入模型
        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 += len(train_y)
        # 梯度清零
        optimizer.zero_grad()
        # 自动微分(反向传播)
        loss.backward()
        # 更新参数
        optimizer.step()
    # 获取每个batch的损失
    loss_epoch.append(total_loss/train_sample)

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

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