4、PyTorch基础与张量操作:PyTorch环境配置、张量创建与运算、自动求导机制、GPU加速
各位同学,欢迎来到第四章。说实话,这一章是整个图神经网络选股模型的「地基」。你想想看,后面所有的GCN、GAT、GraphSAGE,底层跑的都是张量运算。地基打不牢,后面盖楼肯定歪。我当年刚开始接触PyTorch时,也踩过不少坑,今天就把这些经验一次性分享给你们。
4.1 PyTorch环境配置:别让环境卡住你
配置环境这事儿,说简单也简单,说烦人也真烦人。我个人习惯用Anaconda来管理虚拟环境,这样不同项目之间不会打架。
核心要点:PyTorch的安装命令取决于你的CUDA版本。别盲目复制网上的命令,先查一下自己的显卡驱动支持哪个CUDA版本。
具体步骤很简单:
- 打开终端,创建一个新的虚拟环境:
conda create -n gnn_stock python=3.9 - 激活环境:
conda activate gnn_stock - 去PyTorch官网(pytorch.org)选择对应的配置,复制安装命令。
举个例子,如果你用的是CUDA 11.8,命令大概是这样的:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
我的小技巧:如果你不确定CUDA版本,可以用 nvidia-smi 命令查看。我曾经有一次装错了CPU版本,跑模型慢得像蜗牛,排查了半天才发现是CUDA没对上。
装完之后,验证一下:
import torch
print(torch.__version__)
print(torch.cuda.is_available()) # 如果输出True,说明GPU可用
4.2 张量创建与运算:一切皆张量
张量(Tensor)是什么?说白了,它就是多维数组。标量是0维张量,向量是1维,矩阵是2维,再往上就是高维张量。在量化金融里,一只股票的历史价格序列是1维张量,多只股票的多日数据就是2维或3维张量。
4.2.1 创建张量的几种方式
我平时最常用的几种创建方式,列出来给你们看看:
| 方法 | 说明 | 示例 |
|---|---|---|
torch.tensor() |
从列表或数组创建 | torch.tensor([1.0, 2.0, 3.0]) |
torch.zeros() |
创建全零张量 | torch.zeros(3, 4) |
torch.ones() |
创建全一张量 | torch.ones(2, 3) |
torch.randn() |
创建标准正态分布随机张量 | torch.randn(5, 5) |
torch.arange() |
创建等差数列张量 | torch.arange(0, 10, 2) |
举个例子,假设我们要模拟10只股票5天的收盘价数据:
import torch
# 模拟10只股票,5天的数据
stock_data = torch.randn(10, 5)
print(stock_data.shape) # 输出: torch.Size([10, 5])
4.2.2 张量运算:加减乘除与矩阵乘法
张量运算和NumPy非常像,但PyTorch多了自动求导的能力。基本的加减乘除就不多说了,重点说说矩阵乘法。
在选股模型里,我们经常要计算特征矩阵和权重矩阵的乘积。PyTorch提供了两种方式:
torch.mm():标准的矩阵乘法,只适用于2维张量。torch.matmul():更通用的矩阵乘法,支持高维张量。
# 假设特征矩阵是 [10只股票 x 20个特征]
features = torch.randn(10, 20)
# 权重矩阵是 [20个特征 x 5个输出]
weights = torch.randn(20, 5)
# 矩阵乘法
output = torch.mm(features, weights)
print(output.shape) # 输出: torch.Size([10, 5])
注意:矩阵乘法要求第一个矩阵的列数等于第二个矩阵的行数。我刚开始学的时候经常搞混维度,导致报错。建议每次运算前都打印一下 .shape 确认。
4.3 自动求导机制:PyTorch的灵魂
自动求导(Autograd)是PyTorch最核心的功能之一。你想想看,如果没有自动求导,我们得手动推导梯度公式,那对于复杂的图神经网络来说简直是噩梦。
原理其实很简单:PyTorch会记录所有张量上的操作,构建一个计算图。当你调用 .backward() 时,它会自动计算梯度。
4.3.1 开启梯度追踪
默认情况下,张量是不追踪梯度的。你需要设置 requires_grad=True:
x = torch.tensor([2.0, 3.0], requires_grad=True)
y = x ** 2 + 3 * x
z = y.sum()
z.backward() # 自动计算梯度
print(x.grad) # 输出: tensor([7., 9.])
为什么会得到7和9?因为 y = x^2 + 3x,导数 dy/dx = 2x + 3。当 x=2 时,导数为7;当 x=3 时,导数为9。嗯,数学上完全正确。
避坑指南:我曾经在训练循环里忘记清零梯度,导致梯度不断累加,模型直接炸了。记得每次 backward() 之后调用 optimizer.zero_grad()。
4.3.2 计算图与梯度累积
PyTorch的计算图是动态的,每次前向传播都会重新构建。这意味着你可以根据输入动态改变网络结构——这在处理变长序列时特别有用。
另外,默认情况下梯度是累积的。如果你有多个损失项,可以分别调用 backward(),梯度会自动累加。但大多数情况下,我们只需要一个损失函数。
4.4 GPU加速:让训练飞起来
做量化选股,数据量动不动就是几千只股票、几百个交易日、几十个特征。CPU跑起来?太慢了。GPU才是王道。
4.4.1 检查GPU是否可用
第一步,先看看你的机器有没有GPU:
if torch.cuda.is_available():
device = torch.device("cuda")
print(f"使用GPU: {torch.cuda.get_device_name(0)}")
else:
device = torch.device("cpu")
print("使用CPU")
4.4.2 将张量移动到GPU
有两种方式:
- 创建时直接指定设备:
torch.tensor([1, 2], device='cuda') - 创建后移动:
tensor.to('cuda')
# 推荐方式:先创建,再移动
data = torch.randn(1000, 100)
data = data.to(device)
# 模型也要移动
model = MyGNNModel()
model = model.to(device)
重要提醒:张量和模型必须在同一个设备上。如果你把数据放在GPU上,但模型还在CPU,运算时会报错。我刚开始时经常犯这个错,排查了半天才发现是设备不匹配。
4.4.3 性能对比:CPU vs GPU
我做过一个简单的测试,用1000x1000的矩阵乘法,CPU用了0.5秒,GPU只用了0.02秒。对于图神经网络这种需要大量矩阵运算的模型,GPU加速是必须的。
4.5 本章知识体系总览
下面这张图是我自己画的,把本章的核心知识点串了起来。你可以把它当作一个「地图」,学完后再回来看,会更有感觉。
4.6 本章小结
好了,这一章的内容就到这里。我们讲了环境配置、张量创建与运算、自动求导机制,还有GPU加速。这些东西看起来基础,但每一个都是后面搭建图神经网络选股模型的基石。
我个人建议你动手敲一遍代码,别光看。只有亲手跑通了,才算真正掌握。下一章我们会开始接触图神经网络的核心概念,到时候这些基础就会派上大用场。
最后一个小提醒:如果你在运行代码时遇到任何问题,先检查三件事:设备是否一致、维度是否匹配、梯度是否清零。这三个问题占了PyTorch新手报错的80%。