第二章:Python与PyTorch基础回顾
说实话,每次带新人入门图神经网络,我最怕的不是他们数学不好,而是连Python和PyTorch的基本功都没打牢。你想想看,模型还没搭起来,光是在张量维度上就卡住了,这多憋屈。
这一章,咱们就把地基夯实。我会带着你快速过一遍Python核心语法、NumPy和Pandas的数据处理,然后重点攻克PyTorch的张量操作和自动求导机制。最后,咱们亲手搭一个最简单的神经网络——别小看它,这可是你走向GNN的第一步。
本章核心目标:让你在30分钟内,从「能写Python」进化到「能用PyTorch搭网络」。
2.1 Python核心语法速览
Python这东西,上手容易,但坑也不少。我见过太多人把列表推导式写得跟天书似的,其实没必要。咱们只捡最常用的说。
2.1.1 数据结构选型
我个人习惯,处理固定长度的数据用元组,需要频繁增删用列表,查重用集合,键值对用字典。别问我为什么——这都是血泪教训换来的。
# 列表:最常用,可变
features = [0.1, 0.2, 0.3, 0.4]
features.append(0.5)
# 元组:不可变,适合做特征组合
node = (1, 'user', 0.85) # (id, type, score)
# 字典:图结构的基础
graph = {
'nodes': [1, 2, 3],
'edges': [(1,2), (2,3)]
}
# 集合:去重利器
unique_labels = {0, 1, 2, 1, 0} # 结果:{0, 1, 2}
我的小技巧:处理图数据时,我习惯用字典存储邻接表。比如 adj[node] = [neighbor1, neighbor2],比邻接矩阵省内存多了。
2.1.2 函数与Lambda
Python的函数定义很简单,但有个细节要注意——默认参数别用可变对象。我曾经因为这个bug排查了整整一个下午。
# 正确的默认参数写法
def normalize(features, eps=1e-8):
return [f / (sum(features) + eps) for f in features]
# Lambda表达式:图卷积里经常用
edge_weight = lambda x, y: 1.0 / (1.0 + abs(x - y))
2.2 NumPy与Pandas数据处理
做图神经网络,NumPy是绕不开的。你想想看,邻接矩阵、特征矩阵、标签向量,哪个不是多维数组?
2.2.1 NumPy核心操作
我记得刚接触图数据时,最头疼的就是矩阵运算。其实NumPy把一切都简化了。
import numpy as np
# 创建邻接矩阵(3个节点)
adj = np.array([
[0, 1, 1],
[1, 0, 0],
[1, 0, 0]
])
# 特征矩阵(3个节点,每个4维特征)
features = np.random.randn(3, 4)
# 矩阵乘法:图卷积的核心
degree = np.diag(np.sum(adj, axis=1))
laplacian = degree - adj # 拉普拉斯矩阵
print(f"邻接矩阵形状: {adj.shape}")
print(f"特征矩阵形状: {features.shape}")
| NumPy函数 | 用途 | 图神经网络中的应用 |
|---|---|---|
np.dot() |
矩阵乘法 | 特征传播 |
np.sum() |
求和 | 计算节点度 |
np.diag() |
创建对角矩阵 | 度矩阵 |
np.random.randn() |
随机初始化 | 特征初始化 |
2.2.2 Pandas数据清洗
实际项目中,数据很少是干净的。我曾经处理过一个金融交易图,光清洗数据就花了两天。Pandas在这方面是神器。
import pandas as pd
# 模拟交易数据
transactions = pd.DataFrame({
'from_id': [1, 1, 2, 3, 2],
'to_id': [2, 3, 1, 2, 3],
'amount': [100, 200, 150, None, 300],
'time': ['2024-01-01', '2024-01-02', '2024-01-01', '2024-01-03', '2024-01-02']
})
# 处理缺失值
transactions['amount'].fillna(transactions['amount'].mean(), inplace=True)
# 按时间排序
transactions.sort_values('time', inplace=True)
print(transactions.head())
避坑指南:我曾经在构建图数据时,直接用Pandas的DataFrame做循环,结果数据量一大就卡死了。记住:能用向量化操作就别用循环,能用NumPy就别用纯Python。
2.3 PyTorch张量操作与自动求导
好了,重头戏来了。PyTorch的张量(Tensor)和NumPy的数组很像,但多了两个杀手锏:GPU加速和自动求导。
2.3.1 张量创建与操作
说白了,张量就是多维数组的升级版。我建议你从一开始就养成用PyTorch的习惯,别在NumPy和Tensor之间来回倒腾。
import torch
# 创建张量
x = torch.tensor([[1, 2], [3, 4]], dtype=torch.float32)
y = torch.randn(2, 2)
# 张量运算
z = torch.mm(x, y) # 矩阵乘法
print(f"矩阵乘法结果:\n{z}")
# 形状变换
x_flat = x.view(-1) # 展平
print(f"展平后: {x_flat}")
# GPU支持(如果有)
if torch.cuda.is_available():
x = x.cuda()
print("数据已迁移到GPU")
2.3.2 自动求导机制
这是PyTorch最让我爱不释手的地方。你想想看,以前算梯度得手动推导公式,现在只要设置requires_grad=True,PyTorch自动帮你算好。
# 创建需要梯度的张量
w = torch.tensor([2.0], requires_grad=True)
b = torch.tensor([1.0], requires_grad=True)
# 前向传播
x = torch.tensor([3.0])
y_pred = w * x + b
loss = (y_pred - 10) ** 2 # 假设真实值是10
# 反向传播
loss.backward()
print(f"w的梯度: {w.grad}")
print(f"b的梯度: {b.grad}")
关键理解:自动求导的本质是计算图。每次前向传播都会构建一个动态计算图,反向传播时沿着图计算梯度。这就是为什么PyTorch被称为「动态图」框架。
2.4 搭建第一个简单神经网络
理论说再多,不如动手搭一个。咱们用PyTorch实现一个最简单的全连接网络,用来做二分类。
2.4.1 网络结构定义
我习惯把网络定义成一个类,继承nn.Module。这样代码清晰,也方便扩展。
import torch.nn as nn
import torch.nn.functional as F
class SimpleNN(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim):
super(SimpleNN, self).__init__()
self.fc1 = nn.Linear(input_dim, hidden_dim)
self.fc2 = nn.Linear(hidden_dim, output_dim)
def forward(self, x):
x = F.relu(self.fc1(x))
x = torch.sigmoid(self.fc2(x))
return x
# 实例化网络
model = SimpleNN(input_dim=10, hidden_dim=5, output_dim=1)
print(model)
2.4.2 训练循环
训练循环的套路其实很固定:前向传播 -> 计算损失 -> 反向传播 -> 更新参数。我刚开始写的时候总忘记清零梯度,后来养成了习惯,每次反向传播前都调用optimizer.zero_grad()。
import torch.optim as optim
# 生成模拟数据
X = torch.randn(100, 10)
y = torch.randint(0, 2, (100, 1)).float()
# 定义损失函数和优化器
criterion = nn.BCELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 训练
epochs = 100
for epoch in range(epochs):
# 前向传播
outputs = model(X)
loss = criterion(outputs, y)
# 反向传播
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (epoch + 1) % 20 == 0:
print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')
我的经验:刚开始训练时,如果loss不下降,先检查数据是否归一化。我曾经在一个项目里,因为特征值范围差了三个数量级,导致模型怎么都学不动。后来做了标准化,问题立刻解决。
2.4.3 知识体系总览
下面这张图,是我为你梳理的本章知识脉络。从Python基础到PyTorch实战,每一步都是为图神经网络打基础。
看到这张图,你应该能感受到:这一章的内容环环相扣。Python基础是工具,NumPy/Pandas是数据处理的利器,PyTorch是模型构建的核心,而那个简单的神经网络,就是你踏入图神经网络世界的第一块敲门砖。
本章小结:我们快速回顾了Python核心语法,掌握了NumPy和Pandas的数据处理技巧,深入理解了PyTorch的张量操作和自动求导机制,最后亲手搭建了一个完整的神经网络。这些知识,在后续的图神经网络课程中会反复用到。