动手学深度学习-03-实战 Kaggle 比赛:预测房价-数据预处理之标准化数据

Kaggele 代码 Kaggle 房价预测完整代码

一、获取数据

# This Python 3 environment comes with many helpful analytics libraries installed
# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python
# For example, here's several helpful packages to load

import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)

# Input data files are available in the read-only "../input/" directory
# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory

import os
for dirname, _, filenames in os.walk('/kaggle/input'):
    for filename in filenames:
        print(os.path.join(dirname, filename))

打印:

# 以上代码是新建笔记本时默认生成的
/kaggle/input/california-house-prices/sample_submission.csv
/kaggle/input/california-house-prices/train.csv
/kaggle/input/california-house-prices/test.csv

2、读取数据

# 根据打印出的文件路径,将文件读取进内存
sample_submission = pd.read_csv('/kaggle/input/california-house-prices/sample_submission.csv')
train_data = pd.read_csv('/kaggle/input/california-house-prices/train.csv')
test_data = pd.read_csv('/kaggle/input/california-house-prices/test.csv')

# 我们先看一下这三个数据长什么样
sample_submission.shape, train_data.shape, test_data.shape

输出:

((31626, 2), (47439, 41), (31626, 40))

从数字上我们可以看出以下两点:

1) 我们要提交的文件只包含两列,第一列是对应了每一个测试集样本的Id,第二列是我们所预测的SalePrice(如上课所演示的那样)

2) 上课演示的训练集与测试集的形状分别为(1460, 81)和(1459, 80),可以看出比赛用的数据集样本数量更多,但是特征却更少了

打印结果:

# 我们先来粗略看一下数据集包含哪些特征,head方法可以查看前五行数据
train_data.head()

file

# train_data.loc[:, train_data.columns != 'Sold Price'] # 这行代码用于提取除'Sold Price'外的其他列
all_features = pd.concat((train_data.loc[:, train_data.columns != 'Sold Price'], test_data.iloc[:, 1:]))
all_features.info() # info方法可以总览数据

# 将所有缺失的值替换为相应特征的平均值。通过将特征重新缩放到零均值和单位方差来标准化数据
numeric_features = all_features.dtypes[all_features.dtypes != 'object'].index
all_features[numeric_features] = all_features[numeric_features].apply(
    lambda x: (x - x.mean()) / (x.std()))
all_features[numeric_features] = all_features[numeric_features].fillna(0)

这段代码的目的是将训练集 (train_data) 和测试集 (test_data) 的特征数据(即输入特征)合并成一个大的数据集 all_features,以便在机器学习模型中进行特征处理、预处理或者某些算法操作(比如数据归一化、特征选择等)时,确保训练集和测试集使用相同的特征标准。

解释代码:

  1. train_data.loc[:, train_data.columns != 'Sold Price']

    • 这一行代码用于从 train_data 中选择除 'Sold Price' 列以外的所有列。train_data.columns != 'Sold Price' 创建了一个布尔条件,返回一个布尔值序列,然后通过 loc 提取这些列。
    • 'Sold Price' 通常是目标变量(即预测的价格),而不是特征,因此我们在这一步排除了它,保留了其他特征列。
  2. test_data.iloc[:, 1:]

    • 这行代码用于从 test_data 中提取所有特征列。iloc[:, 1:] 表示选择从第二列开始到最后一列的所有数据,排除掉了第一列。一般来说,第一列可能是索引或ID列,可能不包含实际的特征数据,因此这里排除掉了第一列。
  3. pd.concat((train_data.loc[:, train_data.columns != 'Sold Price'], test_data.iloc[:, 1:]))

    • 这行代码将 train_data 中的特征列与 test_data 中的特征列按行(横向)拼接起来,形成一个新的数据框 all_features
    • pd.concat() 是一个 pandas 函数,用于按指定轴(行或列)连接多个数据框。这里连接的是列,因此 axis=1 默认会按列合并。
  4. all_features.info()

    • 这行代码输出 all_features 数据框的简要信息(例如数据的维度、每列的类型和非空值数量等),方便查看合并后的数据集结构。

为什么要将 traintest 数据集合并在一起?

合并训练集和测试集的主要目的是为后续的特征处理提供一致性。例如:

  • 统一的特征标准化:如果需要对数据进行标准化(如归一化或标准化处理),将两个数据集合并在一起可以确保训练集和测试集应用相同的处理标准。
  • 填充缺失值:合并后可以对整个数据集(包括训练集和测试集)统一进行缺失值处理,避免训练集和测试集之间的不一致。
  • 特征选择/工程:有时候在特征选择或者特征工程时需要同时查看训练集和测试集的数据,合并后可以方便地进行操作。

通过这种方法,能够确保后续在训练模型时,训练集和测试集的特征是一致的,有助于避免数据泄露或测试集特征不一致的问题。

代码解释

请解释下边的代码:
# 将所有缺失的值替换为相应特征的平均值。通过将特征重新缩放到零均值和单位方差来标准化数据
numeric_features = all_features.dtypes[all_features.dtypes != 'object'].index
all_features[numeric_features] = all_features[numeric_features].apply(
    lambda x: (x - x.mean()) / (x.std()))
all_features[numeric_features] = all_features[numeric_features].fillna(0)

这段代码主要进行的是数据预处理,涉及数据标准化(对数值型特征进行零均值和单位方差处理)和填补缺失值的操作。具体来说,它对 all_features 数据集中的数值型特征进行了标准化处理,并且将缺失值(NaN)填补为该特征的平均值。

代码解释:

  1. 选择数值型特征:

    numeric_features = all_features.dtypes[all_features.dtypes != 'object'].index
    • all_features.dtypes 返回 all_features 数据框中每一列的类型(如 int64、float64、object 等)。
    • all_features.dtypes != 'object' 创建了一个布尔 Series,表示哪些列的数据类型不是 object(即不是字符串类型)。
    • 通过 .index 获取符合条件的列的名称(即数值型特征的列名),并将这些列名存储在 numeric_features 变量中。
  2. 标准化数值型特征:

    all_features[numeric_features] = all_features[numeric_features].apply(
       lambda x: (x - x.mean()) / (x.std()))
    • all_features[numeric_features] 表示从 all_features 数据框中选出所有数值型特征的列。
    • .apply(lambda x: (x - x.mean()) / (x.std())) 对这些数值型特征列应用了一个 lambda 函数,函数的作用是:
      • 对每一列(x)进行标准化处理:将每个值减去该列的均值(x.mean()),然后除以该列的标准差(x.std())。
      • 这种标准化方法使得每列数据的均值变为0,标准差变为1,常用于机器学习模型前的数据预处理,尤其是对距离敏感的模型(如 KNN、SVM、神经网络)特别重要。
  3. 填补缺失值:

    all_features[numeric_features] = all_features[numeric_features].fillna(0)
    • 这一行代码是对数值型特征的缺失值进行填补。fillna(0) 表示将所有数值型特征中的缺失值(NaN)替换为0。
    • 注意,标准化后的数据可能会包含缺失值,这时通过填补缺失值来确保数据的完整性,以便后续的机器学习模型训练可以正常进行。

总结:

这段代码的目的是对数值型特征进行预处理,包括:

  1. 标准化:将数值特征缩放到零均值和单位方差,这对于许多机器学习算法(如KNN、SVM、线性回归等)非常重要,能够帮助提高算法性能和训练稳定性。
  2. 填补缺失值:将缺失值替换为0,确保数据集在进行机器学习训练时不受缺失值影响。

这种处理方式在数据科学和机器学习中是非常常见的,旨在提高模型的准确性和效率。

问题:为什么要数据标准化?

问题:为什么要将数据做标准化,如房价预测里边的房龄,做数据标准化,请举例说明;

在房价预测任务中,标准化(或归一化)是一种常见的数据预处理方法,它将数据调整为零均值和单位方差的分布形式,目的是让不同特征具有相似的数值范围,从而提高模型的训练效果。下面详细解释为什么要对数据(如房龄)进行标准化,并通过举例说明其重要性。


为什么要进行数据标准化?

  1. 防止特征尺度影响模型:

    • 房价预测中,特征可能包括房龄(如5-100年)、面积(如50-500平方米)、房间数(如1-10个)、地段评分(如0-1)。这些特征的数值范围可能差异很大。
    • 如果不标准化,数值较大的特征(如面积)会对模型的损失函数和优化过程产生更大的影响,而数值较小的特征(如地段评分)可能被忽略。
  2. 提高模型收敛速度:

    • 在梯度下降优化算法中,特征的数值范围大不相同会导致权重更新步长不均匀,进而导致收敛变慢或陷入局部最优。标准化后,每个特征的均值为0、标准差为1,可以更快地收敛。
  3. 增强模型性能:

    • 一些算法(如支持向量机、KNN、主成分分析)对特征的量纲非常敏感。如果特征没有标准化,算法可能会偏向数值较大的特征,从而降低模型性能。

以房龄为例的说明

情境描述:

假设数据集中的特征如下:

  • 房龄:取值范围为 0-100 年。
  • 面积:取值范围为 50-500 平方米。
  • 地段评分:取值范围为 0-1

现在需要预测房价(单位:万元),模型可能通过学习特征和目标之间的关系给出预测结果。

影响对比:

  1. 未标准化的情况:

    • 如果房龄的取值范围是 0-100,而地段评分的取值范围是 0-1,模型在计算梯度或拟合权重时,可能会优先关注值较大的房龄,而忽略地段评分的作用。
    • 例如:
      • 模型可能认为房龄权重为 0.1,地段评分权重为 5,但由于房龄范围大,它可能被误判为更重要的特征。
    • 结果:模型可能错误地预测房龄对房价的影响,而忽视更重要的特征。
  2. 标准化后的情况:

    • 房龄经过标准化后,变为 (房龄 - 均值)/标准差,其值范围大约在 -33 之间,与其他特征(如地段评分、面积)在同一数量级。
    • 例如:
      • 如果房龄从 30年 变为 60年,标准化后的变化可能是从 -11,不会对模型优化产生不必要的权重偏向。
    • 结果:模型能更准确地学习每个特征的真实作用。

具体示例:梯度下降收敛

  • 如果房龄的范围是 0-100,而其他特征的范围是 0-1,在模型训练时,不同特征的梯度会差异很大。
    • 房龄的梯度值可能是 10,而地段评分的梯度可能是 0.01,优化过程会不平衡,导致模型需要更多的迭代次数才能收敛。
  • 标准化后,各特征梯度的值会处于类似的范围内,例如房龄的梯度变为 0.1,地段评分的梯度也是 0.1,这能显著加快收敛速度。

总结

对房龄等数据进行标准化,可以解决以下问题:

  1. 消除特征尺度差异,确保每个特征公平地影响模型。
  2. 加速模型优化,提高收敛速度。
  3. 增强模型对不同特征的学习能力,避免被高数值特征主导。

标准化对于涉及多种尺度特征的任务(如房价预测)尤其重要,是提升模型性能的一项关键操作。


相关文章:
d2l.ai | 动手学深度学习在线课程
d2l.ai | 实战Kaggle比赛:预测房价
Kaggle | House Prices - Advanced Regression Techniques

为者常成,行者常至