自我学习与理解:keras框架下的深度学习(三)回归问题

  本文主要是使用keras对其有的波士顿房价数据集做一个回归预测,其代码架构与之前一样(都只是使用多层感知机):数据的预处理、搭建网络框架、编译、循环训练以及测试训练的网络模型。其中除了数据预处理与之前归回模型略有不同,其他基本类似。但是在本文的回归预测代码中会提到一个数据集比较少时常用到的训练方法——交叉验证。

       回归预测房价,也就是说选定影响房价的因素,将其量化,然后使用该数据和对应的房价价格训练神经网络,最后使用因素的量化值来预测房价的走势。

       Keras中的波士顿房价数据集,其中一共只有506个样本,其中只有404个用来做训练。其他是用来做测试。每个样本有13个特征,也就是有13个房价影响因素(13个因素中有些是具体的数值也有的是给定的权重值)。所以训练数据集是:[404,13]。

       1.数据的预处理

       首先使用keras导入所需要使用的包以及数据集

from keras.datasets import boston_housing
(train_data,train_targets),(test_data,test_targets)=boston_housing.load_data()

  然后对数据进行标准化处理,得到特征平均值为0,标准差为1的数据,这样更加有利于网络的处理及其收敛。

mean = train_data.mean(axis=0)  
train_data -= mean  
std = train_data.std(axis=0) 
train_data/=std 

test_data-=mean
test_data/=std

 

  第一部分代码中的train_data.mean(axis=0)表示是求train_data中每一行的特征平均值,其std所求的也是每一行的标准差,也就是对每一组数据中的13个影响因素做标注化。(使用print(train_data.shape)可以得到训练数据的形状[404,13],上述代码中的axis=0就是指的404)

       第二部分代码中,我们直接使用训练集上所得到的特征平均值和标准差来对测试集进行标准化,其原因是不能使得网络提前知道了测试集的数据。

       2.搭建网络架构

model=models.Sequential()
model.add(layers.Dense(32,activation='relu',input_shape=(trian_data.shape[1],)))
model.add(layers.Dense(32,activation='relu'))
model.add(layers.Dense(1))

  网络架构的搭建与之前文章一样,但是在最后不需要进行非线性的处理,因为改网络是需要做一个预测,所以直接输出网络得到的数值即可。

       3.编译

model.compile(
        optimizer='rmsprop',loss='mse',metrics=['mae'] )

  编译这里采用的损失函数是mae,也就是平均绝对误差,即取预测值和真实值之间误差的平方作为网络得到的误差进行返回训练。

       4.循环网络

k=4
num=len(trian_data)//k
num_epochs=60
all_list=[]
for i in range(k):
    print('proccesing #',i)
    val_data=trian_data[i*num:(i+1)*num]
    val_target=trian_target[i*num:(i+1)*num]

    par_data=np.concatenate(
        [trian_data[:i*num],
        trian_data[(i+1)*num:]],
        axis=0
    )
    par_target=np.concatenate(
        [trian_target[:i*num],
        trian_target[(i+1)*num:]],
        axis=0
    )
           his=model.fit(par_data,par_target,epochs=num_epochs,batch_size=1,validation_data=(val_data,val_target))
    history=his.history['mae']
    all_list.append(history)

  因为该数据集十分稀少(404个),所以为了提升网络的性能,这里使用交叉验证来加强网络性能。交叉验证,也就是把所以的训练数据分成n分,按顺序选取从其中一份做验证集,其余做测试集,直到n份数据都做过验证集为止。如下图所示:

  在代码中,用k表示一共分成的份数,然后进行,其中一共需要进行k次验证,每次进行验证时都会运行num_epochs次。最后把每一次的的mae值保存在all_list的列表中,方便后面的画图。

  在上述代码中,因为一个训练了k(k=4)轮,每轮60次(epochs=60),所以我们求60次的均值(一共四组数据,求均值,从4*60个数值得到60个数值),然后再使用得到的均值作图,代码如下:

ave_list=[np.mean([x[i] for x in all_list]) for i in range(num_epochs)]
plt.plot(range(1,len(ave_list)+1),ave_list)
plt.xlabel('epochs')
plt.ylabel('validation mae')
plt.show()

  第一行代码是分别对4组中的数据求60个epochs的均值;剩下的代码是做mae的验证值曲线,得到的曲线如图所示:

 

 

 

   mae越小,表示预测越准确;其余曲线,比如说是验证集的损失值曲线,只需替换 4.循环网络中的history:

#替换前
history=his.history['mae']
#替换后
history=his.history['val_mae']

  之后修改y轴名称即可,关于能画什么曲线,因为在model.fit中,我们使用了训练集和验证集,所以最后得到训练集的loss和mae以及验证集的loss和mae。

  5.所有代码

from keras.datasets import boston_housing
from keras import layers
from keras import models
import numpy as np
import matplotlib.pyplot as plt
(train_data,train_target),(tesr_data,test_target)=boston_housing.load_data()
print(train_data[1])
mean=np.mean(train_data)
train_data-=mean
str=np.std(train_data)
train_data/=str

tesr_data-=mean
tesr_data/=str
print(train_data[1])

model=models.Sequential()
model.add(layers.Dense(32,activation='relu',input_shape=(train_data.shape[1],)))
model.add(layers.Dense(32,activation='relu'))
model.add(layers.Dense(1))
model.compile(
        optimizer='rmsprop',loss='mse',metrics=['mae'] )


k=4
num=len(train_data)//k
num_epochs=60
all_list=[]
for i in range(k):
    print('proccesing #',i)
    val_data=train_data[i*num:(i+1)*num]    #从训练集中提取出验证的数据部分
    val_target=train_target[i*num:(i+1)*num]    #从训练集中提取出验证的标签部分(房价)

    par_data=np.concatenate(        #把训练数据的其他部分粘合在一起
        [train_data[:i*num],
        train_data[(i+1)*num:]],
        axis=0
    )
    par_target=np.concatenate(      #把训练标签的其他部分粘合在一起
        [train_target[:i*num],
        train_target[(i+1)*num:]],
        axis=0
    )
    his=model.fit(par_data,par_target,epochs=num_epochs,batch_size=1,validation_data=(val_data,val_target))
    history=his.history['mae']
    all_list.append(history)


ave_list=[np.mean([x[i] for x in all_list]) for i in range(num_epochs)]
plt.plot(range(1,len(ave_list)+1),ave_list)
plt.xlabel('epochs')
plt.ylabel('train mae')
plt.show()

   目前为之所有用到的网络层次都是使用多层感知机,也就是神经网络算法,在后面的文章中会开始介绍卷积神经网络算法。

 

posted @ 2021-12-27 21:28  眼前有座山  阅读(529)  评论(0编辑  收藏  举报