机器学习实践-01数据准备流程
- 1.导入库
- 2.加载数据
-
- [2.1 读取sklearn内置数据](#2.1 读取sklearn内置数据)
- 2.2读取本地数据集
- 3.数据探索
-
- [3.1 打印数据信息(辅助删除无意义字段、识别类别/数值特征)](#3.1 打印数据信息(辅助删除无意义字段、识别类别/数值特征))
- 3.2绘图(使用matplotlib和seaborn库)
-
- [3.2.1 直方图](#3.2.1 直方图)
- [3.2.2 箱线图](#3.2.2 箱线图)
- [3.2.3 散点图](#3.2.3 散点图)
- [3.2.4 相关性热力图](#3.2.4 相关性热力图)
- [3.2.5 特征配对图](#3.2.5 特征配对图)
- [3.2.6 小提琴图](#3.2.6 小提琴图)
- [3.2.7 计数图](#3.2.7 计数图)
- 4.缺失值、异常值处理
-
- [4.1 缺失值处理](#4.1 缺失值处理)
- [4.2 异常值处理](#4.2 异常值处理)
- 5.离散数据编码
-
- [6.1 标签编码(LabelEncoder,适合有序分类 / 标签列)](#6.1 标签编码(LabelEncoder,适合有序分类 / 标签列))
- [6.2 离散特征独热编码(鸢尾花数据集没有离散特征,因此以最后一列作为示例)](#6.2 离散特征独热编码(鸢尾花数据集没有离散特征,因此以最后一列作为示例))
- [6.划分训练集 / 测试集](#6.划分训练集 / 测试集)
- 7.数据标准化
- 8.输出可训练数据(可选)
机器学习比较完整的实践流程为
①问题定义(回归、分类、聚类)
②数据采集(公开数据集、自采数据集)
③数据探索及预处理(缺失值、异常值)
④离散特征编码
⑤数据集划分(聚类不需要)
⑥数据标准化 / 归一化
⑦特征工程
⑧模型评估(留出法、交叉验证法等等)
⑨模型构建与训练
⑩模型预测
最后调参优化模型
其中,数据探索及预处理就像做饭前的洗菜切菜工作。下列是较为详细的过程。
1.导入库
导入核心工具库,包括numpy(数值、矩阵运算)、pandas(处理表格数据)、sklearn(机器学习各种方法)、matplotlib(任何图)、seaborn(好看的统计图表,Matplotlib的升级、美化版)等。
安装方法(后面是清华源镜像地址,可以不用科学上网快速安装所有库):
bash
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install scikit-learn -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install seaborn -i https://pypi.tuna.tsinghua.edu.cn/simple
导入:
bash
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.XXX import XXX(这里XXX需要看具体的需求,数据预处理\数据集划分\模型训练\模型评估等)
2.加载数据
读取数据,有两种形式,一种是读取sklearn内置数据,一种是读取本地数据集,这里以鸢尾花数据集为例。
2.1 读取sklearn内置数据
bash
import pandas as pd
from sklearn.datasets import load_iris # 自带数据集
# 1. 加载数据
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = pd.Series(iris.target)
2.2读取本地数据集
bash
import pandas as pd
df = pd.read_csv("iris.csv") #文件需要和代码在同一文件夹
#读取本地Excel文件
# df = pd.read_excel("iris.xlsx")
3.数据探索
数据探索包括
①打印数据信息 (文本形式)
②绘图
3.1 打印数据信息(辅助删除无意义字段、识别类别/数值特征)
bash
print(df.head()) #打印数据集前几行,默认为前5行
print(df.info()) #打印数据基本信息
print(df.describe())#打印数据集统计信息,包括总数、最大值、最小值等
df.drop("Unnamed: 0", axis=1, inplace=True)##删除索引列
3.2绘图(使用matplotlib和seaborn库)
3.2.1 直方图
查看单个特征的数据分布、是否对称、有无异常值、是否接近正态分布
bash
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
plt.figure(figsize=(8,4))
plt.hist(df['sepal_length'], bins=15, color='skyblue', edgecolor='black')
plt.title('花萼长度直方图')
plt.xlabel('sepal_length')
plt.ylabel('count')
plt.show()
3.2.2 箱线图
检测异常值、查看数据离散程度、对比不同类别特征的分布差异
bash
import seaborn as sns
plt.figure(figsize=(8,5))
sns.boxplot(x='species', y='sepal_length', data=df)
plt.title('不同品种花萼长度箱线图')
plt.show()
3.2.3 散点图
查看两个特征之间的关系、是否线性相关、不同品种是否能明显区分
bash
plt.figure(figsize=(8,6))
sns.scatterplot(x='sepal_length', y='petal_length', hue='species', data=df)
plt.title('花萼长度 vs 花瓣长度')
plt.show()
3.2.4 相关性热力图
直观展示所有数值特征之间的相关性强弱,用于特征筛选
bash
# 只取数值列计算相关系数
df.drop("Unnamed: 0", axis=1, inplace=True)
numeric_df = df.select_dtypes(include=['number'])
plt.figure(figsize=(8,6))
sns.heatmap(numeric_df.corr(), annot=True, cmap='coolwarm', fmt='.2f')
plt.title('特征相关性热力图')
plt.show()
3.2.5 特征配对图
一次性查看所有特征两两之间的关系 + 单特征分布,最适合分类任务
bash
sns.pairplot(df, hue='species')
plt.show()
3.2.6 小提琴图
结合箱线图 + 密度分布,同时展示数据分布形状、离散度、密度
python
plt.figure(figsize=(8,5))
sns.violinplot(x='species', y='petal_length', data=df)
plt.title('不同品种花瓣长度小提琴图')
plt.show()
3.2.7 计数图
查看每个类别样本数量是否均衡,判断数据集是否平衡
bash
plt.figure(figsize=(6,4))
sns.countplot(x='species', data=df)
plt.title('鸢尾花品种数量统计')
plt.show()
4.缺失值、异常值处理
4.1 缺失值处理
bash
print(df.isnull().sum())#检查缺失值
col = '含有空白值的列名'
| 方法名称 | 方法作用 | 可直接运行代码 | 适用场景 |
|---|---|---|---|
| 均值填充 | 使用整列特征的平均值填充缺失值 | df[col] = df[col].fillna(df[col].mean()) |
数据服从正态分布、无明显异常值 |
| 中位数填充 | 使用整列特征的中位数填充 | df[col] = df[col].fillna(df[col].median()) |
数据分布偏态、存在异常值(机器学习最常用) |
| 众数填充 | 使用出现次数最多的数值填充 | df[col] = df[col].fillna(df[col].mode()[0]) |
离散数值特征、整数型数据 |
| 固定值填充 | 使用自定义常数填充 | df[col] = df[col].fillna(0) |
缺失本身代表特定含义(未记录/未测量) |
| 前向填充 | 使用上方一行数据向下填充 | df[col] = df[col].ffill() |
时序数据、顺序有连续性的数据 |
| 后向填充 | 使用下方一行数据向上填充 | df[col] = df[col].bfill() |
时序数据、顺序有连续性的数据 |
| 线性插值填充 | 根据前后数值线性推算缺失值 | df[col] = df[col].interpolate(method='linear') |
连续变化特征、时序数据 |
| 分组填充 | 按分类标签分组后填充 | df[col] = df.groupby('species')[col].transform(lambda x: x.fillna(x.median())) |
分类任务,缺失值与类别高度相关 |
| KNN 模型填充 | 通过邻近样本特征预测缺失值 | from sklearn.impute import KNNImputer numeric_cols = df.select_dtypes(include=[np.number]).columns imputer = KNNImputer(n_neighbors=5) df[numeric_cols] = imputer.fit_transform(df[numeric_cols]) | 缺失值较多、追求高精度填充 |
| 直接删除 | 删除包含缺失值的行/列 | df = df.dropna(subset=[col]) |
缺失率极低(<5%),删除不影响数据量 |
4.2 异常值处理
箱线图外面的点 → 异常值
直方图远离群体 → 异常值
散点图孤零零的点 → 异常值
print(df.describe ()) 最大 / 最小值极端 → 异常值
| 方法名称 | 方法作用 | 可直接运行代码 | 适用场景 |
|---|---|---|---|
| 箱线图法(IQR 法) | 基于四分位数识别并删除异常值,最常用且稳定 | 见下方完整代码 | 适用于绝大多数数值特征,无严格分布要求 |
| 3σ 原则(Z 分数法) | 正态分布下,将超出 ±3σ 的值视为异常值 | 见下方完整代码 | 数据近似服从正态分布时适用 |
| 百分位法 | 通过上下百分位截断,消除极端值影响 | df = df[(df[col] > 0.01) & (df[col] < 0.99)] |
存在极端大/小值的情况 |
| 盖帽法(分位数替换) | 保留样本,将异常值替换为分位数边界值 | 见下方完整代码 | 样本量小且不希望删除数据时适用 |
| 直接删除法 | 直接删除包含异常值的行 | `df = df[~((df[col] < lower) | (df[col] > upper))]` |
| 按类别处理异常值 | 按不同类别分别处理异常值,提高精准度 | df = df.groupby('species').apply(remove_outliers) |
适用于分类任务(如鸢尾花数据集) |
bash
# 异常值处理:箱线图法(IQR法)
import numpy as np
# 定义异常值处理函数
#箱线图法(IQR)
def remove_outliers(df, col):
Q1 = df[col].quantile(0.25) # 下四分位数
Q3 = df[col].quantile(0.75) # 上四分位数
IQR = Q3 - Q1 # 四分位距
lower_bound = Q1 - 1.5 * IQR # 下界
upper_bound = Q3 + 1.5 * IQR # 上界
# 保留正常范围内的数据
df_clean = df[(df[col] >= lower_bound) & (df[col] <= upper_bound)]
return df_clean
# 对鸢尾花所有数值特征批量处理异常值
numeric_cols = ['sepal_length','sepal_width','petal_length','petal_width']
for col in numeric_cols:
df = remove_outliers(df, col)
print("异常值处理完成,数据形状:", df.shape)
bash
# 异常值处理:3σ原则(Z分数法)
#3σ 原则(Z 分数法)
def remove_outliers_zscore(df, col):
mean = df[col].mean()
std = df[col].std()
lower_bound = mean - 3 * std
upper_bound = mean + 3 * std
df_clean = df[(df[col] >= lower_bound) & (df[col] <= upper_bound)]
return df_clean
# 批量处理所有数值列
numeric_cols = df.select_dtypes(include=[np.number]).columns
for col in numeric_cols:
df = remove_outliers_zscore(df, col)
print("异常值处理完成,数据形状:", df.shape)
5.离散数据编码
6.1 标签编码(LabelEncoder,适合有序分类 / 标签列)
bash
# 对species列做标签编码(0,1,2对应3个品种)
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
le = LabelEncoder()
df['species'] = le.fit_transform(df['species'])
print(df.head())
6.2 离散特征独热编码(鸢尾花数据集没有离散特征,因此以最后一列作为示例)
bash
# 对species列做独热编码(生成3列0/1特征)
# 方式1:pandas原生get_dummies(简单易用)
df_onehot = pd.get_dummies(df, columns=['species'], drop_first=True)
print(df_onehot.head())
bash
#方式2 OneHotEncoder编码
# 1. 创建编码器
ohe = OneHotEncoder()
# 2. 对species列编码
encoded = ohe.fit_transform(df[["species"]]).toarray()
# 3. 转成 DataFrame
encoded_df = pd.DataFrame(encoded, columns=ohe.get_feature_names_out(["species"]))
# 4. 和原来的数字列合并(完整表格)
df_final = pd.concat([df.drop("species", axis=1), encoded_df], axis=1)
#不隐藏行列
pd.set_option("display.max_columns", None)
pd.set_option("display.width", None)
# pd.set_option('display.max_columns', 10) # 显示最多10列
# pd.set_option('display.max_rows', 20) # 显示最多20行
print(df_final.head())
6.划分训练集 / 测试集
bash
from sklearn.model_selection import train_test_split
X = df.drop('species', axis=1)
y = df['species']
X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y)
# 查看结果
print("训练集特征形状:", X_train.shape)
print("测试集特征形状:", X_test.shape)
print("\n训练集标签分布:\n", y_train.value_counts())
print("\n测试集标签分布:\n", y_test.value_counts())
7.数据标准化
bash
# 7. 数据标准化(Z-score 标准化)
from sklearn.preprocessing import StandardScaler
# 初始化标准化器
scaler = StandardScaler()
# 只在训练集上拟合(防止数据泄露)
X_train_scaled = scaler.fit_transform(X_train)
# 测试集直接用训练集的规则转换
X_test_scaled = scaler.transform(X_test)
# 查看结果
print("标准化前 训练集前2行:")
print(X_train[:2])
print("\n标准化后 训练集前2行:")
print(X_train_scaled[:2])
8.输出可训练数据(可选)
bash
# 8. 输出处理完成的可训练数据(可选)
import pandas as pd
# 合并训练集(特征 + 标签)
train_df = pd.DataFrame(X_train_scaled, columns=X.columns)
train_df['species'] = y_train.reset_index(drop=True)
# 合并测试集
test_df = pd.DataFrame(X_test_scaled, columns=X.columns)
test_df['species'] = y_test.reset_index(drop=True)
# 保存为 CSV
train_df.to_csv("train_iris.csv", index=False, encoding="utf-8")
test_df.to_csv("test_iris.csv", index=False, encoding="utf-8")
print("可训练数据已保存!")
print("训练集:train_iris.csv")
print("测试集:test_iris.csv")