欢迎来到预测波士顿房价项目!在此文件中,咱们已经提供了一些示例代码,但你还须要完善更多功能才能让项目成功运行。除非有明确要求,你无需修改任何已给出的代码。习题的标题为编程练习。每一部分都会有详细的指导,须要实现的部分也会在注释中以TODO标出。请仔细阅读全部的提示!html
除了实现代码外,你还必须回答一些问题。请仔细阅读每一个问题,而且在问题后的'回答'文字框中写出完整的答案。咱们的项目审阅者将会根据你对问题的回答和撰写代码所实现的功能来进行评分。python
提示:代码 和 Markdown单元格 可经过 Shift + Enter 快捷键运行。另外,Markdown单元格 能够经过双击进入编辑模式。
在这个项目中,你将使用咱们提供的波士顿房屋信息数据来训练和测试一个模型,并对模型的性能和预测能力进行评估。咱们但愿能够经过该模型实现对房屋的价值预估,提升房地产经纪人的工做效率。算法
此项目的数据集来自kaggle原始数据,未通过任何处理。该数据集统计了2006年至2010年波士顿我的住宅销售状况,包含2900多条观测数据(其中一半是训练数据,即咱们的housedata.csv
文件)。更多文档信息能够参考做者的文档(能够不看),以及项目附件data_description.txt
文件(特征描述文件,必定要看)。编程
运行下面区域的代码以载入一些此项目所需的Python库。若是成功返回提示语句,则说明载入成功。api
# 载入此项目须要的库 import numpy as np import pandas as pd import visuals as vs # Supplementary code 补充的可视化代码 import matplotlib.pyplot as plt import seaborn as sns plt.style.use('seaborn') # use seaborn style 使用seaborn风格 import warnings warnings.filterwarnings('ignore') %matplotlib inline print('你已经成功载入全部库!')
你已经成功载入全部库!
你的第一个编程练习是加载波士顿房价数据。咱们已为你导入了 Pandas
,你须要使用这个库中的read_csv方法来执行必要的过程。数组
导入数据将会是你整个项目的开始dom
若是成功返回数据集的大小,表示数据集已载入成功。机器学习
# 1 TODO:载入波士顿房屋的数据集:使用pandas载入csv,并赋值到data_df data_df = pd.read_csv('housedata.csv') # 成功载入的话输出训练数据行列数目 print("Boston housing dataset has {} data points with {} variables each.".format(*data_df.shape))
Boston housing dataset has 1460 data points with 81 variables each.
这个部分,你要对已有的波士顿房地产数据进行初步的观察与处理。同时,经过对数据的探索可让你更好地理解数据。ide
因为这个项目的最终目标是创建一个预测房屋价值的模型,咱们须要将数据集分为特征(features)和目标变量(target variable)。函数
'SalePrice'
,是咱们但愿预测的变量。 'SalePrice'
外的属性都是特征,它们反应了数据点在某些方面的表现或性质。你的第二个编程练习是对波士顿房价的数据进行观察,这一步会让你掌握更多数据自己的信息。具体问题以下:
问题2.1:使用head方法打印并观察前7条data_df
数据
# 2.1 TODO: 打印出前7条data_df print(data_df.head(7))
Id MSSubClass MSZoning LotFrontage LotArea Street Alley LotShape \ 0 1 60 RL 65.0 8450 Pave NaN Reg 1 2 20 RL 80.0 9600 Pave NaN Reg 2 3 60 RL 68.0 11250 Pave NaN IR1 3 4 70 RL 60.0 9550 Pave NaN IR1 4 5 60 RL 84.0 14260 Pave NaN IR1 5 6 50 RL 85.0 14115 Pave NaN IR1 6 7 20 RL 75.0 10084 Pave NaN Reg LandContour Utilities ... PoolArea PoolQC Fence MiscFeature MiscVal \ 0 Lvl AllPub ... 0 NaN NaN NaN 0 1 Lvl AllPub ... 0 NaN NaN NaN 0 2 Lvl AllPub ... 0 NaN NaN NaN 0 3 Lvl AllPub ... 0 NaN NaN NaN 0 4 Lvl AllPub ... 0 NaN NaN NaN 0 5 Lvl AllPub ... 0 NaN MnPrv Shed 700 6 Lvl AllPub ... 0 NaN NaN NaN 0 MoSold YrSold SaleType SaleCondition SalePrice 0 2 2008 WD Normal 208500 1 5 2007 WD Normal 181500 2 9 2008 WD Normal 223500 3 2 2006 WD Abnorml 140000 4 12 2008 WD Normal 250000 5 10 2009 WD Normal 143000 6 8 2007 WD Normal 307000 [7 rows x 81 columns]
问题2.2:Id特征对咱们训练数据没有任何用处,在data_df
中使用drop方法删除'Id'
列数据
# 2.2 TODO: 删除data_df中的Id特征(保持数据仍在data_df中,不更改变量名) data_df.drop(columns=['Id'], inplace=True)
问题2.3:使用describe方法观察data_df
各个特征的统计信息:
# 2.3 TODO: data_df.describe(include=[np.number])
MSSubClass | LotFrontage | LotArea | OverallQual | OverallCond | YearBuilt | YearRemodAdd | MasVnrArea | BsmtFinSF1 | BsmtFinSF2 | ... | WoodDeckSF | OpenPorchSF | EnclosedPorch | 3SsnPorch | ScreenPorch | PoolArea | MiscVal | MoSold | YrSold | SalePrice | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 1460.000000 | 1201.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1452.000000 | 1460.000000 | 1460.000000 | ... | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 |
mean | 56.897260 | 70.049958 | 10516.828082 | 6.099315 | 5.575342 | 1971.267808 | 1984.865753 | 103.685262 | 443.639726 | 46.549315 | ... | 94.244521 | 46.660274 | 21.954110 | 3.409589 | 15.060959 | 2.758904 | 43.489041 | 6.321918 | 2007.815753 | 180921.195890 |
std | 42.300571 | 24.284752 | 9981.264932 | 1.382997 | 1.112799 | 30.202904 | 20.645407 | 181.066207 | 456.098091 | 161.319273 | ... | 125.338794 | 66.256028 | 61.119149 | 29.317331 | 55.757415 | 40.177307 | 496.123024 | 2.703626 | 1.328095 | 79442.502883 |
min | 20.000000 | 21.000000 | 1300.000000 | 1.000000 | 1.000000 | 1872.000000 | 1950.000000 | 0.000000 | 0.000000 | 0.000000 | ... | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 | 2006.000000 | 34900.000000 |
25% | 20.000000 | 59.000000 | 7553.500000 | 5.000000 | 5.000000 | 1954.000000 | 1967.000000 | 0.000000 | 0.000000 | 0.000000 | ... | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 5.000000 | 2007.000000 | 129975.000000 |
50% | 50.000000 | 69.000000 | 9478.500000 | 6.000000 | 5.000000 | 1973.000000 | 1994.000000 | 0.000000 | 383.500000 | 0.000000 | ... | 0.000000 | 25.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 6.000000 | 2008.000000 | 163000.000000 |
75% | 70.000000 | 80.000000 | 11601.500000 | 7.000000 | 6.000000 | 2000.000000 | 2004.000000 | 166.000000 | 712.250000 | 0.000000 | ... | 168.000000 | 68.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 8.000000 | 2009.000000 | 214000.000000 |
max | 190.000000 | 313.000000 | 215245.000000 | 10.000000 | 9.000000 | 2010.000000 | 2010.000000 | 1600.000000 | 5644.000000 | 1474.000000 | ... | 857.000000 | 547.000000 | 552.000000 | 508.000000 | 480.000000 | 738.000000 | 15500.000000 | 12.000000 | 2010.000000 | 755000.000000 |
# data_df.info() #查看dataFrame的信息
咱们的数据不多是百分百的‘干净’数据(即有用数据),总会在采集整理时有些”失误“、“冗余”,形成“脏”数据,因此咱们要从数据的正确性和完整性这两个方面来清理数据。
I would recommend removing any houses with more than 4000 square feet from the data set (which eliminates these five unusual observations) before assigning it to students.
建议咱们去掉数据中'GrLivArea'
中超过4000平方英尺的房屋(具体缘由能够参考文档),固然本数据集还有其余的异常点,这里再也不处理。
问题3.1:正确性
请按下述步骤删除一些不合理的数据
问题3.1.1:使用matplotlib
库中的scatter方法 绘制'GrLivArea'
和'SalePrice'
的散点图,x轴为'GrLivArea'
,y轴为'SalePrice'
,观察数据
# 3.1.1 TODO:绘制要求的图形 plt.scatter(data_df['GrLivArea'], data_df['SalePrice'], c='blue', marker='.', s=30) plt.xlabel('GrLivArea') plt.ylabel('SalePrice') plt.show()
问题3.1.2:经过上图咱们能够看到那几个异常值,即'GrLivArea'
大于4000,可是'SalePrice'
又极低的数据,从data_df
删除这几个异常值,删除后从新绘制'GrLivArea'
和'SalePrice'
的关系图,确认异常值已删除。
# 3.1.2 # TODO:从data_df中删除 GrLivArea大于4000 且 SalePrice低于300000 的值 index = data_df[(data_df['GrLivArea'] > 4000) & (data_df['SalePrice'] < 300000)].index data_df.drop(index=index, inplace=True) # TODO:从新绘制GrLivArea和SalePrice的关系图,确认异常值已删除 plt.scatter(data_df['GrLivArea'], data_df['SalePrice'], c='blue', marker='.', s=50) plt.xlabel('GrLivArea') plt.ylabel('SalePrice') plt.show()
问题3.2:完整性
请按下述步骤,补足数据的完整性
问题3.2.1:筛选出过多空数据的特征,咱们这个项目定为筛选出有超过25%为空数据的特征
limit_percent = 0.25 limit_value = len(data_df) * limit_percent # 3.2.1 TODO 统计并打印出超过25%的空数据的特征,你能够考虑使用isna() list(data_df.columns[data_df.isna().sum() > limit_value])
['Alley', 'FireplaceQu', 'PoolQC', 'Fence', 'MiscFeature']
若是你整理出的特征是'Alley', 'FireplaceQu', 'PoolQC', 'Fence', 'MiscFeature'
,那就说明你统计对了,接着咱们查看data_description.txt
文件,就会发现,这些并不是必定是空缺数据,而没有游泳池,篱笆等也会用NA来表示,那么就不须要删除这些特征了,而是用None
来填充NA
数据。
问题3.2.2:根据data_description.txt
特征描述,使用fillna方法填充空数据,具体哪种数据须要填充什么已经整理好了,请按提示要求来进行填充
# 直接运行不用修改 # 肯定全部空特征 missing_columns = list(data_df.columns[data_df.isnull().sum() != 0]) # 肯定哪些是类别特征,哪些是数值特征 missing_numerical = list(data_df[missing_columns].dtypes[data_df[missing_columns].dtypes != 'object'].index) missing_category = [i for i in missing_columns if i not in missing_numerical] print("missing_numerical:",missing_numerical) print("missing_category:",missing_category)
missing_numerical: ['LotFrontage', 'MasVnrArea', 'GarageYrBlt'] missing_category: ['Alley', 'MasVnrType', 'BsmtQual', 'BsmtCond', 'BsmtExposure', 'BsmtFinType1', 'BsmtFinType2', 'Electrical', 'FireplaceQu', 'GarageType', 'GarageFinish', 'GarageQual', 'GarageCond', 'PoolQC', 'Fence', 'MiscFeature']
data_df.mode() # 取众数,返回DataFrame
MSSubClass | MSZoning | LotFrontage | LotArea | Street | Alley | LotShape | LandContour | Utilities | LotConfig | ... | PoolArea | PoolQC | Fence | MiscFeature | MiscVal | MoSold | YrSold | SaleType | SaleCondition | SalePrice | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 20.0 | RL | 60.0 | 7200.0 | Pave | Grvl | Reg | Lvl | AllPub | Inside | ... | 0.0 | Ex | MnPrv | Shed | 0.0 | 6.0 | 2009.0 | WD | Normal | 140000.0 |
1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | Fa | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
2 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | Gd | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
# 须要填充众数的特征 fill_Mode = ['Electrical'] # 须要填充None的特征 fill_None = ['Alley', 'MasVnrType', 'BsmtQual', 'BsmtCond', 'BsmtExposure', 'BsmtFinType1', 'BsmtFinType2', 'FireplaceQu', 'GarageType', 'GarageFinish', 'GarageQual', 'GarageCond', 'PoolQC', 'Fence', 'MiscFeature'] # 须要填充0的特征 fill_0 = ['GarageYrBlt'] # 须要填充中位数的特征 fill_median = ['LotFrontage', 'MasVnrArea'] # 3.4.1 TODO:按需填补上面数据 # 个人实现: # # 填充众数: # mode = data_df[fill_Mode].mode().iloc[0,0] # data_df.fillna(value={fill_Mode[0]: mode}, inplace=True) # # 填充None: # d_None={} # for i in fill_None: # d_None[i] = 'None' # data_df.fillna(value=d_None, inplace=True) # # 填充0: # data_df[fill_0].fillna(value=0, inplace=True) # # 填充中位数: # data_df[fill_median].fillna(data_df[fill_median].median(), inplace=True) # 简化实现: data_df[fill_Mode] = data_df[fill_Mode].fillna(data_df[fill_Mode].mode()) data_df[fill_None] = data_df[fill_None].fillna('None') data_df[fill_0] = data_df[fill_0].fillna(0) data_df[fill_median] = data_df[fill_median].fillna(data_df[fill_median].median()) # 验证 # data_df.isna().sum()
有这么一句话在业界普遍流传:特征数据决定了机器学习的上限,而模型和算法只是逼近这个上限而已。特征工程,是整个数据分析过程当中不可缺乏的一个环节,其结果质量直接关系到模型效果和最终结论。从上面两步中咱们获得了“干净”的数据,可是data_df
总共有81个特征,咱们应当剔除那些可有可无的特征(噪声),使用真正关键的特征来进行模型训练。如今须要咱们对这些庞大的数据进行分析,提取出与目标最为关联的数据。
问题4.1:绘制'SalePrice'
的直方图,并说明该直方图属于什么分布
# 4.1 TODO:绘制要求的图形 # plt.hist(data_df['SalePrice'], bins=50, normed=False, color=None) # plt.xlabel('SalePrice') # plt.show() data_df['SalePrice'].hist(bins=50)
<matplotlib.axes._subplots.AxesSubplot at 0x22186a3e7b8>
回答问题4.1:'SalePrice'
属于 正偏态 分布
import scipy scipy.stats.skew(data_df['SalePrice'])
1.8793604459195012
结果>0,表明正偏,从计算上也说明了'SalePrice'属于正偏态分布。
若是特征极其多,很难清晰的看到特征与目标变量之间的关系,就须要利用统计知识来进行多变量分析了。咱们常使用热图heatmap结合corr方法来进行客观分析,热图Heatmap能够用颜色变化来反映变量之间的相关性二维矩阵或说相关性表格中的数据信息,它能够直观地将数据值的大小以定义的颜色深浅表示出来。这个项目,为了简化训练,咱们以相关性绝对值大于0.5为界来选取咱们须要的特征。
# 不用修改直接运行 corrmat = data_df.corr().abs() #计算连续型特征之间的相关系数 #将于SalePrice的相关系数大于5的特征取出来,并按照SalePrice降序排列,而后取出对应的特征名,保存在列表中 top_corr = corrmat[corrmat["SalePrice"]>0.5].sort_values(by = ["SalePrice"], ascending = False).index cm = abs(np.corrcoef(data_df[top_corr].values.T)) #注意这里要转置,不然变成样本之间的相关系数,而咱们要计算的是特征之间的相关系数 f, ax = plt.subplots(figsize=(20, 9)) sns.set(font_scale=1.3) hm = sns.heatmap(cm, cbar=True, annot=True, square=True, fmt='.2f', annot_kws={'size': 13}, yticklabels=top_corr.values, xticklabels=top_corr.values); data_df = data_df[top_corr]
咱们已经从庞大的特征群中筛选出了最相关的特征,也了解了咱们目标数据的分布,那么接下来,咱们从创造性方面来对咱们的特征进行“改造”。
由于咱们筛选出来的特征都为数值类型特征,因此咱们只作标准化的操做:这个项目是一个回归类型的项目,而咱们的回归算法对标准正态分步预测较为准确,从咱们的目标数据能够看出数据是一个偏态分布,那么咱们使用log将数据从偏态分布转换为标准正态分布,最后进行标准化。
# 不要修改,直接运行 from scipy.special import boxcox1p from sklearn.preprocessing import StandardScaler data_df['SalePrice'] = np.log1p(data_df['SalePrice']) # np.log1p()函数将数据从偏态分布转换成标准正态分布 numeric_features = list(data_df.columns) numeric_features.remove('SalePrice') for feature in numeric_features: #all_data[feat] += 1 data_df[feature] = boxcox1p(data_df[feature], 0.15) scaler = StandardScaler() scaler.fit(data_df[numeric_features]) data_df[numeric_features] = scaler.transform(data_df[numeric_features])
笔记:
在项目的第三步中,你须要了解必要的工具和技巧来让你的模型可以进行预测。用这些工具和技巧对每个模型的表现作精确的衡量能够极大地加强你预测的可信度。
若是不能对模型的训练和测试的表现进行量化地评估,咱们就很难衡量模型的好坏。一般咱们会定义一些衡量标准,这些标准能够经过对某些偏差或者拟合程度的计算来获得。在这个项目中,你将经过运算决定系数 $R^2$ 来量化模型的表现。模型的决定系数是回归分析中十分经常使用的统计信息,常常被看成衡量模型预测能力好坏的标准。
$R^2$ 的数值范围从0至1,表示目标变量的预测值和实际值之间的相关程度平方的百分比。一个模型的 $R^2$ 值为0还不如直接用平均值来预测效果好;而一个 $R^2$ 值为1的模型则能够对目标变量进行完美的预测。从0至1之间的数值,则表示该模型中目标变量中有百分之多少可以用特征来解释。模型也可能出现负值的 $R^2$,这种状况下模型所作预测有时会比直接计算目标变量的平均值差不少。
问题5.1:
在下方代码的 performance_metric
函数中,你要实现:
sklearn.metrics
中的 r2_score
来计算 y_true
和 y_predict
的 $R^2$ 值,做为对其表现的评判。score
变量中。# 5.1 TODO: 引入 'r2_score' from sklearn.metrics import r2_score def performance_metric(y_true, y_predict): """ Calculates and returns the performance score between true and predicted values based on the metric chosen. """ # TODO: 计算 'y_true' 与 'y_predict' 的r2值 score = r2_score(y_true, y_predict) # 返回这一分数 return score
笔记:
R^2是评价模型表现的方法之一,每一个机器学习模型的创建都要有相对应的评价指标,后面咱们会学到更多的评价指标。不过R^2其实也有不少局限性须要注意 https://en.wikipedia.org/wiki...
skearn对于常见的模型表现衡量方法也有详细的介绍。
http://scikit-learn.org/stabl...
问题 5.2:拟合程度
假设一个数据集有五个数据且某一模型作出下列目标变量的预测:
真实数值 | 预测数值 |
---|---|
3.0 | 2.5 |
-0.5 | 0.0 |
2.0 | 2.1 |
7.0 | 7.8 |
4.2 | 5.3 |
你以为这个模型已成功地描述了目标变量的变化吗?若是成功,请解释为何,若是没有,也请给出缘由。
提示1:运行下方的代码,使用 performance_metric
函数来计算 y_true
和 y_predict
的决定系数。
提示2:$R^2$ 分数是指能够从自变量中预测的因变量的方差比例。 换一种说法:
#TODO 5.2:计算这一模型的表现 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))
Model has a coefficient of determination, R^2, of 0.923.
问题 5.2 - 回答:模型能够描述目标变量的变化,由于R^2值为0.923,说明自变量(预测数值)对因变量(真实数值)的解释越好。
接下来,你须要分割波士顿房屋数据集,包括特征与目标变量、训练集和测试集。一般在这个过程当中,数据也会被重排,以消除数据集中因为顺序而产生的误差。
在下面的代码中,你须要
问题6.1:将data_df
分割为特征和目标变量
# TODO: 6.1 labels = data_df['SalePrice']#TODO:提取SalePrice做为labels features = data_df.drop(['SalePrice'], axis=1)#TODO:提取除了SalePrice之外的特征赋值为features
问题6.2 :
使用 sklearn.model_selection
中的 train_test_split
, 将 features
和 prices
的数据都分红用于训练的数据子集和用于测试的数据子集。
train_test_split
中的 random_state
,这会确保结果的一致性;X_train
, X_test
, y_train
和 y_test
。# TODO: 引入 'train_test_split' from sklearn.model_selection import train_test_split # TODO: 打乱并分割训练集与测试集 X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size=0.2, random_state=1) # 成功~ print("Training and testing split was successful.")
Training and testing split was successful.
问题 6.3 - 训练及测试
将数据集按必定比例分为训练用的数据集和测试用的数据集对学习算法有什么好处?
若是用模型已经见过的数据,例如部分训练集数据进行测试,又有什么坏处?
提示: 若是没有数据来对模型进行测试,会出现什么问题?
问题 6.3 - 回答:
在项目的第四步,咱们来观察不一样参数下,模型在训练集和验证集上的表现。这里,咱们专一于一个特定的算法(带剪枝的决策树DecisionTreeRegressor
,但这并非这个项目的重点)和这个算法的一个参数 'max_depth'
。用所有训练集训练,选择不一样'max_depth'
参数,观察这一参数的变化如何影响模型的表现。画出模型的表现来对于分析过程十分有益。
下方区域内的代码会输出四幅图像,它们是一个决策树模型在不一样最大深度下的表现。每一条曲线都直观得显示了随着训练数据量的增长,模型学习曲线在训练集评分和验证集评分的变化,评分使用决定系数 $R^2$。曲线的阴影区域表明的是该曲线的不肯定性(用标准差衡量)。
运行下方区域中的代码,并利用输出的图形回答下面的问题。
# Produce learning curves for varying training set sizes and maximum depths vs.ModelLearning(features, labels)
提示:学习曲线的评分是否最终会收敛到特定的值?通常来讲,你拥有的数据越多,模型表现力越好。可是,若是你的训练和测试曲线以高于基准阈值的分数收敛,这是否有必要?基于训练和测试曲线已经收敛的前提下,思考添加更多训练点的优缺点。
问题 7 - 回答:当max_depth为3时,随着训练数据的增长,训练集曲线的评分下降,验证集曲线的评分提升,可是二者会收敛到一特定数值,随着训练数据的增长,模型表现再也不提升,此时没有必要再继续增长训练数据,由于会增长模型的训练时间。可是,若是在过拟合的状况下,比方说当max_depth为6或者10时,随着训练数据的增长,模型表现也不断提升,此时反而有必要增长训练数据。
笔记:
对训练曲线和测试曲线趋势和意义解释的很好。这里随着数据的增多,max_depth不变的状况下,模型提高的幅度也愈来愈小。
传统的机器学习算法(又被称为基于统计的机器学习)在数据量达到必定程度后,更多的数据没法提高模型的表现。深度学习的一个优点就是它能够把大量的数据利用起来,提高学习表现。
这里还有更多关于学习曲线的介绍:
https://www.coursera.org/lear...
http://scikit-learn.org/stabl...
传统的机器学习算法(又被称为基于统计的机器学习)在数据量达到必定程度后,更多的数据没法提高模型的表现。深度学习的一个优点就是它能够把大量的数据利用起来,提高学习表现。
这里还有更多关于学习曲线的介绍:
https://www.coursera.org/lear...
http://scikit-learn.org/stabl...
下列代码内的区域会输出一幅图像,它展现了一个已经通过训练和验证的决策树模型在不一样最大深度条件下的表现。这个图形将包含两条曲线,一个是训练集的变化,一个是验证集的变化。跟学习曲线类似,阴影区域表明该曲线的不肯定性,模型训练和测试部分的评分都用的 performance_metric
函数。
运行下方区域中的代码,根据问题5与问题6对输出的图形进行分析并给出你思考的结果。
vs.ModelComplexity(X_train, y_train)
提示: 高误差表示欠拟合(模型过于简单),而高方差表示过拟合(模型过于复杂,以致于没法泛化)。考虑哪一种模型(深度1或10)对应着上述的状况,并权衡误差与方差。
问题 8 - 回答:当max_depth为1时,模型表现出高误差,由于训练集和测试集的R2分数都比较低;当max_depth为10时,模型表现出高方差,由于训练集的R2分数较高,而验证集的R2分数较低。
笔记:
误差-方差分解是解释学习算法泛化性能的重要工具。这里你须要理解三个方面:
什么是泛化偏差(Generalization error):
Bias-Variance分解:
Bias-Variance trade-off:
通常状况下,误差和方差是有冲突的,以下图所示。为了取得好的泛化性能,则须要误差较小,即可以充分拟合数据,而且方差较小,即便得数据扰动产生的影响小。
更多内容请阅读参考资料。
参考资料:
[1] «机器学习», 周志华, 2.5 节误差与方差.
[2] Understanding the Bias-Variance Tradeoff
提示:查看问题8上方的图表,并查看模型在不一样 depth
下的验证分数。随着深度的增长模型的表现力会变得更好吗?咱们在什么状况下得到最佳验证分数而不会使咱们的模型过分复杂?请记住,奥卡姆剃刀:“在竞争性假设中,应该选择假设最少的那一个。”
问题 9 - 回答:
在项目的最后一节中,你将构建一个模型,并使用 fit_model
中的优化模型去预测客户特征集。
提示:在解释网格搜索算法时,首先要理解咱们为何使用网格搜索算法,以及咱们使用它的最终目的是什么。为了使你的回答更具备说服力,你还能够给出一个模型中可使用此方法进行优化参数的示例。
问题 10 - 回答: 网格搜索法是给定参数值,穷举搜索寻找最优参数的算法。网格搜索法经过构建一个参数的字典,创造出不一样的参数组合,输入给分类器进行训练,采用交叉验证,寻找验证分数最高的那一组参数,这一组参数就是模型的最优参数。
'cv_results_'
属性能告诉咱们什么?提示:在解释k-fold交叉验证时,必定要理解'k'是什么,和数据集是如何分红不一样的部分来进行训练和测试的,以及基于'k'值运行的次数。
在考虑k-fold交叉验证如何帮助网格搜索时,你可使用特定的数据子集来进行训练与测试有什么缺点,以及K折交叉验证是如何帮助缓解这个问题。
问题 11 - 回答:
在这个练习中,你将须要将所学到的内容整合,使用决策树算法训练一个模型。为了得出的是一个最优模型,你须要使用网格搜索法训练模型,以找到最佳的 'max_depth'
参数。你能够把'max_depth'
参数理解为决策树算法在作出预测前,容许其对数据提出问题的数量。决策树是监督学习算法中的一种。
在下方 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课程的视频。
# TODO: Import 'make_scorer', 'DecisionTreeRegressor', and 'GridSearchCV' 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): """ Performs grid search over the 'max_depth' parameter for a decision tree regressor trained on the input data [X, y]. """ cross_validator = KFold(n_splits=10) # TODO: Create a decision tree regressor object regressor = DecisionTreeRegressor(random_state=1) # TODO: Create a dictionary for the parameter 'max_depth' with a range from 1 to 10 params = {'max_depth':[i for i in range(1, 11)]} # TODO: Transform 'performance_metric' into a scoring function using 'make_scorer' scoring_fnc = make_scorer(performance_metric) # TODO: Create the grid search cv object --> GridSearchCV() # Make sure to include the right parameters in the object: # (estimator, param_grid, scoring, cv) which have values 'regressor', 'params', 'scoring_fnc', and 'cross_validator' respectively. grid = GridSearchCV(regressor, params, scoring_fnc, cv = cross_validator) # Fit the grid search object to the data to compute the optimal model grid = grid.fit(X, y) # Return the optimal model after fitting the data return grid.best_estimator_
当咱们用数据训练出一个模型,它就可用于对新的数据进行预测。在咱们的例子--决策树回归函数中,模型已经学会对新输入的数据“提问”,并返回对目标变量的预测值。你能够用这些预测来获取未知目标变量的数据的信息,可是,输入的新数据必须不能是已有训练数据之中的。
最优模型的最大深度(maximum depth)是多少?此答案与你在问题 9所作的猜想是否相同?
运行下方区域内的代码,将决策树回归函数代入训练数据的集合,以获得最优化的模型。
# Fit the training data to the model using grid search reg = fit_model(X_train, y_train) # Produce the value for 'max_depth' print("Parameter 'max_depth' is {} for the optimal model.".format(reg.get_params()['max_depth']))
Parameter 'max_depth' is 5 for the optimal model.
最终,使用咱们确认好的参数来对测试数据进行预测,完成下面的问题,来看看咱们的训练结果如何吧
问题12.1:填入上题所确认的最优参数,查看测试结果
depth = 5 regressor = DecisionTreeRegressor(max_depth = depth) regressor.fit(X_train, y_train) y_pred = regressor.predict(X_test) score = performance_metric(y_test, y_pred) print("The R2 score is ",score)
The R2 score is 0.7520883029841192
问题12.2:你刚刚计算了最优模型在测试集上的决定系数,你会如何评价这个结果?还有什么地方能够改进,以提高这一分数呢?
回答问题12.2:这个结果并非理想的,应该还须要利用决策树的其余参数进行网格搜索,以及使用更多的特征;