3.利用Tensorflow进行回归问题的处理

之前的两个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]

不仅有下载数据的代码还有打乱数据的代码.

1.1 样本和特征

代码:

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]

1.2 标签

也就是多少美金

代码:展示前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]

三.创造模型

注意分类模型的评价标准是准确率,但是对于回归问题的评价标准存在下面几个定义:

3.利用Tensorflow进行回归问题的处理_第1张图片

实现每一个评价标准的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有助于防止过拟合.

你可能感兴趣的:(tensorflow)