波士顿房价预测(Python深度学习——回归问题)

记:电影评论分类,新闻分类不同的是预测房价不属于分类问题,而是回归问题,所用的损失函数以及验证方法也与前面由很大的不同。

 

1、回归与logistic回归:很容易将这两个混为一谈,从名字来看好像这两个都是回归算法,但其实logistic回归是分类算法。

2、回归问题:相对于分类问题的目标是预测输入数据点所对应的单一离散的标签来说,回归问题是预测一个连续值而不是离散的标签,例如根据掌握的气象数据来预测明天的气温等。

3、波士顿房价数据集:是20世纪70年代中期波士顿郊区房价的中位数,该数据集的数据点相对较少,只有506个,其中404个训练样本,102个测试样本。输入数据的每个特征(比如犯罪率)都有不同的取值范围,因此如果将取值范围相差很大的数据输入到神经网络中的话是有很大的问题的,我们需要对数据的特征进行标准化处理(具体在后面代码中给出)

4、由于我们的样本数量比较少,我们将使用一个非常小的网络,因为训练数据越少的话过拟合现象就会越严重,而较小的网络可以降低过拟合。并且网络的最后一层只有一个单元,没有激活函数,是一个线性层(因此网络可以学会预测任意范围内的值,如果添加sigmoid激活函数的话,网络只能学会预测0~1范围内的值)

5、该网络使用mse损失函数,mse代表均方误差,即预测值与目标值之差的平方

      监控指标mae是指平均绝对误差,是预测值与目标值之差的绝对值

6、有关axis:

轴用来为超过一维数组定义的属性,二维数据拥有两个轴:第0轴沿着行的方向垂直向下,第1轴沿着列的方向水平延申。

根据官方的说法,1表示横轴,方向从左到右;0表示纵轴,方向从上到下。当axis=1时,数组的变化是横向的,体现出列的增加或者减少。反之,当axis=0时,数组的变化是纵向的,体现出行的增加或减少。

下图为dataframe中axis为0和1时的图示:

 

有关concatenate():实现矩阵的拼接

       concatenate()函数根据指定的维度,对一个元组、列表中的list或者ndarray进行连接

       函数原型:numpy.concatenate((a1, a2, ...), axis=0)

       两个例子:

a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])
np.concatenate((a, b), axis=0)


#输出为:

array([[1, 2],
       [3, 4],
       [5, 6]])


np.concatenate((a, b.T), axis=1)

#输出为:

array([[1, 2, 5],
       [3, 4, 6]])

####################################
np.concatenate((a, b), axis=1)
上面的代码会报错:

ValueError: all the input array dimensions except for the concatenation axis must match exactly

 

7、k折验证:当可用的数据非常少,那么验证集也会非常小,所以验证分数可能会有很大的波动,导致无法对模型进行可靠的评估,此时用k折交叉验证来解决,k折验证方法的图解如下:

import numpy as np
k = 4
num_val_samples = len(train_data) // k
num_epochs = 100
all_scores = []
for i in range(k):
    print('processing fold #', i)

# 准备验证数据:第k个分区的数据
    val_data = train_data[i * num_val_samples: (i + 1) * num_val_samples] 
    val_targets = train_targets[i * num_val_samples: (i + 1) * num_val_samples]

# 准备训练数据:其他所有分区的数据,即除了上面第k个分区的其他所有数据,注意表示方法
    partial_train_data = np.concatenate( 
                                [train_data[:i * num_val_samples],
                                train_data[(i + 1) * num_val_samples:]], 
                                 axis=0)
    partial_train_targets = np.concatenate(
                                [train_targets[:i * num_val_samples],
                                train_targets[(i + 1) * num_val_samples:]], 
                                axis=0)
    model = build_model() 

# 训练模型,verbose=0代表静默模式
    model.fit(partial_train_data, partial_train_targets, 
              epochs=num_epochs, batch_size=1, verbose=0)

# 在验证数据上评估模型
    val_mse, val_mae = model.evaluate(val_data, val_targets, verbose=0) 
    all_scores.append(val_mae)

8、完整代码以及部分注释如下:

#加载波士顿房价数据
from keras.datasets import boston_housing

(train_data,train_targets),(test_data,test_targets)=boston_housing.load_data()

print(train_data.shape)
print(test_data.shape)
print(train_data[0])
print(train_targets)

输出结果如图所示:

#数据标准化
#axis=0表示沿着行的方向垂直线下,axis=1表示沿着列的方向水平延申
#mean求均值,std计算标准差

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

test_data-=mean
test_data/=std

print(mean)
print(mean.shape)
print(std)
print(std.shape)


#结果为:

[-1.01541438e-16  1.09923072e-17  1.80933376e-15 -7.80453809e-17
 -5.25047552e-15  6.43187374e-15  2.98441140e-16  4.94653823e-16
  1.12671149e-17 -1.05526149e-16  2.36614908e-14  5.96710525e-15
  6.13920356e-16]
(13,)
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
(13,)
#构建网络
#模型定义
from keras import models
from keras import layers

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



# k折验证
import numpy as np
k=4
num_val_samples=len(train_data)//k
num_epochs=500
all_mae_histories=[]

for i in range(k):
    print('processing fold #:',i)
    val_data=train_data[i*num_val_samples:(i+1)*num_val_samples]
    val_targets=train_targets[i*num_val_samples:(i+1)*num_val_samples]
    
    partial_train_data=np.concatenate([train_data[:i*num_val_samples],
                                         train_data[(i+1)*num_val_samples:]],
                                        axis=0)
    partial_train_targets = np.concatenate([train_targets[:i * num_val_samples],
                                            train_targets[(i + 1) * num_val_samples:]], 
                                            axis=0)
    
    model=build_model()
    history=model.fit(partial_train_data,partial_train_targets,
                      validation_data=(val_data,val_targets),
                      epochs=num_epochs,batch_size=1,verbose=0)
    mae_history=history.history['val_mean_absolute_error']
    all_mae_histories.append(mae_history)



print(len(mae_history))
print(len(all_mae_histories))
print(type(all_mae_histories))
print(len(all_mae_histories[0]))

#结果的信息输出如下:
500
4
<class 'list'>
500

#计算所有轮次中的k折验证分数平均值
# for x in all_mae_histories意思是每一折的结果(共计4个,每一个是500长度的数组),如上面输出的all_mae_histories的信息
# 在此基础上,固定一个轮次i,求四个x[i]的平均值

average_mae_history = [
                        np.mean([x[i] for x in all_mae_histories]) 
                        for i in range(num_epochs)
                        ]
print(average_mae_history)
print(len(average_mae_history))
#绘制验证分数,x轴为迭代次数,y轴为平均k折验证分数的平均值
import matplotlib.pyplot as plt

plt.plot(range(1,len(average_mae_history)+1),average_mae_history)
plt.xlabel('Epochs')
plt.ylabel('Validation MAE')
plt.show()

结果如下图所示:

#因为纵轴的范围较大,且数据方差相对较大,所以难以看清这张图的规律
#删除前 10 个数据点,因为它们的取值范围与曲线上的其他点不同。
#将每个数据点替换为前面数据点的指数移动平均值,以得到光滑的曲线。

def smooth_curve(points, factor=0.9):
    smoothed_points = []
    for point in points:
        if smoothed_points:
            previous = smoothed_points[-1]
            smoothed_points.append(previous * factor + point * (1 - factor))
        else:
            smoothed_points.append(point)
    return smoothed_points

smooth_mae_history = smooth_curve(average_mae_history[10:])
plt.plot(range(1, len(smooth_mae_history) + 1), smooth_mae_history)
plt.xlabel('Epochs')
plt.ylabel('Validation MAE')
plt.show()

#训练最终模型,如上图从80之后开始过拟合,所以把迭代次数改为80次
model = build_model() 
model.fit(train_data, train_targets, 
 epochs=80, batch_size=16, verbose=0)
test_mse_score, test_mae_score = model.evaluate(test_data, test_targets)
print(test_mae_score)



#输出结果
102/102 [==============================] - 0s 1ms/step
2.6021013540380142

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.无名之辈

1毛也是爱~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值