​通透!十大数据预处理方法 最强总结!

文摘   2024-08-21 14:37   北京  

哈喽,我是cos大壮~

今儿和大家聊聊数据预处理方法。

数据预处理在机器学习和数据科学中是非常非常重要的,因为它直接影响模型的性能和准确性。

  1. 提高数据质量: 现实中的数据往往存在噪声、缺失值和异常值。如果不清洗和修正,这些问题会导致模型做出错误的预测或分析。因此,数据预处理通过清理、修复和标准化数据,确保输入的数据是干净、可靠的。

  2. 增强模型性能: 不同的特征在数据集中可能有不同的量纲或尺度,这可能会使某些特征对模型的影响过大或过小。通过归一化、标准化和特征选择,可以让模型更均衡地利用所有特征,从而提高模型的性能。

  3. 防止过拟合: 过多的特征或不相关的数据会增加模型的复杂性,导致过拟合。通过特征选择和降维,可以减少特征的数量,降低模型的复杂度,从而提高模型的泛化能力,防止过拟合。

  4. 处理不平衡数据: 在实际应用中,数据集的类别分布可能严重不平衡,如果不加以处理,模型可能会偏向多数类,忽视少数类。通过过采样、降采样等方法可以平衡数据集,从而提高模型对少数类的识别能力。

  5. 提高模型的解释性和效率: 简化数据结构和减少无用特征不仅可以提高模型的计算效率,还能使模型更容易解释。这样,决策者可以更好地理解模型的输出,并做出更明智的决策。

没有有效的数据预处理,模型可能难以捕捉到数据中的真实模式,最终影响预测结果的可靠性。

老规矩如果大家伙觉得近期文章还不错!欢迎大家点个赞、转个发,文末赠送《机器学习学习小册》
文末可取本文PDF版本~

今天提到的10种数据预处理方法有:

  • 标准化
  • 归一化
  • 主成分分析
  • 标签编码
  • 独热编码
  • 过采样
  • 滑动窗口
  • 插值
  • 降采样
  • 特征选择

咱们下面详细的聊聊这些方法,大家一定会有一个完整的认识。

1. 标准化(Standardization)

核心公式

标准化的目标是使数据具有零均值和单位方差。给定一个数据集 ,标准化的步骤如下:

  1. 计算均值:
  1. 计算标准差:
  1. 标准化公式:

通过上述公式,我们将每个数据点  转换为标准化值 ,使得所有数据点的均值为0,方差为1。

优点

  • 提高模型训练的稳定性。
  • 使不同特征具有相同的尺度,适合于对距离敏感的算法。

缺点

  • 对于有明显离群值的数据,标准化可能会受到影响,导致结果不理想。

适用场景

  • 特别适用于要求数据分布近似正态分布的算法,如SVM、线性回归和KNN等。

核心案例

from sklearn.datasets import fetch_california_housing
from sklearn.preprocessing import StandardScaler
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 加载数据集
california = fetch_california_housing()
data = pd.DataFrame(california.data, columns=california.feature_names)

# 原始数据统计信息
print("原始数据统计信息:\n", data.describe())

# 标准化
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data)

# 将标准化后的数据转为DataFrame
data_scaled = pd.DataFrame(data_scaled, columns=california.feature_names)

# 标准化后数据统计信息
print("标准化后数据统计信息:\n", data_scaled.describe())

# 可视化前后数据分布
plt.figure(figsize=(166))

# 标准化前的分布
plt.subplot(121)
sns.histplot(data['MedInc'], kde=True, color='blue')
plt.title('Distribution of Median Income before Standardization')

# 标准化后的分布
plt.subplot(122)
sns.histplot(data_scaled['MedInc'], kde=True, color='red')
plt.title('Distribution of Median Income after Standardization')

plt.show()

2. 归一化(Normalization)

核心公式

归一化的目标是将数据缩放到特定的范围(通常是[0, 1])。给定一个数据集 ,归一化的步骤如下:

  1. 找到最小值和最大值:
  1. 归一化公式:

通过该公式,所有数据点将被缩放到 [0, 1] 范围内。

优点

  • 使得数据在同一尺度上,有助于加快梯度下降的收敛速度。
  • 适用于需要计算距离的算法,如KNN和神经网络。

缺点

  • 对于有离群值的数据,归一化后的数据分布可能会受到影响。

适用场景

  • 特别适用于距离度量敏感的算法,如KNN、神经网络。

核心案例

我们将使用Iris数据集来展示归一化的效果,并生成相关的图表。

from sklearn.datasets import load_iris
from sklearn.preprocessing import MinMaxScaler
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 加载数据集
iris = load_iris()
data = pd.DataFrame(iris.data, columns=iris.feature_names)

# 原始数据统计信息
print("原始数据统计信息:\n", data.describe())

# 归一化
scaler = MinMaxScaler()
data_normalized = scaler.fit_transform(data)

# 将归一化后的数据转为DataFrame
data_normalized = pd.DataFrame(data_normalized, columns=iris.feature_names)

# 归一化数据统计信息
print("归一化后数据统计信息:\n", data_normalized.describe())

# 可视化前后数据分布
plt.figure(figsize=(166))

# 归一化前的分布
plt.subplot(121)
sns.histplot(data['sepal length (cm)'], kde=True, color='green')
plt.title('Distribution of Sepal Length before Normalization')

# 归一化后的分布
plt.subplot(122)
sns.histplot(data_normalized['sepal length (cm)'], kde=True, color='orange')
plt.title('Distribution of Sepal Length after Normalization')

plt.show()

3. 主成分分析(PCA)

核心公式

主成分分析的目标是将高维数据投影到低维空间,同时最大化投影后的方差。核心步骤包括:

  1. 数据中心化:

其中  是数据的均值向量。

  1. 计算协方差矩阵:
  1. 特征分解: 对协方差矩阵  进行特征分解,得到特征值和特征向量:

其中  为特征值, 为对应的特征向量。

  1. 降维: 选择前  个最大特征值对应的特征向量,形成投影矩阵 ,然后将数据投影到低维空间:

优点

  • 能有效降低数据的维度,减少计算复杂度。
  • 可以去除冗余特征,提高模型的泛化能力。

缺点

  • PCA是线性方法,对于非线性数据效果不佳。
  • 主成分的物理意义不明确,可能不利于解释。

适用场景

  • 特别适用于高维数据的降维,如图像处理、基因数据分析。

核心案例

我们使用Wine数据集来展示PCA的效果~

from sklearn.datasets import load_wine
from sklearn.decomposition import PCA
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 加载数据集
wine = load_wine()
data = pd.DataFrame(wine.data, columns=wine.feature_names)

# 原始数据统计信息
print("原始数据统计信息:\n", data.describe())

# PCA降维至2维
pca = PCA(n_components=2)
data_pca = pca.fit_transform(data)

# 将PCA后的数据转为DataFrame
data_pca = pd.DataFrame(data_pca, columns=['PC1''PC2'])

# 可视化PCA结果
plt.figure(figsize=(108))
sns.scatterplot(x='PC1', y='PC2', hue=wine.target, palette='bright', data=data_pca)
plt.title('PCA of Wine Dataset')
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.show()

4. 标签编码(Label Encoding)

核心逻辑

标签编码的目标是将分类变量转换为整数值,使得模型可以处理非数值数据。

具体步骤如下:

类别映射:

假设有一个分类特征 ,标签编码将每个类别  映射为一个整数值 

例如,

优点

  • 简单易用,适合有序的类别数据。
  • 对存储空间需求小,直接使用整数表示。

缺点

  • 对无序类别数据引入了虚假的顺序关系,可能影响模型性能。

适用场景

  • 适用于有序类别数据,如学历(高中、本科、硕士)。

核心案例

我们使用模拟的学历数据来展示标签编码的效果,并生成相关的图表。

import pandas as pd
from sklearn.preprocessing import LabelEncoder
import matplotlib.pyplot as plt
import seaborn as sns

# 创建示例数据
data = pd.DataFrame({
    'Education': ['High School''Bachelor''Master''PhD''Bachelor''High School''Master''PhD']
})

# 标签编码
label_encoder = LabelEncoder()
data['Education_encoded'] = label_encoder.fit_transform(data['Education'])

# 可视化标签编码结果
plt.figure(figsize=(86))
sns.countplot(x='Education_encoded', data=data, palette='coolwarm')
plt.title('Label Encoded Education Levels')
plt.xlabel('Encoded Labels')
plt.ylabel('Count')
plt.show()

print("标签编码结果:\n", data)

5. 独热编码(One-Hot Encoding)

核心公式

独热编码的目标是将分类变量转换为二进制向量,使得每个类别被单独表示。假设有一个分类特征 ,独热编码的步骤如下:

类别向量化:

每个类别  被表示为一个长度为  的二进制向量,其中第  位为1,其余为0。

例如,

优点

  • 消除类别之间的顺序关系,避免模型引入虚假的顺序信息。
  • 提高模型对类别变量的处理能力,适合无序类别。

缺点

  • 当类别较多时,会显著增加数据的维度,导致“维度灾难”。
  • 对于高基数的分类特征,如城市、国家,编码后的稀疏矩阵会占用大量内存。

适用场景

  • 适用于无序类别数据,如性别、颜色等。

核心案例

我们使用Titanic数据集中的性别特征来展示独热编码的效果~

import pandas as pd
from sklearn.preprocessing import OneHotEncoder
import matplotlib.pyplot as plt
import seaborn as sns

# 创建示例数据
data = pd.DataFrame({
    'Gender': ['Male''Female''Female''Male''Female''Male''Male''Female']
})

# 独热编码
onehot_encoder = OneHotEncoder(sparse=False)
gender_encoded = onehot_encoder.fit_transform(data[['Gender']])

# 将独热编码后的数据转为DataFrame
gender_encoded_df = pd.DataFrame(gender_encoded, columns=onehot_encoder.categories_[0])

# 可视化独热编码结果
plt.figure(figsize=(86))
sns.heatmap(gender_encoded_df, annot=True, cbar=False, cmap='coolwarm')
plt.title('One-Hot Encoded Gender')
plt.xlabel('Gender')
plt.ylabel('Sample Index')
plt.show()

print("独热编码结果:\n", gender_encoded_df)

6. 过采样(Over-sampling)

核心公式

过采样的目标是通过复制少数类样本来平衡类别分布,主要方法包括简单复制和SMOTE(合成少数类过采样技术)。

SMOTE的核心步骤如下:

  1. 选择样本: 从少数类样本中随机选择一个样本 

  2. 找到k个最近邻样本: 在少数类样本中找到k个最近邻样本 

  3. 生成新样本: 在原样本  和一个最近邻样本  之间生成一个新样本 ,其计算公式为:

其中  是一个0到1之间的随机数。

优点

  • 增加少数类样本数量,提高分类模型对少数类的识别能力。
  • 使用SMOTE生成的新样本更具多样性,减轻了过拟合的风险。

缺点

  • 可能会引入噪声样本,导致模型过拟合。
  • 简单复制方法可能会加剧少数类的过拟合问题。

适用场景

  • 特别适用于类别不平衡问题,如欺诈检测、医疗诊断等。

核心案例

我们使用模拟的二分类不平衡数据集来展示过采样的效果~

from sklearn.datasets import make_classification
from imblearn.over_sampling import SMOTE
import matplotlib.pyplot as plt
import seaborn as sns

# 创建不平衡数据集
X, y = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0,
                           n_clusters_per_class=1, weights=[0.90.1], random_state=42)

# 使用SMOTE进行过采样
smote = SMOTE(random_state=42)
X_resampled, y_resampled = smote.fit_resample(X, y)

# 可视化过采样前后的数据分布
plt.figure(figsize=(166))

# 过采样前
plt.subplot(121)
sns.scatterplot(X[:, 0], X[:, 1], hue=y, palette='coolwarm')
plt.title('Before SMOTE')

# 过采样后
plt.subplot(122)
sns.scatterplot(X_resampled[:, 0], X_resampled[:, 1], hue=y_resampled, palette='coolwarm')
plt.title('After SMOTE')

plt.show()

7. 滑动窗口(Sliding Window)

核心公式

滑动窗口的目标是在时间序列数据上提取固定大小的子序列,用于捕捉局部时间特征。

核心步骤:

  1. 定义窗口大小: 设定窗口大小  和步长 

  2. 生成窗口: 对时间序列数据  ,从第  个时间步开始,生成子序列 

  1. 移动窗口: 按照步长  移动窗口,生成下一个子序列,直到覆盖整个时间序列。

优点

  • 能有效捕捉时间序列中的局部模式或趋势。
  • 适合短期预测和时间序列特征提取。

缺点

  • 选择合适的窗口大小较为困难。
  • 对于长序列,滑动窗口生成的大量子序列可能会带来计算开销。

适用场景

  • 特别适用于时间序列预测,如股票价格预测、天气预报等。

核心案例

我们使用模拟的股票价格数据来展示滑动窗口的效果~

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 创建模拟的股票价格数据
np.random.seed(42)
time = np.arange(100)
price = np.sin(time / 10) + np.random.normal(scale=0.1, size=len(time))

data = pd.DataFrame({'Time': time, 'Price': price})

# 定义滑动窗口函数
def sliding_window(data, window_size):
    return np.array([data[i:i + window_size] for i in range(len(data) - window_size + 1)])

# 设置窗口大小
window_size = 10
windows = sliding_window(data['Price'], window_size)

# 可视化滑动窗口结果
plt.figure(figsize=(166))
for i, window in enumerate(windows[:5]):
    plt.plot(range(i, i + window_size), window, marker='o')

plt.title('Sliding Window on Simulated Stock Price')
plt.xlabel('Time')
plt.ylabel('Price')
plt.show()

8. 插值(Interpolation)

核心公式

插值的目标是通过已知数据点估计未知数据点。常用方法包括线性插值、多项式插值和样条插值。

核心步骤:

  1. 线性插值公式: 对于两个已知数据点   ,插值点  对应的  值为:
  1. 多项式插值: 利用拉格朗日插值公式或牛顿插值公式,通过高阶多项式拟合已知数据点。

  2. 样条插值: 在每个子区间上使用低阶多项式插值,同时保证多项式在区间连接处的光滑性。

优点

  • 能有效填补缺失数据,提高数据集的完整性。
  • 多种插值方法可用于不同数据特征的拟合。

缺点

  • 插值方法过于复杂时可能引入噪声或过拟合。
  • 在外推时(即在数据范围之外进行预测),插值结果不可靠。

适用场景

  • 特别适用于有缺失值的数据,如气象数据、传感器数据。

核心案例

我们使用模拟的温度数据来展示插值的效果~

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d

# 创建模拟的温度数据
np.random.seed(42)
time = np.arange(01000.5)
temperature = np.sin(time) + np.random.normal(scale=0.1, size=len(time))

# 模拟缺失值
temperature[5:7] = np.nan

data = pd.DataFrame({'Time': time, 'Temperature': temperature})

# 线性插值
linear_interp = interp1d(data['Time'], data['Temperature'], kind='linear', fill_value="extrapolate")
time_new = np.arange(01000.1)
temperature_linear = linear_interp(time_new)

# 可视化插值结果
plt.figure(figsize=(126))
plt.plot(data['Time'], data['Temperature'], 'o', label='Original Data')
plt.plot(time_new, temperature_linear, '-', label='Linear Interpolation')
plt.title('Linear Interpolation of Simulated Temperature Data')
plt.xlabel('Time')
plt.ylabel('Temperature')
plt.legend()
plt.show()

9. 降采样(Under-sampling)

核心公式

降采样的目标是通过减少多数类样本来平衡类别分布。最简单的方法是随机采样,即从多数类中随机选择与少数类同等数量的样本。

  1. 计算多数类样本数: 假设多数类样本数为 ,少数类样本数为 

  2. 随机采样: 从多数类样本中随机选择  个样本。

优点

  • 降低数据集的不平衡性,提高分类器对少数类的识别能力。
  • 减少计算开销,适合大规模数据集。

缺点

  • 可能丢失多数类的关键信息,降低模型的整体性能。
  • 只适用于多数类样本数远多于少数类样本数的情况。

适用场景

  • 特别适用于类别严重不平衡的数据,如垃圾邮件检测、不良信用记录分析等。

核心案例

我们使用模拟的二分类不平衡数据集来展示降采样的效果~

from sklearn.datasets import make_classification
from imblearn.under_sampling import RandomUnderSampler
import matplotlib.pyplot as plt
import seaborn as sns

# 创建不平衡数据集
X, y = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0,
                           n_clusters_per_class=1, weights=[0.90.1], random_state=42)

# 使用随机降采样
undersampler = RandomUnderSampler(random_state=42)
X_resampled, y_resampled = undersampler.fit_resample(X, y)

# 可视化降采样前后的数据分布
plt.figure(figsize=(166))

# 降采样前
plt.subplot(121)
sns.scatterplot(X[:, 0], X[:, 1], hue=y, palette='coolwarm')
plt.title('Before Under-sampling')

# 降采样后
plt.subplot(122)
sns.scatterplot(X_resampled[:, 0], X_resampled[:, 1], hue=y_resampled, palette='coolwarm')
plt.title('After Under-sampling')

plt.show()

10. 特征选择(Feature Selection)

核心公式

特征选择的目标是从高维数据集中选出最具代表性的一部分特征,常用方法包括过滤法(Filter)、包裹法(Wrapper)和嵌入法(Embedded)。

以过滤法中的卡方检验为例,核心步骤:

  1. 卡方检验公式: 对于每个特征  与标签  之间,计算卡方统计量:

其中  是观察值, 是期望值。

  1. 特征选择: 选择卡方统计量最大的前  个特征。

优点

  • 减少特征数量,降低模型复杂度,防止过拟合。
  • 提高模型的泛化能力和解释性。

缺点

  • 可能丢失有用信息,影响模型性能。
  • 需要精心选择特征选择方法,适应不同的模型和数据。

适用场景

  • 特别适用于高维数据集,如文本分类、基因表达数据分析。

核心案例

我们使用Breast Cancer数据集来展示特征选择的效果~

from sklearn.datasets import load_breast_cancer
from sklearn.feature_selection import SelectKBest, chi2
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 加载数据集
cancer = load_breast_cancer()
data = pd.DataFrame(cancer.data, columns=cancer.feature_names)

# 使用卡方检验选择前10个最重要的特征
selector = SelectKBest(chi2, k=10)
selector.fit(data, cancer.target)
data_selected = data.iloc[:, selector.get_support(indices=True)]

# 可视化特征选择结果
plt.figure(figsize=(126))
sns.barplot(x=data.columns[selector.get_support()], y=selector.scores_[selector.get_support()])
plt.title('Top 10 Features Selected by Chi-Square Test')
plt.xlabel('Features')
plt.ylabel('Chi-Square Score')
plt.xticks(rotation=90)
plt.show()


最后

大家有问题可以直接在评论区留言即可~

喜欢本文的朋友可以收藏、点赞、转发起来!
需要本文PDF的同学,扫码备注「模型汇总」即可~ 
关注本号,带来更多算法干货实例,提升工作学习效率!
最后,给大家准备了《机器学习学习小册》PDF版本16大块的内容,124个问题总结

推荐阅读

原创、超强、精华合集
100个超强机器学习算法模型汇总
机器学习全路线
机器学习各个算法的优缺点
7大方面,30个最强数据集
6大部分,20 个机器学习算法全面汇总
铁汁,都到这了,别忘记点赞呀~

深夜努力写Python
Python、机器学习算法
 最新文章