简介:这份资源是《1. 机器学习前置知识》的配套数据集,面向刚入门机器学习、需要动手练习数据处理与建模的初学者,以及希望用真实数据巩固基础技能的学习者。压缩包共6个文件,以csv为主,另含1个h5和1个json,整体约2.76MB,体积轻便,便于快速加载与反复实验。数据覆盖多个典型场景:电影信息、讽刺新闻标题、星巴克门店目录、股票日线行情以及网约车出行记录,可分别用于回归、分类、文本处理和时间序列等基础练习。csv适合直接读取做特征工程与统计分析,h5便于高效存储与读取较大表格,json则可用于嵌套结构与文本字段的解析训练。目前已有4367人学习下载,说明该数据集在入门阶段具有较好的参考价值。通过它,读者可以熟悉数据加载、缺失值处理、字段类型转换与可视化探索等前置流程,为后续模型训练打下扎实基础。
1. 配套数据集到底解决什么问题:从“跑不动代码”到“跑通第一个模型”
很多人学机器学习,卡住的地方不是看不懂公式,而是打开教程第一行pd.read_csv('xxx.csv')就报错——文件不存在。教程里的数据集要么需要注册登录才能下载,要么路径写得含糊,要么版本对不上导致列名全变了。一套合格的《机器学习前置知识》配套数据集,核心价值就一个:让环境配置、数据加载、特征观察、简单建模这条链路,在没有任何外部依赖的情况下完整跑通。它通常包含结构化表格数据、少量图像或文本样本、以及一份说明字段含义的文档。适合两类人:刚学完 Python 基础、想验证自己能不能独立完成一次建模流程的新手;以及需要给教学或分享准备可复现材料的从业者。这一章先把“配套数据集该长什么样”讲清楚,后面再落到具体操作。
2. 配套数据集的结构设计与字段规范
2.1 为什么不能只丢一个 CSV 文件
常见做法是给一个data.csv就完事,但这对前置知识阶段很不友好。前置知识涵盖数据读取、缺失值处理、特征缩放、类别编码、训练集划分这几个环节,如果只有一个干净到没有任何问题的表格,学习者根本练不到清洗和预处理。我一般会把数据集拆成三层:原始层保留缺失值、异常值和混合类型字段;中间层提供一份已经做过基础清洗的版本用于对照;说明层用 Markdown 或纯文本写清楚每个字段的类型、取值范围、缺失比例和业务含义。这样做的理由是,学习者可以先在原始层踩坑,再拿中间层验证自己的处理结果是否合理,而不是对着一个“完美数据”无从下手。
2.2 目录结构与文件命名约定
一个可复现的配套数据集,目录结构本身就要有教学意义。下面是我常用的组织方式,不依赖任何特定平台,直接放在本地文件夹即可:
ml-prereq-dataset/ ├── raw/ # 原始数据,保留缺失和异常 │ ├── tabular_raw.csv │ ├── images_raw/ # 少量图像样本,用于演示读取 │ └── text_raw.txt ├── processed/ # 清洗后数据,用于对照 │ ├── tabular_clean.csv │ └── label_mapping.json ├── docs/ │ ├── field_description.md │ └── preprocessing_log.md └── load_data.py # 统一加载入口,避免路径写死raw/下的文件故意保留问题:tabular_raw.csv里数值列混入空字符串,类别列大小写不一致,还有几行重复记录。processed/下的tabular_clean.csv是参考答案,但不要一开始就看。load_data.py的作用是把路径统一管理起来,避免每个教程里都写绝对路径。
2.3 字段设计:让每个前置知识点都有对应练习
字段不是随便凑的。前置知识阶段需要覆盖:数值型与类别型区分、缺失值识别、异常值判断、类别不平衡观察、特征相关性初探。下面这张表是我设计表格数据时用的字段模板,可以直接照着改:
| 字段名 | 类型 | 是否含缺失 | 设计意图 |
|---|---|---|---|
| sample_id | 字符串 | 否 | 唯一标识,练习去重和索引设置 |
| age | 整数 | 是(约8%) | 缺失值填充练习 |
| income | 浮点数 | 是(约5%) | 缺失值+异常值(有负值) |
| category | 字符串 | 否 | 类别编码练习,大小写不统一 |
| score | 浮点数 | 否 | 特征缩放练习,量纲差异大 |
| label | 整数 | 否 | 二分类目标,正负样本约7:3 |
income列里故意放了几条负值,用来练习异常值检测;category列里同时出现"A"、"a"、" A "三种写法,用来练习字符串清洗。这些设计不是为了刁难,而是让学习者在真正拿到业务数据之前,先在小规模数据上把pandas的isnull()、describe()、value_counts()这些基础操作练熟。
3. 用配套数据集跑通第一个完整流程
3.1 环境准备与最小依赖
不需要装完整的数据科学全家桶。前置知识阶段,下面这几个包足够:
pip install pandas numpy scikit-learn matplotlib版本不用追新,pandas>=1.3、scikit-learn>=1.0就能跑通本文所有代码。如果用的是 conda,对应命令换成conda install pandas numpy scikit-learn matplotlib即可。装完之后用下面这段代码验证环境:
import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score print(pd.__version__, np.__version__)能正常打印版本号,说明基础环境没问题。如果报ModuleNotFoundError,优先检查是不是在虚拟环境里装的包,但当前终端用的是系统 Python。
3.2 加载原始数据并观察问题
不要一上来就清洗。先加载原始数据,把问题看清楚:
import pandas as pd # 加载原始数据,故意不指定 dtype,让 pandas 自己推断 df_raw = pd.read_csv('ml-prereq-dataset/raw/tabular_raw.csv') # 查看基本信息:行数、列数、类型、缺失情况 print(df_raw.info()) print(df_raw.isnull().sum()) print(df_raw['category'].value_counts()) print(df_raw['income'].describe())info()会告诉你哪些列被推断成了object类型——如果income里混了空字符串,它就不会是float64。isnull().sum()给出每列缺失数量。value_counts()看category列有多少种写法。describe()看income的最小值是不是负数。这一步的目的是建立“数据直觉”:先知道数据脏在哪,再决定怎么处理。
3.3 清洗、编码与划分:一步一验证
清洗过程要分步做,每步做完检查一次,不要一口气写几十行然后调试半天。下面是我常用的顺序:
# 1. 处理 income 列:先转数值,无法转换的变成 NaN df_raw['income'] = pd.to_numeric(df_raw['income'], errors='coerce') # 2. 用中位数填充 income 缺失值(比均值更抗异常值) median_income = df_raw['income'].median() df_raw['income'] = df_raw['income'].fillna(median_income) # 3. 处理 age 缺失值:用均值填充 df_raw['age'] = df_raw['age'].fillna(df_raw['age'].mean()) # 4. 清洗 category:去空格、统一小写 df_raw['category'] = df_raw['category'].str.strip().str.lower() # 5. 处理 income 负值:视为异常,用中位数替换 df_raw.loc[df_raw['income'] < 0, 'income'] = median_income # 6. 类别编码:用 pandas 的 get_dummies 做独热编码 df_encoded = pd.get_dummies(df_raw, columns=['category'], drop_first=True) # 7. 划分特征和目标 X = df_encoded.drop(['sample_id', 'label'], axis=1) y = df_encoded['label'] # 8. 划分训练集和测试集,固定随机种子保证可复现 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y ) # 9. 特征缩放:只对数值列做标准化 scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test)每一步的参数都有讲究。errors='coerce'让无法转换的值变成NaN而不是报错,适合脏数据。中位数填充比均值更稳,因为income有负值异常。stratify=y保证训练集和测试集里正负样本比例一致,避免小数据集上划分偏差。fit_transform只在训练集上做,测试集用transform,这是防止数据泄露的基本操作。
3.4 训练一个逻辑回归并检查结果
前置知识阶段不需要上复杂模型,逻辑回归足够验证流程是否跑通:
model = LogisticRegression(max_iter=1000, random_state=42) model.fit(X_train_scaled, y_train) y_pred = model.predict(X_test_scaled) acc = accuracy_score(y_test, y_pred) print(f'测试集准确率: {acc:.4f}') # 查看系数,理解哪些特征影响大 coef_df = pd.DataFrame({ 'feature': X.columns, 'coef': model.coef_[0] }).sort_values('coef', key=abs, ascending=False) print(coef_df.head(10))max_iter=1000是因为默认的 100 在未标准化或特征量纲差异大时可能不收敛。准确率不用追求高,前置知识阶段能到 0.75 以上就说明流程没问题。看系数是为了建立“特征重要性”的直觉,绝对值大的特征对预测影响大,但要注意这是标准化之后的系数,不能直接跨数据集比较。
4. 避坑与常见问题排查
4.1 路径写死导致换电脑就报错
现象:在自己电脑上跑得好好的,发给别人就FileNotFoundError。原因:代码里写了绝对路径,比如C:/Users/xxx/data.csv。解决:统一用相对路径,并且把数据目录和代码目录的相对关系固定下来。我一般会在项目根目录放一个load_data.py,里面用os.path.dirname(__file__)定位当前文件所在目录,再拼接raw/或processed/,这样不管项目被拷到哪都能找到数据。
4.2 缺失值填充用了全局统计量
现象:模型在测试集上表现异常好,但换一批数据就崩。原因:填充缺失值时用了整个数据集的均值或中位数,包括测试集的信息,造成数据泄露。解决:填充值只能从训练集计算,然后应用到测试集。正确做法是先把数据划分好,再在训练集上算median或mean,用这个值去填训练集和测试集。本文 3.3 节的代码为了演示方便在划分前做了填充,实际项目中要调整顺序。
4.3 类别编码后列名对不上
现象:训练时特征有 12 列,预测时只有 10 列,报feature_names mismatch。原因:get_dummies在训练集和测试集上分别调用时,如果某个类别只在其中一个集合出现,生成的列数会不一致。解决:先合并再做编码,或者用sklearn的OneHotEncoder并设置handle_unknown='ignore'。更简单的办法是在划分之前就完成编码,保证训练集和测试集共享同一套列。
4.4 标准化时对类别列也做了缩放
现象:模型准确率极低,或者报类型错误。原因:StandardScaler默认对所有列做数值计算,如果 DataFrame 里还有字符串列,会直接报错或产生无意义结果。解决:先做编码,把所有列变成数值型,再统一缩放;或者只选数值列做缩放,类别列保持独热编码后的 0/1 状态。本文 3.3 节是先编码再缩放,顺序不能反。
4.5 随机种子不固定导致结果无法复现
现象:每次运行准确率都不一样,没法判断改动是否有效。原因:train_test_split和模型初始化都有随机性。解决:所有涉及随机的环节都设random_state,并且整条流水线用同一个值。本文代码里train_test_split和LogisticRegression都设了random_state=42,就是为了保证任何人跑出来的结果一致。
5. 把配套数据集用出更大价值:从跑通到讲清楚
跑通一次流程只是起点。配套数据集真正的价值在于,它可以反复用来验证你对前置知识的理解是否到位。我习惯在每次学完一个新概念后,回到这套数据上做一个小实验。比如学完交叉验证,就把train_test_split换成cross_val_score,看准确率的波动范围;学完混淆矩阵,就把accuracy_score换成classification_report,观察正负样本的召回率差异。下面这张表是我常用的“概念-实验”对照,可以直接照着做:
| 学完的概念 | 在配套数据集上的实验 | 观察重点 |
|---|---|---|
| 交叉验证 | 用 5 折交叉验证替代单次划分 | 准确率均值与标准差 |
| 混淆矩阵 | 输出 classification_report | 正负样本召回率是否均衡 |
| 特征工程 | 增加一个组合特征再训练 | 系数变化和准确率变化 |
| 正则化 | 调整 LogisticRegression 的 C 参数 | C 越小正则越强,看系数收缩 |
| 不平衡处理 | 用 class_weight='balanced' 再训练 | 少数类召回率是否提升 |
做这些实验时,有一个习惯让我少走了很多弯路:每次只改一个变量。比如调C参数时,不要同时改特征或换模型,否则准确率变了你也不知道是哪个改动带来的。另一个习惯是记录实验日志,用最简单的文本文件就行,写清楚改了哪个参数、准确率从多少变到多少、有没有报错。这些记录积累下来,比任何教程都更贴合你自己的理解盲区。
还有一个容易被忽略的点:配套数据集里的docs/preprocessing_log.md不是摆设。我一般会要求自己在这个文件里写清楚每一步清洗的理由,比如“income 负值用中位数替换,因为负值可能是录入错误,且中位数不受极端值影响”。写不出来理由,说明这一步还没真正理解。这个习惯坚持下来,后面拿到真实业务数据时,清洗决策会快很多,也更有底气。
最后说一个我自己的教训。刚开始学的时候,我总想找“更大更真实”的数据集,觉得小数据练不出东西。后来发现,恰恰是这种字段少、问题明确的小数据集,才能让我把每个操作的前因后果想清楚。真实数据往往脏得没有规律,新手直接上手很容易陷入“调了半天也不知道哪里错了”的困境。这套配套数据集的作用,就是给你一个可控的练习场,把基础动作练成肌肉记忆。希望帮到你。
本文还有配套的精品资源,点击获取