2018-07-24 14:12:00 weixin_34185512 阅读数 19
  • 从零开始学习机器学习视频教程

    零基础入门机器学习视频培训课程概况:机器学习数学基础、Python基础、机器学习算法(线性回归、逻辑回归、聚类算法、EM算法),机器学习项目实战(Kmeans篮球数据分析、贝叶斯算法训练)、推荐算法、项目实战。  任务作业:很多人都喜欢看NBA,也喜欢拿实力相近的球员进行比较,你能利用机器学习的方式进行分析吗?动手的机会来了!请 结合课程【项目实战】章节中的【Kmeans篮球数据分类】。从NBA网站中随机拿到30名篮球运动员的得分和助攻(尽量数据间隔较大)。用python对数据进行处理(换算成每分钟的得分和助攻)。然后用Kmeans对获取的球员进行分类。看看自己心仪的球员属于哪一类~  (温馨提示: 注意 作业需写在CSDN博客中,请把作业链接贴在评论区,老师会定期逐个批改~~)

    5410 人正在学习 去看看 陆永剑

摘要:本文作者利用自己过去三个月里所学到的东西,来预测所在城市的房价。所用到的技术有网络爬取技术、文本自然语言处理,图像上的深度学习模型以及梯度增强技术等。

对于我在梅蒂斯的最后一个项目,我希望能包含过去三个月里所学到的东西,而预测波特兰房价这个题目正符合我的要求,因为我能够将网络爬取技术、文本自然语言处理,图像上的深度学习模型以及梯度增强技术进行整合来实现这个项目。

下面你可以看到我抓取到的2016年7月至2017年7月这段时间内波特兰市8300个独户住宅的销售数据。

显然,街区在这其中起了非常重要的作用。西山(红色)是镇上最昂贵的地区之一,而东波特兰则便宜很多。平均售价为44.2万美元。

我希望能够在比街区更细粒度的水平上预测价格。例如,假设以下房子是彼此毗邻的。

这些房子面积相同,在同一年份建成,并位于同一条街上。但是,一个明显能让人产生购买的欲望,而另一个则没有。那么Zillow或Redfin(美国的两家大型房地产网站)或其他公司能够仅仅依靠一些房屋的文字数据来预测它们的价格呢?他们不能。这就是为什么我要把对房屋门口照片的分析作为其中一个特征纳入预测模型的原因。

当务之急就是要获取到所有的数据。这比原本预想的要困难的多。首先,我使用波特兰地图的官方API来爬取波特兰独户住宅的销售数据。不幸的是,API存在调用限制(每10分钟约150次调用),所以我不得不在AWS服务器上长时间地运行程序来抓取所有的详细数据。我使用Zillow API抓取了每个家庭的元数据和房地产商对房屋的描述。但是,抓取的速度也很慢,因为Zillow只允许你每天调用API 1000次。(我让丈夫、母亲和几个朋友来帮我获取更多的API密钥)

最后,数据收集过程中最困难的部分是获取图像。这是因为Zillow有获取图片的API,但Redfin没有,但Redfin会在房子出售后仍把图片留那,而Zillow不会。为了获取到Redfin网站上的图片,我编写了一个Selenium脚本,在Google Images上通过在搜索条目后增加“Redfin”一词来搜索房屋地址,然后抓取Google列出的第一张图片的URL。

不幸的是,虽然我有了图像的URL,实际要直接将它们下载下来并不简单。这是因为Redfin不允许你使用标准的Python包,例如发送请求获取数据,也不允许你使用简单的curl命令。幸运的是,在与别人讨论后,我们提出了这样一个想法:在curl命令的末尾加上“User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)……”,以此来将你的终端请求伪装成浏览器请求。这终于成功了,最终我抓取到了8300个房屋的数据和图片!

现在数据有了,我准备要开始实现模型了。如下图所示:

让我们来详细介绍一下这三种输入数据类型。 Zillow元数据包含你原本预期的描述性文字:平方英尺、街区、建造年份等等。当我按p值对每个特征进行排序时,出现了一些惊喜的发现。我一直不知道格鲁吉亚建筑是什么样子的,直到我查了一下之后。

我准备采用自然语言处理技术来分析地产商的描述性文字。我对地产商的描述性文字做了两件事情:为每一个描述创建一个字矢量矩阵,这样就可以将其与Zillow元数据合并到一个特征矩阵中,还有,用NLTK情绪包来计算情绪评分:

我想,房地产经纪商的平均积极分数很高(平均分数为0.6,范围在-1到+1之间)并不让人觉得奇怪。因此,把情绪评分作为特征并没有改善模型。但是,在数据集中挖取最积极和最负面的分数非常有趣:

最后,为了将图片合并到模型中,我采用了VGG16深度神经网络对图像进行处理,以便提取出它们的特征(8300 x 25000的图像特征矩阵)。运行该模型的计算量相当得大,所以我需要在AWS上安装一个g2.8xlarge的GPU ubuntu实例。

图片模型在预测房价方面的效果如何呢?不错!这些是测试集中预测价格最高的三间屋子,显然,它们真的不错:

同样的,图片模型在预测廉价房屋方面也表现得很好:

我的模型在处理什么类型的图片时会存在问题呢?包含绿化的房屋!我的模型预测下面这个房屋价值250万,但实际上,图中的很多绿化都是免费赠送的!

好的,现在我确信我的图像模型已经挺不错了。我准备将Zillow元数据、地产商描述字矩阵和图像特征矩阵组合并到一个矩阵中,然后通过使用梯度提升算法来预测房价。作为一个基准预测,回想一下,数据集的平均房价是44.2万元。如果我预测每个家庭都值得这么多,那么平均而言,每个房子的价格就会下降16.1万元。而将图像合并到模型中能够立即将该错误降低2万元。把地产商描述添加到模型中则会将错误再降低1万元。最后,将Zillow元数据添加进来,则将平均绝对误差降低到大约7.1万元。

也许你想知道如果在预测房价上只使用Zillow元数据的话效果会怎么样?平均来说,它给出了一个7.0万元的误差。在添加了房地产商的描述后略微下降到6.9万元,但后来添加了图片后却增加到7.1万元。换句话说,现在的图片会轻微地降低模型的质量,而不是提升质量。

但是,请注意,图像特征矩阵具有25000列,而我只使用了8300张照片。我根本没有足够的数据来支撑这种模型。如果我在网上爬一个月并能获得更多的图片的话,我相信将图片整合到模型中将有助于提升预测的准确率。

总而言之,在完成这个项目的过程中,我学到了很多东西,也克服了几个重要的困难。我遇到的最大的困难是如何抓取Redfin图像以及如何使用VGG16模型。我发现Keras的文档仍然很少,所以在使用它的时候需要试错很多次。我为自己能完成这个项目而感到自豪,现在我需要做的只是获取更多的数据!

转载于:https://www.cnblogs.com/tecdat/p/9359654.html

2019-01-14 09:52:54 kepengs 阅读数 1555
  • 从零开始学习机器学习视频教程

    零基础入门机器学习视频培训课程概况:机器学习数学基础、Python基础、机器学习算法(线性回归、逻辑回归、聚类算法、EM算法),机器学习项目实战(Kmeans篮球数据分析、贝叶斯算法训练)、推荐算法、项目实战。  任务作业:很多人都喜欢看NBA,也喜欢拿实力相近的球员进行比较,你能利用机器学习的方式进行分析吗?动手的机会来了!请 结合课程【项目实战】章节中的【Kmeans篮球数据分类】。从NBA网站中随机拿到30名篮球运动员的得分和助攻(尽量数据间隔较大)。用python对数据进行处理(换算成每分钟的得分和助攻)。然后用Kmeans对获取的球员进行分类。看看自己心仪的球员属于哪一类~  (温馨提示: 注意 作业需写在CSDN博客中,请把作业链接贴在评论区,老师会定期逐个批改~~)

    5410 人正在学习 去看看 陆永剑

加州房价分析和预测

步骤
1、分析工作内容
2、获得数据
3、分析和预处理数据
4、选择模型并训练
5、参数调优
6、描述我们最终方案
7、上线我们的系统

数据集的几个来源

我们用的数据集

基于加州人口普查数据的美国加州房价数据集

开始我们的工作

第一步

  • 分析工作内容

利用加州的人口普查数据来对房价进行预测。
这份数据以街区(district)为最小单位,对应的信息有:人口、收入中位数、房价中位数等等。

  • 明确问题

我们要做什么
记住一个概念--管道(pipline),类似于Linux中的管道
管道各组件独立工作,前一个组件没产出后一个组件就会使用老数据,增强系统鲁棒性

1、收集数据
2、通过数据对街区价格预测
3、通过街区价格预测模型评估街区,获得投资建议

问题:

  • 监督学习?无监督学习?
  • 分类?回归?
  • 批量学习还是在线学习?
  • 判断模型好坏的指标
    1、均方根误差,L2范数,对高阶项敏感,回归问题典型的衡量标准
    2、平均绝对误差,L1范数,适用于数据集中有一些极端数据


    RMSE和MAE都是衡量两个向量之间距离的指标,向量指的是模型预测的预测值和样本自己真实值组成的向量。
    RMSE其实就是L2范数,对应的物理含义是欧几里得距离。
    MAE就是L1范数,对应的是曼哈顿距离,是指我们只能垂直或者水平地运动,那么两点之间的距离就是各个坐标轴之间的距离之和。
    范数的阶越高,那么它就越关注值大的数据,对值小的数据就会忽视一些。这就是为什么RMSE相较于MAE对于极值更加敏感的原因。不过如果极值点并不多的话,RMSE表现得其实很好,也是最常使用的指标。

第二步

  • 1、获取数据

该数据集,没有持续不断的数据流,也没有对于快速变化数据的即时响应的特殊需求,而且整个数据集也不大,完全可以加载到内存里,所以
常规的批量学习算法就可以胜任了。
如果数据量很大,我们完全可以使用分布式学习框架,比如mapreduce。

In [1]:

import os
import pandas as pd
HOUSE_PATH = './dataset'
def load_housing_data(housing_path=HOUSE_PATH):
    csv_path = os.path.join(housing_path, 'housing.csv')
    return pd.read_csv(csv_path)
  • 2、观察数据

In [2]:

housing = load_housing_data()
housing.head()

Out[2]:

  longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value ocean_proximity
0 -122.23 37.88 41.0 880.0 129.0 322.0 126.0 8.3252 452600.0 NEAR BAY
1 -122.22 37.86 21.0 7099.0 1106.0 2401.0 1138.0 8.3014 358500.0 NEAR BAY
2 -122.24 37.85 52.0 1467.0 190.0 496.0 177.0 7.2574 352100.0 NEAR BAY
3 -122.25 37.85 52.0 1274.0 235.0 558.0 219.0 5.6431 341300.0 NEAR BAY
4 -122.25 37.85 52.0 1627.0 280.0 565.0 259.0 3.8462 342200.0 NEAR BAY

经度、维度、街区平均房龄、街区总房数、街区总卧室、街区人口、街区住户、收入中位数、房价中位数、离海距离

In [3]:

housing.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 20640 entries, 0 to 20639
Data columns (total 10 columns):
longitude             20640 non-null float64
latitude              20640 non-null float64
housing_median_age    20640 non-null float64
total_rooms           20640 non-null float64
total_bedrooms        20433 non-null float64
population            20640 non-null float64
households            20640 non-null float64
median_income         20640 non-null float64
median_house_value    20640 non-null float64
ocean_proximity       20640 non-null object
dtypes: float64(9), object(1)
memory usage: 1.5+ MB

total_bedrooms 20433 有缺失值,我们重点关注有缺失值的项

  • pandas 的value_counts()函数可以对Series里面的每个值进行计数并且排序。

In [4]:

housing['ocean_proximity'].value_counts()

Out[4]:

<1H OCEAN     9136
INLAND        6551
NEAR OCEAN    2658
NEAR BAY      2290
ISLAND           5
Name: ocean_proximity, dtype: int64

describe方法可以得到关于数值型字段的一些摘要信息。
count,mean,min, max这几列都是自解释的。这里所有的统计都会把空值排除在外,比如total_bedroom的count是20433,而不是20640。
Std这一行显示了数据的标准差,它衡量了数据的分散程度
25%,50%,75%这几行显示了对应的百分位点。比如,25%的街区的房龄中位数低于18年,50%的街区的房龄中位数低于29年,75%的低于37年。
这些点也常常被叫做1/4分位点,中值点和3/4分为点。

In [5]:

housing.describe()

Out[5]:

  longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value
count 20640.000000 20640.000000 20640.000000 20640.000000 20433.000000 20640.000000 20640.000000 20640.000000 20640.000000
mean -119.569704 35.631861 28.639486 2635.763081 537.870553 1425.476744 499.539680 3.870671 206855.816909
std 2.003532 2.135952 12.585558 2181.615252 421.385070 1132.462122 382.329753 1.899822 115395.615874
min -124.350000 32.540000 1.000000 2.000000 1.000000 3.000000 1.000000 0.499900 14999.000000
25% -121.800000 33.930000 18.000000 1447.750000 296.000000 787.000000 280.000000 2.563400 119600.000000
50% -118.490000 34.260000 29.000000 2127.000000 435.000000 1166.000000 409.000000 3.534800 179700.000000
75% -118.010000 37.710000 37.000000 3148.000000 647.000000 1725.000000 605.000000 4.743250 264725.000000
max -114.310000 41.950000 52.000000 39320.000000 6445.000000 35682.000000 6082.000000 15.000100 500001.000000

In [6]:

%matplotlib inline
import matplotlib.pyplot as plt
  • 画直方图
  • hist函数参数
    arr: 需要计算直方图的一维数组
    bins: 直方图的柱数,可选项,默认为10
    normed: 是否将得到的直方图向量归一化。默认为0
    facecolor: 直方图颜色
    edgecolor: 直方图边框颜色
    alpha: 透明度
    histtype: 直方图类型,‘bar’, ‘barstacked’, ‘step’, ‘stepfilled’

In [7]:

housing.hist(bins=50,figsize=(20,15))
plt.show()

    1.收入中位数的单位看起来并不是美元。它的取值范围是0~15,这个具体含义是什么我们其实并不清楚,需要跟收集数据的团队沟通。我们可能会被告知,说这个字段已经被放缩了,而且超过15的都统一被设置成15,而小于0.5的则全部被设置成了0.5。
    在机器学习应用中,使用已经被预处理过的数据是一件很平常的事情,而且一般都不太会造成什么问题,不过为了保险起见,我们总是应该清楚我们使用的数据都是怎样处理的。
    2.房龄和房价看起来也都进行了掐头去尾的操作。对房价的这种掐头去尾的操作可能对我们而言是非常严重的,因为它是我们的预测目标。这可能会导致我们的系统永远也不会预测出高于50万美元的房价。我们必须跟下游团队沟通,确定这对它们而言是不是一个问题。如果他们说对于高于50万美元的房子他们也需要精确的价格预测信息,那么我们基本上只有两个选择:
        a)对于被掐头去尾的街区重新收集真实的价格数据
        b)把这些被掐头去尾的街区数据从数据集中移除
    3.所有的这些字段的取值范围差异很大。我们得记着后面要做特征缩放。
    4.最后,很多直方图都有些长尾的感觉:右侧分布相较于左侧更加长。这种分布可能对某些机器学习算法会有一些影响。我们后面会想办法把它们尽量转化成钟形分布。

  • 3、将数据分成训练集和测试集

In [8]:

import numpy as np

函数shuffle与permutation都是对原来的数组进行重新洗牌(即随机打乱原来的元素顺序);
区别在于:
shuffle直接在原来的数组上进行操作,改变原来数组的顺序,无返回值。
permutation不直接在原来的数组上进行操作,而是返回一个新的打乱顺序的数组,并不改变原来的数组。

In [9]:

def split_train_test(data, test_ratio):
    np.random.seed(42)
    shuffled_indices = np.random.permutation(len(data))
    test_set_size = int(len(data) * test_ratio)
    test_indices = shuffled_indices[:test_set_size]
    train_indices = shuffled_indices[test_set_size:]
    return data.iloc[train_indices], data.iloc[test_indices]

In [10]:

train_set, test_set = split_train_test(housing, 0.2)
print(len(train_set), '训练样本\n', len(test_set), '测试样本')
16512 训练样本
 4128 测试样本
  • 测试阶段保持样本数据集每次测试一致

    为了让评估尽可能地具有一致性,我们应该让原本处于训练集的样本仍然处于训练集,
    原来处于测试集的样本仍然处于测试集。

In [11]:

import hashlib

In [12]:

def test_set_check(identifier, test_ratio, hash):
    return hash(np.int64(identifier)).digest()[-1] < 256 * test_ratio

def split_train_test_by_id(data, test_ratio, id_column, hash=hashlib.md5):
    ids = data[id_column]
    in_test_set = ids.apply(lambda id_: test_set_check(id_, test_ratio, hash))
    return data.loc[~in_test_set], data.loc[in_test_set]

In [13]:

# 使用样本序号作为id
housing_with_id = housing.reset_index()                                      # 增加一个id列
train_set, test_set = split_train_test_by_id(housing_with_id, 0.2, "index")

In [14]:

# 使用最稳定的特征生成id
housing_with_id['id'] = housing['longitude'] * 1000 + housing['latitude']
train_set, test_set = split_train_test_by_id(housing_with_id, 0.2, 'id')
  • sklearn提供了一些API帮助我们方便地进行数据集的划分,最简单的就是train_test_split

In [15]:

from sklearn.model_selection import train_test_split

In [16]:

train_set, test_set = train_test_split(housing, test_size=0.2, random_state=42)

对于重要特征,我们希望测试集的数据能够有足够代表性的样本覆盖。

比如,我们从专家处得知,收入中位数对于房价具有非常强的影响。那么我们需要确定不同层次
的收入水平在测试集中都应该有所覆盖。

In [17]:

housing['income_cat'] = np.ceil(housing['median_income'] / 1.5)
housing['income_cat'].where(housing['income_cat'] < 5, 5.0, inplace=True)

In [18]:

housing['income_cat'].hist()

Out[18]:

<matplotlib.axes._subplots.AxesSubplot at 0x122f1d90>

  • 基于收入水平----分层抽样

In [19]:

from sklearn.model_selection import StratifiedShuffleSplit

split = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=42)
for train_index, test_index in split.split(housing, housing['income_cat']):
    strat_train_set = housing.loc[train_index]
    strat_test_set = housing.loc[test_index]

In [20]:

housing['income_cat'].value_counts() / len(housing)

Out[20]:

3.0    0.350581
2.0    0.318847
4.0    0.176308
5.0    0.114438
1.0    0.039826
Name: income_cat, dtype: float64
  • 不同抽样方法的偏差比较:

In [21]:

# 删除用于抽样的信息
for s in (strat_train_set, strat_test_set):
    s.drop(['income_cat'], axis=1, inplace=True)

4、分析数据特征之间的相关性

  • 备份数据,观察数据

In [22]:

housing = strat_train_set.copy()
  • 可视化地理数据

In [23]:

housing.plot(kind='scatter', x='longitude', y='latitude')

Out[23]:

<matplotlib.axes._subplots.AxesSubplot at 0xdad4bb0>

  • 改变数据透明度和视觉效果

In [24]:

housing.plot(kind='scatter', x='longitude', y='latitude', alpha=0.1)

Out[24]:

<matplotlib.axes._subplots.AxesSubplot at 0xc711b90>

  • 观察地域和房价的关系

In [25]:

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

Out[25]:

<matplotlib.legend.Legend at 0xd7266b0>

  • 分析和处理数据相关性

In [26]:

corr_matrix = housing.corr()                                    # 用corr计算两两特征之间的相关性系数
  • 跟房价最相关的特性

In [27]:

corr_matrix["median_house_value"].sort_values(ascending=False)   # 跟街区价格中位数特征的其他特征的相关系数

Out[27]:

median_house_value    1.000000
median_income         0.687160
total_rooms           0.135097
housing_median_age    0.114110
households            0.064506
total_bedrooms        0.047689
population           -0.026920
longitude            -0.047432
latitude             -0.142724
Name: median_house_value, dtype: float64
  • 相关性值(线性相关)的关系图:
  • 用pandas来表示

In [28]:

from pandas.plotting import scatter_matrix
attributes = ["median_house_value", "median_income", "total_rooms","housing_median_age"]
scatter_matrix(housing[attributes], figsize=(12, 8))

Out[28]:

array([[<matplotlib.axes._subplots.AxesSubplot object at 0x0D80AED0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0C67A0B0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0D849FB0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0D828F50>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x0D884370>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0D884610>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0D8A4A50>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0D8CD090>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x0D8EA6F0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0D9AAB70>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0D98D9B0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0D9143B0>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x0D932210>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0E030A70>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0D758670>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0DFF6DD0>]],
      dtype=object)

  • 从中发现收入跟房价非常相关

In [29]:

housing.plot(kind='scatter', x='median_income', 
             y='median_house_value', alpha=0.1)

Out[29]:

<matplotlib.axes._subplots.AxesSubplot at 0xd945ab0>

第三步

  • 为机器学习算法准本数据
  • 数据预处理

In [30]:

housing['rooms_per_household'] = housing['total_rooms'] / housing['households']
housing['bedrooms_per_room'] = housing['total_bedrooms'] / housing['total_rooms']
housing['population_per_household'] = housing['population'] / housing['households']
  • 观察相关性

In [31]:

corr_matrix = housing.corr()
corr_matrix['median_house_value'].sort_values(ascending=False)

Out[31]:

median_house_value          1.000000
median_income               0.687160
rooms_per_household         0.146285
total_rooms                 0.135097
housing_median_age          0.114110
households                  0.064506
total_bedrooms              0.047689
population_per_household   -0.021985
population                 -0.026920
longitude                  -0.047432
latitude                   -0.142724
bedrooms_per_room          -0.259984
Name: median_house_value, dtype: float64
  • 准备用于机器学习的数据

In [32]:

housing = strat_train_set.drop('median_house_value', axis=1)   # drop掉median_house_value
housing_labels = strat_train_set['median_house_value'].copy()  # 从原始数据集中copy一份median_house_value
  • 清洗数据

卧室数量(total_bedrooms)这个特征有一些缺失值,我们需要对它们进行处理。
一般我们有三种方式:

1、housing.dropna(subset=["total_bedrooms"]) # option 1 剔除掉有缺失值的样本
2、housing.drop("total_bedrooms", axis=1) # option 2 剔除有缺失值的整个特征
3、median = housing["total_bedrooms"].median()
  housing["total_bedrooms"].fillna(median) # option 3 用均值填充缺失值
  • sklearn中关于缺失值处理类--Imputer

In [33]:

from sklearn.impute import SimpleImputer

In [34]:

imputer = SimpleImputer(strategy='median')

In [35]:

# 中位数只能用于数值类型
housing_num = housing.drop('ocean_proximity', axis=1)

In [36]:

imputer.fit(housing_num)
imputer.statistics_

Out[36]:

array([-118.51  ,   34.26  ,   29.    , 2119.5   ,  433.    , 1164.    ,
        408.    ,    3.5409])

In [37]:

housing_num.median().values

Out[37]:

array([-118.51  ,   34.26  ,   29.    , 2119.5   ,  433.    , 1164.    ,
        408.    ,    3.5409])

In [38]:

X = imputer.transform(housing_num)

In [39]:

housing_tr = pd.DataFrame(X, columns=housing_num.columns)
housing_tr.describe()

Out[39]:

  longitude latitude housing_median_age total_rooms total_bedrooms population households median_income
count 16512.000000 16512.000000 16512.000000 16512.000000 16512.000000 16512.000000 16512.000000 16512.000000
mean -119.575834 35.639577 28.653101 2622.728319 533.998123 1419.790819 497.060380 3.875589
std 2.001860 2.138058 12.574726 2138.458419 410.839621 1115.686241 375.720845 1.904950
min -124.350000 32.540000 1.000000 6.000000 2.000000 3.000000 2.000000 0.499900
25% -121.800000 33.940000 18.000000 1443.000000 296.000000 784.000000 279.000000 2.566775
50% -118.510000 34.260000 29.000000 2119.500000 433.000000 1164.000000 408.000000 3.540900
75% -118.010000 37.720000 37.000000 3141.000000 641.000000 1719.250000 602.000000 4.744475
max -114.310000 41.950000 52.000000 39320.000000 6210.000000 35682.000000 5358.000000 15.000100
  • 处理类别特征
  • 如,距离海边距离进行数字型编码

In [40]:

from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
housing_cat = housing['ocean_proximity']
housing_cat_encoded = encoder.fit_transform(housing_cat)
housing_cat_encoded

Out[40]:

array([0, 0, 4, ..., 1, 0, 3])

In [41]:

# 0,1,2,3,4特征分别表达什么意思,即把枚举特征转化成数值特征
encoder.classes_

Out[41]:

array(['<1H OCEAN', 'INLAND', 'ISLAND', 'NEAR BAY', 'NEAR OCEAN'],
      dtype=object)

现在,所有特征都是数值类型的了,都可以直接被机器学习算法使用了.
但是,我们仔细想一下机器学习的内部原理,以简单的线性回归为例:
y=∑nj=0θjxjy=∑j=0nθjxj
编码数值的相对大小对房价影响很乏! 对于离海距离这个特征,它是一个枚举型的类别特征,不应该存在大小的关系。 如何解决?
五个特征中我们可以设置其中某一个为1其他为0,因为一个房子只有一个特征

  • 独热编码one-hot-encoding

In [42]:

from sklearn.preprocessing import OneHotEncoder
encoder = OneHotEncoder()
# one-hot-encoding接受的是一列数据,就是接受一个向量,所以我们要数据转化一下reshape(-1, 1)成一列
housing_cat_1hot = encoder.fit_transform(housing_cat_encoded.reshape(-1, 1))
housing_cat_1hot    # 稀疏矩阵

C:\Anaconda3\lib\site-packages\sklearn\preprocessing\_encoders.py:368: FutureWarning: The handling of integer data will change in version 0.22. Currently, the categories are determined based on the range [0, max(values)], while in the future they will be determined based on the unique values.
If you want the future behaviour and silence this warning, you can specify "categories='auto'".
In case you used a LabelEncoder before this OneHotEncoder to convert the categories to integers, then you can now use the OneHotEncoder directly.
  warnings.warn(msg, FutureWarning)

Out[42]:

<16512x5 sparse matrix of type '<class 'numpy.float64'>'
	with 16512 stored elements in Compressed Sparse Row format>

In [43]:

housing_cat_1hot.toarray()

Out[43]:

array([[1., 0., 0., 0., 0.],
       [1., 0., 0., 0., 0.],
       [0., 0., 0., 0., 1.],
       ...,
       [0., 1., 0., 0., 0.],
       [1., 0., 0., 0., 0.],
       [0., 0., 0., 1., 0.]])

OneHotEncoder无法接受字符串类型的数据,只能接受数值型的数据。所以我们必须把枚举型的类别特征转成数值类型,再转换成OneHot编码。
不过在sklearn中有现成的实现: LabelBinarizer

In [44]:

from sklearn.preprocessing import LabelBinarizer
encoder = LabelBinarizer()
housing_cat_1hot = encoder.fit_transform(housing_cat)
housing_cat_1hot

Out[44]:

array([[1, 0, 0, 0, 0],
       [1, 0, 0, 0, 0],
       [0, 0, 0, 0, 1],
       ...,
       [0, 1, 0, 0, 0],
       [1, 0, 0, 0, 0],
       [0, 0, 0, 1, 0]], dtype=int32)
  • 自己写一个转换器

虽然scikit-learn提供了非常多有用的转换器(transformers),我们有时候仍然会需要自定义一些转换器。
scikit-learn依赖所谓的duck typing,并不是通过继承的方式实现接口,因此我们自定义转换器只需要实现fittransformfit_transform三个方法就可以把它作为转换器直接使用。
我们这里实现一个用于组合特征的转换器:

In [45]:

from sklearn.base import BaseEstimator, TransformerMixin

rooms_ix, bedrooms_ix, population_ix, household_ix = 3, 4, 5, 6

class CombinedAttributesAdder(BaseEstimator, TransformerMixin):
    def __init__(self, add_bedrooms_per_room = True): # no *args or **kargs
        self.add_bedrooms_per_room = add_bedrooms_per_room
    def fit(self, X, y=None):
        return self # nothing else to do
    def transform(self, X, y=None):
        rooms_per_household = X[:, rooms_ix] / X[:, household_ix]
        population_per_household = X[:, population_ix] / X[:, household_ix]
        if self.add_bedrooms_per_room:
            bedrooms_per_room = X[:, bedrooms_ix] / X[:, rooms_ix]
            return np.c_[X, rooms_per_household, population_per_household,
                         bedrooms_per_room]
        else:
            return np.c_[X, rooms_per_household, population_per_household]

attr_adder = CombinedAttributesAdder(add_bedrooms_per_room=False)
housing_extra_attribs = attr_adder.transform(housing.values)
  • 特征缩放

特征放缩是一个不可缺少的步骤
最常用的两种放缩是:

  • 最大最小放缩(min-max scaling): MinMaxScaler 放缩完是[0,1]之间

    x−minmaxx−minmax

  • 标准化(standardization): StandardScaler 对极端数据的容忍能力比较强

    x−μσx−μσ

注意,无论什么转换器(包括放缩),不要在整个数据集上调用fit。只应该在训练数据集上fit。

转换器管道(transformation pipeline)

我们在把数据从最原始的形态转换成最终供机器学习算法使用的形态,可能需要做多次转换,这个过程可以使用scikit-learn的pipeline来组装起来。

Pipeline的构造器接收一个list,里面的每一个元素都是一个二元组,包括我们对转换器的命名以及转换器对象实例。List中除了最后一个esitmator以外,其他的都必须是transformer(也就是必须有fit_transform方法)

当我们调用pipeline的fit方法时,它会顺序地调用所有transformer的fit_transform方法,而对于最后一个esitmater只会调用它的fit方法。 实际上,pipeline向外会暴露跟最后一个estimator一模一样的方法。

In [46]:

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

num_pipline = Pipeline([
    ('imputer', SimpleImputer(strategy='median')),
    ('attribs_adder', CombinedAttributesAdder()),
    ('std_scaler', StandardScaler())
])
housing_num_tr = num_pipline.fit_transform(housing_num)

前面是对数值型数据的转换,那么对于枚举型的类别数据,我们也需要进行转换,那么对于既有数值型又有枚举型,我们可以使用scikit-learn提供的FeatureUnion

In [47]:

from sklearn.base import BaseEstimator, TransformerMixin
    
class DataFrameSelector(BaseEstimator, TransformerMixin):
    def __init__(self, attribute_names):
        self.attribute_names = attribute_names
    def fit(self, X, y=None):
        return self
    def transform(self, X):
        return X[self.attribute_names].values

In [48]:

from sklearn.pipeline import FeatureUnion

class CustomLabelBinarizer(BaseEstimator, TransformerMixin):
    def __init__(self, sparse_output=False):
        self.sparse_output = sparse_output
    def fit(self, X, y=None):
        return self
    def transform(self, X, y=None):
        enc = LabelBinarizer(sparse_output=self.sparse_output)
        return enc.fit_transform(X)

num_attribs = list(housing_num)
cat_attribs = ['ocean_proximity']

num_pipeline = Pipeline([
    ('selector', DataFrameSelector(num_attribs)),
    ('imputer', SimpleImputer(strategy='median')),
    ('attribs_adder', CombinedAttributesAdder()),
    ('std_scalar', StandardScaler())
])

cat_pipeline = Pipeline([
    ('selector', DataFrameSelector(cat_attribs)),
    ('label_binarizer', CustomLabelBinarizer())
])

full_pipeline = FeatureUnion(transformer_list=[
    ('num_pipeline', num_pipeline),
    ('cat_pipeline', cat_pipeline)
])

housing_prepared = full_pipeline.fit_transform(housing)

In [49]:

housing_prepared = full_pipeline.fit_transform(housing)
housing_prepared

Out[49]:

array([[-1.15604281,  0.77194962,  0.74333089, ...,  0.        ,
         0.        ,  0.        ],
       [-1.17602483,  0.6596948 , -1.1653172 , ...,  0.        ,
         0.        ,  0.        ],
       [ 1.18684903, -1.34218285,  0.18664186, ...,  0.        ,
         0.        ,  1.        ],
       ...,
       [ 1.58648943, -0.72478134, -1.56295222, ...,  0.        ,
         0.        ,  0.        ],
       [ 0.78221312, -0.85106801,  0.18664186, ...,  0.        ,
         0.        ,  0.        ],
       [-1.43579109,  0.99645926,  1.85670895, ...,  0.        ,
         1.        ,  0.        ]])

第四步

选择模型并训练

1、 线性模型

In [50]:

from sklearn.linear_model import LinearRegression

In [51]:

lin_reg = LinearRegression()
# 有监督的学习housing_prepare特征, housing_labels目标变量
lin_reg.fit(housing_prepared, housing_labels)

Out[51]:

LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None,
         normalize=False)

In [52]:

# 测试看看
some_data = housing.iloc[:5]
some_labels = housing_labels.iloc[:5]
some_data_prepared = full_pipeline.transform(some_data)
  • 我们使用scikit-learn的mean_squared_error来看看RMSE:

In [53]:

from sklearn.metrics import mean_squared_error
housing_predictions = lin_reg.predict(housing_prepared)
lin_mse = mean_squared_error(housing_labels, housing_predictions)
lin_rmse = np.sqrt(lin_mse)
lin_rmse

Out[53]:

68628.19819848923

大部分街区(district)的房价中位数都在$120,000 ~ $265,000之间,所以这里平均$68,628的误差显然有点不太合适。
训练集上误差很大
这显然是欠拟合了,那么应对欠拟合,我们的措施有:

  1. 换一个更加强大的模型
  2. 构造出更好的特征
  3. 减少对模型的约束

让我们换个模型试试:

2、决策树

In [54]:

from sklearn.tree import DecisionTreeRegressor

tree_reg = DecisionTreeRegressor()
tree_reg.fit(housing_prepared, housing_labels)

Out[54]:

DecisionTreeRegressor(criterion='mse', max_depth=None, max_features=None,
           max_leaf_nodes=None, min_impurity_decrease=0.0,
           min_impurity_split=None, min_samples_leaf=1,
           min_samples_split=2, min_weight_fraction_leaf=0.0,
           presort=False, random_state=None, splitter='best')
  • 观察效果

In [55]:

housing_predictions = tree_reg.predict(housing_prepared)
tree_mse = mean_squared_error(housing_labels, housing_predictions)
tree_rmse = np.sqrt(tree_mse)
tree_rmse

Out[55]:

0.0
  • 训练集上的误差为0,说明过拟合

用交叉验证集来选择更好的模型

我们可以继续使用train_test_split来把原来的训练集切分成训练集和交叉验证集。
不过scikit-learn为我们准备好了更易用的交叉验证功能。

In [56]:

from sklearn.model_selection import cross_val_score

scores = cross_val_score(tree_reg, housing_prepared, housing_labels,
                         scoring="neg_mean_squared_error", cv=10)
rmse_scores = np.sqrt(-scores)

In [57]:

def display_scores(scores):
    print("RMSE:", scores)
    print("平均RMSE:", scores.mean())
    print("RMSE标准差:", scores.std())

display_scores(rmse_scores)
RMSE: [69327.01708558 65486.39211857 71358.25563341 69091.37509104
 70570.20267046 75529.94622521 69895.20650652 70660.14247357
 75843.74719231 68905.17669382]
平均RMSE: 70666.74616904806
RMSE标准差: 2928.322738055112
  • 用交叉验证方法评价线性回归:

In [58]:

lin_scores = cross_val_score(lin_reg, housing_prepared, housing_labels,
                             scoring="neg_mean_squared_error", cv=10)
lin_rmse_scores = np.sqrt(-lin_scores)
display_scores(lin_rmse_scores)
RMSE: [66782.73843989 66960.118071   70347.95244419 74739.57052552
 68031.13388938 71193.84183426 64969.63056405 68281.61137997
 71552.91566558 67665.10082067]
平均RMSE: 69052.46136345084
RMSE标准差: 2731.6740017983475

显然决策树过拟合了

3、 用随机森林

In [59]:

from sklearn.ensemble import RandomForestRegressor

forest_reg = RandomForestRegressor()
forest_reg.fit(housing_prepared, housing_labels)
housing_predictions = forest_reg.predict(housing_prepared)
forest_mse = mean_squared_error(housing_labels, housing_predictions)
forest_rmse = np.sqrt(forest_mse)
print('训练集误差:', forest_rmse)
C:\Anaconda3\lib\site-packages\sklearn\ensemble\forest.py:246: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22.
  "10 in version 0.20 to 100 in 0.22.", FutureWarning)
训练集误差: 22256.354579885898

In [60]:

forest_reg = RandomForestRegressor()
forest_scores = cross_val_score(forest_reg, housing_prepared, housing_labels,
                                scoring="neg_mean_squared_error", cv=10)
forest_rmse_scores = np.sqrt(-forest_scores)
display_scores(forest_rmse_scores)
C:\Anaconda3\lib\site-packages\sklearn\ensemble\forest.py:246: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22.
  "10 in version 0.20 to 100 in 0.22.", FutureWarning)
C:\Anaconda3\lib\site-packages\sklearn\ensemble\forest.py:246: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22.
  "10 in version 0.20 to 100 in 0.22.", FutureWarning)
C:\Anaconda3\lib\site-packages\sklearn\ensemble\forest.py:246: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22.
  "10 in version 0.20 to 100 in 0.22.", FutureWarning)
C:\Anaconda3\lib\site-packages\sklearn\ensemble\forest.py:246: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22.
  "10 in version 0.20 to 100 in 0.22.", FutureWarning)
C:\Anaconda3\lib\site-packages\sklearn\ensemble\forest.py:246: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22.
  "10 in version 0.20 to 100 in 0.22.", FutureWarning)
C:\Anaconda3\lib\site-packages\sklearn\ensemble\forest.py:246: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22.
  "10 in version 0.20 to 100 in 0.22.", FutureWarning)
C:\Anaconda3\lib\site-packages\sklearn\ensemble\forest.py:246: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22.
  "10 in version 0.20 to 100 in 0.22.", FutureWarning)
C:\Anaconda3\lib\site-packages\sklearn\ensemble\forest.py:246: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22.
  "10 in version 0.20 to 100 in 0.22.", FutureWarning)
C:\Anaconda3\lib\site-packages\sklearn\ensemble\forest.py:246: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22.
  "10 in version 0.20 to 100 in 0.22.", FutureWarning)
C:\Anaconda3\lib\site-packages\sklearn\ensemble\forest.py:246: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22.
  "10 in version 0.20 to 100 in 0.22.", FutureWarning)
RMSE: [52868.21871547 49194.92340594 51713.77716246 55012.10310441
 50973.88861214 55990.4479905  52298.68285092 50953.09058463
 54428.48087563 53461.73225682]
平均RMSE: 52689.53455589254
RMSE标准差: 1980.36257012708

我们通常会试验很多模型,特别是应用不同的参数。
那么,我们可以把模型存储下来,以后再次加载,可以快速地进行模型间的对比:

from sklearn.externals import joblib

joblib.dump(my_model, "my_model.pkl")

my_model_loaded = joblib.load("my_model.pkl")

第五步

参数调优

  • 网格搜索

In [61]:

from sklearn.model_selection import GridSearchCV

param_grid = [
    {'n_estimators': [3, 10, 30], 'max_features': [2, 4, 6, 8]},
    {'bootstrap': [False], 'n_estimators': [3, 10], 'max_features': [2, 3, 4]},
]

forest_reg = RandomForestRegressor()

grid_search = GridSearchCV(forest_reg, param_grid, cv=5,
                           scoring='neg_mean_squared_error')
grid_search.fit(housing_prepared, housing_labels)

Out[61]:

GridSearchCV(cv=5, error_score='raise-deprecating',
       estimator=RandomForestRegressor(bootstrap=True, criterion='mse', max_depth=None,
           max_features='auto', max_leaf_nodes=None,
           min_impurity_decrease=0.0, min_impurity_split=None,
           min_samples_leaf=1, min_samples_split=2,
           min_weight_fraction_leaf=0.0, n_estimators='warn', n_jobs=None,
           oob_score=False, random_state=None, verbose=0, warm_start=False),
       fit_params=None, iid='warn', n_jobs=None,
       param_grid=[{'n_estimators': [3, 10, 30], 'max_features': [2, 4, 6, 8]}, {'bootstrap': [False], 'n_estimators': [3, 10], 'max_features': [2, 3, 4]}],
       pre_dispatch='2*n_jobs', refit=True, return_train_score='warn',
       scoring='neg_mean_squared_error', verbose=0)

In [62]:

grid_search.best_params_

Out[62]:

{'max_features': 6, 'n_estimators': 30}

In [63]:

grid_search.best_estimator_

Out[63]:

RandomForestRegressor(bootstrap=True, criterion='mse', max_depth=None,
           max_features=6, max_leaf_nodes=None, min_impurity_decrease=0.0,
           min_impurity_split=None, min_samples_leaf=1,
           min_samples_split=2, min_weight_fraction_leaf=0.0,
           n_estimators=30, n_jobs=None, oob_score=False,
           random_state=None, verbose=0, warm_start=False)

In [64]:

# 看看每一组的评估
cvres = grid_search.cv_results_
for mean_score, params in zip(cvres["mean_test_score"], cvres["params"]):
    print(np.sqrt(-mean_score), params)
64560.56453532923 {'max_features': 2, 'n_estimators': 3}
55582.7022830937 {'max_features': 2, 'n_estimators': 10}
52946.41821544518 {'max_features': 2, 'n_estimators': 30}
60706.36585084631 {'max_features': 4, 'n_estimators': 3}
52620.50721816631 {'max_features': 4, 'n_estimators': 10}
50524.81738581646 {'max_features': 4, 'n_estimators': 30}
58527.66047437809 {'max_features': 6, 'n_estimators': 3}
52222.271025610295 {'max_features': 6, 'n_estimators': 10}
49935.06005093446 {'max_features': 6, 'n_estimators': 30}
58659.80511658877 {'max_features': 8, 'n_estimators': 3}
52363.81008209303 {'max_features': 8, 'n_estimators': 10}
50107.93319293479 {'max_features': 8, 'n_estimators': 30}
62413.99504781873 {'bootstrap': False, 'max_features': 2, 'n_estimators': 3}
54498.69196389087 {'bootstrap': False, 'max_features': 2, 'n_estimators': 10}
60335.933168485164 {'bootstrap': False, 'max_features': 3, 'n_estimators': 3}
52359.94950597992 {'bootstrap': False, 'max_features': 3, 'n_estimators': 10}
59131.91266427517 {'bootstrap': False, 'max_features': 4, 'n_estimators': 3}
51851.7761074725 {'bootstrap': False, 'max_features': 4, 'n_estimators': 10}

随机搜索

scikit-learn提供的RandomizedSearchCV在超参空间很大的时候可以帮助我们更加方便地去寻找合适的超参。
它的使用方式和GridSearchCV没什么区别,不过它有额外的两个好处:

  1. 假如我们让它迭代1000次,它会对每一个超参设置1000个不同的值,使得搜索的空间变得更大
  2. 只要算力够,就可以简单地通过设置迭代次数来扩大搜索空间

集成方法(Ensemble Methods)

将多个模型组合在一起来形成一个更为强大的集成模型,特别是在不同的子模型误差类型迥异的时候效果更佳。

分析最好的模型以及它们的误差

通过分析模型误差,我们可能发现更深刻的洞见。

In [65]:

feature_importances = grid_search.best_estimator_.feature_importances_
feature_importances

Out[65]:

array([7.69687766e-02, 7.04319887e-02, 4.38660619e-02, 1.80630448e-02,
       1.66508742e-02, 1.79482850e-02, 1.59942989e-02, 3.27548930e-01,
       5.57736006e-02, 1.05319561e-01, 9.13965806e-02, 1.16638033e-02,
       1.38350194e-01, 1.03976446e-04, 3.83940095e-03, 6.08062375e-03])

In [66]:

extra_attribs = ["rooms_per_hhold", "pop_per_hhold", "bedrooms_per_room"]
cat_one_hot_attribs = list(encoder.classes_)
attributes = num_attribs + extra_attribs + cat_one_hot_attribs
sorted(zip(feature_importances, attributes), reverse=True)

Out[66]:

[(0.32754893001195934, 'median_income'),
 (0.13835019350471953, 'INLAND'),
 (0.10531956070724346, 'pop_per_hhold'),
 (0.09139658055040592, 'bedrooms_per_room'),
 (0.07696877663966344, 'longitude'),
 (0.07043198869339834, 'latitude'),
 (0.05577360056115168, 'rooms_per_hhold'),
 (0.04386606192454317, 'housing_median_age'),
 (0.018063044805051474, 'total_rooms'),
 (0.01794828495917463, 'population'),
 (0.016650874220719983, 'total_bedrooms'),
 (0.01599429894210943, 'households'),
 (0.01166380333543238, '<1H OCEAN'),
 (0.006080623745976418, 'NEAR OCEAN'),
 (0.0038394009525752966, 'NEAR BAY'),
 (0.00010397644587548845, 'ISLAND')]

第六步

最终方案

在测试集上评估最终效果

In [67]:

final_model = grid_search.best_estimator_

X_test = strat_test_set.drop("median_house_value", axis=1)
y_test = strat_test_set["median_house_value"].copy()

X_test_prepared = full_pipeline.transform(X_test)
final_predictions = final_model.predict(X_test_prepared)

final_mse = mean_squared_error(y_test, final_predictions)
final_rmse = np.sqrt(final_mse)

print(final_rmse)
47579.68069327446

第七步

上线、监控、维护

  • 正式化代码、编写测试
  • 编写监控代码
  • 人工评估旁路
  • 定期重训模型的机制

改进

  1. 试试使用支持向量机(sklearn.svm.SVR),尝试使用不同的核以及正则化因子C
  2. 试试把教程中的GridSearchCV换成RandomizedSearchCV看看是不是能找到更好的超参
  3. 试试在数据准备的pipeline中增加挑选最重要的特征的转换器(transformer)
  4. 试试使用GridSearchCV来自动地决定某些数据准备工作是不是需要做
2019-12-13 10:14:01 weixin_44953795 阅读数 20
  • 从零开始学习机器学习视频教程

    零基础入门机器学习视频培训课程概况:机器学习数学基础、Python基础、机器学习算法(线性回归、逻辑回归、聚类算法、EM算法),机器学习项目实战(Kmeans篮球数据分析、贝叶斯算法训练)、推荐算法、项目实战。  任务作业:很多人都喜欢看NBA,也喜欢拿实力相近的球员进行比较,你能利用机器学习的方式进行分析吗?动手的机会来了!请 结合课程【项目实战】章节中的【Kmeans篮球数据分类】。从NBA网站中随机拿到30名篮球运动员的得分和助攻(尽量数据间隔较大)。用python对数据进行处理(换算成每分钟的得分和助攻)。然后用Kmeans对获取的球员进行分类。看看自己心仪的球员属于哪一类~  (温馨提示: 注意 作业需写在CSDN博客中,请把作业链接贴在评论区,老师会定期逐个批改~~)

    5410 人正在学习 去看看 陆永剑

#加州房价预测实例#
任务:
基于加州房价数据集建立一个预测模型,使之可以在给定的条件下,预测加州任何地点的房价的中位数。
在这里插入图片描述
一、定义问题
1.公司要如何利用我的模型?
模型的输出将作为另一个机器学习算法的输入,该算法在综合考虑其他因素之后,决定是否值得在该区域投资。
2. 目前是否有可行的解决方案?
目前该区域的房价信息由一个专家团队完成,他们建立了非常复杂的模型。不仅费时费力,而且他们的评估泵不够准确,差错率达到15%。

二、将工程问题归纳为机器学习的问题
有监督学习任务,因为数据样本包含标签。
回归任务,因为你要预测一个价格。这是一个多变量回归任务,你要基于多个特征变量预测价格。
批量学习任务,因为并没有连续数据流输入系统。

三、选择评价指标
回归任务通常采用平方根均方误差(RMSE)作为评价指标,他衡量了系统预测差错的标准差。
???(?,ℎ)=√(1/? ∑_(?=1)?▒〖(ℎ(?((?) ))−?^((?) ) )^2 〗 )
如果有很多街区数据有异常,肯恒需要使用平均绝对误差(MAE)
???(?,ℎ)=1/? ∑_(?=1)?▒〖|ℎ(?((?) ))−?^((?) ) )|〗

四、windows环境配置和软件安装
书上案例是建议用linux系统或者macOS系统去做,但是我用的是window系统,所以将配置过程记录下来。我用的是Anaconda软件去做的。
软件下载过程及配置可以参考安装Anaconda教程这篇文章。
1.创建空间
这时候最好选择一个虚拟空间vitualenv,这样在以后做的过程中可以省去很多麻烦。
打开Anaconda Prompt,输入命令:cd D:\Anaconda3\Scripts(这里的路径是你安装的路径,可以按你的需求更改。注意,这个路径是加入到系统变量里的。)
然后输入:virtualenv env
这里是调用virtualenv这个程序,生成名为env的虚拟空间。
这时候就生成了名为env的虚拟空间,要想激活,输入命令activate env
这时候就进入了你的虚拟空间,这时候命令行开头会有env字样。
如:在这里插入图片描述
2.安装需要用到的python包
房价预测可以用得到的包是
接着上面的输入:
在这里插入图片描述
出现:
在这里插入图片描述
为了检测安装的正确性,尝试着用下面的命令导入模块:
在这里插入图片描述
这一步不应该出现任何错误。现在激活Jupyter:
在这里插入图片描述
这时候Jupyter服务器就在终端运行,接口8889,同时在IE浏览器打开了Jupyter的主页。如果没有打开,可以自己复制网址在浏览器里打开。
在这里插入图片描述
这一步完成了三件事:第一个就是创造了一个名为Untitle.ipynb的记事本。二是打开了一个Jupyter Python kernel来运行这个notebook。三是在新的tab里打开了一个这个notebook。我们可以点击Untitled改为自己要定义的名字。我们测试一下,输入hello world!
在这里插入图片描述
第一次输入出错了,因为是用中文输入法中的(),所以一定要用英文输入法!!!!

五、对数据进行处理
S1、好了,现在所有的准备工作就只剩下数据的下载了。该数据是一个公开数据集,可以在互联网上直接下载获取。在这个项目中,事情很多更简单:你只需要下载一个压缩文件housing.tgz即可,这个文件夹里包含housing.csv,包含所有数据。
下载数据的网址是:数据下载
housing.csv在datasets/housing目录下。
下载过程输入代码:
在这里插入图片描述
当我们引用fetch_housing_data(),它就会创建一个datasets/housing目录在你的工作空间下面,并且会下载housing.tgz文件,并进行解压出housing.csv文件。

S2、当我们需要加载数据时,用到的python包是Pandas。我们需要写一个小的功能程序去加载这些数据。
在这里插入图片描述
这个功能返回来一个Pandas DataFrame,其中包含你的所有数据。

S3:让我们先来看一下这个数据的前五行部分。
在这里插入图片描述
注意:housing.csv文件一定要在datasets文件目录下面,如果没有的话需要手动upload。否则会出现找不到文件的错误。
从数据中我们可以看出,数据主要对经纬度、房价的中位数、总的房间数、总的卧室数、人口数量等特征进行的描述。
每一行代表一个街区,一共有10个特征。

S4、info()函数是对数据进行一个快速直观的描述,尤其是列的总数和每一个分类的特点以及空特征的数量。
在这里插入图片描述
在这个数据集里一共有20640个例子,这意味着相对于机器学习来说,这是一个相对小的数据集。请注意,total_bed rooms属性只有20433个非空值,这意味着207个地区没有使用此功能。我们以后需要处理这个问题。

所有属性都是数值的,除了ocean_proximity。它的类型是object,所以可以保存任何类型的python对象,但由于你是从csv文件加载此数据的,你知道它一定是一个文本属性。当你看前五排的时候,你可能注意到该列中的值是重复的,这意味着可能是一个分类属性。我们通过value_counts()发现存在哪些类别以及有多少个类别属于每一类。
在这里插入图片描述
所以这确实是一个分类信息。
S5:、让我们来看一下其他领域。除了ocean_proximity,其他都是数值特征,因此我们可以通过describe()来展示一系列数值特征。
在这里插入图片描述
我们同样可以把它打印出来。
在这里插入图片描述
通过这个图中我们可以看出:count、mean、min和max行的意义是显而易见的。请注意,空值被忽略了(例如,卧室总数为20433,而不是20640)。std行即标准偏差(测量值的分散程度)。25%、50%和75%行显示相应的百分位数:百分位数表示一组观测值中给定百分比低于的值。例如25%的街区其房龄值小于18年,50%少于29年,75%少于37年。

另一个对数据得到直观感受到方法就是画直方图。你可以用hist()来描述。用hist()需要引用python的matplotlib包,所以需要提前导入。
在这里插入图片描述
观察结果:
收入中位数似乎并非以美元计算。查看数据团队的报告可以发现,收入数值均已按比例放缩,高收入样本收入截止到15,而低收入样本截止到0.5;
通过直方图我们可以很轻松的发现有大于800个街区的房价的中位数高于$5000,000;
Housing median age和median house value也设置了截止点;
各属性的放缩比例不同;
很多数据都有长尾现象,从中位数向左比向右的距离短得多。不利于机器学习算法的学习,因此应该采取某种变换方式,变换为钟形。

这一部分主要是机器学习的初级部分,以房价预测为实例,介绍怎么用Anaconda的Jupyter以及各种配置,方便大家学习。再就是对这个实例的数据进行的分析,各种程序需要理解其意思。

2019-03-19 21:21:07 qq_41185868 阅读数 10191
  • 从零开始学习机器学习视频教程

    零基础入门机器学习视频培训课程概况:机器学习数学基础、Python基础、机器学习算法(线性回归、逻辑回归、聚类算法、EM算法),机器学习项目实战(Kmeans篮球数据分析、贝叶斯算法训练)、推荐算法、项目实战。  任务作业:很多人都喜欢看NBA,也喜欢拿实力相近的球员进行比较,你能利用机器学习的方式进行分析吗?动手的机会来了!请 结合课程【项目实战】章节中的【Kmeans篮球数据分类】。从NBA网站中随机拿到30名篮球运动员的得分和助攻(尽量数据间隔较大)。用python对数据进行处理(换算成每分钟的得分和助攻)。然后用Kmeans对获取的球员进行分类。看看自己心仪的球员属于哪一类~  (温馨提示: 注意 作业需写在CSDN博客中,请把作业链接贴在评论区,老师会定期逐个批改~~)

    5410 人正在学习 去看看 陆永剑

ML之回归预测:利用13种机器学习算法对Boston(波士顿房价)数据集【13+1,506】进行回归预测(房价预测)+预测新数据得分

导读
本文章基于前边的一篇文章,对13种机器学习的回归模型性能比较以后,然后利用各个模型对新的数据进行实际回归预测,然后提交到官方,进行成绩测试。发现LGBR算法性能最好,XGBR算法次之,其中rbf_SVR算法性能最差,博主没有把该算法运行的结果提交,只提交了其中一些算的预测文件,然后列出了官方得出的score。
各个模型性能请参考文章:ML之回归预测:利用13种机器学习算法对Boston(波士顿房价)数据集【13+1,506】进行回归预测(房价预测)来比较各模型性能

相关文章:ML之回归预测:利用13种机器学习算法对Boston(波士顿房价)数据集【13+1,506】进行回归预测(房价预测)+预测新数据得分

 

目录

输出结果

设计思路


 

 

 

输出结果

 

设计思路

 

 

 

 

 

 

 

2019-01-07 21:54:15 chuan403082010 阅读数 862
  • 从零开始学习机器学习视频教程

    零基础入门机器学习视频培训课程概况:机器学习数学基础、Python基础、机器学习算法(线性回归、逻辑回归、聚类算法、EM算法),机器学习项目实战(Kmeans篮球数据分析、贝叶斯算法训练)、推荐算法、项目实战。  任务作业:很多人都喜欢看NBA,也喜欢拿实力相近的球员进行比较,你能利用机器学习的方式进行分析吗?动手的机会来了!请 结合课程【项目实战】章节中的【Kmeans篮球数据分类】。从NBA网站中随机拿到30名篮球运动员的得分和助攻(尽量数据间隔较大)。用python对数据进行处理(换算成每分钟的得分和助攻)。然后用Kmeans对获取的球员进行分类。看看自己心仪的球员属于哪一类~  (温馨提示: 注意 作业需写在CSDN博客中,请把作业链接贴在评论区,老师会定期逐个批改~~)

    5410 人正在学习 去看看 陆永剑

项目 1: 预测波士顿房价

第一步. 导入数据

在这个项目中,你将利用马萨诸塞州波士顿郊区的房屋信息数据训练和测试一个模型,并对模型的性能和预测能力进行测试。通过该数据训练后的好的模型可以被用来对房屋做特定预测---尤其是对房屋的价值。对于房地产经纪等人的日常工作来说,这样的预测模型被证明非常有价值。

此项目的数据集来自UCI机器学习知识库(数据集已下线)。波士顿房屋这些数据于1978年开始统计,共506个数据点,涵盖了麻省波士顿不同郊区房屋14种特征的信息。本项目对原始数据集做了以下处理:

  • 有16个'MEDV' 值为50.0的数据点被移除。 这很可能是由于这些数据点包含遗失看不到的值
  • 有1个数据点的 'RM' 值为8.78. 这是一个异常值,已经被移除。
  • 对于本项目,房屋的'RM', 'LSTAT''PTRATIO'以及'MEDV'特征是必要的,其余不相关特征已经被移除。
  • 'MEDV'特征的值已经过必要的数学转换,可以反映35年来市场的通货膨胀效应。

运行下面区域的代码以载入波士顿房屋数据集,以及一些此项目所需的Python库。如果成功返回数据集的大小,表示数据集已载入成功。

# 载入此项目所需要的库
import numpy as np
import pandas as pd
import visuals as vs # Supplementary code

# 检查你的Python版本
from sys import version_info
if version_info.major != 2 and version_info.minor != 7:
    raise Exception('请使用Python 2.7来完成此项目')
    
# 让结果在notebook中显示
%matplotlib inline
# 载入波士顿房屋的数据集
data = pd.read_csv('housing.csv')
prices = data['MEDV']
features = data.drop('MEDV', axis = 1)
    
# 完成
print "Boston housing dataset has {} data points with {} variables each.".format(*data.shape)

第二步. 分析数据

在项目的第一个部分,你会对波士顿房地产数据进行初步的观察并给出你的分析。通过对数据的探索来熟悉数据可以让你更好地理解和解释你的结果。

由于这个项目的最终目标是建立一个预测房屋价值的模型,我们需要将数据集分为特征(features)目标变量(target variable)

  • 特征 'RM', 'LSTAT',和 'PTRATIO',给我们提供了每个数据点的数量相关的信息。
  • 目标变量'MEDV',是我们希望预测的变量。

他们分别被存在featuresprices两个变量名中。

编程练习 1:基础统计运算

你的第一个编程练习是计算有关波士顿房价的描述统计数据。我们已为你导入了numpy,你需要使用这个库来执行必要的计算。这些统计数据对于分析模型的预测结果非常重要的。 在下面的代码中,你要做的是:

  • 计算prices中的'MEDV'的最小值、最大值、均值、中值和标准差;
  • 将运算结果储存在相应的变量中。
    #TODO 1
    
    #目标:计算价值的最小值
    minimum_price = np.min(prices)
    
    #目标:计算价值的最大值
    maximum_price = np.max(prices)
    
    #目标:计算价值的平均值
    mean_price = np.mean(prices)
    
    #目标:计算价值的中值
    median_price = np.median(prices)
    
    #目标:计算价值的标准差
    std_price = np.std(prices)
    
    #目标:输出计算的结果
    print "Statistics for Boston housing dataset:\n"
    print "Minimum price: ${:,.2f}".format(minimum_price)
    print "Maximum price: ${:,.2f}".format(maximum_price)
    print "Mean price: ${:,.2f}".format(mean_price)
    print "Median price ${:,.2f}".format(median_price)
    print "Standard deviation of prices: ${:,.2f}".format(std_price)

    问题 1 - 特征观察

    如前文所述,本项目中我们关注的是其中三个值:'RM''LSTAT' 和'PTRATIO',对每一个数据点:

  • 'RM' 是该地区中每个房屋的平均房间数量;
  • 'LSTAT' 是指该地区有多少百分比的业主属于是低收入阶层(有工作但收入微薄);
  • 'PTRATIO' 是该地区的中学和小学里,学生和老师的数目比(学生/老师)。
  • 凭直觉,上述三个特征中对每一个来说,你认为增大该特征的数值,'MEDV'的值会是增大还是减小呢?每一个答案都需要你给出理由。

    提示:你预期一个'RM' 值是6的房屋跟'RM' 值是7的房屋相比,价值更高还是更低呢?

问题 1 - 回答:

RM 增大, MEDV会相对增大: RM增大,单个房屋里的房间数增大, 侧面也可以反映出或许是有更多的人入住, 有更多的需求,MEDV价格也会相对提高 LSTAT增大,MEDV会相对降低: LSTAT代表低收入阶层的比例, 低收入阶层比例增大, 证明此地区消费水平变低,或者此地区产业不景气, MEDC的价格也会随之降低 PREARIO增大,MEDV会降低: 老师和学生的比例越来越大,说明有更多的学生,更少的老师, 更多的学生是否可以理解成此地区居住人口多, 老师变少,可以理解为,此地区待遇不好,或者地区发展并不完善, 社区匹配越不健全,房价也就越低

编程练习 2: 数据分割与重排

接下来,你需要把波士顿房屋数据集分成训练和测试两个子集。通常在这个过程中,数据也会被重排列,以消除数据集中由于顺序而产生的偏差。 在下面的代码中,你需要

使用 sklearn.model_selection 中的 train_test_split, 将featuresprices的数据都分成用于训练的数据子集和用于测试的数据子集。

  • 分割比例为:80%的数据用于训练,20%用于测试;
  • 选定一个数值以设定 train_test_split 中的 random_state ,这会确保结果的一致性;
    # TODO 2
    from sklearn.model_selection import train_test_split
    
    X_train, X_test, y_train, y_test = train_test_split(features,prices,test_size = 0.20, random_state=10)

    问题 2 - 训练及测试

    将数据集按一定比例分为训练用的数据集和测试用的数据集对学习算法有什么好处?

    如果用模型已经见过的数据,例如部分训练集数据进行测试,又有什么坏处?

    提示: 如果没有数据来对模型进行测试,会出现什么问题?

    问题 2 - 回答:

    将数据集按一定比例分为训练用的数据集和测试用的数据集对学习算法有什么好处? 可以使用训练的数据反复进行训练, 来找出最佳的模型, 然后通过测试集数据测试 来确定此模型是否也应用于其他数据

    如果用模型已经见过的数据,例如部分训练集数据进行测试,又有什么坏处? 使用训练数据集数据进行 测试, 造成的结果是 模型一直适用, 当碰到其他新的数据的时候,就会出现很大偏差


    第三步. 模型衡量标准

    在项目的第三步中,你需要了解必要的工具和技巧来让你的模型进行预测。用这些工具和技巧对每一个模型的表现做精确的衡量可以极大地增强你预测的信心。

    编程练习3:定义衡量标准

    如果不能对模型的训练和测试的表现进行量化地评估,我们就很难衡量模型的好坏。通常我们会定义一些衡量标准,这些标准可以通过对某些误差或者拟合程度的计算来得到。在这个项目中,你将通过运算决定系数 R2 来量化模型的表现。模型的决定系数是回归分析中十分常用的统计信息,经常被当作衡量模型预测能力好坏的标准。

    R2的数值范围从0至1,表示目标变量的预测值和实际值之间的相关程度平方的百分比。一个模型的R2 值为0还不如直接用平均值来预测效果好;而一个R2 值为1的模型则可以对目标变量进行完美的预测。从0至1之间的数值,则表示该模型中目标变量中有百分之多少能够用特征来解释。模型也可能出现负值的R2,这种情况下模型所做预测有时会比直接计算目标变量的平均值差很多。

    在下方代码的 performance_metric 函数中,你要实现:

  • 使用 sklearn.metrics 中的 r2_score 来计算 y_true 和 y_predict的R2值,作为对其表现的评判。
  • 将他们的表现评分储存到score变量中。
  • (可选) 不使用任何外部库,参考决定系数的定义进行计算,这也可以帮助你更好的理解决定系数在什么情况下等于0或等于1。
  • # TODO 3
    from sklearn.metrics import r2_score
    
    def performance_metric(y_true, y_predict):
        """计算并返回预测值相比于预测值的分数"""
        score = r2_score(y_true,y_predict)
    
        return score
    # TODO 3 可选
    
    # 不允许导入任何计算决定系数的库
    
    def performance_metric2(y_true, y_predict):
    
        return None

    问题 3 - 拟合程度

    假设一个数据集有五个数据且一个模型做出下列目标变量的预测:

    真实数值 预测数值
    3.0 2.5
    -0.5 0.0
    2.0 2.1
    7.0 7.8
    4.2 5.3

    你觉得这个模型已成功地描述了目标变量的变化吗?如果成功,请解释为什么,如果没有,也请给出原因。

    提示:运行下方的代码,使用performance_metric函数来计算模型的决定系数。

    # 计算这个模型的预测结果的决定系数
    score = performance_metric([3, -0.5, 2, 7, 4.2], [2.5, 0.0, 2.1, 7.8, 5.3])
    print "Model has a coefficient of determination, R^2, of {:.3f}.".format(score)

    问题 3 - 回答:

    我觉得不能成功的描述目标变量的变化, 数据量太少了, 如果数据量大于50 或许可以


    第四步. 分析模型的表现

    在项目的第四步,我们来看一下不同参数下,模型在训练集和验证集上的表现。这里,我们专注于一个特定的算法(带剪枝的决策树,但这并不是这个项目的重点),和这个算法的一个参数 'max_depth'。用全部训练集训练,选择不同'max_depth' 参数,观察这一参数的变化如何影响模型的表现。画出模型的表现来对于分析过程十分有益,这可以让我们看到一些单看结果看不到的行为。

    学习曲线

    下方区域内的代码会输出四幅图像,它们是一个决策树模型在不同最大深度下的表现。每一条曲线都直观得显示了随着训练数据量的增加,模型学习曲线的在训练集评分和验证集评分的变化,评分使用决定系数R2。曲线的阴影区域代表的是该曲线的不确定性(用标准差衡量)。

    运行下方区域中的代码,并利用输出的图形回答下面的问题。

    # 根据不同的训练集大小,和最大深度,生成学习曲线
    vs.ModelLearning(X_train, y_train)

  • 问题 4 - 学习曲线

    选择上述图像中的其中一个,并给出其最大深度。随着训练数据量的增加,训练集曲线的评分有怎样的变化?验证集曲线呢?如果有更多的训练数据,是否能有效提升模型的表现呢?

    提示:学习曲线的评分是否最终会收敛到特定的值?

    问题 4 - 回答:

    图二 max_depth = 3, 随着训练数据量的增加, 训练集曲线稍许下滑后,然后趋向于平缓. 验证集曲线缓慢上升后 也趋向于平缓, 且波动比较小 我觉得学习曲线的评分不会到收敛到一个特定值, 到会收敛到一个特定范围,一个比较小的范围

    复杂度曲线

    下列代码内的区域会输出一幅图像,它展示了一个已经经过训练和验证的决策树模型在不同最大深度条件下的表现。这个图形将包含两条曲线,一个是训练集的变化,一个是验证集的变化。跟学习曲线相似,阴影区域代表该曲线的不确定性,模型训练和测试部分的评分都用的 performance_metric 函数。

    运行下方区域中的代码,并利用输出的图形并回答下面的两个问题。

  • # 根据不同的最大深度参数,生成复杂度曲线
    vs.ModelComplexity(X_train, y_train)

  • 问题 5 - 偏差(bias)与方差(variance)之间的权衡取舍

    当模型以最大深度 1训练时,模型的预测是出现很大的偏差还是出现了很大的方差?当模型以最大深度10训练时,情形又如何呢?图形中的哪些特征能够支持你的结论?

    提示: 你如何得知模型是否出现了偏差很大或者方差很大的问题?

    问题 5 - 回答:

    当模型以最大深度1训练时,r2_score值比较低,说明预测不准确,不能很好的使用特征来解释, 所以会出现很大偏差 当模型以最大深度10训练时, 训练集的R2_score接近了1, 但是测试集的R2_score反而在下降, 说明对训练集有很好的拟合度,但是却不能很好的推广到新的数据,这也是高方差的表现

    问题 6- 最优模型的猜测

    结合问题 5 中的图,你认为最大深度是多少的模型能够最好地对未见过的数据进行预测?你得出这个答案的依据是什么?

    问题 6 - 回答:


    第五步. 选择最优参数

    我觉得深度在4左右的模型能够最好的对未见过的数据进行预测 4左右, 训练集的r2_score在0.8-0.9附近, 可以很好的预测训练集 测试集的r2_score在 0.8附近, 也是所有深度里 表现最好的情况 而且 训练集与测试集之间的差距也不算很大,说明这些特征可以进行较好的预测

    问题 7- 网格搜索(Grid Search)

    什么是网格搜索法?如何用它来优化模型?

    问题 7 - 回答:

    在你不确定什么才是最优参数的时候, 使用Grid Search, Grid Search会使用这些参数 分别进行交叉验证, 并计算得分,帮你找出最优参数 我们可以通过最有参数来 优化模型 假设有俩个参数(a和b) 需要确定, 那么先确定a和b的可能范围, 这样在a和b的坐标轴上,a和b的各个可能值组成了一个个网格(Grid),GridSearch便依次将该网格上的参数带入到模型里,用cv方法计算并评分,等搜索完全部网格后, 取出最高分为最优参数

    网格搜索也不一定总是选择得分最高的模型,如果评分标准是loss,会返回评分最低 参考链接:http://blog.csdn.net/fushunsu/article/details/46332203

    问题 8 - 交叉验证

  • 什么是K折交叉验证法(k-fold cross-validation)?
  • GridSearchCV是如何结合交叉验证来完成对最佳参数组合的选择的?
  • GridSearchCV中的'cv_results_'属性能告诉我们什么?
  • 网格搜索时如果不使用交叉验证会有什么问题?交叉验证又是如何解决这个问题的?
  • 在下方 fit_model 函数中,你需要做的是:

  • 定义 'cross_validator' 变量: 使用 sklearn.model_selection 中的 KFold 创建一个交叉验证生成器对象;
  • 定义 'regressor' 变量: 使用 sklearn.tree 中的 DecisionTreeRegressor 创建一个决策树的回归函数;
  • 定义 'params' 变量: 为 'max_depth' 参数创造一个字典,它的值是从1至10的数组;
  • 定义 'scoring_fnc' 变量: 使用 sklearn.metrics 中的 make_scorer 创建一个评分函数; 将 ‘performance_metric’ 作为参数传至这个函数中;
  • 定义 'grid' 变量: 使用 sklearn.model_selection 中的 GridSearchCV 创建一个网格搜索对象;将变量'regressor''params''scoring_fnc'和 'cross_validator' 作为参数传至这个对象构造函数中;
  • 如果你对python函数的默认参数定义和传递不熟悉,可以参考这个MIT课程的视频

    提示: 在下面 fit_model函数最后加入 print pd.DataFrame(grid.cv_results_) 可以帮你查看更多信息。

    问题 8 - 回答:

    1.k折交叉验证,是将所有数据平分到相同大小的k个容器内, 挑一个容器作为验证容器,剩下k-1作为训练容器,进行k-1次循环的实验,每次挑选一个不容的k容器,交叉验证的要点是这个运行多次,然后取平均值. 2.CridSeaarchCV 每一次取不同的参数,然后通过k折交叉验证 得到最后得. 进行多次取参(每一次都会进行k折交叉验证), 来找出最优组合 3.GridSearchCV中的'cvresults'属性 可以知道所有参数的组合,以及这些参数组合的训练得分 测试得分, 平均值, 标准差 一类的信息 4.不使用交叉验证的话 可能得到的并不是最优结果,可能会造成误差挺大, 交叉验证,多次更换训练集和测试集,获得所有测试组的评分, 可以最优模型,来提高训练的准确度

    如果数据量不大,随机性也不够好,比如分布有顺序性,那么分出来的验证集有可能只包含数据集中一种特点的数据,这时候在验证集上得到的分数可能是不准确的。有可能是模型拟合得比较好的数据,得到的成绩优于真实表现;有可能是模型拟合得比较差的数据,得到的成绩差于真实表现。如果使用交叉验证,那么就会取多次不同的验证集分数的平均值,多次取平均值能够减少对模型表现评分的误差,这样就可以更准确地找到最优参数。 交叉验证的作用并不是直接避免过拟合欠拟合等问题,而是给出准确的评分,帮助网格搜索选择参数。

    编程练习 4:训练最优模型

    在这个练习中,你将需要将所学到的内容整合,使用决策树算法训练一个模型。为了得出的是一个最优模型,你需要使用网格搜索法训练模型,以找到最佳的 'max_depth' 参数。你可以把'max_depth' 参数理解为决策树算法在做出预测前,允许其对数据提出问题的数量。决策树是监督学习算法中的一种。

  • # TODO 4
    from sklearn.model_selection import KFold
    from sklearn.tree import DecisionTreeRegressor
    from sklearn.metrics import make_scorer
    from sklearn.model_selection import GridSearchCV
    
    def fit_model(X, y):
        """ 基于输入数据 [X,y],利于网格搜索找到最优的决策树模型"""
        
        cross_validator = KFold(n_splits = 10,shuffle = True)
        
        regressor = DecisionTreeRegressor()
    
        params = {'max_depth':[1,2,3,4,5,6,7,8,9,10]}
    
        scoring_fnc = make_scorer(performance_metric)
    
        grid = GridSearchCV(cv=cross_validator,estimator = regressor,param_grid=params,scoring=scoring_fnc )
    
        # 基于输入数据 [X,y],进行网格搜索
        grid = grid.fit(X, y)
    
        # 返回网格搜索后的最优模型
        return grid.best_estimator_
    

    编程练习 4:训练最优模型 (可选)

    在这个练习中,你将需要将所学到的内容整合,使用决策树算法训练一个模型。为了得出的是一个最优模型,你需要使用网格搜索法训练模型,以找到最佳的 'max_depth' 参数。你可以把'max_depth' 参数理解为决策树算法在做出预测前,允许其对数据提出问题的数量。决策树是监督学习算法中的一种。

    在下方 fit_model 函数中,你需要做的是:

  • 遍历参数‘max_depth’的可选值 1~10,构造对应模型
  • 计算当前模型的交叉验证分数
  • 返回最优交叉验证分数对应的模型
    # TODO 4 可选
    
    '''
    不允许使用 DecisionTreeRegressor 以外的任何 sklearn 库
    
    提示: 你可能需要实现下面的 cross_val_score 函数
    
    def cross_val_score(estimator, X, y, scoring = performance_metric, cv=3):
        """ 返回每组交叉验证的模型分数的数组 """
        scores = [0,0,0]
        return scores
    '''
    
    def fit_model2(X, y):
        """ 基于输入数据 [X,y],利于网格搜索找到最优的决策树模型"""
        
        #最优交叉验证分数对应的最优模型
        best_estimator = None
        
        return best_estimator

    问题 9 - 最优模型

    最优模型的最大深度(maximum depth)是多少?此答案与你在问题 6所做的猜测是否相同?

    运行下方区域内的代码,将决策树回归函数代入训练数据的集合,以得到最优化的模型。

    # 基于训练数据,获得最优模型
    optimal_reg = fit_model(X_train, y_train)
    
    # 输出最优模型的 'max_depth' 参数
    print "Parameter 'max_depth' is {} for the optimal model.".format(optimal_reg.get_params()['max_depth'])

    问题 9 - 回答:

    最优模型的最大深度是4, 与题6的猜测相同

    第六步. 做出预测

    当我们用数据训练出一个模型,它现在就可用于对新的数据进行预测。在决策树回归函数中,模型已经学会对新输入的数据提问,并返回对目标变量的预测值。你可以用这个预测来获取数据未知目标变量的信息,这些数据必须是不包含在训练数据之内的。

    问题 10 - 预测销售价格

    想像你是一个在波士顿地区的房屋经纪人,并期待使用此模型以帮助你的客户评估他们想出售的房屋。你已经从你的三个客户收集到以下的资讯:

    特征 客戶 1 客戶 2 客戶 3
    房屋内房间总数 5 间房间 4 间房间 8 间房间
    社区贫困指数(%被认为是贫困阶层) 17% 32% 3%
    邻近学校的学生-老师比例 15:1 22:1 12:1

    你会建议每位客户的房屋销售的价格为多少?从房屋特征的数值判断,这样的价格合理吗?为什么?

    提示:用你在分析数据部分计算出来的统计信息来帮助你证明你的答案。

    运行下列的代码区域,使用你优化的模型来为每位客户的房屋价值做出预测。

    # 生成三个客户的数据
    client_data = [[5, 17, 15], # 客户 1
                   [4, 32, 22], # 客户 2
                   [8, 3, 12]]  # 客户 3
    
    # 进行预测
    predicted_price = optimal_reg.predict(client_data)
    for i, price in enumerate(predicted_price):
        print "Predicted selling price for Client {}'s home: ${:,.2f}".format(i+1, price)

    问题 10 - 回答:

    客户房屋销售价格分别为:416,850.00416,850.00228,156.25 $913,500.00 我认为这个价格是合理的

    上面计算的最大值是1,024,800 最小值是105,000 均值是454,342.94 预测上面三个房屋的价格都在这个范围内

    与之前分析的一致 RM 增大, MEDV会相对增大; LSTAT增大,MEDV会相对降低; PREARIO增大,MEDV会降低;

    编程练习 5

    你刚刚预测了三个客户的房子的售价。在这个练习中,你将用你的最优模型在整个测试数据上进行预测, 并计算相对于目标变量的决定系数 R2的值**。

    #TODO 5
    
    # 提示:你可能需要用到 X_test, y_test, optimal_reg, performance_metric
    # 提示:你可能需要参考问题10的代码进行预测
    # 提示:你可能需要参考问题3的代码来计算R^2的值
    
    predicted_price = optimal_reg.predict(X_test)
    
    r2 = performance_metric(y_test,predicted_price)
    
    print "Optimal model has R^2 score {:,.2f} on test data".format(r2)

    问题11 - 分析决定系数

    你刚刚计算了最优模型在测试集上的决定系数,你会如何评价这个结果?

    问题11 - 回答

    决定系数在0.87, 与问题6分析的 测试数据将在0.8附近一致,0.87 说明这些特征可以体现房屋的价格

    模型健壮性

    一个最优的模型不一定是一个健壮模型。有的时候模型会过于复杂或者过于简单,以致于难以泛化新增添的数据;有的时候模型采用的学习算法并不适用于特定的数据结构;有的时候样本本身可能有太多噪点或样本过少,使得模型无法准确地预测目标变量。这些情况下我们会说模型是欠拟合的。

    问题 12 - 模型健壮性

    模型是否足够健壮来保证预测的一致性?

    提示: 执行下方区域中的代码,采用不同的训练和测试集执行 fit_model 函数10次。注意观察对一个特定的客户来说,预测是如何随训练数据的变化而变化的。

  • # 请先注释掉 fit_model 函数里的所有 print 语句
    vs.PredictTrials(features, prices, fit_model, client_data)
    

    问题 12 - 回答:

    数据会有浮动, 数据的浮动在 $30,372.22 这个价格之间,幅度差不到10分之一 我觉得模型已经足够健壮 可以保证预测的一致性

    问题 13 - 实用性探讨

    简单地讨论一下你建构的模型能否在现实世界中使用?

    提示:回答以下几个问题,并给出相应结论的理由:

  • 1978年所采集的数据,在已考虑通货膨胀的前提下,在今天是否仍然适用?
  • 数据中呈现的特征是否足够描述一个房屋?
  • 在波士顿这样的大都市采集的数据,能否应用在其它乡镇地区?
  • 你觉得仅仅凭房屋所在社区的环境来判断房屋价值合理吗?
  • 问题 13 - 回答:

    1.在考虑到通货膨胀的前提下,我觉得今天仍然适用 2.不能足够描述一个房屋,还与其地区未来政策, 其地区的发展有关 3.不适用与乡镇 4.不合理,还需考虑地区

    可选问题 - 预测北京房价

    (本题结果不影响项目是否通过)通过上面的实践,相信你对机器学习的一些常用概念有了很好的领悟和掌握。但利用70年代的波士顿房价数据进行建模的确对我们来说意义不是太大。现在你可以把你上面所学应用到北京房价数据集中 bj_housing.csv

    免责声明:考虑到北京房价受到宏观经济、政策调整等众多因素的直接影响,预测结果仅供参考。

    这个数据集的特征有:

  • Area:房屋面积,平方米
  • Room:房间数,间
  • 目标变量:

  • Value: 房屋人民币售价,万
  • 你可以参考上面学到的内容,拿这个数据集来练习数据分割与重排、定义衡量标准、训练模型、评价模型表现、使用网格搜索配合交叉验证对参数进行调优并选出最佳参数,比较两者的差别,最终得出最佳模型对验证集的预测分数。

  • Living: 厅数,间
  • School: 是否为学区房,0或1
  • Year: 房屋建造时间,年
  • Floor: 房屋所处楼层,层
    # TODO 6
    
    # 载入波士顿房屋的数据集
    data = pd.read_csv('bj_housing.csv')
    prices = data['Value']
    features = data.drop('Value', axis = 1)
    X_train, X_test, y_train, y_test = train_test_split(features,prices,test_size = 0.20)
    optimal_reg = fit_model(X_train, y_train)
    predicted_price = optimal_reg.predict(X_test)
    r2 = performance_metric(y_test,predicted_price)
    print r2
    

    问题14 - 北京房价预测

    你成功的用新的数据集构建了模型了吗?他能对测试数据进行验证吗?它的表现是否符合你的预期?交叉验证是否有助于提升你模型的表现?

    提示:如果你是从零开始构建机器学习的代码会让你一时觉得无从下手。这时不要着急,你要做的只是查看之前写的代码,把每一行都看明白,然后逐步构建你的模型。当中遇到什么问题也可以在我们论坛寻找答案。也许你会发现你所构建的模型的表现并没有达到你的预期,这说明机器学习并非是一项简单的任务,构建一个表现良好的模型需要长时间的研究和测试。这也是我们接下来的课程中会逐渐学到的。

    问题14 - 回答

    使用新的数据构建了模型, 但是觉得不能对测试数据进行验证, r2的波动幅度太大, 小则0.2左右 大则0.7左右, 表现不符合预期,交叉验证在此模型中似乎没起到什么作用

     

没有更多推荐了,返回首页