数据操作与数据预处理
本文整理自李沐老师《动手学深度学习》课程笔记,涵盖张量的基本操作与 Pandas 数据预处理流程,是深度学习入门的必备基础。
一、数据操作:张量基础
1. 创建张量
python
import torch
x = torch.arange(12) # 创建 0~11 的一维张量
x.shape # 查看形状:torch.Size([12])
x.numel() # 查看标量总个数:12
x = x.reshape(3, 4) # 变形为 3×4 矩阵
# reshape 返回的是 view(视图),与原张量共享内存
torch.zeros((2, 3, 4)) # 全零张量
torch.ones((2, 3, 4)) # 全一张量
torch.tensor([[1, 2], [3, 4]]) # 由 Python 列表创建张量
2. 基本运算
python
x = torch.tensor([1.0, 2, 4, 8])
y = torch.tensor([2, 2, 2, 2])
x + y # 加
x - y # 减
x * y # 乘
x / y # 除
x ** y # 幂运算(** 是求幂运算符)
3. 张量拼接
python
x = torch.arange(12, dtype=torch.float32).reshape(3, 4)
y = torch.tensor([[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3, 4]])
torch.cat((x, y), dim=0) # 沿行方向拼接,结果形状 (6, 4)
torch.cat((x, y), dim=1) # 沿列方向拼接,结果形状 (3, 8)
4. 逻辑判断与求和
python
x == y # 逐元素比较,返回布尔张量
x.sum() # 对所有元素求和,返回标量张量
5. 广播机制
不同形状的张量相加时,PyTorch 会自动触发广播(Broadcasting):
python
x = torch.arange(3).reshape(3, 1) # 形状 (3, 1)
y = torch.arange(2).reshape(1, 2) # 形状 (1, 2)
x + y # 广播后结果形状为 (3, 2)
6. 索引与切片
python
x[-1] # 最后一行
x[1:3] # 第 1~2 行(左闭右开)
x[1, 0] = 9 # 修改指定位置的值
7. 内存管理:原地操作
python
before = id(y)
y = y + x # 为新结果分配了新内存
id(y) == before # False,y 指向了新地址
# 原地操作:避免重复分配内存
z = torch.zeros_like(y)
print(id(z))
z[:] = x + y # 原地写入,z 的地址不变
print(id(z)) # 与上面相同
为什么要在意内存?
在大规模模型训练中,反复执行
x = x + y会不断申请新内存,极易导致内存溢出。使用
x[:] = x + y或x += y可以做到原地更新,显著降低内存开销。
8. 与 NumPy 互转
python
a = x.numpy() # Tensor → NumPy ndarray
b = torch.tensor(a) # NumPy ndarray → Tensor
type(a), type(b)
9. 单元素张量转 Python 标量
python
a = torch.tensor([3.5])
a.item() # 转为 Python float
float(a) # 同上
int(a) # 转为 Python int
二、数据预处理:从 CSV 到张量
真实场景中,数据往往以表格形式存储,需要经过读取、清洗、编码等步骤后才能喂给模型。
1. 创建示例数据集
python
import os
import pandas as pd
import torch
os.makedirs(os.path.join('.', 'data'), exist_ok=True)
data_file = os.path.join('.', 'data', 'house_tiny.csv')
with open(data_file, 'w') as f:
f.write('NumRooms,Alley,Price\n')
f.write('NA,Pave,127500\n')
f.write('2,NA,106000\n')
f.write('4,NA,178100\n')
f.write('NA,NA,140000\n')
2. 读取与分割数据
python
data = pd.read_csv(data_file)
print(data)
inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2]
3. 缺失值处理
python
# 注意:直接 fillna(mean()) 会因非数值列报错
# 正确做法:只对数值列做均值填充
numeric_cols = inputs.select_dtypes(include='number').columns
inputs[numeric_cols] = inputs[numeric_cols].fillna(inputs[numeric_cols].mean())
print(inputs)
4. 类别特征独热编码
python
# get_dummies 将字符串列转为 0/1 编码,dummy_na=True 会为 NaN 单独生成一列
inputs = pd.get_dummies(inputs, dummy_na=True, dtype=int)
print(inputs)
5. 转换为张量
python
X = torch.tensor(inputs.values)
y = torch.tensor(outputs.values)
# 注意:Pandas 默认转为 float64,但深度学习中通常使用 float32
# 如有需要,可指定:torch.tensor(inputs.values, dtype=torch.float32)
X, y
三、小结
| 知识点 | 核心要点 |
|---|---|
reshape |
返回 view,与原张量共享内存 |
| 广播机制 | 形状不同的张量运算时自动扩展维度 |
| 原地操作 | x += y / x[:] = ... 避免内存浪费 |
| 缺失值处理 | 数值列均值填充,类别列独热编码 |
| 张量类型 | 深度学习中优先使用 float32 |