机器学习笔记一-数据预处理

数据预处理是数据分析、机器学习和深度学习等领域中的重要步骤。它包括清洗、转换、归一化、编码等操作,旨在使数据适合于建模和分析。数据预处理的质量直接影响模型的性能和准确性。下面详细介绍数据预处理的常见步骤和技术。

1. 数据清洗

  • 处理缺失值:
    • 删除缺失数据: 如果缺失值的数量较少,或者缺失的样本对分析无关紧要,可以直接删除。
    • 插值填补: 使用均值、中位数、众数、或插值等方法填补缺失值。
    import pandas as pd
    
    # 删除包含缺失值的行
    df.dropna(inplace=True)
    
    # 用均值填补缺失值
    df.fillna(df.mean(), inplace=True)
    
    • 预测填补: 使用其他变量预测缺失值,例如使用回归模型填补。
      你可以使用回归模型来填补缺失值。以下是使用 scikit-learn 中的回归模型来填补缺失值的代码示例。假设我们有一个数据集,其中某一列有缺失值,其他列将用于预测该列的缺失值。

步骤

  1. 数据准备:我们会将数据分为两部分——缺失值部分和非缺失值部分。
  2. 训练模型:在非缺失值部分使用回归模型来训练。
  3. 预测缺失值:使用模型对缺失值部分进行预测。

以下是代码示例:

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.impute import SimpleImputer

# 示例数据集
data = {
    'feature1': [1, 2, 3, 4, 5],
    'feature2': [2, 4, np.nan, 8, 10],
    'target': [5, 10, 15, np.nan, 25]
}

df = pd.DataFrame(data)

# 1. 将有缺失值的部分和没有缺失值的部分分开
# 找到 target 列中没有缺失值的行
df_no_missing = df[df['target'].notna()]
df_missing = df[df['target'].isna()]

# 2. 使用 feature1 和 feature2 作为预测特征,target 作为标签
X_train = df_no_missing[['feature1', 'feature2']]
y_train = df_no_missing['target']

# 填补 feature2 中的缺失值(假设 feature2 中也有缺失值)
imputer = SimpleImputer(strategy='mean')
X_train = imputer.fit_transform(X_train)

# 3. 使用回归模型进行训练
regressor = LinearRegression()
regressor.fit(X_train, y_train)

# 4. 对缺失值部分进行预测
X_missing = df_missing[['feature1', 'feature2']]
X_missing = imputer.transform(X_missing)
df_missing['target'] = regressor.predict(X_missing)

# 5. 填补原始数据中的缺失值
df.loc[df['target'].isna(), 'target'] = df_missing['target']

print(df)
  • 处理异常值:

    • 检测异常值: 可以使用箱线图、标准差、Z-score 等方法检测异常值。
    # 使用Z-score检测异常值
    from scipy import stats
    z_scores = stats.zscore(df['column_name'])
    abs_z_scores = np.abs(z_scores)
    filtered_entries = (abs_z_scores < 3)
    df = df[filtered_entries]
    

使用箱线图检测异常值

你可以使用箱线图(Box Plot)来检测数据集中的异常值。箱线图通过展示数据的五数概括(最小值、第一四分位数、中位数、第三四分位数、最大值)来识别潜在的异常值。通常,超出 1.5 倍四分位距(IQR: Interquartile Range) 的数据点被视为异常值。

以下是如何使用 matplotlibseaborn 来绘制箱线图并检测异常值的代码示例。

步骤

  1. 计算 IQR:第一四分位数(Q1)和第三四分位数(Q3)的差值。
  2. 定义上下限:用 Q1 - 1.5 * IQR 和 Q3 + 1.5 * IQR 作为异常值检测的标准。
  3. 绘制箱线图:使用 seaborn 库绘制。

代码示例

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

# 示例数据集
data = {
    'feature1': [10, 12, 14, 15, 16, 18, 22, 25, 30, 100],  # 100 是异常值
    'feature2': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}

df = pd.DataFrame(data)

# 绘制箱线图
plt.figure(figsize=(8, 6))
sns.boxplot(data=df['feature1'])
plt.title("Box Plot for Feature1")
plt.show()

# 计算 IQR 进行异常值检测
Q1 = df['feature1'].quantile(0.25)
Q3 = df['feature1'].quantile(0.75)
IQR = Q3 - Q1

# 定义异常值的上下限
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

# 找到异常值
outliers = df[(df['feature1'] < lower_bound) | (df['feature1'] > upper_bound)]
print("异常值为:")
print(outliers)

代码说明

  1. 箱线图:使用 seaborn.boxplot() 来展示 feature1 列的箱线图。
  2. IQR 计算:通过 quantile() 方法来计算 Q1 和 Q3。
  3. 异常值检测:通过计算上下限,筛选出异常值。
  4. 绘制图表:用 matplotlib 显示箱线图。

输出结果

  • 图表中,箱线图的 “胡须” 部分会标识正常范围的数据点,位于胡须之外的数据点被视为异常值(例如 100)。
  • 控制台中会输出检测出的异常值。

使用标准差检测异常值

使用标准差来检测异常值是另一种常用的方法。通过计算数据的均值和标准差,可以定义一个数据范围,通常使用 3倍标准差 作为上下界。任何超出此范围的值都被视为异常值。

步骤

  1. 计算均值和标准差
  2. 定义上下界:用 mean ± 3 * standard deviation 作为异常值检测的标准。
  3. 检测异常值

以下是如何使用 pandasnumpy 来基于标准差检测异常值的代码示例。

代码示例

import pandas as pd
import numpy as np

# 示例数据集
data = {
    'feature1': [10, 12, 14, 15, 16, 18, 22, 25, 30, 100],  # 100 是异常值
    'feature2': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}

df = pd.DataFrame(data)

# 计算均值和标准差
mean = df['feature1'].mean()
std_dev = df['feature1'].std()

# 定义异常值的上下界 (mean ± 3 * standard deviation)
lower_bound = mean - 3 * std_dev
upper_bound = mean + 3 * std_dev

# 找到异常值
outliers = df[(df['feature1'] < lower_bound) | (df['feature1'] > upper_bound)]
print("异常值为:")
print(outliers)

# 输出上下界
print(f"下界: {lower_bound}, 上界: {upper_bound}")

代码说明

  1. 均值和标准差计算mean()std() 函数用于计算 feature1 列的均值和标准差。
  2. 定义上下界:使用均值和 3 倍标准差来确定检测异常值的范围。
  3. 筛选异常值:通过条件筛选找到超出上下界的值。

输出结果

  • 控制台中会输出检测出的异常值(例如 100)。
  • 输出上下界的数值范围,用于进一步分析。

方法解释

  • 3倍标准差法:对于符合正态分布的数据,大约 99.7% 的数据点应该在均值的 ±3 标准差范围内。因此,超出此范围的数据点被视为潜在的异常值。
  • 适用性:该方法适用于正态分布或近似正态分布的数据。如果数据的分布偏离正态分布,则应谨慎使用此方法。

处理异常值: 异常值可以被删除、替换或者转换。可以使用插值法来平滑异常值。

插值法是一种通过已知数据点之间的插值来平滑数据的方法,能够很好地处理异常值。常用的插值方法包括线性插值、样条插值等。对于异常值,可以通过替换为插值值来实现平滑。

以下是如何使用 pandas 提供的插值功能来平滑异常值的步骤:

步骤

  1. 识别异常值:先通过某种方法(如标准差法或箱线图)检测到异常值。
  2. 使用插值法:利用 pandas 中的 interpolate() 函数平滑异常值。
  3. 替换异常值:将异常值替换为插值后的值。

代码示例

import pandas as pd
import numpy as np

# 示例数据集
data = {
    'feature1': [10, 12, 14, 15, 16, 18, 22, 25, 30, 100],  # 100 是异常值
    'feature2': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}

df = pd.DataFrame(data)

# 使用标准差法检测异常值
mean = df['feature1'].mean()
std_dev = df['feature1'].std()

lower_bound = mean - 3 * std_dev
upper_bound = mean + 3 * std_dev

# 找到异常值位置
outliers = (df['feature1'] < lower_bound) | (df['feature1'] > upper_bound)

# 将异常值替换为 NaN
df.loc[outliers, 'feature1'] = np.nan

# 使用线性插值平滑数据
df['feature1'] = df['feature1'].interpolate(method='linear')

# 查看结果
print("插值后数据:")
print(df)

代码说明

  1. 检测异常值:通过标准差法识别异常值,找到异常值所在的位置。
  2. 替换为 NaN:将检测到的异常值替换为 NaN,为后续插值做准备。
  3. 线性插值:使用 pandasinterpolate() 函数对 NaN 位置进行线性插值,平滑异常值。
  4. 输出结果:异常值(如 100)将被替换为插值后的值。

插值方法说明

  • 线性插值:基于两个相邻点之间的直线关系插入值,适用于简单数据。
  • 其他插值方法:你也可以使用 polynomial, spline, 或 nearest 等插值方法。
    • 示例:df['feature1'].interpolate(method='polynomial', order=2) 可以进行二次多项式插值。

优势

  • 插值法可以在保持数据趋势的情况下,平滑掉异常值,避免直接删除数据点带来的数据损失。
  • 适用于时序数据或连续数据,能够补充缺失值或异常值。

2. 数据转换

  • 标准化(Standardization):

    • 将特征值转换为均值为0、方差为1的标准正态分布。常用于模型对数据尺度敏感的情况(如线性回归、逻辑回归、SVM)。
    from sklearn.preprocessing import StandardScaler
    
    scaler = StandardScaler()
    df_scaled = scaler.fit_transform(df)
    
  • 归一化(Normalization):

    • 将特征值缩放到指定范围内(通常是 [0, 1])。适用于范围差异较大的数据,如深度学习中的输入数据。
    from sklearn.preprocessing import MinMaxScaler
    
    scaler = MinMaxScaler()
    df_normalized = scaler.fit_transform(df)
    
  • 对数变换(Log Transformation):

    • 将数据转换为对数形式,通常用于处理数据的偏态分布或减少异方差性。
    import numpy as np
    
    df['log_column'] = np.log(df['column_name'] + 1)  # +1防止log(0)
    
  • 分箱(Binning):

    • 将连续变量转换为离散变量,可以使用等宽分箱或等频分箱。
    df['binned_column'] = pd.cut(df['column_name'], bins=5)
    
  • One-Hot编码:

    • 将分类变量转换为二进制向量,适用于机器学习算法需要数值输入的场景。
    df = pd.get_dummies(df, columns=['categorical_column'])
    
  • 标签编码(Label Encoding):

    • 将分类变量转换为整数值,每个类别对应一个整数。适用于树模型等不需要特征标准化的算法。
    from sklearn.preprocessing import LabelEncoder
    
    le = LabelEncoder()
    df['encoded_column'] = le.fit_transform(df['categorical_column'])
    

3. 特征选择

  • 过滤法(Filter Method):

    • 使用统计方法(如方差、卡方检验、相关系数)选择特征,剔除冗余或不相关的特征。
    from sklearn.feature_selection import SelectKBest, chi2
    
    X_new = SelectKBest(chi2, k=10).fit_transform(X, y)
    
  • 嵌入法(Embedded Method):

    • 基于模型的特征选择,例如 L1 正则化(Lasso)、决策树的特征重要性。
    from sklearn.linear_model import Lasso
    
    lasso = Lasso(alpha=0.01)
    lasso.fit(X, y)
    model = SelectFromModel(lasso, prefit=True)
    X_new = model.transform(X)
    
  • 包裹法(Wrapper Method):

    • 使用递归特征消除(RFE)或其他算法通过不断地训练模型来选择特征。
    from sklearn.feature_selection import RFE
    from sklearn.linear_model import LogisticRegression
    
    model = LogisticRegression()
    rfe = RFE(model, 10)
    X_new = rfe.fit_transform(X, y)
    

4. 特征工程

  • 特征交互:

    • 创建特征的组合,生成新的特征。例如,将两个特征相乘或相除。
    df['new_feature'] = df['feature1'] * df['feature2']
    
  • 多项式特征:

    • 生成特征的多项式项,用于线性模型中提升表现。
    from sklearn.preprocessing import PolynomialFeatures
    
    poly = PolynomialFeatures(degree=2)
    X_poly = poly.fit_transform(X)
    
  • 时间特征提取:

    • 从时间戳中提取出年、月、日、星期等信息。
    df['year'] = df['date_column'].dt.year
    df['month'] = df['date_column'].dt.month
    df['day_of_week'] = df['date_column'].dt.dayofweek
    

5. 数据拆分

  • 训练集与测试集划分:

    • 将数据集拆分为训练集和测试集,常用的划分比例是 70% / 30% 或 80% / 20%。
    from sklearn.model_selection import train_test_split
    
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
    
  • 交叉验证:

    • 使用 K 折交叉验证评估模型性能,避免过拟合。
    from sklearn.model_selection import cross_val_score
    
    scores = cross_val_score(model, X, y, cv=5)
    

6. 数据增强:

  • 数据扩增:

    • 对图像、文本等数据进行增强,生成新的样本,通常用于深度学习。
    from keras.preprocessing.image import ImageDataGenerator
    
    datagen = ImageDataGenerator(rotation_range=40, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.2, zoom_range=0.2, horizontal_flip=True)
    

总结:

数据预处理是模型构建过程中至关重要的一步。高质量的预处理能帮助模型更好地理解数据,从而提升模型性能。不同类型的数据和任务可能需要不同的预处理方法,因此在具体项目中应灵活应用这些技术。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Carrie_Lei

接咨询接亲自带

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值