新手必看:PyTorch从安装到第一个模型
引言:踏入深度学习的奇妙世界
在当今人工智能浪潮中,深度学习无疑是最激动人心的领域之一。从智能语音助手到自动驾驶汽车,再到个性化推荐系统,深度学习技术正以前所未有的速度改变着我们的生活。而PyTorch,作为Facebook AI Research(FAIR)开发的一个开源机器学习库,以其“Pythonic”的风格、动态计算图(Dynamic Computational Graph)的灵活性以及强大的GPU加速能力,迅速成为研究人员和开发者构建、训练深度学习模型的热门选择。
对于初学者而言,面对一个全新的框架,往往会感到无从下手。别担心!本文将带你一步步穿越PyTorch的迷雾,从最基础的环境搭建开始,到理解其核心概念,再到亲手搭建并训练你的第一个深度学习模型。读完本文,你将对PyTorch有一个全面而扎实的理解,为未来更深入的学习打下坚实的基础。
我们将涵盖以下几个核心章节:
第一章:环境搭建与PyTorch安装
第二章:PyTorch核心概念:Tensor与Autograd
第三章:构建你的第一个神经网络模型
第四章:训练神经网络的核心要素
第五章:实战:从数据到模型训练(以线性回归为例)
第六章:进阶之路与学习资源
准备好了吗?让我们开始这段深度学习的旅程!
第一章:环境搭建与PyTorch安装
在开始编写任何PyTorch代码之前,我们首先需要为它创建一个干净、稳定的运行环境。推荐使用Anaconda或Miniconda进行环境管理,这能有效避免不同项目间的库冲突。
A. Anaconda/Miniconda的安装
-
下载与安装:
访问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”(添加到环境变量)的选项,或者在安装完成后手动配置。 -
创建虚拟环境:
打开终端(Windows用户打开Anaconda Prompt),创建一个名为pytorch_env的虚拟环境,并指定Python版本(例如3.9):
bash
conda create -n pytorch_env python=3.9
这条命令会创建一个新的、独立的Python环境。 -
激活虚拟环境:
创建完成后,每次开始PyTorch开发前,都需要激活这个环境:
bash
conda activate pytorch_env
你的终端提示符会显示当前所处的环境名称(例如(pytorch_env)),表示你已成功进入该环境。
B. PyTorch的安装
PyTorch的安装通常通过其官方网站提供的命令进行,官方网站会根据你的系统、CUDA版本等生成最适合的安装命令。
-
访问PyTorch官网:
打开浏览器,访问https://pytorch.org/get-started/locally/。 -
选择你的配置:
在页面上,你需要根据以下选项进行选择:- 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上运行,速度会慢很多,但对于初学者和小型项目来说完全足够。
- 如果你有NVIDIA显卡且支持CUDA,请选择对应的CUDA版本(例如
- PyTorch Build: 通常选择
-
复制并执行安装命令:
根据你的选择,官网会生成一条conda install或pip 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会自动解决依赖并安装所有必要的包。
将生成的命令粘贴到已激活 -
验证安装:
安装完成后,在激活的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进行加速计算。
-
创建Tensor:
“`python
import torch
import numpy as np1. 直接从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)
“` -
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 -
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()`方法转换回NumPy数组的Tensor会共享底层内存。修改其中一个,另一个也会改变。
**注意:** 从NumPy数组创建的Tensor和通过
-
-
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上的所有操作的梯度。这是训练神经网络(通过反向传播算法)的核心机制。
-
工作原理:
当我们在Tensor上执行操作时,PyTorch会构建一个计算图(Computational Graph)。图中的节点是Tensor,边是操作。当我们对某个Tensor(通常是损失函数)调用.backward()方法时,Autograd会遍历这个计算图,并使用链式法则自动计算图中所有requires_grad=True的Tensor的梯度。 -
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。 -
计算梯度:
loss.backward()
现在我们有了y,我们想计算y对x的导数。在深度学习中,这通常是损失函数对模型参数的导数。
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的梯度。 -
梯度累积:
默认情况下,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.0z = x**3
z.backward()
print(“Second backward (dz/dx = 3x^2, total = 4 + 12):”, x.grad) # 4.0 + 12.0 = 16.0
“` -
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模块提供了构建神经网络所需的所有核心组件。
-
nn.Module基类:
所有你自定义的神经网络模型都应该继承自nn.Module。它封装了模型的所有参数(权重和偏置),并提供了管理它们的方法。
继承nn.Module时,你需要实现两个主要方法:__init__(self): 在这里定义模型的各个层和其他组件。forward(self, x): 在这里定义数据在模型中如何从输入层流向输出层(即前向传播逻辑)。
-
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) -
激活函数:
激活函数引入了非线性,使得神经网络能够学习和表示更复杂的模式。如果网络中只有线性层,那么无论堆叠多少层,整个网络仍然只是一个线性模型。
常用的激活函数有: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)。
-
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)
``forward`方法描述了数据如何通过这些层进行转换。最后,我们将模型实例移动到GPU(如果可用),并测试了一个随机输入。
这段代码定义了一个包含两个线性层和一个ReLU激活函数的简单神经网络。
第四章:训练神经网络的核心要素
构建完模型只是第一步,要让模型具备学习能力,我们还需要定义如何评估其表现、如何更新其内部参数。这涉及到数据准备、损失函数和优化器。
A. 数据准备:Dataset与DataLoader
在PyTorch中,数据的处理通常涉及到torch.utils.data.Dataset和torch.utils.data.DataLoader。
-
Dataset:
Dataset是一个抽象类,用于表示数据集。你需要自定义一个继承自Dataset的类,并实现两个方法:__len__(self): 返回数据集中的样本总数。__getitem__(self, idx): 根据索引idx获取一个样本(特征和标签)。
这使得数据能够被按需加载,而不是一次性全部加载到内存中。
-
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(): 常用于多分类问题。它结合了LogSoftmax和NLLLoss(负对数似然损失),可以直接接收模型的原始输出(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(): 常用于二分类问题。它结合了Sigmoid和BCELoss(二元交叉熵损失),可以直接接收模型的原始输出(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的参数。
- 训练循环中的步骤:
在每个训练批次中,优化器会执行以下三个关键步骤: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}”)
``X_train
这里我们生成了100个数据点,是输入特征,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()
``2
通过上述代码,你已经成功地安装了PyTorch,理解了Tensor和Autograd,定义了一个神经网络模型,并完成了从数据生成到模型训练和评估的完整流程!你看到模型学到的权重和偏置应该会接近我们原始数据生成时的和1`。
第六章:进阶之路与学习资源
恭喜你,你已经完成了PyTorch的入门,并训练了你的第一个模型!但这仅仅是深度学习旅程的开始。未来还有更广阔的天地等待你去探索。
A. 进阶学习方向
- 更复杂的模型:
- 卷积神经网络 (CNNs): 用于图像识别、物体检测等。学习
nn.Conv2d,nn.MaxPool2d等。 - 循环神经网络 (RNNs/LSTMs/GRUs): 用于序列数据处理,如自然语言处理 (NLP)、时间序列预测等。学习
nn.RNN,nn.LSTM,nn.GRU。 - Transformer: 当前NLP和计算机视觉领域最先进的模型架构,学习注意力机制。
- 卷积神经网络 (CNNs): 用于图像识别、物体检测等。学习
- 高级训练技巧:
- 学习率调度器 (Learning Rate Schedulers): 动态调整学习率以提高训练效果。
- 正则化 (Regularization): 如Dropout、L1/L2正则化,防止过拟合。
- 批归一化 (Batch Normalization): 加速训练并提高模型稳定性。
- 模型保存与加载:
torch.save(),torch.load()。
- 数据增强 (Data Augmentation): 扩充数据集,提高模型泛化能力。
- 迁移学习 (Transfer Learning): 利用预训练模型解决新任务。
- 分布式训练: 在多GPU或多台机器上训练大型模型。
- 部署: 将训练好的模型部署到生产环境(如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奇迹!