摘要说明:



最近在学习“Hands-On Machine Learning with Scikit-Learn &TensorFlow”,
其中一些机器学习的思考和处理方式很具有项目级开发的特点。我在原文提供的实例基础上,结合自己的分析,模拟了一个机器学习项目的分析和实现过程,包括项目分析,数据分析,模型分析,性能分析等,在原文的样本代码基础上,编写了完整的可全面自动化运行的代码,供大家一起参考。(文章后面将提供源码的
github地址)






一. 项目的总体分析

* 业务分析
*

内容

分析设计


项目名称

加利福尼亚房价预测


商业背景及价值

本公司是一家投资公司,现有一套综合投资分析系统,将汇总各类信息,对行政区进行全面分析后,决定是否值得进行投资。

本项目获得的各行政区的房价中值预测值,将提供给公司的综合投资分析系统,作为其中的一项分析指标,帮助公司进行决策。

目前房价中值的计算,完全依靠业务专家,通过复杂的人工推导分析后获得,费时费力,不及时,不准确。

本项目将实现房价中值的自动化预测计算和处理,其预测结果将影响公司投资决策的速度和准确性,从而直接影响公司的商业业绩。


业务需求

利用加利福尼亚房价数据库提供的统计数据,通过机器学习,从这些数据中构建模型,获得信息,用于预测加利福尼亚州不同行政区的房价中值


非功能性需求

目前采用人工分析的方法,全部计算一次所有行政区的房价中值,需要5 人天。

本项目完成后,正常情况下,要求在1小时内完成所有计算。


* 系统分析



内容

分析设计


基本训练模型方案

1.     由于有明确的预测值要求,因此将使用有监督的模型(不是无监督模型);

2.     由于预测的是具体数值,不是标签,因此属于回归问题(不是分类问题,或聚类问题);

3.     根据跟专家的沟通,房价的预测将需要涉及数据集中提供的多个特征属性,属于多变量回归问题

4.    
房价数据源信息不是实时连续变化的数据,数据量也不是特别大,完全可以装载到内存后进行处理,因此采用简单的单机批处理方式来完成。(不考虑大数据下的分布式处理及实时数据流的在线处理方式)



综上分析,本项目将采用的基本回归分析模型有:

* 线性回归模型:LinearRegression
* 决策树模型:DecisionTreeRegressor
* 随机森林树模型: RandomForestRegressor



模型效果的测量指标

回归分析模型的性能,可采用的测量指标有:



* 均方根误差(RMSE)
* 均方误差(MSE)
* 平均绝对误差(MAE)
* 中位值误差
* r方误差
RMSE对异常数据比较敏感,若数据集的异常数据很少时(即数据分布比较集中,像一个钟型),用RMSE来衡量模型效果还是比较好的,




因此,本项目将采用 RMSE 指标进行模型性能的衡量比较,RMSE值越小,模型性能越好。


开发环境

Python的生态环境提供了我们完成该项目需要的机器学习函数库,开源,通用性好,运行性能可满足项目要求;如 numpy, pandas,
scikit-Learn等,其中scikit-Learn模块中有一些流程化处理的函数,可以让自动化处理的实现更加简洁和优雅。




因此,本项目将采用 Python + Scikit-Learn 为主要开发平台


自动化及可重用性


这是一个需要可重复使用的生产系统,不是一次性工具,也不是单纯研究用的人机交互程序;需要尽量把处理代码自动化,以提高调试优化的效率,并在生产环境中部署后自动化运行,提供必要的运维日志信息


前提假设

1.     加利福尼亚房价数据库持续提供更新的房价数据

2.    
公司综合投资分析系统的数据接口保持不变,需要本项目提供的是房价的具体数值,而不是“昂贵”,“中等”,“低廉”的分类标签。否则,本项目的学习模型将会更改为分类模型


术语说明

关于记录集变量的定义说明如下:(括号内为全名称)


变量名

含义


train_set

原始训练数据集,包含标签列,特征列


test_set

原始数据测试集,包含标签列,特征列


train(train_feature)

训练集中的特征集,不含标签列,简写成 train


train_label

 

训练集中的标签列


train_num(train_feature_num)

训练集中的数值意义特征集


train_cat(train_feature_cat)

 

训练集中的分类意义特征集


train_prepared (train_feature_prepared)

已经处理完成的训练集,含所有特征属性,且全是数值型,将输入给模型进行训练使用


train_pred(train_label_pred)

 

训练集的预测标签值,可跟 train_label进行比较,获得性能评分







二. 原始数据分析




* 数据源分析



内容

分析设计


数据来源

StatLib 库为公开的数据库,其中提供了自1990年以来的加利福尼亚房价数据

Github 上的镜像,也可更方便地获得该数据集


https://raw.githubusercontent.com/ageron/handson-ml/master/datasets/housing/housing.tgz

<https://raw.githubusercontent.com/ageron/handson-ml/master/datasets/housing/housing.tgz>

(注:本演示项目将使用github上的数据集样本文件)


数据内容及数据量

主要为加利福尼亚的各行政区的房价数据,下载解压,保存为CSV文件后,在几百兆左右。


数据法律义务,授权情况及访问权限

项目用到的数据源,属于对外公开的数据集,可合理使用在项目中,不需要授权,不需要承担任何法律义务。


磁盘空间的分析


根据目前数据源的下载量分析和数据可能的增长趋势,5年内,数据集文件不会超过500M,考虑系统的环境安装,数据处理过程的需要,原始数据的备份,以及处理完的数据的备份等,该项目的磁盘空间建议预留100G以支持5年的运维。




* 获取数据分析



内容

分析设计


获取数据

1.  数据源:


https://raw.githubusercontent.com/ageron/handson-ml/master/datasets/housing/housing.tgz

<https://raw.githubusercontent.com/ageron/handson-ml/master/datasets/housing/housing.tgz>




2. 获取 hoursing.tgz 文件后,解压出 housing.csv数据集文件


抽取一个原始测试集

需要留一部分原始且未做任何处理的数据,来完整测试整个处理过程,并验证训练模型的实际性能。




该原始测试集不同于交叉验证时测试集,交叉验证是将已经清理干净的输入学习模型的数据随机分成训练集,测试集;而原始测试集是未清理过的数据。




基本处理过程:

1. 将原始数据拆分为2个数据集,train_set, test_set, 分别保存到文件中(train_set.csv,
test_set.csv),供以后重复使用

2. 装入训练数据集(train_set.csv),供后续的分析,清理,训练使用


实现整个过程的自动化处理

获取数据集,抽取原始测试集,装载训练集,需要自动化完成




参看代码: load_data.py


三. 数据特征分析


该步骤主要是在人机交互的 Jupyter
notebook中完成,需要业务专家的配合,通过分析,可以使我们了解清楚需要处理的数据集的基本特征和业务特征,为下一阶段的数据清理和模型构建提供信息。该步骤不修改数据,也没有相应的自动化处理代码,需要记录分析结果。

本文列出了一些分析检查表,其中的分析内容和举例仅供参考。而实际项目中,该步骤很重要,需要花费很多的时间,因为后续的处理,都将基于对数据集的全面了解。(
Jupyter notebook 文件包含在提供的源代码中)




内容

分析设计


将数据集装载到内存

import pandas as pd

import matplotlib.pyplot as plt

%matplotlib inline

 

datafilename = r"train_set.csv"

train_set_original = pd.read_csv(datafilename)


创建一个数据集的副本

 

train_set = train_set_original.copy()

 

这个数据集,是已经抽取掉原始测试集后的数据集,专门用于分析,训练,交叉测试用的。

该数据集包含标签列和特征列


检查数据集的大小

train_set.shape

(16512, 10)

一共有16512条样本数据,每条数据有10个特征列(其中含标签列)


获得数据集的所有特征名称及数据类型

train_set.dtypes

longitude                       float64

latitude                          float64

housing_median_age   float64

total_rooms                   float64

total_bedrooms             float64

population                     float64

households                   float64

median_income            float64

median_house_value   float64

ocean_proximity           object

 

除[ocean_proximity] 为字符型数据列(类别意义特征属性),其他特征列均为数值意义特征。

类别意义特征需要在后续处理中,转换为数值意义特征,因为输入学习训练模型的必须是数值特征


若为监督学习任务,需要确定标签列

 本项目中,标签列为 [median_house_value]

房屋价格的中值 (不是平均值)

 

明确标签列后,可以针对性地分析了解特征列跟标签列的相关性


数据集的样本具体内容

train_set.head()

train_set.tail()




特征数据的分布情况

比如:字符分类特征列 ocean_proximity

train_set[“ocean_proximity”].value_counts()




<1H OCEAN       7341   小于1小时车程

INLAND               5227   内陆

NEAR OCEAN    2086   靠近海

NEAR BAY         1854    靠近海湾

ISLAND                   4     海岛

 


分析特征属性的基本业务含义

需要在跟业务专家的配合下,分析主要特征属性的含义及对标签列的影响程度,机器学习是用来分析和解决实际业务问题的,不单是数据处理。这里做了简单分析,纯属个人观点


特征列

分析


longitude

地理经度,用于识别位置,获得所属行政区的信息。 行政区的不同,商业,政治,文化,教育环境也会不一样,会影响房价


latitude

地理纬度, 用于识别位置,,会影响房价


housing_median_age

房屋的平均年龄,房型信息,房龄大,房型较老,房龄小,比较新,会影响房价


total_rooms

总的房间数,房型信息,会影响房价


total_bedrooms

卧室的房间数,房型信息,房间多,居住会舒适,会影响房价


population

该地区的人口总数,影响供求比例,会影响房价


households

家庭数,影响供求比例,会影响房价


median_income

平均收入,影响购买力,会影响房价


ocean_proximity

跟海相关的环境分类,物以稀为贵,会影响房价




数据集的快速统计分析

train_set.isnull().sum()

train_set.info()

train_set.describe()


可视化数据进行分析

利用各种图表工具,对数据集进行可视化查看分析

 

每个列的数据直方图

train_set.hist(bins=50,figsize=(20,15))




按地理位置的人口分布散点图

train_set.plot(kind='scatter',x='longitude', y='latitude', alpha=0.4,
s=train_set['population']/100,label='population',
c='median_house_value',cmap=plt.get_cmap("jet"),colorbar=True)

plt.legend()







数据可视化分析很重要,涉及的内容也相对广泛,本文不再继续展开


分析样本属性之间的关系

特征属性跟标签列 及 特征属性间的线性相关性

corr_matrix = train_set.corr()

corr_matrix

corr_matrix["median_house_value"].sort_values(ascending=False)

 

median_house_value    1.000000

median_income         0.690647

total_rooms           0.133989

housing_median_age    0.103706

households            0.063714

total_bedrooms        0.047980

population           -0.026032

longitude            -0.046349

latitude             -0.142983

 

media_income, total_rooms, housing_media_age 跟房价中值的相关性比较大

 

可视化这些属性的关系

from pandas.tools.plotting import scatter_matrix

attributes =

["median_house_value","median_income","total_rooms","housing_median_age"]

scatter_matrix(train_set[attributes],figsize=(12,8))






行政区的media_house_value(房价中值) 跟 media income (收入中值)的线性相关性确实比较明显。


确认可用的额外字段

对属性字段进行加工及合并的分析,以便生成新的特征属性,表现出更多的内部关系。

例如:

增加属性列 population_per_household = poplation / households,  可获得每个家庭的平均人口数


确认不需要的字段

对预测标签没有任何影响的字段,如随机字段等,可以标记为删除。如日志记录中的随机序列号等。

本数据集中的特征属性,通过分析,都跟标签列有关系,因此,没有需要删除的列。


记录所有的分析内容,用于后续的数据自动化处理

以上分析结果,我们需要进行详细记录。而这些只是初步的分析处理方案,在实际训练过程中,需要根据模型性能评分,多次反复地分析,调整,才能获得最理想的效果。


四. 特征工程




特征工程是在原始数据特征分析的基础上,对数据进行全面特征处理和特征提取,构建最终的特征数据集,供学习模型进行训练使用。提供给模型的数据和特征,决定了机器学习的上限,可见其重要性。

该步骤需要能自动化运行,以便重复使用。分析,开发中,可以使用Jupyter进行调试,最终,应该是可以完整运行的 Python 代码模块。




内容

分析设计


创建一个特征数据集的副本

 

该步骤进行处理的数据集不包含标签列。

上一步骤的数据集包含标签列,是因为可以用来分析特征列和标签列的相关性,而清理数据时,不应该包含标签列的,因为标签列一般不需要进行清理或单独进行处理。




修复或删除异常值

任何情况都应该考虑null值,即使当前训练集没有,也无法保证测试集及将来的数据集都没有。

null值的处理方式有以下几种:

删除行,删除列,填充具体值等,本项目采用填充中值的方式处理null值

本项目使用 scikit-learn的转换器 Imputer 来完成


聚合生成新的特征

本项目将增加 population_per_household 等新特征。

编写自定义转换器来完成

class CombinedAttributesAdder()


添加多项式新特征

本项目没有其他新特征列

在代码中,提供了一个在对 pandas.DataFrame类型数据进行字段增加的转换器供参考。

class FeatureAdder()


删除不需要的特征

本项目没有删除特征列

在代码中,提供了一个在对 pandas.DataFrame类型数据进行字段删除的转换器供参考

class FeatureDeleter()


对连续特征离散化处理

本项目没有用到

就是把数据分段,线性值变成离散数据或分类值,如可以将population_per_household进行离散化处理

n <= 3        : 小家庭,    取值1

3 < n <= 7  : 中等家庭, 取值2

n > 7          : 大家庭,     取值3


对特征进行归一化处理或标准化处理

归一化处理后,数据的业务敏感度降低,数据的分布和方差保持不变,数据量减少,算法更容易收敛。

本项目使用scikit-learn提供的StandardScaler,进行归一化处理


对文本分类属性的处理

机器学习算法一般认为数据值越相近,则距离越近。将文本分类属性单纯用数字来代替,跟实际情况不符合,需要进行处理。

本项目采用 one-hot编码,即为每个分类值创建一个新特征属性,若原分类值为对应分类列,则该列特征值为1,否则为0

本项目使用 scikit-learn的 LabelBinarizer 转换器,并做了兼容性调整


自动化处理数据清理过程

所有转换处理都用函数实现自动化处理,从而可快速处理新的训练集,原始测试集。


scikit-learn 提供了一套 Pipeline 的流程化处理函数,可以让数据清理过程按设计流程顺序依次执行,很是干净和优雅。

 




 

 


五. 训练模型





内容

分析设计


若数据量太大,可抽取部分数据进行快速模型分析

本项目数据量不大,将使用全部训练集数据进行处理


训练模型并分析性能

传入训练数据集,训练模型,采用交叉验证的方式,随机生成训练集,测试集,计算RMSE评分。

保存每次测量的训练模型,用于后续分析和预测使用,同时显示模型训练的性能评分,以便跟其他训练结果进行比较







使用标准参数训练不同的基本模型

本项目的基本训练模型为



* 线性回归模型:LinearRegression
* 决策树模型:DecisionTreeRegressor
* 随机森林树模型: RandomForestRegressor


 




调整模型参数,进行优化

可能需要在多个模型中,使用多套参数组合方案,然后分析模型性能结果。

利用 Grid Search, 给出参数列表,然后让系统自动构建所有组合参数进行训练,返回性能最好的模型参数




集成多个模型,共同进行训练

本项目暂不需要

 


比较模型性能,获得最佳模型

需要重复以上分析步骤和过程,调整数据,调整特征,调整模型参数等,并对每次的训练结果进行记录和全面分析,以获得最佳的训练器。




本项目采用 RMSE 指标进行模型性能的衡量比较,RMSE值越小,模型性能越好


所有训练过程实现自动化

运行 python main.py , 完成数据获取,清理,训练,性能结果比较的自动化处理。

获得最佳的训练模型







六. 对原始测试集进行测试





内容

分析设计


对原始测试集进行预测

选用训练获得的最佳模型,对原始测试数据集进行测试,分析性能,并处理预测值













七. 后续工作

到目前为止,主要完成的是项目分析,设计和开发部分的工作,后续还有很多项目级的工作需要逐步配合完成,本文只做基本列举,不再详细描述





内容


提供项目的结果分析报告,并跟业务部门沟通分析



根据业务部门的反馈,继续进行参数和代码的优化,到达最佳的业务效果


开发跟公司决策分析系统的数据接口


项目提交测试部门进行正式测试


测试通过后,进行项目的生产部署和运维管理


定期更新训练数据,重新训练模型,保持并提高模型的性能


项目的经验总结(有效做法,无效做法,前提假设,局限性及改进方案),这些都将是公司和个人在项目开发和项目管理上的宝贵财富

附录:

该演示项目的源代码 github 地址:


https://github.com/EdwinZhang1970/Python/tree/master/California%20Housing%20Prices

<https://github.com/EdwinZhang1970/Python/tree/master/California%20Housing%20Prices>



友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信