使用 Keras 进行回归
我们在之前的课程之中学习到的模型都是分类模型,也就是说模型的输出是某一个类别;而这节课我们来学习回归模型。
1. 回归模型与分类模型的不同
简单来说,两者最直观的区别就是:回归模型的输出是一个连续的数值,而回归模型的输出是一个具体的类别。
举个例子,在生活中:
- 测量体温、计算运动时间等都属于回归任务;
- 掷色子、抛硬币等都属于分类任务。
但是从整体的程序角度来说,回归模型又与回归模型有以下几个详细的不同:
- 激活函数不同,回归模型的激活函数一般是 Relu 等激活函数,或者没有激活函数;
- 损失函数不同,回归模型的损失函数一般是 MSE 和 RMSE 等损失函数;
- 衡量标准不再使用准确率,因为回归任务无法定义准确率。
2. 数据获取
我们这次采用的任务示例数据是 TensorFlow 的 Keras 内部内置的波士顿房屋价格数据集合,我们会以此数据集合为基础进行我们的回归任务模型的构建。
因为该数据集合已经包含在 TensorFlow 之中,因此我们可以直接使用以下语句进行数据集合的下载。
(train_data, train_labels), (test_data, test_labels) = tf.keras.datasets.boston_housing.load_data()
让我们先来认识一下数据,该数据集合包含:
- 每个样本包含13个特征,每个特征表示特定的因素,这些特征包括:
- CRIM:犯罪率;
- ZN: 2.5 平凡英尺及其以上的住宅比例;
- INDUS: 非零售业务地区比例;
- CHAS:1-土地在河边,0-土地不在河边;
- NOX:一氧化碳浓度;
- RM:平居每人房子数量;
- AGE:1940年之前建成的建筑的比例;
- DIS:与波士顿就业中心的距离;
- RAD:辐射指标;
- TAX:税率指标;
- PTRATTO:师生比例;
- B:黑人比例指数;
- LSTAT:较低地位人群的比例;
- 每个样本的标签是房价 MEDV,采用自有住房的中位数来表示。
我们可以使用以下方式来查看数据的部分内容:
print(train_data.shape)
print(test_data.shape)
print(train_data[0])
print(train_labels[0])
得到的结果为:
(404, 13)
(102, 13)
[1.23247 0. 8.14 0. 0.538 6.142 91.7 3.9769 4. 307. 21. 396.9 18.72]
15.2
3. 模型的构建
在这里我们仍然使用最普通的顺序模型来进行表示,于是我们可以得到我们的模型表示为:
model = tf.keras.models.Sequential([
tf.keras.layers.Dense(128, activation='relu', input_shape=(13,)),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(1)
])
在该模型之中,前两层是我们很熟悉的全连接层。
这里值得注意的是在最后一层,因为我们想要输出一个连续的值,因此我们仅仅使用了一个神经元的全连接层,而且没有规定激活函数,而实将其简单输出。
4. 整体程序与输出结果
经过了上面两个步骤,我们已经可以得到我们的程序代码了,具体如下:
import tensorflow as tf
(train_data, train_labels), (test_data, test_labels) = tf.keras.datasets.boston_housing.load_data()
train_shape = train_data.shape
train_dataset = tf.data.Dataset.from_tensor_slices((train_data, train_labels)).batch(8).shuffle(buffer_size=train_shape[0])
test_dataset = tf.data.Dataset.from_tensor_slices((test_data, test_labels)).batch(8)
model = tf.keras.models.Sequential([
tf.keras.layers.Dense(128, activation='relu', input_shape=(13,)),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(1)
])
model.summary()
model.compile(optimizer='rmsprop', loss='mse')
model.fit(train_dataset, epochs=60)
result = model.evaluate(test_dataset)
print(result)
在该程序之中,唯一的不同就是该程序的优化器采用了 RMSProp ,与Adam相比,该优化器更加使用于回归任务。
而且我们的损失函数也采用了均方误差 (MSE) 的形式来衡量。简单来说,均方误差就是用来衡量“模型输出”与“真实值”之间的距离,MSE 越小则表示该模型的精确度越高,被广泛应用于回归任务之中。
该程序的输出结果为:
Model: "sequential_11"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_36 (Dense) (None, 128) 1792
_________________________________________________________________
dense_37 (Dense) (None, 64) 8256
_________________________________________________________________
dense_38 (Dense) (None, 1) 65
=================================================================
Total params: 10,113
Trainable params: 10,113
Non-trainable params: 0
_________________________________________________________________
Epoch 1/40
51/51 [==============================] - 0s 1ms/step - loss: 291.5432
Epoch 2/40
51/51 [==============================] - 0s 1ms/step - loss: 169.2546
Epoch 3/40
51/51 [==============================] - 0s 977us/step - loss: 165.5226
...........................
Epoch 38/40
51/51 [==============================] - 0s 950us/step - loss: 41.2446
Epoch 39/40
51/51 [==============================] - 0s 1ms/step - loss: 40.0520
Epoch 40/40
51/51 [==============================] - 0s 1ms/step - loss: 41.2494
13/13 [==============================] - 0s 1ms/step - loss: 33.5408
33.54079818725586
由此可见,我们的模型在误差方面已经降低到了 33 的 MSE。
5. 小结
这节课我们学习了回归任务与分类任务的不同,同时了解了回归任务常用的 MSE 与 RMSProp 等指标与优化器。最后我们知道了如何使用 TensorFlow 中的 Keras 来构建一个回归任务的模型。
这节课之中我们自己动手实现了一个回归模型,虽然比较简单,但是这却是回归任务的基本程序框架。