内容提要

  1. 项目分析
  2. 预备知识
  3. 项目实战

一、项目分析

1、提出问题

房子是家的缩影,咱们中国人对房子有一种特别的情愫,这与中国人的传统文化有关,如“金碧辉煌”、“亭台楼阁”、“栋梁之才”、“不蔽风雨”等成语都与房屋有关,拥有一套属于自己的房子是许多人梦寐以求的事情。

如果能从房屋交易的历史记录中发现某种规律,来预测未来房价的走势,这无论是对普通的购房客,还是房屋中介公司而言,都是非常有吸引力的。

那如何才能找到这个规律呢?我们不妨让机器学习替我们找到这个问题的答案。

2、解决方案

我们首先利用前面掌握的matplotlib知识,对房屋价格进行可视化分析,看价格走势是否符合线性回归的变化趋势,如果是,则采用机器学习提供的线性回归模型对数据进行训练,并测试模型的精度。

当训练出合适的模型后,就相当于我们找到了一个明确的关于面积与价格的数学表达式,然后我们就可以利用它来预测未来某套房屋的价格,帮助购房者做出合理的选择。

解决方案如下图所示:

二、预备知识

1、数据归一化

用样本数据训练模型前,还需要对数据进行处理。有个别数据点偏离度较大,远离房屋价格趋势直线,这些数据有可能是收集错误或测量误差。

因此,为了减少样本属性取值的差异范围,提高数据质量,就要用到数据的一种常见操作:归一化方法。

(1)min-max标准化(Min-Max Normalization)

该方法也称为离差标准化,是对原始数据的线性变换,使结果值映射到[0-1]之间。转换公式如下:

其中x‘为归一化后的值,x_min为样本数据的最小值,x_max为样本数据的最大值。

该方法有个缺陷就是当样本有新数据加入时,可能导致x_min和x_max的变化,导致需要重新计算归一化值。

(2)0均值标准化(Z-score standardization)

这种方法基于原始数据的均值(mean) 和标准差(standard deviation)进行数据的 标准化。经过处理的数据符合标准正态分布, 即均值为0,标准差为1。

转化公式为:

上式中的μ为所有样本数据的均值,σ为所有样本数据的标准差。

2、线性回归模型的训练

在准备好数据后,下一步就要构建模型。本案例的数据集只有面积和价格两列,即线性模型中,只要一个自变量x(面积),模型的输出值就是价格y。

因此,模型的假设函数表达式是:

y‘就是我们要预测的值,模型要学习的参数是(φ_0,φ_1)。

建立好这个假设模型后,在后续模型学习过程中,需要给模型一个学习的目标,让它在学习过程中达到目标后即可停止学习,使得学习得到的参数(φ_0,φ_1)尽可能让预测值y^’接近真实值y。

在此,我们使用前面提到的均方误差MSE,其表达式为:

有了模型的定义,就按照以下步骤对模型进行训练和测试:

(1)初始化参数,包括(φ_0,φ_1)、学习率∝和迭代次数n。

(2)将样本数据输入模型,计算损失函数Loss。

(3)利用学习优化算法如梯度下降法处理损失函数,寻找损失函数的最小值,并在此过程中依次更新模型的参数。

(4)不断重复步骤2、3,直到模型收敛于损失函数的最小值或训练迭代次数到达设定值n。

三、项目实战

3.1 可视化房屋数据

预测房屋价格是线性回归最经典的应用案例。房屋的样本数据见下表:

序号

面积

价格

0

98.87

599.0

1

68.74

450.0

869

97.00

600.0

样本数据有两列,一列是房屋的面积,一列是价格,显然,面积是自变量x,价格是因变量y。

我们的目标是看能否利用线性回归模型来预测某一面积房屋的价格,为购房者或其他客户提供价格参考。

首先我们需要简单直观地了解下数据集中面积和价格之间是否存在线性关系,为此,新建文件task1.ipynb。

1、绘制散点图

先从数据集文件house.txt中读取数据,将一行数据的值(面积,价格)作为一个点的坐标值(x,y),然后用散点函数绘制出所有点的散点图。

源代码如下:

	%matplotlib inline
	import numpy as np
	import pandas as pd 
	import matplotlib.pyplot as plt
	df=pd.read_csv('data\house.txt',sep=',',header=0)
	plt.scatter(df['area'],df['price'],c='b')

按Ctrl+Enter键执行该程序,运行结果如下图所示(红色直线是后加上去的)。

2、观察数据分布规律

由上图看出,房屋整体样本数据呈现出一个线性分布的态势(见红色直线标识),所有样本点基本均匀分布在直线周围。

因此,对于该问题,我们完全可以尝试使用线性回归模型来解决房屋价格预测的问题。

3.2 线性回归模型训练

首先要构建一个线性回归模型,然后利用数据对它进行训练和测试,训练的目的就是让该模型拟合数据,让数据尽量分布在一条直线上。

测试的目的就是要评估训练的效果如何,验证模型在测试集上是否能获得较好的性能。

1、数据的归一化处理

为消除不同量纲数据带来的影响,尽量提高模型训练精度,对房屋样本数据按照min-max标准化方法进行归一化处理。实现代码如下。

df=(df-df.min())/(df.max()-df.min())

经过上述代码处理后,df数据就缩放到[0-1]的范围,有利于后续模型的训练和测试。

原始样本数据归一化后的结果如图所示。

2、产生训练集和测试集

在归一化房屋数据后,为了更好地训练和评估模型,通常将数据分成两份,一份是用于训练模型的训练集,另一份是用于评估模型好坏的测试集。

显然,当样本数据足够大时,两份数据集的比例可以为5:5,因为无论对于训练和测试而言,大量的数据都有利于模型参数调整和降低测试误差。

本次样本数据只有870个,考虑到将更多的训练集用来训练模型,以得到更可信的模型,同时兼顾一定的测试误差,将训练集和测试集比例分配为8:2,代码如下。

train_data=df.sample(frac=0.8,replace=False)
	test_data=df.drop(train_data.index)
	x_train=train_data['area'].values.reshape(-1, 1)
	y_train=train_data['price'].values
	x_test=test_data['area'].values.reshape(-1, 1)
	y_test=test_data['price'].values

3、构建并训练模型

我们采用机器学习库scikit-learn中的随机梯度下降回归模型函数SGDRegressor来构建模型,并利用归一化后的数据对它进行训练。

如果没有安装scikit-learn机器学习库,请在dos命令窗口下执行以下命令,来安装该第三方库。

pip3 install scikit-learn

安装好机器学习库scikit-learn后,编写如下代码,构建模型并对它进行训练。

from  sklearn.linear_model import SGDRegressor
from sklearn.externals import joblib
	model=SGDRegressor(max_iter=500,learning_rate='optimal',eta0=0.01)
	model.fit(x_train,y_train)
	pre_score=model.score(x_train,y_train)
	print('score=',pre_score)
	print('coef=',model.coef_,'intercept=',model.intercept_)
 	joblib.dump(model,'.\sava_model\SGDRegressor.model')

执行上述代码,结果如下:

3.3 模型的测试与评价

在模型训练完成后,接下来要利用测试集对模型的训练效果进行评估,评估的基本思想是:

(1)在模型上用测试集x_test计算出预测集y_pred。

(2)计算测试集y_test和预测集y_pred两者之间的损失误差,此处采用均方差MSE作为评估模型的指标,来评估预测值和真实值之间的差距。

(3)如果评估结果比较理想,就可以利用该模型进行房屋价格的预测;如果评估结果不够理想,可以对模型进行进一步优化,如增加训练集的数量,去除一些异常值,或者想办法增加训练样本的特征个数等。

1、计算均方差MSE

在训练好的模型model上运用测试集x_test得到测试集y_pred;然后利用测试样本的真实值y_test和对应的预测集y_pred来计算损失MSE,以此作为模型的评价标准。实现代码如下。

model=joblib.load('.\sava_model\SGDRegressor.model')
	y_pred=model.predict(x_test)#得到预测值
	print('测试集准确性得分=%.5f'%model.score(x_test,y_test))
	MSE=np.mean((y_test - y_pred)**2)
	print('损失MSE={:.5f}'.format(MSE))

执行上述代码,结果如下:

由上图可以看出,测试集的均方差约为0.007,预测的拟合得分为0.70548,说明房屋价格的变动因素中约70%可由面积的变动来解释,拟合度还是不错的。

2、绘制预测效果图

为直观了解预测效果,我们在真实样本散点图上绘制出预测直线,观察真实样本与预测直线的整体分布是否趋于一致,然后对比真实值与预测值的折线图的拟合情况如何。

总之,当得到理想的模型后,就可以利用该模型对提供的自变量x预测出对应的y值,从而完成房屋价格的预测工作。绘图代码如下:

plt.rcParams['font.sans-serif'] = ['SimHei']
	plt.figure(figsize=(10,4))
	ax1=plt.subplot(121)
	plt.scatter(x_test,y_test,label='测试集')
	plt.plot(x_test,y_pred,'r',label='预测回归线')
	ax1.set_xlabel('面积')
	ax1.set_ylabel('价格')
	plt.legend(loc='upper left')
	ax2=plt.subplot(122)
	x=range(0,len(y_test))
	plt.plot(x,y_test,'g',label='真实值')
	plt.plot(x,y_pred,'r',label='预测值')
	ax2.set_xlabel('样本序号')
	ax2.set_ylabel('价格')
	plt.legend(loc='upper right')

代码执行结果如下图所示:

上面两图基本得出相同的结论:回归模型对房屋价格的预测是趋于一致的,这样,我们就可以利用训练好的模型,随时对你提供的房屋面积预测出房屋的价格。

当然,这个预测是相对准确的,要想得到更高的预测精度,还需要考虑如何进一步完善描述房屋的特征数据,并尽可能增加样本的规模。

更多精彩内容请持续关注本站!

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐