新手必看:PyTorch从安装到第一个模型 – wiki基地


新手必看:PyTorch从安装到第一个模型

引言:踏入深度学习的奇妙世界

在当今人工智能浪潮中,深度学习无疑是最激动人心的领域之一。从智能语音助手到自动驾驶汽车,再到个性化推荐系统,深度学习技术正以前所未有的速度改变着我们的生活。而PyTorch,作为Facebook AI Research(FAIR)开发的一个开源机器学习库,以其“Pythonic”的风格、动态计算图(Dynamic Computational Graph)的灵活性以及强大的GPU加速能力,迅速成为研究人员和开发者构建、训练深度学习模型的热门选择。

对于初学者而言,面对一个全新的框架,往往会感到无从下手。别担心!本文将带你一步步穿越PyTorch的迷雾,从最基础的环境搭建开始,到理解其核心概念,再到亲手搭建并训练你的第一个深度学习模型。读完本文,你将对PyTorch有一个全面而扎实的理解,为未来更深入的学习打下坚实的基础。

我们将涵盖以下几个核心章节:
第一章:环境搭建与PyTorch安装
第二章:PyTorch核心概念:Tensor与Autograd
第三章:构建你的第一个神经网络模型
第四章:训练神经网络的核心要素
第五章:实战:从数据到模型训练(以线性回归为例)
第六章:进阶之路与学习资源

准备好了吗?让我们开始这段深度学习的旅程!


第一章:环境搭建与PyTorch安装

在开始编写任何PyTorch代码之前,我们首先需要为它创建一个干净、稳定的运行环境。推荐使用Anaconda或Miniconda进行环境管理,这能有效避免不同项目间的库冲突。

A. Anaconda/Miniconda的安装

  1. 下载与安装:
    访问Anaconda官网(https://www.anaconda.com/products/distribution)或Miniconda官网(https://docs.conda.io/en/latest/miniconda.html),根据你的操作系统选择对应的Python 3.x版本进行下载和安装。Miniconda是Anaconda的轻量级版本,只包含conda、Python和一些核心包,适合需要节省磁盘空间的用户。
    安装过程中,请务必勾选“Add Anaconda to my PATH environment variable”(添加到环境变量)的选项,或者在安装完成后手动配置。

  2. 创建虚拟环境:
    打开终端(Windows用户打开Anaconda Prompt),创建一个名为pytorch_env的虚拟环境,并指定Python版本(例如3.9):
    bash
    conda create -n pytorch_env python=3.9

    这条命令会创建一个新的、独立的Python环境。

  3. 激活虚拟环境:
    创建完成后,每次开始PyTorch开发前,都需要激活这个环境:
    bash
    conda activate pytorch_env

    你的终端提示符会显示当前所处的环境名称(例如(pytorch_env)),表示你已成功进入该环境。

B. PyTorch的安装

PyTorch的安装通常通过其官方网站提供的命令进行,官方网站会根据你的系统、CUDA版本等生成最适合的安装命令。

  1. 访问PyTorch官网:
    打开浏览器,访问 https://pytorch.org/get-started/locally/

  2. 选择你的配置:
    在页面上,你需要根据以下选项进行选择:

    • PyTorch Build: 通常选择Stable(稳定版)。
    • Your OS: 你的操作系统(Linux, Mac, Windows)。
    • Package: 包管理器(Conda推荐,Pip次之)。
    • Language: 编程语言(Python)。
    • CUDA: 这是最关键的一步。
      • 如果你有NVIDIA显卡且支持CUDA,请选择对应的CUDA版本(例如CUDA 11.8)。你需要确保你的NVIDIA驱动程序与所选的CUDA版本兼容。你可以通过在终端运行nvidia-smi来查看你的CUDA驱动版本。
      • 如果你没有NVIDIA显卡或不想使用GPU加速,请选择CPU。这将使PyTorch在CPU上运行,速度会慢很多,但对于初学者和小型项目来说完全足够。
  3. 复制并执行安装命令:
    根据你的选择,官网会生成一条conda installpip install命令。例如:

    – 使用CUDA(推荐有NVIDIA显卡的用户):
    “`bash
    conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia

    或者如果使用pip

    pip install torch torchvision torchaudio –index-url https://download.pytorch.org/whl/cu118

    ``
    请注意,
    pytorch-cuda=11.8中的11.8`需要与你系统安装的CUDA版本一致或兼容。如果你的系统没有安装CUDA Toolkit,这条命令会自动安装PyTorch所需的CUDA运行时库。

    – 仅使用CPU(没有NVIDIA显卡或不希望GPU加速的用户):
    “`bash
    conda install pytorch torchvision torchaudio cpuonly -c pytorch

    或者如果使用pip

    pip install torch torchvision torchaudio –index-url https://download.pytorch.org/whl/cpu

    ``
    将生成的命令粘贴到已激活
    pytorch_env`的终端中,然后回车执行。Conda会自动解决依赖并安装所有必要的包。

  4. 验证安装:
    安装完成后,在激活的pytorch_env环境中打开Python交互式解释器:
    bash
    python

    然后输入以下命令:
    python
    import torch
    print(torch.__version__)
    print(torch.cuda.is_available()) # 如果你安装了CUDA版本,这里应该返回True
    # 如果torch.cuda.is_available()返回True,你可以尝试创建一个CUDA张量
    if torch.cuda.is_available():
    x = torch.zeros(1).cuda()
    print(x)

    如果没有报错,并且输出了PyTorch版本信息,torch.cuda.is_available()返回了正确的值,那么恭喜你,PyTorch已经成功安装并准备就绪!

C. 其他常用库的安装

在深度学习项目中,我们通常还会用到一些其他辅助库:
* NumPy: Python科学计算的基础库,常用于数据预处理。
* Matplotlib: 强大的绘图库,用于结果可视化。
* Scikit-learn: 包含多种机器学习算法和数据处理工具。
pytorch_env环境下安装它们:
bash
pip install numpy matplotlib scikit-learn


第二章:PyTorch核心概念:Tensor与Autograd

PyTorch的强大之处在于其灵活的Tensor操作和自动微分(Autograd)系统。理解这两个核心概念是掌握PyTorch的关键。

A. Tensor(张量)

Tensor是PyTorch中最基本的数据结构,它是一个N维数组,类似于NumPy的ndarray,但Tensors可以利用GPU进行加速计算。

  1. 创建Tensor:
    “`python
    import torch
    import numpy as np

    1. 直接从Python列表或NumPy数组创建

    data = [[1, 2],[3, 4]]
    x_data = torch.tensor(data)
    print(“From list:\n”, x_data)

    np_array = np.array(data)
    x_np = torch.from_numpy(np_array)
    print(“From NumPy:\n”, x_np)

    2. 创建特定形状的Tensor

    填充0

    x_zeros = torch.zeros(2, 3)
    print(“Zeros:\n”, x_zeros)

    填充1

    x_ones = torch.ones(2, 3)
    print(“Ones:\n”, x_ones)

    随机值 (0到1之间均匀分布)

    x_rand = torch.rand(2, 3)
    print(“Random (uniform):\n”, x_rand)

    随机值 (标准正态分布)

    x_randn = torch.randn(2, 3)
    print(“Random (normal):\n”, x_randn)

    创建一个未初始化的Tensor (其内容取决于内存状态)

    x_empty = torch.empty(2, 3)
    print(“Empty:\n”, x_empty)

    3. 仿照另一个Tensor的属性创建 (形状, 数据类型, 设备)

    x_likes_zeros = torch.zeros_like(x_data)
    print(“Zeros like x_data:\n”, x_likes_zeros)
    “`

  2. Tensor的属性:
    Tensor有三个重要属性:shape(形状)、dtype(数据类型)、device(设备)。
    python
    tensor = torch.rand(3, 4)
    print(f"Shape: {tensor.shape}")
    print(f"Data type: {tensor.dtype}")
    print(f"Device: {tensor.device}") # 默认是CPU

  3. Tensor的操作:
    Tensor支持类似于NumPy的各种操作。

    • 算术运算:
      “`python
      tensor_a = torch.tensor([[1, 2], [3, 4]])
      tensor_b = torch.tensor([[5, 6], [7, 8]])

      加法

      print(“Addition:\n”, tensor_a + tensor_b)
      print(“Addition (torch.add):\n”, torch.add(tensor_a, tensor_b))

      乘法 (逐元素)

      print(“Element-wise multiplication:\n”, tensor_a * tensor_b)
      print(“Element-wise multiplication (torch.mul):\n”, torch.mul(tensor_a, tensor_b))

      矩阵乘法

      matrix_mul = tensor_a.matmul(tensor_b)

      或者使用 @ 运算符

      matrix_mul_op = tensor_a @ tensor_b
      print(“Matrix multiplication:\n”, matrix_mul)
      “`

    • 索引和切片:
      python
      tensor = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
      print("First row:", tensor[0])
      print("Last column:", tensor[:, -1])
      print("Middle element:", tensor[1, 1])

    • 改变形状:
      “`python
      tensor = torch.ones(4, 4)
      print(“Original tensor shape:”, tensor.shape) # torch.Size([4, 4])

      view() 共享底层数据,如果内存是连续的

      reshaped_view = tensor.view(16)
      print(“Reshaped with view:”, reshaped_view.shape) # torch.Size([16])

      reshape() 更通用,不一定共享底层数据,但通常会尝试

      reshaped_reshape = tensor.reshape(2, 8)
      print(“Reshaped with reshape:”, reshaped_reshape.shape) # torch.Size([2, 8])

      增加/减少维度

      expanded_tensor = tensor.unsqueeze(0) # 在0维增加一个维度
      print(“Expanded tensor shape:”, expanded_tensor.shape) # torch.Size([1, 4, 4])

      squeezed_tensor = expanded_tensor.squeeze(0) # 移除0维的维度
      print(“Squeezed tensor shape:”, squeezed_tensor.shape) # torch.Size([4, 4])
      “`

    • NumPy与Tensor的转换:
      “`python
      np_array = np.ones(5)
      torch_tensor = torch.from_numpy(np_array) # NumPy到Tensor
      print(“NumPy to Tensor:”, torch_tensor)

      torch_to_np = torch_tensor.numpy() # Tensor到NumPy
      print(“Tensor to NumPy:”, torch_to_np)
      ``
      **注意:** 从NumPy数组创建的Tensor和通过
      .numpy()`方法转换回NumPy数组的Tensor会共享底层内存。修改其中一个,另一个也会改变。

  4. CUDA加速:
    如果你的机器有NVIDIA GPU且已正确安装CUDA版PyTorch,你可以将Tensor移动到GPU上进行计算:
    python
    if torch.cuda.is_available():
    device = torch.device("cuda")
    x = torch.ones(5, device=device) # 直接在GPU上创建
    y = torch.ones(5).to(device) # 将CPU Tensor移动到GPU
    z = x + y # 在GPU上执行加法
    print("GPU Tensor:", z)
    # 将结果移回CPU进行后续处理或可视化
    z_cpu = z.to("cpu")
    print("CPU from GPU:", z_cpu)
    else:
    print("CUDA is not available. Using CPU.")

    重要: 在进行计算时,所有参与运算的Tensor必须位于同一个设备上(同在CPU或同在同一个GPU)。

B. Autograd(自动微分)

Autograd是PyTorch的魔法所在,它能够自动计算Tensors上的所有操作的梯度。这是训练神经网络(通过反向传播算法)的核心机制。

  1. 工作原理:
    当我们在Tensor上执行操作时,PyTorch会构建一个计算图(Computational Graph)。图中的节点是Tensor,边是操作。当我们对某个Tensor(通常是损失函数)调用.backward()方法时,Autograd会遍历这个计算图,并使用链式法则自动计算图中所有requires_grad=True的Tensor的梯度。

  2. requires_grad=True
    默认情况下,Tensor的梯度不会被跟踪。要让PyTorch跟踪某个Tensor上的操作并计算其梯度,需要设置requires_grad=True
    python
    x = torch.tensor(2.0, requires_grad=True) # 标量,初始值2.0
    y = x**2 + x + 1 # y = 2^2 + 2 + 1 = 7.0
    print("y:", y)

    这里x是需要求导的变量,所以requires_grad设为True

  3. 计算梯度:loss.backward()
    现在我们有了y,我们想计算yx的导数。在深度学习中,这通常是损失函数对模型参数的导数。
    python
    y.backward() # 对y执行反向传播,计算梯度
    print("dy/dx:", x.grad) # dy/dx = 2x + 1。当x=2时,2*2 + 1 = 5。

    执行y.backward()后,x.grad属性将存储y相对于x的梯度。

  4. 梯度累积:
    默认情况下,backward()会累积梯度。这意味着如果你多次调用backward(),梯度会叠加到.grad属性中。因此,在每次反向传播之前,通常需要使用optimizer.zero_grad()(或者手动tensor.grad.zero_())来清零之前的梯度。
    “`python
    x = torch.tensor(2.0, requires_grad=True)
    y = x**2
    y.backward()
    print(“First backward (dy/dx = 2x):”, x.grad) # 4.0

    z = x**3
    z.backward()
    print(“Second backward (dz/dx = 3x^2, total = 4 + 12):”, x.grad) # 4.0 + 12.0 = 16.0
    “`

  5. torch.no_grad()
    在模型评估或推理阶段,我们通常不需要计算梯度,这可以节省内存和计算资源。可以使用torch.no_grad()上下文管理器来禁用梯度计算。
    python
    x = torch.tensor(3.0, requires_grad=True)
    with torch.no_grad():
    y = x * 2
    print("y:", y) # 6.0
    print("y.requires_grad:", y.requires_grad) # False, 因为在no_grad()中计算

    对于模型参数更新,通常使用优化器的step()方法,它会自动处理梯度的更新。


第三章:构建你的第一个神经网络模型

在PyTorch中,构建神经网络模型主要通过torch.nn模块实现。nn.Module是所有神经网络模块的基类。

A. 什么是神经网络?

简单来说,神经网络是一种受生物神经系统启发的计算模型,它由大量相互连接的节点(神经元)组成,这些节点分层排列。每个连接都有一个权重,每个神经元有一个偏置项和一个激活函数。通过调整这些权重和偏置,神经网络可以从数据中学习复杂的模式和关系。

一个基本的神经网络包括:
* 输入层: 接收原始数据。
* 隐藏层: 执行大部分计算,提取特征。可以有一个或多个。
* 输出层: 产生最终的预测结果。

B. torch.nn 模块

torch.nn模块提供了构建神经网络所需的所有核心组件。

  1. nn.Module基类:
    所有你自定义的神经网络模型都应该继承自nn.Module。它封装了模型的所有参数(权重和偏置),并提供了管理它们的方法。
    继承nn.Module时,你需要实现两个主要方法:

    • __init__(self): 在这里定义模型的各个层和其他组件。
    • forward(self, x): 在这里定义数据在模型中如何从输入层流向输出层(即前向传播逻辑)。
  2. nn.Linear(线性层/全连接层):
    这是神经网络中最基本的层之一。它对输入数据执行线性变换:y = Wx + b,其中W是权重矩阵,x是输入,b是偏置向量。
    python
    import torch.nn as nn
    linear_layer = nn.Linear(in_features=10, out_features=1)
    # 输入特征数是10,输出特征数是1。
    # 例如,一个包含10个特征的数据样本会通过这个层输出一个标量。
    print(linear_layer)
    # Linear(in_features=10, out_features=1, bias=True)

  3. 激活函数:
    激活函数引入了非线性,使得神经网络能够学习和表示更复杂的模式。如果网络中只有线性层,那么无论堆叠多少层,整个网络仍然只是一个线性模型。
    常用的激活函数有:

    • nn.ReLU() (Rectified Linear Unit): f(x) = max(0, x)。最常用,计算简单,缓解梯度消失问题。
    • nn.Sigmoid(): f(x) = 1 / (1 + exp(-x))。将输出压缩到(0, 1)之间,常用于二分类的输出层。
    • nn.Tanh() (Hyperbolic Tangent): f(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x))。将输出压缩到(-1, 1)之间。
    • nn.Softmax(): 常用于多分类任务的输出层,将一组数值转换为概率分布(和为1)。
  4. nn.Sequential容器:
    nn.Sequential是一个方便的容器,可以按顺序堆叠多个层和模块。当你的模型只是简单地将各个层堆叠起来时,使用它会非常简洁。
    python
    model_sequential = nn.Sequential(
    nn.Linear(10, 5), # 10个输入特征,5个输出特征
    nn.ReLU(),
    nn.Linear(5, 1) # 5个输入特征,1个输出特征
    )
    print(model_sequential)

C. 定义一个简单的模型

现在,让我们来定义一个简单的多层感知机(MLP)模型。假设我们要对一个包含4个特征的输入进行二分类,输出一个概率值。

“`python
import torch
import torch.nn as nn
import torch.nn.functional as F # 通常用于函数式的激活函数或损失函数

检查是否有GPU,并设置设备

device = “cuda” if torch.cuda.is_available() else “cpu”
print(f”Using {device} device”)

class SimpleNeuralNetwork(nn.Module):
def init(self):
super(SimpleNeuralNetwork, self).init() # 调用父类构造函数
# 定义模型的各个层
self.linear1 = nn.Linear(in_features=4, out_features=16) # 输入层到第一隐藏层
self.relu = nn.ReLU() # 激活函数
self.linear2 = nn.Linear(in_features=16, out_features=1) # 第二隐藏层到输出层
# 对于二分类,输出层通常不直接加激活函数,而是在损失函数中处理(如BCEWithLogitsLoss)
# 或者在forward中手动加sigmoid,这里我们先不加,留给损失函数处理logits

def forward(self, x):
    # 定义数据的前向传播路径
    x = self.linear1(x)
    x = self.relu(x)
    logits = self.linear2(x) # 输出未经激活处理的logits
    return logits

实例化模型并将其移动到指定设备

model = SimpleNeuralNetwork().to(device)
print(model)

打印模型中的所有可学习参数(权重和偏置)

print(“\nModel parameters:”)
for name, param in model.named_parameters():
if param.requires_grad:
print(f”Layer: {name}, Size: {param.size()}”)

尝试用一个随机输入通过模型

假设批量大小为1,输入有4个特征

random_input = torch.randn(1, 4).to(device)
output_logits = model(random_input)
print(“\nOutput logits for random input:”, output_logits)

如果是二分类,通常会在输出后应用sigmoid函数得到概率

output_probability = torch.sigmoid(output_logits)
print(“Output probability (after sigmoid):”, output_probability)
``
这段代码定义了一个包含两个线性层和一个ReLU激活函数的简单神经网络。
forward`方法描述了数据如何通过这些层进行转换。最后,我们将模型实例移动到GPU(如果可用),并测试了一个随机输入。


第四章:训练神经网络的核心要素

构建完模型只是第一步,要让模型具备学习能力,我们还需要定义如何评估其表现、如何更新其内部参数。这涉及到数据准备、损失函数和优化器。

A. 数据准备:Dataset与DataLoader

在PyTorch中,数据的处理通常涉及到torch.utils.data.Datasettorch.utils.data.DataLoader

  1. Dataset
    Dataset是一个抽象类,用于表示数据集。你需要自定义一个继承自Dataset的类,并实现两个方法:

    • __len__(self): 返回数据集中的样本总数。
    • __getitem__(self, idx): 根据索引idx获取一个样本(特征和标签)。
      这使得数据能够被按需加载,而不是一次性全部加载到内存中。
  2. DataLoader
    DataLoader负责将Dataset中的数据批次化(batching)、打乱(shuffling)和并行加载(num_workers)。这对于高效训练非常重要。
    “`python
    from torch.utils.data import Dataset, DataLoader

    假设我们有一个非常简单的数据集 (通常你会从文件加载或生成更复杂的数据)

    class CustomDataset(Dataset):
    def init(self, data_features, data_labels):
    self.features = torch.tensor(data_features, dtype=torch.float32)
    self.labels = torch.tensor(data_labels, dtype=torch.float32).unsqueeze(1) # 增加一个维度,匹配模型输出

    def __len__(self):
        return len(self.features)
    
    def __getitem__(self, idx):
        return self.features[idx], self.labels[idx]
    

    示例数据

    X_data = np.random.rand(100, 4) # 100个样本,每个4个特征
    y_data = np.random.randint(0, 2, 100) # 100个标签,0或1

    创建Dataset实例

    my_dataset = CustomDataset(X_data, y_data)

    创建DataLoader实例

    batch_size = 16
    data_loader = DataLoader(my_dataset, batch_size=batch_size, shuffle=True)

    迭代DataLoader

    for batch_idx, (features, labels) in enumerate(data_loader):
    print(f”Batch {batch_idx}: Features shape {features.shape}, Labels shape {labels.shape}”)
    if batch_idx == 0:
    break # 只看第一个批次
    “`

B. 损失函数(Loss Function / Criterion)

损失函数衡量模型预测值与真实值之间的差异。在训练过程中,我们的目标是最小化这个损失。torch.nn模块提供了多种常用的损失函数。

  • 回归任务:

    • nn.MSELoss() (Mean Squared Error Loss):计算预测值和真实值之间差的平方的均值。
      python
      loss_fn = nn.MSELoss()
      pred = torch.tensor([[1.0], [2.0]])
      target = torch.tensor([[1.5], [2.1]])
      loss = loss_fn(pred, target) # ( (1-1.5)^2 + (2-2.1)^2 ) / 2
      print("MSE Loss:", loss) # 0.13
  • 分类任务:

    • nn.CrossEntropyLoss(): 常用于多分类问题。它结合了LogSoftmaxNLLLoss(负对数似然损失),可以直接接收模型的原始输出(logits)和类别索引作为目标。
      python
      loss_fn = nn.CrossEntropyLoss()
      # 假设有3个类别,batch_size=2
      # 模型输出的logits (未经过softmax)
      pred_logits = torch.randn(2, 3) # batch_size=2, num_classes=3
      # 真实标签 (类别索引)
      target_labels = torch.tensor([0, 2]) # 第一个样本属于类别0,第二个样本属于类别2
      loss = loss_fn(pred_logits, target_labels)
      print("Cross Entropy Loss:", loss)
    • nn.BCEWithLogitsLoss(): 常用于二分类问题。它结合了SigmoidBCELoss(二元交叉熵损失),可以直接接收模型的原始输出(logits)。
      python
      loss_fn = nn.BCEWithLogitsLoss()
      # 假设batch_size=2,模型输出一个logit
      pred_logits = torch.randn(2, 1) # batch_size=2, output_dim=1
      # 真实标签 (0或1)
      target_labels = torch.tensor([[0.0], [1.0]])
      loss = loss_fn(pred_logits, target_labels)
      print("BCEWithLogits Loss:", loss)

C. 优化器(Optimizer)

优化器的作用是根据损失函数计算出的梯度,更新模型的权重和偏置,以最小化损失。torch.optim模块提供了各种优化算法。

  • optim.SGD() (Stochastic Gradient Descent): 随机梯度下降。是最基本的优化器,通常需要手动调整学习率(lr),可以添加momentum来加速收敛。
  • optim.Adam() (Adaptive Moment Estimation): 自适应矩估计。一种更高级的优化器,通常效果更好,对学习率的调整不那么敏感。是目前最常用的优化器之一。

如何使用优化器:
1. 实例化优化器: 将模型的参数和学习率传递给优化器。
python
import torch.optim as optim
# model是前面定义的神经网络实例
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 或者
# optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

model.parameters()会返回一个迭代器,包含模型中所有requires_grad=True的参数。

  1. 训练循环中的步骤:
    在每个训练批次中,优化器会执行以下三个关键步骤:

    • optimizer.zero_grad(): 清除上一步计算的梯度。PyTorch默认会累积梯度,所以在每次反向传播前需要清零。
    • loss.backward(): 执行反向传播,计算所有可学习参数的梯度。
    • optimizer.step(): 根据计算出的梯度和优化器规则更新模型的参数。

第五章:实战:从数据到模型训练(以线性回归为例)

现在,让我们把前面学到的知识综合起来,从生成数据开始,构建一个最简单的线性回归模型并进行训练。

A. 定义问题与生成数据

我们将尝试拟合一个简单的线性关系:y = 2x + 1 + noise
“`python
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt

1. 检查GPU并设置设备

device = “cuda” if torch.cuda.is_available() else “cpu”
print(f”Using {device} device for training.”)

2. 生成模拟数据

随机生成100个x值

X_numpy = np.random.rand(100, 1) * 10 # 0到10之间的随机数

真实y值,加上一些随机噪声

y_numpy = 2 * X_numpy + 1 + np.random.randn(100, 1) * 2 # y = 2x + 1 + 噪声

将NumPy数组转换为PyTorch Tensor,并移动到指定设备

X_train = torch.from_numpy(X_numpy).float().to(device)
y_train = torch.from_numpy(y_numpy).float().to(device)

print(f”X_train shape: {X_train.shape}, y_train shape: {y_train.shape}”)
``
这里我们生成了100个数据点,
X_train是输入特征,y_train`是对应的标签。

B. 定义模型

对于线性回归,我们只需要一个简单的线性层。

“`python

3. 定义线性回归模型

class LinearRegressionModel(nn.Module):
def init(self):
super(LinearRegressionModel, self).init()
# nn.Linear(输入特征维度, 输出特征维度)
# 我们的X_train是(100, 1),所以输入特征维度是1
# 我们的y_train是(100, 1),所以输出特征维度是1
self.linear = nn.Linear(1, 1)

def forward(self, x):
    return self.linear(x)

实例化模型并移动到设备

model = LinearRegressionModel().to(device)
print(“\nOur Linear Regression Model:”)
print(model)
“`

C. 定义损失函数和优化器

线性回归通常使用均方误差(MSE)作为损失函数,优化器我们选择Adam。

“`python

4. 定义损失函数和优化器

criterion = nn.MSELoss() # 均方误差损失
optimizer = optim.Adam(model.parameters(), lr=0.01) # Adam优化器,学习率为0.01

print(f”\nLoss Function: {criterion}”)
print(f”Optimizer: {optimizer}”)
“`

D. 训练循环

训练的核心是一个循环,在每个epoch(遍历整个数据集一次)和每个批次中执行以下步骤:
1. 前向传播: 将数据输入模型,得到预测值。
2. 计算损失: 比较预测值和真实值,计算损失。
3. 梯度清零: 清除之前计算的梯度。
4. 反向传播: 计算损失对模型参数的梯度。
5. 参数更新: 根据梯度更新模型参数。

“`python

5. 训练模型

num_epochs = 1000 # 训练1000个epoch
losses = [] # 用于记录每个epoch的损失

print(“\nStarting Training…”)
for epoch in range(num_epochs):
# 前向传播:得到模型预测值
outputs = model(X_train)

# 计算损失
loss = criterion(outputs, y_train)

# 梯度清零:清空上一步的梯度
optimizer.zero_grad()

# 反向传播:计算当前batch中所有可训练参数的梯度
loss.backward()

# 参数更新:根据梯度更新模型参数(W和b)
optimizer.step()

# 记录损失
losses.append(loss.item())

# 每100个epoch打印一次损失
if (epoch+1) % 100 == 0:
    print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}")

print(“Training Finished!”)
“`

E. 模型评估与预测

训练完成后,我们可以用模型进行预测,并可视化结果来评估模型效果。

“`python

6. 模型评估与预测

将模型设置为评估模式,这将禁用dropout等层(如果存在的话)

model.eval()

在推理时禁用梯度计算,节省内存并加速

with torch.no_grad():
predicted_numpy = model(X_train).cpu().numpy() # 预测,并将结果移回CPU转为NumPy

打印模型学到的参数

访问线性层的权重 (weight) 和偏置 (bias)

.item() 用于从0维Tensor中获取Python数值

learned_weight = model.linear.weight.item()
learned_bias = model.linear.bias.item()
print(f”\nLearned Weight (slope): {learned_weight:.2f}”)
print(f”Learned Bias (intercept): {learned_bias:.2f}”)
print(“Original function was: y = 2x + 1 + noise”)

可视化结果

plt.figure(figsize=(10, 6))
plt.scatter(X_numpy, y_numpy, label=’Original Data’, s=10)
plt.plot(X_numpy, predicted_numpy, color=’red’, label=’Fitted Line’)
plt.title(‘Linear Regression with PyTorch’)
plt.xlabel(‘X’)
plt.ylabel(‘Y’)
plt.legend()
plt.grid(True)
plt.show()

绘制损失曲线

plt.figure(figsize=(10, 6))
plt.plot(losses, label=’Training Loss’)
plt.title(‘Loss over Epochs’)
plt.xlabel(‘Epoch’)
plt.ylabel(‘Loss’)
plt.legend()
plt.grid(True)
plt.show()
``
通过上述代码,你已经成功地安装了PyTorch,理解了Tensor和Autograd,定义了一个神经网络模型,并完成了从数据生成到模型训练和评估的完整流程!你看到模型学到的权重和偏置应该会接近我们原始数据生成时的
21`。


第六章:进阶之路与学习资源

恭喜你,你已经完成了PyTorch的入门,并训练了你的第一个模型!但这仅仅是深度学习旅程的开始。未来还有更广阔的天地等待你去探索。

A. 进阶学习方向

  1. 更复杂的模型:
    • 卷积神经网络 (CNNs): 用于图像识别、物体检测等。学习nn.Conv2d, nn.MaxPool2d等。
    • 循环神经网络 (RNNs/LSTMs/GRUs): 用于序列数据处理,如自然语言处理 (NLP)、时间序列预测等。学习nn.RNN, nn.LSTM, nn.GRU
    • Transformer: 当前NLP和计算机视觉领域最先进的模型架构,学习注意力机制。
  2. 高级训练技巧:
    • 学习率调度器 (Learning Rate Schedulers): 动态调整学习率以提高训练效果。
    • 正则化 (Regularization): 如Dropout、L1/L2正则化,防止过拟合。
    • 批归一化 (Batch Normalization): 加速训练并提高模型稳定性。
    • 模型保存与加载: torch.save(), torch.load()
  3. 数据增强 (Data Augmentation): 扩充数据集,提高模型泛化能力。
  4. 迁移学习 (Transfer Learning): 利用预训练模型解决新任务。
  5. 分布式训练: 在多GPU或多台机器上训练大型模型。
  6. 部署: 将训练好的模型部署到生产环境(如TorchScript, ONNX)。

B. 学习资源推荐

  • PyTorch官方文档和教程 (强烈推荐!)
    • https://pytorch.org/docs/stable/index.html (官方文档)
    • https://pytorch.org/tutorials/ (官方教程,从入门到高级,覆盖广泛)
  • Fast.ai课程: 一个以实践为主导的深度学习课程,使用PyTorch作为主要框架。
    • https://course.fast.ai/
  • 在线课程平台: Coursera、edX、Udemy、B站等都有大量优秀的深度学习和PyTorch课程。
  • GitHub上的开源项目: 阅读和理解优秀的PyTorch开源项目代码是学习高级技巧的绝佳方式。
  • 技术博客和社区: 例如Medium、知乎、CSDN等,关注PyTorch相关的技术分享。

结语

PyTorch是一个功能强大且易于使用的深度学习框架。通过本文,你已经掌握了从环境搭建到第一个模型训练的完整流程,并对Tensor、Autograd、nn.Module、损失函数和优化器等核心概念有了深入的理解。

深度学习的道路充满挑战,但也充满乐趣。不要害怕尝试,多动手实践,多阅读代码和文档,你会发现更多的可能性。愿你在深度学习的旅程中,收获满满,创造属于自己的AI奇迹!

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部