📅  最后修改于: 2020-08-20 13:53:55             🧑  作者: Mango
深度学习是当前人工智能(AI)和机器学习中最有趣和最有前途的领域之一。近年来,随着技术和算法的巨大进步,深度学习为AI应用的新时代打开了大门。
在许多此类应用中,深度学习算法的性能与人类专家相当,有时甚至超过了他们。
Python已经成为去到语言的机器学习和许多最流行的和强大的深度学习库和框架喜欢的TensorFlow,Keras和PyTorch都建在Python。
在本系列中,我们将使用Keras进行探索性数据分析(EDA)和数据预处理,最后建立一个深度学习模型并对其进行评估。
在这个阶段,我们将建立一个深度神经网络模型,我们将对其进行训练,然后将其用于预测房价。
深度学习神经网络只是具有许多隐藏层的神经网络。
定义模型可以分为几个特征:
深度学习模型的层有很多类型。卷积层和池化层用于对图像进行分类或对象检测的CNN中,而递归层用于自然语言处理和语音识别中常见的RNN中。
我们将使用Dense和Dropout层。密集层是最常见和最受欢迎的层类型-它只是常规的神经网络层,其中每个神经元都与上一层和下一层的神经元相连。
每个密集层都有一个激活功能,可以根据输入和突触的权重确定其神经元的输出。
辍学层只是正则化层,将某些输入单元随机地降低为0。这有助于减少过度拟合神经网络的机会。
还可以将许多类型的激活功能应用于图层。它们每个都以不同的方式链接神经元的输入和权重,并使网络的行为不同。
真正常见的功能是ReLU(整流线性单位),Sigmoid函数和线性函数。我们将混合几个不同的功能。
除了隐藏层,模型还具有输入层和输出层:
输入层中神经元的数量与我们数据中要素的数量相同。我们想教网络对这些功能做出反应。在train_df
和test_df
数据框中,我们有67个要素-因此,我们的输入层将有67个神经元。这些将成为我们数据的切入点。
对于输出层-神经元的数量取决于您的目标。由于我们只是在预测价格-一个单一的值,因此我们将仅使用一个神经元。分类模型将具有class
-个输出神经元数量。
由于模型的输出将是一个连续数字,因此我们将使用linear
激活函数,因此不会截断任何值。
考虑到这些参数,让我们使用Keras定义模型:
model = keras.Sequential([
layers.Dense(64, activation='relu', input_shape=[train_df.shape[1]]),
layers.Dropout(0.3, seed=2),
layers.Dense(64, activation='swish'),
layers.Dense(64, activation='relu'),
layers.Dense(64, activation='swish'),
layers.Dense(64, activation='relu'),
layers.Dense(64, activation='swish'),
layers.Dense(1)
])
在这里,我们使用Keras’ Sequential()
实例化模型。它需要一组顺序的层,并将它们堆叠在一起成为一个模型。在Sequential()
构造函数中,我们传递一个列表,其中包含要在模型中使用的图层。
在此模型中,我们制作了Dense
几层和Dropout
一层。我们使数据中的input_shape
要素数量相等。我们在第一层上将其定义为该层的输入。
每层有64个神经元。这通常取决于测试-每层放置更多的神经元将有助于提取更多特征,但是有时这些特征也可能对您不利。经过一些测试,在此示例中,每层64个神经元产生了相当准确的结果。强烈建议您使用数字!
为了避免过度拟合,我们迅速删除了30%的输入数据。将seed
设置为2,以便获得更可重复的结果。如果我们只是完全随机地丢弃它们,则每个模型都会有所不同。
最后,我们有一个Dense
具有单个神经元的层作为输出层。默认情况下,它具有linear
激活功能,因此我们没有进行任何设置。
定义我们的模型后,下一步是对其进行编译。编译Keras模型意味着对其进行配置以进行训练。
要编译模型,我们需要选择:
考虑到这些,让我们编译模型:
optimizer = tf.keras.optimizers.RMSprop(learning_rate=0.001)
model.compile(loss=tf.keras.losses.MeanSquaredError(),
optimizer=optimizer,
metrics=['mae'])
在这里,我们创建了一个RMSprop
优化器,学习率为0.001
。随意尝试使用其他优化器,例如Adam
优化器。
注意:您可以声明优化器并使用该对象,也可以在compile()
方法中传递它的字符串表示形式。
我们将损失函数设置为均方误差。同样,请随意尝试其他损失函数并评估结果。由于我们将MSE作为损失函数,因此我们选择了“ 平均绝对误差”作为评估模型的指标。
编译模型后,我们可以使用train_df
数据集对其进行训练。这可以通过以下fit()
函数来完成:
history = model.fit(
train_df, train_labels,
epochs=70, validation_split=0.2
)
在这里,我们已经传递了训练数据(train_df
)和火车标签(train_labels
)。
同样,学习是一个反复的过程。我们已通知网络,该网络要遍历该训练数据集70次,以从中学习尽可能多的信息。在最后一个时期的模型结果将比在第一个时期更好。
最后,我们传递用于验证的训练数据。具体来说,我们告诉它使用0.2
训练数据的(20%)来验证结果。请勿将其与test_df
我们将用于评估的数据集混淆。
这20%不会用于培训,而是用于验证以确保其取得进展。
此函数将打印每个时期的结果-损失函数的值以及我们选择要跟踪的度量。
完成后,我们可以看一下每个时期的完成情况:
Epoch 65/70
59/59 [==============================] - 0s 2ms/step - loss: 983458944.0000 - mae: 19101.9668 - val_loss: 672429632.0000 - val_mae: 18233.3066
Epoch 66/70
59/59 [==============================] - 0s 2ms/step - loss: 925556032.0000 - mae: 18587.1133 - val_loss: 589675840.0000 - val_mae: 16720.8945
Epoch 67/70
59/59 [==============================] - 0s 2ms/step - loss: 1052588800.0000 - mae: 18792.9805 - val_loss: 608930944.0000 - val_mae: 16897.8262
Epoch 68/70
59/59 [==============================] - 0s 2ms/step - loss: 849525312.0000 - mae: 18392.6055 - val_loss: 613655296.0000 - val_mae: 16914.1777
Epoch 69/70
59/59 [==============================] - 0s 2ms/step - loss: 826159680.0000 - mae: 18177.8945 - val_loss: 588994816.0000 - val_mae: 16520.2832
Epoch 70/70
59/59 [==============================] - 0s 2ms/step - loss: 920209344.0000 - mae: 18098.7070 - val_loss: 571053952.0000 - val_mae: 16419.8359
训练后,模型(存储在model
变量中)将了解其功能并可以进行预测。fit()
还会返回一个包含损失函数值和mae
每个时期之后的值的字典,因此我们也可以使用它。我们将其放入history
变量中。
在做出预测之前,让我们直观地看到损失值和mae
时间的变化情况:
model_history = pd.DataFrame(history.history)
model_history['epoch'] = history.epoch
fig, ax = plt.subplots(figsize=(14,8))
num_epochs = model_history.shape[0]
ax.plot(np.arange(0, num_epochs), model_history["mae"],
label="Training MAE", lw=3, color='#f4b400')
ax.plot(np.arange(0, num_epochs), model_history["val_mae"],
label="Validation MAE", lw=3, color='#0f9d58')
ax.legend()
plt.tight_layout()
plt.show()
我们可以清楚地看到mae
和损失值都随时间下降。这正是我们想要的-随着时间的推移,模型的预测变得更加准确。
现在我们的模型已经训练完毕,让我们使用它来进行一些预测。我们从测试数据(在中test_df
)中提取一项:
test_unit = test_df.iloc[[0]]
test_unit
为简洁起见,存储在其中的该项目具有以下值,为了简洁起见,仅裁剪了7个条目:
Lot Frontage | Lot Area | Overall Qual | Overall Cond | Year Built | Total Bsmt SF | 1st Flr SF | |
14 | 0.0157117 | -0.446066 | 1.36581 | -0.50805 | 0.465714 | 1.01855 | 0.91085 |
这些是要素单元的值,我们将使用该模型预测其售价:
test_pred = model.predict(test_unit).squeeze()
我们使用predict()
模型的功能,并将其传递给模型,test_unit
以预测目标变量-销售价格。
注意: predict()
返回一个NumPy数组,因此我们使用squeeze()
,这是一个NumPy函数,用于“压缩”该数组并以数字而不是数组的形式获取预测值。
现在,让我们从中获取单位的实际价格test_labels
:
test_lbl = test_labels.iloc[0]
现在,让我们比较一下预测价格和实际价格:
print("Model prediction = {:.2f}".format(test_pred))
print("Actual value = {:.2f}".format(test_lbl))
Model prediction = 225694.92
Actual value = 212000.00
因此,该单元的实际销售价格为212,000美元,我们的模型预测为* $ 225,694 *。尽管该型号的价格超过了5%,但价格已经相当接近。
让我们尝试另一个来自的单元test_df
:
test_unit = test_df.iloc[[100]]
我们将重复相同的过程以比较价格:
test_pred = model.predict(test_unit).squeeze()
test_lbl = test_labels.iloc[100]
print("Model prediction = {:.2f}".format(test_pred))
print("Actual value = {:.2f}".format(test_lbl))
Model prediction = 330350.47
Actual value = 340000.00
这是我们构建Keras深度学习模型的旅程的最后阶段。在此阶段,我们将使用模型在测试数据(test_df
)中的所有单位上生成预测,然后通过将这些预测与实际真实值(test_labels
)相比较来计算这些预测的平均绝对误差。
Keras提供了evaluate()
可与我们的模型一起使用以对其进行评估的功能。evaluate()
计算损失值以及我们在编译模型时选择的所有指标的值。
我们选择MAE作为指标,因为它很容易解释。MAE值表示模型误差的平均值:
为了我们的方便,该evaluate()
函数为我们解决了这一问题:
为了我们的方便,该evaluate()
函数为我们解决了这一问题:
loss, mae = model.evaluate(test_df, test_labels, verbose=0)
对于这种方法,我们传递模型的测试数据(待评估)和实际数据(待比较)。此外,我们使用了该verbose
参数来避免打印任何不需要的额外数据。
让我们运行代码,看看它是如何工作的:
print('MAE = {:.2f}'.format(mae))
MAE = 17239.13
平均绝对误差为17239.13
。也就是说,对于所有单位,该模型平均预测的实际价格为高于或低于实际价格17239美元。
结果有多好?们可以看到原始数据中这些单元的平均销售价格为$ 180,796。也就是说,MAE为17,239相当不错。
为了用另一种方式解释这些结果,让我们将预测与实际价格作图:
test_predictions_ = model.predict(test_df).flatten()
test_labels_ = test_labels.to_numpy().flatten()
fig, ax = plt.subplots(figsize=(14,8))
plt.scatter(test_labels_, test_predictions_, alpha=0.6,
color='#ff7043', lw=1, ec='black')
lims = [0, max(test_predictions_.max(), test_labels_.max())]
plt.plot(lims, lims, lw=1, color='#00acc1')
plt.tight_layout()
plt.show()
如果我们的模型在0 MAE的情况下是100%准确的,则所有点都将精确显示在对角青色线上。但是,没有一个模型是100%准确的,并且我们可以看到大多数点都靠近对角线,这意味着预测值接近于实际值。
有一些离群值,其中一些离得很远。这些使我们模型的平均MAE大大提高。实际上,对于这些要点中的大多数而言,MAE远小于17,239。
我们可以检查这些点并找出是否可以执行更多数据预处理和特征工程以使模型更准确地预测它们。
在本教程中,我们使用Keras构建了一个深度学习模型,对其进行了编译,并使用我们准备的干净数据进行了拟合,最后-根据所学知识进行了预测。
尽管不是100%准确,但我们设法以少量异常值获得了非常不错的结果。