📜  Keras中的深度学习-数据预处理

📅  最后修改于: 2020-08-21 02:32:25             🧑  作者: Mango

介绍

深度学习是当前人工智能(AI)和机器学习中最有趣和最有前途的领域之一。近年来,随着技术和算法的巨大进步,深度学习为AI应用的新时代打开了大门。

在许多此类应用中,深度学习算法的性能与人类专家相当,有时甚至超过了他们

Python已经成为去到语言的机器学习和许多最流行的和强大的深度学习库和框架喜欢的TensorFlowKerasPyTorch都建在Python。

在本系列中,我们将使用Keras进行探索性数据分析(EDA)数据预处理,最后建立一个深度学习模型并对其进行评估。

数据预处理

在预处理阶段,我们将准备将数据馈送到Keras模型。第一步是清除空值数据集。然后,我们将使用一键编码将分类变量转换为数值变量。神经网络处理数字数据,而不是分类数据。

我们还将数据分为训练和测试集。最后,我们将缩放数据/对其进行标准化,以使其范围从-1到1。此标准化有助于更好地训练模型并使其易于收敛。

处理缺失的价值观

让我们找出数据集中每个变量中缺失值的数量和百分比: 

missing_values = pd.DataFrame({
    'Column': df.columns.values,
    '# of missing values': df.isna().sum().values,
    '% of missing values': 100 * df.isna().sum().values / len(df),
})

missing_values = missing_values[missing_values['# of missing values'] > 0]
print(missing_values.sort_values(by='# of missing values', 
                                 ascending=False
                                ).reset_index(drop=True))

此代码将产生下表,该表向我们显示了包含缺失值的变量以及它们包含多少缺失值:

Column # of missing values % of missing values
0 Pool QC 2917 99.5563
1 Misc Feature 2824 96.3823
2 Alley 2732 93.2423
3 Fence 2358 80.4778
4 Fireplace Qu 1422 48.5324
5 Lot Frontage 490 16.7235
6 Garage Cond 159 5.42662
7 Garage Qual 159 5.42662
8 Garage Finish 159 5.42662
9 Garage Yr Blt 159 5.42662
10 Garage Type 157 5.35836
11 Bsmt Exposure 83 2.83276
12 BsmtFin Type 2 81 2.76451
13 BsmtFin Type 1 80 2.73038
14 Bsmt Qual 80 2.73038
15 Bsmt Cond 80 2.73038
16 Mas Vnr Area 23 0.784983
17 Mas Vnr Type 23 0.784983
18 Bsmt Half Bath 2 0.0682594
19 Bsmt Full Bath 2 0.0682594
20 Total Bsmt SF 1 0.0341297

因为Pool QCMisc FeatureAlleyFence,和Fireplace Qu变量包含如表所示缺失值的比例很高,我们会直接删除他们,因为他们可能不会在所有影响结果了:

df.drop(['Pool QC', 'Misc Feature', 'Alley', 'Fence', 'Fireplace Qu'], 
        axis=1, inplace=True)

对于其他包含缺失值的变量,我们将根据变量的数据类型来替换这些缺失值:数值类型还是分类类型

如果是数字形式,我们将用变量均值替换缺失值。如果是分类的,我们将用变量模式替换缺少的值。这消除了可能会以中立的方式使用缺失值创建的错误偏差。

为了知道哪些变量是数字变量,哪些是分类变量,我们将使用以下代码为每个包含缺失值的变量打印出5个唯一项:

cols_with_missing_values = df.columns[df.isna().sum() > 0]
for col in cols_with_missing_values:
    print(col)
    print(df[col].unique()[:5])
    print('*'*30)

我们得到以下结果:

Lot Frontage
[141.  80.  81.  93.  74.]
******************************
Mas Vnr Type
['Stone' 'None' 'BrkFace' nan 'BrkCmn']
******************************
...

让我们用均值替换缺失数值的值:

num_with_missing = ['Lot Frontage', 'Mas Vnr Area', 'BsmtFin SF 1', 'BsmtFin SF 2', 
                    'Bsmt Unf SF', 'Total Bsmt SF', 'Bsmt Full Bath', 'Bsmt Half Bath', 
                    'Garage Yr Blt', 'Garage Cars', 'Garage Area']

for n_col in num_with_missing:
    df[n_col] = df[n_col].fillna(df[n_col].mean())

在这里,我们只是将它们全部放入列表中并为其分配新值。接下来,让我们替换分类变量的缺失值:

cat_with_missing = [x for x in cols_with_missing_values if x not in num_with_missing]

for c_col in cat_with_missing:
    df[c_col] = df[c_col].fillna(df[c_col].mode().to_numpy()[0])

完成此步骤后,我们的数据集将没有任何缺失值。

分类变量的一键编码

像所有机器学习模型一样,Keras模型从根本上处理数字数据。分类数据对计算机没有任何意义,但确实可以做到。为了使数据集可用,我们需要将这些分类变量转换为数字表示形式。

我们将用于执行此转换的技术是“ 一键编码”。熊猫为我们提供了一种简单的方法,可以对数据中的所有分类变量自动执行“一键编码”。

但是,在此之前,我们必须确保数据中的分类变量不会偶然地表示为数字变量。

检查变量数据类型

当我们像以前一样使用Pandas读取CSV数据集时,Pandas会自动尝试确定数据集中每个变量的类型。

有时,Pandas可能会错误地确定这一点-如果分类变量用数字表示,则可能会错误地推断出它是数字变量。

让我们检查一下:是否存在任何数据类型差异DataFrame: 

data_types = pd.DataFrame({
    'Column': df.select_dtypes(exclude='object').columns.values,
    'Data type': df.select_dtypes(exclude='object').dtypes.values
})

print(data_types)
Column Data type
0 MS SubClass int64
1 Lot Frontage float64
2 Lot Area int64
3 Overall Qual int64
4 Overall Cond int64
5 Year Built int64
6 Year Remod/Add int64

根据该表和Kaggle的变量说明,我们可以注意到Pandas将哪些变量误认为是数字变量。

例如,MS SubClass被检测为数据类型为的数字变量int64。但是,基于对该变量的描述,它指定了要出售的商品的类型。

如果我们看一下该变量的唯一值: 

df['MS SubClass'].unique().tolist()

我们得到以下输出: 

[20, 60, 120, 50, 85, 160, 80, 30, 90, 190, 45, 70, 75, 40, 180, 150]

此变量用数字表示不同的单位类型,例如20(1946年及以后建造的一个故事住宅),60(1946年及以后建造的两个故事住宅)等。

实际上,这不是数字变量,而是绝对变量。通过将其重新分配为字符串,将其转换回类别变量:

df['MS SubClass'] = df['MS SubClass'].astype(str)

执行一键编码

在执行一键编码之前,我们希望从数据中选择功能的一个子集,从现在开始使用。我们要这么做是因为我们的数据集包含2,930条记录和75个要素。

其中许多功能都是分类的。因此,如果我们保留所有功能并执行一键编码,那么生成的功能数量将很大,结果模型可能会遭受维度诅咒

让我们列出要保留在子集中的变量并修剪它们,DataFrame以便仅使用这些变量: 

selected_vars = ['MS SubClass', 'MS Zoning', 'Lot Frontage', 'Lot Area',
                 'Neighborhood', 'Overall Qual', 'Overall Cond',
                 'Year Built', 'Total Bsmt SF', '1st Flr SF', '2nd Flr SF',
                 'Gr Liv Area', 'Full Bath', 'Half Bath', 'Bedroom AbvGr', 
                 'Kitchen AbvGr', 'TotRms AbvGrd', 'Garage Area', 
                 'Pool Area', 'SalePrice']

df = df[selected_vars]

现在,我们可以使用Pandas的get_dummies()功能轻松地执行一键编码: 

df = pd.get_dummies(df)

一键编码后,数据集将具有67个变量。这是有上限的前几行-变量比这还多:

Lot Frontage Lot Area Overall Qual Overall Cond Year Built Total Bsmt SF 1st Flr SF 2nd Flr SF Gr Liv Area
0 141 31770 6 5 1960 1080 1656 0 1656
1 80 11622 5 6 1961 882 896 0 896
2 81 14267 6 6 1958 1329 1329 0 1329

将数据分为训练和测试集

数据预处理的最后一步之一是将其分为训练和测试子集。我们将在训练子集中训练模型,并使用看不见的测试集对其进行评估。

我们将随机拆分数据,以便训练集将拥有80%的数据,而测试集将拥有20%的数据。通常,训练集通常具有70-80%的数据,而20-30%的数据用于验证。

这是由与大熊猫很简单sample()drop()功能:

train_df = df.sample(frac=0.8, random_state=9)
test_df = df.drop(train_df.index)

现在train_df保存我们的培训数据并test_df保存我们的测试数据。

接下来,我们将为SalePrice每个训练和测试集分别存储目标变量:

train_labels = train_df.pop('SalePrice')
test_labels = test_df.pop('SalePrice')

我们之所以删除SalePrice价值,是因为我们希望对其进行预测。预测我们已经知道并且已经馈入模型的东西毫无意义。我们将使用实际值来验证我们的预测是否正确。

在此步骤之后,train_df将包含训练数据的预测变量(即,除目标变量外的所有变量),train_labels并将包含的目标变量值train_dftest_df和和相同test_labels

我们执行此操作为下一步数据缩放做准备。

请注意,Pandas pop()函数将从SalePrice数据框中返回指定的列(例如,在我们的示例中为),并从数据框中train_df删除该列。

在这一步结束后,这里是为每个记录(行)和功能(列)数train_dftest_df

此外,train_labels有2344分的标签为2344个记录的train_dftest_labels具有586个标签586个记录test_df

如果不对这些数据进行预处理,我们将需要处理混乱的数据集。

数据缩放:标准化

最后,我们将标准化数据中的每个变量-当然,除了目标变量。

对于现在存储在中的训练数据train_df,我们将计算每个变量的平均值和标准偏差。之后,我们将从每个变量的值中减去平均值,然后将结果值除以标准差。

对于测试数据,我们将从每个变量的值中减去训练数据的平均值,然后将结果值除以训练数据的标准偏差。

 

由于一般原则,我们使用通过训练数据计算出的值:您学到的任何东西都必须从模型的训练数据中学习。测试之前,测试数据集中的所有内容对于模型都是完全未知的。

让我们现在执行标准化: 

predictor_vars = train_df.columns

for col in predictor_vars:
    # Calculating variable mean and std from training data
    col_mean = train_df[col].mean()
    col_std = train_df[col].std()
    if col_std == 0:
        col_std = 1e-20
    train_df[col] = (train_df[col] - col_mean) / col_std
    test_df[col] = (test_df[col] - col_mean) / col_std 

在此代码中,我们首先获取数据中的预测变量的名称。这些名称对于训练和测试集是相同的,因为这两个集包含相同的变量,但数据值不同。

然后,对于每个预测变量,我们使用训练数据(train_df)计算均值和标准差,减去计算出的均值,然后除以计算出的标准差。

请注意,有时某些变量的标准偏差等于0。在那种情况下,我们使标准偏差等于一个非常小的量,因为如果将其保持等于0,则稍后将其用于除法时,将得到零除误差。

这使我们获得了介于-1和1之间的缩放和标准化数据。

完成后,我们的数据集即可用于训练和评估模型。在下一篇文章中,我们将构建一个深度神经网络。

 

结论

数据预处理是机器学习管道中的关键步骤。在不删除某些变量,处理缺失值,编码分类值和标准化的情况下,我们会将混乱(或不可能的)数据集输入模型。

该模型将仅与我们提供的数据一样好,在本文中-我们已经准备好数据集以适合模型。