之前的两个tensorflow的案例都是分类问题,现在我们来讲回归问题,之前的分类问题都是返回离散值,回归问题返回的是连续值.
代码如下:
import tensorflow as tf
from tensorflow import keras
import numpy as np
boston_housing=keras.datasets.boston_housing
(train_data,train_labels),(test_data,test_labels)=boston_housing.load_data()
#打乱数据,这里产生的是shape大小的0-1之间的浮点数,进行排序取下标
order=np.argsort(np.random.random(train_labels.shape))
train_data=train_data[order]
train_labels=train_labels[order]
不仅有下载数据的代码还有打乱数据的代码.
代码:
print("Training set:{}".format(train_data.shape))
print('Testing set:{}'.format(test_data.shape))
print(train_data[0])
结果:从结果来看,我们的训练集有404个样本,测试集有102个样本,每个样本都存在13个特征.展示第一个样本可以看出每一个特征的规模都不一样,需要归一化.
通过pandas这个库,来友好的展示前几个数据集的数据.
代码如下:
import pandas as pd
column_names=['CRIM','ZN','INDUS','CHAS','NOX','RM','AGE',
'DIS','RAD','TAX','PTRATIO','B','LSTAT']
df=pd.DataFrame(train_data,columns=column_names)
print(df.head())
结果如下:
Training set:(404, 13)
Testing set:(102, 13)
[7.8750e-02 4.5000e+01 3.4400e+00 0.0000e+00 4.3700e-01 6.7820e+00
4.1100e+01 3.7886e+00 5.0000e+00 3.9800e+02 1.5200e+01 3.9387e+02
6.6800e+00]
也就是多少美金
代码:展示前10个结果,以千为单位.
print(train_labels[0:10])
结果:
[32. 27.5 32. 23.1 50. 20.6 22.6 36.2 21.8 19.5]
归一化=(每一个特征-均值)/样本
代码:
mean=train_data.mean(axis=0)
std=train_data.std(axis=0)
train_data=(train_data-mean)/std
test_data=(test_data-mean)/std
print(train_data[0])
结果:
[-0.39725269 1.41205707 -1.12664623 -0.25683275 -1.027385 0.72635358
-1.00016413 0.02383449 -0.51114231 -0.04753316 -1.49067405 0.41584124
-0.83648691]
注意分类模型的评价标准是准确率,但是对于回归问题的评价标准存在下面几个定义:
实现每一个评价标准的Python代码:
y_predict=model.predict(train_data)
mse=np.sum((y_predict-train_labels)**2)/len(train_labels)
rmse=mse**0.5
mae=np.sum(np.absolute(y_predict-train_labels))/len(train_labels)
r_squared=1-mse/np.var(train_labels)
这里我们不自己写评价的代码,而是直接调用.
详见创建模型的代码如下:可以看到这里的loss使用的是mse,跟我纸上写的一样,其评价标准使用的是mae.
print(train_data[0])
def build_model():
model=keras.Sequential([
keras.layers.Dense(64,activation=tf.nn.relu,
input_shape=(train_data.shape[1],)),
keras.layers.Dense(64,activation=tf.nn.relu),
keras.layers.Dense(1)
])
optimizer=tf.train.RMSPropOptimizer(0.001)
model.compile(loss='mse',
optimizer=optimizer,
metrics=['mae'])
return model
model=build_model()
model.summary()
结果:很显然,这里的结果为什么是这样呢?我们可以看我之前在学习吴恩达的ml课程的时候做的笔记,Dense层也就是全连接层,这个层的参数是什么呢?我们第一层的输入是一个(batch,13)的矩阵,这个矩阵每一行就是一个样本,第二层我们定义存在64个神经元,那么我们的参数矩阵的大小为(第二层的单元数*(13+1)),为什么要加1呢,在之前的博客里面也有介绍.假设我们的输出的结果是y=wx+b,如果我们将b作为w的其中一列,然后给X添加上一行,那么直接相乘,无需多一个b.简单明了吧!
第一层是输入层,第二层的dense层,存在64个单元,输出是(batch,64),参数个数896=64*(13+1),
第三层的dense层存在64个单元,输出的大小是(batch,64),参数个数4160=64*(64+1).
Layer (type) Output Shape Param #
=================================================================
dense_1 (Dense) (None, 64) 896
_________________________________________________________________
dense_2 (Dense) (None, 64) 4160
_________________________________________________________________
dense_3 (Dense) (None, 1) 65
=================================================================
Total params: 5,121
Trainable params: 5,121
Non-trainable params: 0
_________________________________________________________________
代码如下:
class PrintDot(keras.callbacks.Callback):
def on_epoch_end(self,epoch,logs):
if epoch%100==0:
print('')
print('.',end='')
EPOCHs=500
#strore train stats
history=model.fit(train_data,train_labels,epochs=EPOCHs,
validation_split=0.2,verbose=0,
callbacks=[PrintDot()])
结果如下:
2018-07-19 10:47:29.582186: I tensorflow/core/platform/cpu_feature_guard.cc:140] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
....................................................................................................
....................................................................................................
....................................................................................................
....................................................................................................
....................................................................................................
很显然每一个epoch存在一个点,然后存在500个点.
还跟之前一样,我们的训练的过程结果是存在history里面的,我们可以决定什么时候停止训练模型.
def plot_history(history):
plt.figure()
plt.xlabel('Epoch')
plt.ylabel('Mean ABS Error[1000$]')
plt.plot(history.epoch,np.array(history.history['mean_absolute_error']),
label='Trian Loss')
plt.plot(history.epoch,np.array(history.history['val_mean_absolute_error']),
label='Val loss')
plt.legend()
plt.ylim([0,5])
plt.show()
plot_history(history)
结果:
这里缺少一张图,不知道为什么放不上来.你跑一下代码就会有结果了.
然后你会发现上图中的交叉验证集的损失在200步之后不在下降,所以这里我们可以使用callback监视训练的过程,如果损失没有明显的下降就停止模型的继续训练.
这里需要更改之前的model训练的代码:这里的patience表示的是我每20个epoch检查一下是否提升.
early_stop=keras.callbacks.EarlyStopping(monitor='val_loss',patience=20)
history=model.fit(train_data,train_labels,epochs=EPOCHs,
validation_split=0.2,verbose=0,
callbacks=[early_stop,PrintDot()])
结果展示:发现只训练了116步.
....................................................................................................
................
接着我们在测试集上看看mae,代码如下:
[loss,mae]=model.evaluate(test_data,test_labels,verbose=0)
print('Testing set Mean Abs Error:${:7.2f}'.format(mae*1000))
结果:
Testing set Mean Abs Error:$2845.73
接下来我们需要在测试集上预测实验的结果:代码如下:
test_predictions=model.predict(test_data).flatten()
print(test_predictions)
结果:
[ 9.4426365 18.845205 21.13545 33.834316 25.48309 20.23648
24.594236 22.1592 20.13256 23.284271 17.962687 16.525255
16.848667 41.222248 20.076002 20.748678 26.62555 19.179808
20.415945 29.01589 12.216666 15.96105 21.455172 17.916454
19.890585 26.519785 29.374914 29.103876 12.293335 20.87983
20.088451 15.920354 33.259586 25.061556 19.075716 9.276594
17.045021 17.670856 21.643147 25.185192 29.574938 27.925776
15.1280575 40.99608 30.246912 25.992918 26.647621 18.128685
23.493486 22.54482 33.298023 20.473692 12.7502575 16.41091
34.06746 28.068274 12.830465 47.138454 34.765335 24.417768
25.649746 17.101204 15.230894 18.754522 23.136755 20.858206
14.392498 22.571886 14.32205 8.156353 28.571703 29.008682
27.352005 14.262512 24.165766 18.822746 20.141558 23.585936
34.895588 11.604717 21.357195 37.172855 16.655071 14.660085
17.873898 19.178114 21.253275 20.048191 21.22543 33.641575
21.79592 20.254305 24.413492 40.021717 35.80399 21.657253
35.134758 51.537617 26.69005 48.193005 30.545536 21.142712 ]
1.mse常用于回归的问题的损失函数计算.
2.mae常用于回归问题的模型的评估.
3.当每一个特征的规模不一样的时候需要进行统一规模.
4.如果训练的数据集很小,我们无需建立更多的单元和层,防止过拟合.
5.early_stopping有助于防止过拟合.