第2集:数据预处理——机器学习的第一步
在机器学习的旅程中,数据预处理是至关重要的第一步。它决定了模型训练的质量和最终性能。没有经过良好预处理的数据就像未经打磨的钻石,虽然可能蕴含价值,但难以展现其光彩。今天我们将深入探讨数据预处理的关键步骤,并通过实践部分展示如何对经典数据集 Titanic 进行清洗与转换。
图片源。1
为什么数据清洗如此重要?
数据通常是“脏”的——包含噪声、缺失值、重复记录或格式不一致等问题。这些问题会直接影响模型的学习能力,甚至导致错误的结论。例如:
- 缺失值可能导致算法无法正常运行。
- 异常值可能误导模型,使其偏向错误的方向。
- 不一致的格式(如日期、单位)会让数据变得不可用。
图1:数据清洗前后对比
(图片描述:待数据清洗示意,包含缺失值、异常值和乱码;)
数据清洗的核心步骤
1. 缺失值处理
缺失值是数据集中最常见的问题之一。处理方法包括:
- 删除:如果缺失值比例较高,可以直接删除相关样本或特征。
- 填充:使用均值、中位数、众数或其他统计量进行填充。
- 插值法:对于时间序列数据,可以采用线性插值等方法。
示例代码(Python实现):
import pandas as pd# 加载数据
data = pd.read_csv('titanic.csv')# 填充年龄列的缺失值(使用中位数)
data['Age'].fillna(data['Age'].median(), inplace=True)# 删除含有大量缺失值的列
data.dropna(axis=1, thresh=int(0.8 * len(data)), inplace=True)
2. 异常值检测与标准化
异常值是指那些偏离正常范围的极端值。它们可能是录入错误,也可能是真实但罕见的情况。常用方法包括:
- 箱线图:可视化识别异常值。
- Z-Score:计算每个数据点的标准分数,剔除超出一定阈值的值。
标准化
为了确保不同特征具有相同的尺度,通常需要对数据进行标准化。常见方法有:
- Min-Max Scaling:将数据缩放到 [0, 1] 区间。
- Z-Score Standardization:将数据转换为均值为 0,标准差为 1 的分布。
示例代码(Python实现):
from sklearn.preprocessing import StandardScaler# 标准化 Fare 列
scaler = StandardScaler()
data['Fare'] = scaler.fit_transform(data[['Fare']])
图2:箱线图显示异常值
(图片描述:箱线图常用于发现和标记异常值。)
3. 特征编码
许多机器学习算法只能处理数值型数据,因此需要将类别型特征转化为数值形式。两种常用方法如下:
One-Hot Encoding
适用于无序分类变量,例如性别(男/女)。每种类别都会生成一个新的二进制特征。
Label Encoding
适用于有序分类变量,例如教育水平(小学 < 初中 < 高中)。直接将类别映射为整数。
示例代码(Python实现):
from sklearn.preprocessing import OneHotEncoder, LabelEncoder# 对 Sex 列进行 One-Hot Encoding
encoder = OneHotEncoder(sparse=False)
sex_encoded = encoder.fit_transform(data[['Sex']])
data = pd.concat([data, pd.DataFrame(sex_encoded, columns=['Male', 'Female'])], axis=1)# 对 Embarked 列进行 Label Encoding
label_encoder = LabelEncoder()
data['Embarked'] = label_encoder.fit_transform(data['Embarked'])
4. 数据分割
为了评估模型的泛化能力,我们需要将数据分为训练集和测试集。一般推荐的比例是 80% 训练集 + 20% 测试集。
示例代码(Python实现):
from sklearn.model_selection import train_test_split# 分割数据集
X = data.drop('Survived', axis=1) # 特征
y = data['Survived'] # 标签
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
实践部分:Titanic 数据集的预处理
我们以著名的 Titanic 数据集为例,演示完整的预处理流程。
数据集简介
Titanic 数据集包含了泰坦尼克号乘客的信息,目标是预测某位乘客是否幸存。主要特征包括:
Pclass
:船票等级Sex
:性别Age
:年龄SibSp
:兄弟姐妹/配偶数量Parch
:父母/子女数量Fare
:票价Embarked
:登船港口
完整代码
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, OneHotEncoder, LabelEncoder# 加载数据
url = "https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv"
data = pd.read_csv(url)# 处理缺失值
data['Age'].fillna(data['Age'].median(), inplace=True)
data['Embarked'].fillna(data['Embarked'].mode()[0], inplace=True)# 删除无关列
data.drop(['Name', 'Ticket', 'Cabin'], axis=1, inplace=True)# 特征编码
encoder = OneHotEncoder(sparse=False)
sex_encoded = encoder.fit_transform(data[['Sex']])
embarked_encoded = encoder.fit_transform(data[['Embarked']])
data = pd.concat([data,pd.DataFrame(sex_encoded, columns=['Male', 'Female']),pd.DataFrame(embarked_encoded, columns=['Embarked_C', 'Embarked_Q', 'Embarked_S'])
], axis=1)
data.drop(['Sex', 'Embarked'], axis=1, inplace=True)# 标准化 Fare 列
scaler = StandardScaler()
data['Fare'] = scaler.fit_transform(data[['Fare']])# 分割数据集
X = data.drop('Survived', axis=1)
y = data['Survived']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)print("数据预处理完成!")
数据可视化清洗结果
在数据清洗和预处理完成后,可视化是展示清洗结果的重要手段。通过可视化,我们可以直观地了解数据分布、缺失值处理效果以及特征编码后的变化。以下是一些常见的可视化方法及其代码示例:
在数据清洗和预处理完成后,可视化是展示清洗结果的重要手段。通过可视化,我们可以直观地了解数据分布、缺失值处理效果以及特征编码后的变化。以下是一些常见的可视化方法及其代码示例:
1. 缺失值处理前后的对比
可视化目标:
- 展示原始数据中缺失值的分布。
- 对比清洗后缺失值是否被成功填补。
示例代码:
import matplotlib.pyplot as plt
import seaborn as sns# 加载原始数据
url = "https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv"
original_data = pd.read_csv(url)# 统计原始数据中的缺失值
missing_before = original_data.isnull().sum()# 统计清洗后的缺失值
missing_after = data.isnull().sum()# 创建对比图
fig, ax = plt.subplots(figsize=(10, 6))
missing_before.plot(kind='bar', color='red', alpha=0.6, label='Before Cleaning')
missing_after.plot(kind='bar', color='green', alpha=0.6, label='After Cleaning')
plt.title('Missing Values Before and After Cleaning', fontsize=16)
plt.xlabel('Features', fontsize=12)
plt.ylabel('Number of Missing Values', fontsize=12)
plt.legend()
plt.show()
图1:缺失值处理前后对比
(图片描述:柱状图展示了每个特征在清洗前后的缺失值数量,红色表示清洗前,绿色表示清洗后。)
2. 年龄(Age)列填充效果的分布对比
可视化目标:
- 比较填充缺失值前后
Age
列的分布,确保填充策略没有显著改变数据分布。
示例代码:
# 原始数据中 Age 的分布(包含缺失值)
sns.histplot(original_data['Age'], color='blue', kde=True, bins=30, label='Original')# 清洗后 Age 的分布
sns.histplot(data['Age'], color='orange', kde=True, bins=30, label='After Filling')plt.title('Age Distribution Before and After Filling Missing Values', fontsize=16)
plt.xlabel('Age', fontsize=12)
plt.ylabel('Frequency', fontsize=12)
plt.legend()
plt.show()
图2:年龄分布对比
(图片描述:直方图展示了Age
列在清洗前后的分布情况,蓝色为原始数据,橙色为填充后的数据。)
3. 标准化前后票价(Fare)的分布对比
可视化目标:
- 展示
Fare
列在标准化前后的分布变化。
示例代码:
# 原始数据中 Fare 的分布
sns.histplot(original_data['Fare'], color='purple', kde=True, bins=30, label='Original')# 标准化后的 Fare 分布
sns.histplot(data['Fare'], color='green', kde=True, bins=30, label='Standardized')plt.title('Fare Distribution Before and After Standardization', fontsize=16)
plt.xlabel('Fare', fontsize=12)
plt.ylabel('Frequency', fontsize=12)
plt.legend()
plt.show()
图3:票价分布对比
(图片描述:直方图展示了Fare
列在标准化前后的分布情况,紫色为原始数据,绿色为标准化后的数据。)
4. 类别型特征编码后的分布
可视化目标:
- 展示类别型特征(如
Sex
和Embarked
)在 One-Hot 编码后的分布。
示例代码:
# 性别分布
gender_counts = original_data['Sex'].value_counts()
plt.figure(figsize=(8, 5))
sns.barplot(x=gender_counts.index, y=gender_counts.values, palette='Set2')
plt.title('Gender Distribution (Before Encoding)', fontsize=16)
plt.xlabel('Gender', fontsize=12)
plt.ylabel('Count', fontsize=12)
plt.show()# One-Hot 编码后的性别分布
encoded_gender = data[['Male', 'Female']].sum()
plt.figure(figsize=(8, 5))
sns.barplot(x=['Male', 'Female'], y=encoded_gender.values, palette='Set2')
plt.title('Gender Distribution (After One-Hot Encoding)', fontsize=16)
plt.xlabel('Gender', fontsize=12)
plt.ylabel('Count', fontsize=12)
plt.show()
图4:性别分布对比
(图片描述:条形图展示了性别在编码前后的分布情况,上图为原始分类数据,下图为 One-Hot 编码后的数据。)
5. 相关性热力图
可视化目标:
- 展示清洗后特征之间的相关性,帮助理解哪些特征对目标变量(
Survived
)的影响较大。
示例代码:
# 计算相关性矩阵
correlation_matrix = data.corr()# 绘制热力图
plt.figure(figsize=(12, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt='.2f')
plt.title('Feature Correlation Matrix', fontsize=16)
plt.show()
图5:特征相关性热力图
(图片描述:热力图展示了清洗后各特征之间的相关性,颜色越深表示相关性越高。)
通过上述可视化方法,我们能够清晰地展示数据清洗的效果,包括缺失值处理、特征编码和标准化的结果。这些图表不仅有助于验证清洗过程的正确性,还能为后续建模提供洞察。
希望这些代码能帮助你更好地展示数据清洗的结果!如果你有其他需求或想法,请随时告诉我!
总结
数据预处理是机器学习项目中最耗时但也最重要的环节。通过本文,我们了解了以下关键步骤:
- 缺失值处理:填补或删除缺失值。
- 异常值检测与标准化:提升数据质量并统一尺度。
- 特征编码:将类别型特征转化为数值型。
- 数据分割:构建训练集和测试集。
希望这篇文章能帮助你更好地理解数据预处理的精髓!如果你有任何疑问,欢迎在评论区留言讨论。
下集预告:第3集:线性回归——预测连续变量
参考资料
- Titanic 数据集
- Scikit-learn 文档: https://scikit-learn.org/stable/documentation.html
注脚的解释 [图片引用来自:https://zhuanlan.zhihu.com/p/469319284] ↩︎