- 文档
- 教程
- 人工智能
- 深度学习
- NLP
- 计算机视觉
- 强化学习
【免费下载链接】d2l-en
Interactive deep learning book with multi-framework code, math, and discussions. Adopted at 500 universities from 70 countries including Stanford, MIT, Harvard, and Cambridge.
真实世界的深度学习应用几乎不会直接遇到现成的张量数据:原始数据通常散落在任意格式的文件中,携带缺失值、分类字段与噪声,必须先经过预处理才能进入模型。本指南以 d2l-en(《动手学深度学习》英文版)第 2 章预备知识中的 pandas 实战章节为核心,完整演示从创建 CSV 文件、用pandas读取、划分输入/目标列、处理缺失值(分类字段 one-hot 编码、数值字段均值填充)到最终转换为 MXNet / PyTorch / TensorFlow / JAX 四种框架张量的全流程,并结合仓库内 Kaggle 房价、目标检测数据集等真实源码用例,帮助你建立一套可直接复用、可扩展的数据预处理管线。
为什么需要 pandas:从现成张量到杂乱数据
在前面章节(如 ndarray 章节)中,我们一直在使用已经构造好的合成数据——数据直接以张量形式提供,省去了中间环节。然而在真实场景中,数据可能来自数据库导出、传感器采集或业务系统,格式五花八门、质量参差不齐。幸运的是,pandas库承担了大部分"脏活累活":它以DataFrame为核心数据结构,提供了读取、清洗、变换、索引与聚合等一整套表格数据处理能力。
需要说明的是,本章是"速成课"而非完整的 pandas 教程——它聚焦于深度学习预处理中最常用的一组例程:读 CSV、分列、缺失值处理、类别编码、转张量。如果你需要系统学习 pandas,可阅读其官方用户指南;本文只讨论与本仓库深度学习流程直接相关的核心操作。
本仓库的所有实战章节都建立在pandas之上:四个框架的 d2l 工具包(d2l/mxnet.py、d2l/torch.py、d2l/tensorflow.py、d2l/jax.py)均在文件头部import pandas as pd,后续的图像分类、目标检测、Kaggle 竞赛等章节都会复用这里介绍的技术。
读取数据集:从 CSV 到 DataFrame
逗号分隔值(CSV)文件是存储表格型(类电子表格)数据最通用的格式之一。CSV 中每一行对应一条记录,由若干个用逗号分隔的字段组成,例如:
Albert Einstein,March 14 1879,Ulm,Federal polytechnic school,field of gravitational physics为了演示如何用pandas加载 CSV,我们首先在本地创建一个小型住宅数据集house_tiny.csv。这个文件代表一个住宅样本集:每一行对应一所房屋,列分别表示房间数(NumRooms)、屋顶类型(RoofType)和价格(Price)。在 d2l-en 的 Jupyter 笔记本中,该文件被写入章节目录的上层data/文件夹(即相对笔记本目录的../data/house_tiny.csv,以仓库根目录计为data/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,RoofType,Price NA,NA,127500 2,NA,106000 4,Slate,178100 NA,NA,140000''')接着导入pandas并用read_csv读取该文件:
import pandas as pd data = pd.read_csv(data_file) print(data)运行后得到的DataFrame如下:
NumRooms RoofType Price 0 NaN NaN 127500 1 2.0 NaN 106000 2 4.0 Slate 178100 3 NaN NaN 140000可以看到,pandas自动把 CSV 中的NA条目替换成了特殊的NaN(not a number)值。同理,如果某条记录存在空字段(如"3,,,270000"),也会产生NaN。这些被称为缺失值,是数据科学中绕不开的持久性难题。缺失值的处理方式取决于具体上下文,通常有两种思路:
- 插补(imputation):用对缺失值的估计来替换它们;
- 删除(deletion):直接丢弃包含缺失值的行或列。
下文将分别介绍针对分类字段和数值字段的常用插补策略。
数据准备:划分输入与目标
在监督学习中,我们训练模型用一组输入值来预测指定的目标值。处理数据集的第一步就是把对应输入与目标的列分开。选择列有两种常用方式:按列名选择,或基于整数位置的索引iloc。
下面代码将前两列(NumRooms、RoofType)作为输入特征inputs,把第三列(Price)作为目标targets:
inputs, targets = data.iloc[:, 0:2], data.iloc[:, 2]iloc[:, 0:2]表示选取所有行、第 0 到第 1 列(左闭右开),iloc[:, 2]表示选取第 2 列。除iloc外,pandas还支持按名称索引(如data[['NumRooms', 'RoofType']]),这在列顺序不稳定但列名稳定时更健壮;该内容可查阅 pandas 官方索引文档深入学习。
分类字段的缺失值处理:把NaN当作一个类别
对于分类输入字段,一个常见的插补启发式是把NaN本身当作一个类别来处理。由于RoofType列只取值Slate和NaN,pandas可以借助get_dummies把这一列转换成一列指示变量(one-hot 编码):
inputs = pd.get_dummies(inputs, dummy_na=True) print(inputs)输出为:
NumRooms RoofType_Slate RoofType_nan 0 NaN 0 1 1 2.0 0 1 2 4.0 1 0 3 NaN 0 1get_dummies将RoofType拆成了两列RoofType_Slate与RoofType_nan:屋顶类型为Slate的行,其RoofType_Slate置 1、RoofType_nan置 0;而RoofType缺失的行则相反。关键参数dummy_na=True的作用正是让缺失值也获得一个专属的指示列,避免把缺失信息静默丢弃——这种"缺失本身也是一种信号"的思想在真实项目中非常实用。
数值字段的缺失值处理:均值填充
对于缺失的数值数据,最常用的启发式是用对应列的均值替换NaN条目。DataFrame.fillna配合mean()即可一次完成:
inputs = inputs.fillna(inputs.mean()) print(inputs)输出为:
NumRooms RoofType_Slate RoofType_nan 0 3.0 0 1 1 2.0 0 1 2 4.0 1 0 3 3.0 0 1此时NumRooms中两个缺失值都被替换成了该列均值(2.0 + 4.0) / 2 = 3.0,而原本就是数值的RoofType_Slate、RoofType_nan列不受影响。注意这里inputs.mean()默认按列(axis=0)计算均值,因此可以逐列对齐填充;若对某些场景需要按行方向处理,可显式指定axis参数。
转换为张量格式:从 DataFrame 到多框架 Tensor
当inputs与targets中所有条目都变成数值后,就可以加载为张量了。转换分两步:先用to_numpy(dtype=float)把DataFrame变成浮点型 NumPy 数组,再用各框架的张量构造器封装。这也是 d2l-en 的独特之处——同一套预处理逻辑可无缝对接四种深度学习框架:
MXNet:
from mxnet import np X, y = np.array(inputs.to_numpy(dtype=float)), np.array(targets.to_numpy(dtype=float)) X, yPyTorch:
import torch X = torch.tensor(inputs.to_numpy(dtype=float)) y = torch.tensor(targets.to_numpy(dtype=float)) X, yTensorFlow:
import tensorflow as tf X = tf.constant(inputs.to_numpy(dtype=float)) y = tf.constant(targets.to_numpy(dtype=float)) X, yJAX:
from jax import numpy as jnp X = jnp.array(inputs.to_numpy(dtype=float)) y = jnp.array(targets.to_numpy(dtype=float)) X, y为什么要显式指定dtype=float?因为RoofType经 one-hot 编码后是整型 0/1 列,若不统一转成浮点,后续与NumRooms的浮点均值混在一起可能出现类型不一致,进而影响张量构造与模型输入。统一转 float 后,X是一个形状为(4, 3)的特征张量,y是形状为(4,)的目标张量,可以直接进入下一章的线性回归或 MLP 训练流程。
提示:d2l-en 全书的多框架代码通过 d2lbook 的标签机制组织(
%load_ext d2lbook.tab与tab.interact_select([...])),读者可在网页端切换 MXNet / PyTorch / TensorFlow / JAX 四个标签查看对应实现。
仓库源码中的 pandas 实战:从 toy 数据到真实数据集
上述三步(读 CSV → 处理缺失值 → 转张量)就是 d2l-en 数据预处理的最小闭环。仓库中多处真实用例可以印证这套模式的可扩展性。
案例一:Kaggle 房价竞赛的完整预处理管线
在 kaggle-house-price 章节 中,pandas 承担了竞赛数据的全部清洗工作。其数据加载使用pd.read_csv配合d2l.download下载并缓存训练/验证集(带 SHA-1 校验);预处理则把本章的技法放大到了 80 个特征的真实数据集上:
features = pd.concat( (self.raw_train.drop(columns=['Id', label]), self.raw_val.drop(columns=['Id']))) # 筛选数值列并标准化 numeric_features = features.dtypes[features.dtypes!='object'].index features[numeric_features] = features[numeric_features].apply( lambda x: (x - x.mean()) / (x.std())) # 数值列缺失值填 0 features[numeric_features] = features[numeric_features].fillna(0) # 离散列 one-hot 编码(缺失也保留一列) features = pd.get_dummies(features, dummy_na=True)可以看到它复用了本文的get_dummies(features, dummy_na=True),同时新增了两个进阶操作:用features.dtypes != 'object'按数据类型自动筛选数值列,以及先用标准化(x - x.mean()) / x.std()再fillna(0)。该章节明确记录:one-hot 编码后特征数从 79 增加到 331(不含 Id 与标签列),这正是dummy_na=True为每个分类列的缺失值单独建列的结果。
案例二:目标检测数据集的逐行读取
在 object-detection-dataset 章节 对应的工具函数 read_data_bananas 中,pandas 被用来读取目标检测标注 CSV,展示了set_index与iterrows的用法:
csv_data = pd.read_csv(csv_fname) csv_data = csv_data.set_index('img_name') for img_name, target in csv_data.iterrows(): images.append(torchvision.io.read_image(...)) targets.append(list(target))把图像文件名设成索引后逐行迭代,每行取出的就是该图像的类别与边界框标注——这正印证了"CSV 是表格数据的通用载体"这一判断,即使是图像任务,其标注也常以表格形式存在。
案例三:轻量级 CSV 解析的取舍
另一方面,仓库也提供了不依赖 pandas 的轻量替代。例如 read_csv_labels 用手工readlines+split(',')解析 CIFAR-10 的标签文件,返回"文件名→标签"字典。这说明在实际项目中应根据数据规模与解析复杂度在"pandas 的便利性"与"手工解析的性能"之间做权衡——这正是本文末尾练习题所引导的思考方向。
真实世界数据的挑战与数据质量
掌握了上述速成技能后,你已经能够划分数据列、插补缺失变量并把 pandas 数据载入张量。但真实的数据处理远比这个 toy 示例复杂,需要提前意识到以下几类问题:
- 多文件与关系型来源:数据集可能不是单个 CSV,而是从关系数据库导出的多个表。例如电商场景中,客户地址与购买记录往往分别存放在不同表中,需要按外键做连接(
merge)与聚合才能拼成训练样本; - 数据类型多样化:除分类与数值外,还有文本字符串、图像、音频、点云等类型。针对它们往往需要专用工具与高效算法(分词、图像解码、特征提取等),否则数据预处理会成为机器学习流水线中最大的瓶颈。这些问题在本书后续的计算机视觉与自然语言处理章节中会反复出现;
- 数据质量问题:真实数据集常受离群点、传感器错误测量与记录误差困扰,必须在喂给模型之前处理。数据可视化工具(如 seaborn、Bokeh、matplotlib 等)可以帮助人工检视数据分布、建立对问题类型的直觉,从而决定该用插补、删除还是修正。
延伸练习与进一步探索
为巩固本章内容,d2l-en 提供了以下进阶练习,读者可结合 pandas 官方文档与 ndarray 章节 中的张量知识逐一实践:
- 尝试加载真实数据集(如 UCI Machine Learning Repository 中的 Abalone 数据集)并检查其属性:有多少比例含缺失值?数值、分类、文本变量各占多少?
- 练习按列名而非列号索引和选择数据列,体会两种方式在不同场景下的优劣。
- 思考用本章方式能加载多大的数据集?瓶颈是什么?提示:考虑读取时间、表示方式、处理开销与内存占用。在自己的笔记本和服务器上分别实测。
- 数据拥有极多类别时如何处理?若类别标签全部唯一(如 ID),是否应该保留这类列?
- pandas 之外的替代方案有哪些?例如 NumPy 的
numpy.load直接加载张量文件,或 Pillow(Python 图像处理库)处理图像格式。
下一站,kaggle-house-price 章节 将在此基础上补全更多数据处理技能(标准化、训练/验证划分、提交预测),把本章的"速成技能"完整应用到一场真实的机器学习竞赛中。
- 文档
- 教程
- 人工智能
- 深度学习
- NLP
- 计算机视觉
- 强化学习
【免费下载链接】d2l-en
Interactive deep learning book with multi-framework code, math, and discussions. Adopted at 500 universities from 70 countries including Stanford, MIT, Harvard, and Cambridge.
相关推荐
《动手学深度学习》数据预处理实战:用 pandas 完成缺失值处理并转换为张量格式
《动手学深度学习》数据预处理实战:用 pandas 完成缺失值处理并转换为张量格式 深度学习模型无法直接消费散落在磁盘上的原始数据(如 CSV、JSON 等文本
人工智能深度学习机器学习教程python-machine-learning-book实战:用Pandas处理缺失值
python machine learning book实战:用Pandas处理缺失值 在机器学习项目中,缺失值是数据预处理阶段最常见的挑战之一。不合理的缺失值
机器学习教程《动手学深度学习》数据预处理实战:用 pandas 清洗原始数据并转换为张量格式
《动手学深度学习》数据预处理实战:用 pandas 清洗原始数据并转换为张量格式 真实世界中的数据往往不是现成的张量,而是散落在 CSV、数据库或 API 中的
人工智能深度学习机器学习教程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考