目录
[Experimenting With Different Models](#Experimenting With Different Models)
[Random Forests](#Random Forests)
在这一步结束时,你将理解欠拟合和过拟合的概念,并且能够应用这些想法来让你的模型更准确。
Experimenting With Different Models
现在你有了一种可靠的方式来衡量模型的准确性,你可以尝试其他模型,看看哪个预测效果最好。但模型有哪些可选方案呢?
你可以在 scikit-learn 的documentation中看到,决策树模型有很多选项(比你短期内想要或需要的还多)。最重要的选项决定了树的深度。回想一下本课程第一课中提到的,树的深度是指在做出预测之前它进行分裂的次数。这是一棵相对较浅的树。


在实际操作中,一棵树从顶层(所有房子)到一个叶子节点有10次分裂并不罕见。随着树的加深,数据集会被切分到包含更少房子的叶子节点。如果一棵树只有一次分裂,它就把数据分成两组。如果每一组再分裂一次,我们就会得到四组房子。再对每组进行分裂,就会生成八组。如果我们在每一层继续通过增加分裂次数来成倍增加组数,到第十层时,我们会有2^10组房子,也就是1024个叶子节点。
当我们把房子分到很多叶子节点时,每个叶子里的房子也会更少。房子很少的叶子节点会让预测值非常接近这些房子的实际数值,但对于新数据可能会非常不可靠(因为每次预测都只基于很少的房子)。
这就是所谓的过拟合现象,意思是模型几乎完美地匹配了训练数据,但在验证数据和其他新数据上表现很差。另一方面,如果我们把决策树做得很浅,它就无法把房子分成很明显的不同组。
极端情况下,如果一棵树只把房子分成2组或4组,每组里的房子仍然差异很大。结果预测可能对大多数房子都差很多,即使是在训练数据上也是如此(验证数据上也会差,原因相同)。当模型无法捕捉数据中的重要区别和模式,以至于即使在训练数据上表现也不好时,这就是所谓的欠拟合。
因为我们关心新数据的准确性,而我们是通过验证数据来估计的,所以我们想找到欠拟合和过拟合之间的最佳点。从视觉上看,我们希望下面图中(红色)验证曲线的最低点。

Example
有几种控制树深度的替代方法,而且很多方法允许树的某些路径比其他路径更深。但 max_leaf_nodes 参数提供了一种非常合理的方式来控制过拟合和欠拟合。我们允许模型生成的叶子节点越多,就越会从上图的欠拟合区域移动到过拟合区域。
我们可以使用一个工具函数来帮助比较不同 max_leaf_nodes 值下的 MAE 分数:
from sklearn.tree import DecisionTreeRegressor
form sklearn.metrics import mean_absoulte_error
def get_mae(max_leaf_nodes , train_X , train_y , val_X , val_y):
iowa_model = DecisionTreeRegressor(max_leaf_nodes = max_leaf_nodes,random_state = 0)
iowa_model.fit(train_X,train_y)
val_prediction = iowa_model.predict(val_X)
mae = mean_absoulte_error(val_prediction,val_y)
return mae
数据已经通过你之前见过(并且已经写过)的代码加载到 train_X、val_X、train_y 和 val_y 中。
# Data Loading Code Runs At This Point
import pandas as pd
# Load data
melbourne_file_path = '../input/melbourne-housing-snapshot/melb_data.csv'
melbourne_data = pd.read_csv(melbourne_file_path)
# Filter rows with missing values
filtered_melbourne_data = melbourne_data.dropna(axis=0)
# Choose target and features
y = filtered_melbourne_data.Price
melbourne_features = ['Rooms', 'Bathroom', 'Landsize', 'BuildingArea',
'YearBuilt', 'Lattitude', 'Longtitude']
X = filtered_melbourne_data[melbourne_features]
from sklearn.model_selection import train_test_split
# split data into training and validation data, for both features and target
train_X, val_X, train_y, val_y = train_test_split(X, y,random_state = 0)
我们可以用 for 循环来比较用不同 max_leaf_nodes 值构建的模型的准确性。
# compare MAE with differing values of max_leaf_nodes
for max_leaf_nodes in [5, 50, 500, 5000]:
my_mae = get_mae(max_leaf_nodes, train_X, val_X, train_y, val_y)
print("Max leaf nodes: %d \t\t Mean Absolute Error: %d" %(max_leaf_nodes, my_mae))
Max leaf nodes: 5 Mean Absolute Error: 347380
Max leaf nodes: 50 Mean Absolute Error: 258171
Max leaf nodes: 500 Mean Absolute Error: 243495
Max leaf nodes: 5000 Mean Absolute Error: 254983
在列出的选项中,500 是最理想的叶子数量。
Conclusion
重点是:模型可能会遇到以下两种情况:
- 过拟合:抓住一些未来不会出现的虚假模式,从而导致预测不够准确,或者
- 欠拟合:没有抓住相关模式,同样会导致预测不够准确。
我们使用验证数据(在模型训练中没有用到的数据)来衡量候选模型的准确性。这样我们可以尝试很多候选模型,并保留最好的那个。
Random Forests
Introduction
决策树会让你面临一个棘手的选择。一棵叶子很多的深树会过拟合,因为每个预测都是基于叶子上少量房子的历史数据。但一棵叶子少的浅树表现会很差,因为它无法捕捉原始数据中的许多差异。
即使是今天最先进的建模技术,也会在欠拟合和过拟合之间遇到这种矛盾。不过,很多模型都有聪明的想法,可以带来更好的表现。我们以随机森林为例。
随机森林使用很多棵树,并通过对每棵组成树的预测取平均值来做出预测。它通常比单棵决策树的预测准确得多,而且使用默认参数就能表现不错。如果你继续建模,还能学到性能更好的模型,但很多模型对参数设置非常敏感。
Example
你已经看到多次加载数据的代码了。在数据加载结束时,我们有以下变量:
-
train_X
-
val_X
-
train_y
-
val_y
import pandas as pd
Load data
melbourne_file_path = '../input/melbourne-housing-snapshot/melb_data.csv'
melbourne_data = pd.read_csv(melbourne_file_path)Filter rows with missing values
melbourne_data = melbourne_data.dropna(axis=0)
Choose target and features
y = melbourne_data.Price
melbourne_features = ['Rooms', 'Bathroom', 'Landsize', 'BuildingArea',
'YearBuilt', 'Lattitude', 'Longtitude']
X = melbourne_data[melbourne_features]from sklearn.model_selection import train_test_split
split data into training and validation data, for both features and target
The split is based on a random number generator. Supplying a numeric value to
the random_state argument guarantees we get the same split every time we
run this script.
train_X, val_X, train_y, val_y = train_test_split(X, y,random_state = 0)
我们构建随机森林模型的方式类似于在 scikit-learn 中构建决策树------这次使用的是 RandomForestRegressor 类,而不是 DecisionTreeRegressor。
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_absolute_error
forest_model = RandomForestRegressor(random_state=1)
forest_model.fit(train_X, train_y)
melb_preds = forest_model.predict(val_X)
print(mean_absolute_error(val_y, melb_preds))
191669.7536453626
Conclusion
可能还有进一步改进的空间,但这已经比最好的决策树错误 250,000 有了很大提升。有一些参数可以让你像调整单棵决策树的最大深度一样改变随机森林的性能。但随机森林模型的一个最佳特性是,即使不进行这些调整,它们通常也能表现得相当不错。