机器学习项目的实例分析设计(附源码)

摘要说明:

最近在学习“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

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

数据内容及数据量

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

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

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

磁盘空间的分析

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


  • 获取数据分析

内容

分析设计

获取数据

1.  数据源:

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


猜你喜欢

转载自blog.csdn.net/superfanstoprogram/article/details/80413639