摘要说明:
最近在学习“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>
热门工具 换一换