【深度学习笔记】数据预处理全流程:从 Pandas 读取到 PyTorch 张量
前言:在深度学习的实际项目中,数据通常不是“喂到嘴边”的完美张量(Tensor)。现实世界的数据往往是包含缺失值、离散文本的原始 CSV 或 Excel 文件。数据预处理是训练模型的第一步,也是决定模型上限的关键环节。本文基于《动手学深度学习》的数据预处理章节,结合在真实工程中的应用经验,梳理从原始数据到机器学习可用张量的完整流程及核心避坑点。
一、 准备工作:原始数据集
在正式处理前,我们模拟现实场景,先通过 Python 内置的os模块,手动生成一份包含缺失值(NA)的房屋数据,并保存为house_tiny.csv文件。
import os # 创建文件夹 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') # 房间数和巷子类型都缺失文件中的NA代表缺失值(Not Available),这是原始数据中最常见的“脏数据”形式。
二、数据读取:使用pandas加载csv
import pandas as pd # 读取刚才生成的 CSV 文件 data = pd.read_csv(data_file) print("原始数据预览:") print(data)输出预览:
text
NumRooms Alley Price 0 NaN Pave 127500 1 2.0 NaN 106000 2 4.0 NaN 178100 3 NaN NaN 140000
三、数据清洗:处理缺失值
# 1. 拆分为输入特征 (inputs) 和 输出标签 (outputs) inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2] # 2. 处理连续数值列的缺失值:用该列的均值填补 # 注意:这里的 numeric_only=True 是为了防止后续 Pandas 版本报错 inputs = inputs.fillna(inputs.mean(numeric_only=True)) print("\n数值列填补均值后:") print(inputs) # 3. 处理类别列的缺失值:使用独热编码 (One-Hot Encoding) # 将 "Alley" 列拆解为 "Alley_Pave" 和 "Alley_nan" 两列 inputs = pd.get_dummies(inputs, dummy_na=True) print("\n类别列进行独热编码后:") print(inputs)四、张量转换:可用于深度学习模型
import torch # 将 Pandas 数据转换为 PyTorch 张量 X = torch.tensor(inputs.values, dtype=torch.float32) y = torch.tensor(outputs.values, dtype=torch.float32) print("\n转换后的输入张量 X:\n", X) print("转换后的输出张量 y:\n", y)五、实战指南⭐
1.数据切分
from sklearn.model_selection import train_test_split # 切分为 80% 训练集 和 20% 测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)2. 独热编码(One-Hot)的问题
使用 Pandas 的get_dummies处理类别特征时,如果测试集中出现了一个训练集中从未见过的类别(比如巷子是“砖块”),Pandas 会在测试集自动多出一列Alley_Brick,导致训练集和测试集的特征列数不匹配,PyTorch 模型会直接报错。
这个情况下我们会再来一部分的代码:
# 如果测试集有训练集没有的新列,直接舍弃; # 如果测试集缺少训练集有的列(即新类别没出现),自动用 0 填补对齐 test_encoded = test_encoded.reindex(columns=train_encoded.columns, fill_value=0)✅ 可以使用
sklearn.preprocessing.OneHotEncoder(handle_unknown='ignore'),当遇到未知类别时,它不会报错,而是直接全部标为 0。
学习中遇到的问题总结:
1、
问:为什么Alley列被转换成了Alley_Pave和Alley_nan两列,而NumRooms列却依然保持原样(3.0, 2.0, 4.0, 3.0),没有对其进行转换?
答:
pandas.get_dummies()的机制:get_dummies的默认行为是将分类变量(categorical variables)(即字符串/文本类型或对象类型)转换成独热编码(one-hot encoding)。会忽略数值型的列
在
inputsDataFrame 中,NumRooms是浮点数(float 类型),而Alley是字符串/对象(object 类型)。因为使用了
dummy_na=True,它也会将缺失值NaN(无论该列是数值型还是类别型)当作一个类别来处理。不过,对于NumRooms列,虽然它包含 NaN(在填充均值后变成了 3.0,所以这里已经没有了 NaN),就算有 NaN,在默认行为下也不会把它作为分类列进行独热编码。
注意:如果有两列不是数值的列,就会把两列都转换成独热编码
2、在第四步张量转换中遇到这个问题
我们需要确保的是y这个numpy 数组得是数值类