【精品系列】【机器学习实战】【实践项目一】区域房价中位数预测(选择和训练模型)

4、选择和训练模型

4.1、训练和评估训练集

4.1.1、LinearRegression 线性回归模型

首先,我们先训练一个线性回归模型:

from sklearn.linear_model import LinearRegression

lin_reg = LinearRegression()
lin_reg.fit(housing_prepared, housing_labels)
LinearRegression()

现在你有一个可以工作的线性回归模型了,让我们用几个训练集的实例试试:

some_data = housing[:5] # 获取前5行数据
some_labels = housing_labels.iloc[:5] # 获取前5行标签,用于验证模型结果
some_data_prepared = full_pipeline.transform(some_data) # 流水线处理数据
print("Predictions:", lin_reg.predict(some_data_prepared)) # 模型预测数据
print("Labels:", list(some_labels)) # 真实结果
Predictions: [210644.60459286 317768.80697211 210956.43331178  59218.98886849 189747.55849879]
Labels: [286600.0, 340600.0, 196900.0, 46300.0, 254500.0]

可以工作了,虽然预测还不是很准确(实际上。。。一点都不准。。。)。我们可以使用Scikit-Learnmean_squared_error()函数来测量整个训练集上回归模型的RMSE(均方根误差):

RMSE

  • Root Mean Square Error,均方根误差
  • 是观测值与真值偏差的平方和与观测次数m比值的平方根。
  • 是用来衡量观测值同真值之间的偏差

MAE

  • Mean Absolute Error ,平均绝对误差
  • 是绝对误差的平均值
  • 能更好地反映预测值误差的实际情况.

SD

  • Standard Deviation ,标准差
  • 是方差的算数平方根
  • 是用来衡量一组数自身的离散程度
    在这里插入图片描述
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
68628.19819848922

median_housing_values分布在 120000~265000 美元之间,所以典型的预测误差达到 68628 美元只能说明差强人意。

这就是一个典型的模型对训练数据欠拟合的案例。这种情况发生时,通常意味着这些:

  1. 特征可能无法提供足够的信息来做出更好的预测;
  2. 或者是模型本身不够强大。

想要修正欠拟合,可以通过:

  1. 选择更强大的模型;
  2. 或为算法训练提供更好的特征;
  3. 又或者减少模型的限制等方法。

我们这个模型不是一个正则化的模型,所以可以排除最后一个选项。你可以尝试添加更多的特征(比如,人口数量的日志),但首选,让我们尝试一个更复杂的模型,看看它到底是怎样工作的。

4.1.2、DecisionTreeRegressor 决策树模型

我们来训练一个DecisionTreeRegressor。这是一个非常强大的模型,它能够从数据中找到复杂的非线性关系(决策树)。使用方法与上面的线性回归模型相同:

from sklearn.tree import DecisionTreeRegressor

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

训练集评估结果

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

结果是0,没有预测误差,这个模型真的可以做到绝对完美么?当然,更可能是这个模型对数据严重过拟合了。我们应该怎么确认?前面提到过,在你有信心启动模型之前,都不要触碰测试集。

所有这里,你需要那训练集中的一部分用于训练,另一部分用于模型验证。

4.1.2.1、使用交叉验证来更好地进行评估

评估决策树模型的一种方法是使用train_test_split函数将训练集分为较小的训练集和验证集,然后根据这些较小的训练集来训练模型,并对其进行评估。这虽然有一些工作量,但是也不会太难,并且非常有效。

另一个不错的选择市使用Scikit-LearnK-折交叉验证功能。以下是执行K-折交叉验证的代码:

  1. 它将训练集随机分割成10个不同的子集,每个子集称为一个折叠;
  2. 对决策树模型进行10次训练和评估 – 每次挑选1个折叠进行评估,使用另外的9个折叠进行训练;
  3. 产生的结果是一个包含10次评估分数的数组。
def display_scores(scores):
    print("分  数:", scores)
    print("平均值:", scores.mean())
    print("标准差:", scores.std())
from sklearn.model_selection import cross_val_score

# neg_mean_squared_error: 负均方误差
scores = cross_val_score(tree_reg, housing_prepared, housing_labels,
                         scoring="neg_mean_squared_error", cv=10)
tree_rmse_scores = np.sqrt(-scores)
display_scores(tree_rmse_scores)
分  数: [70062.5222628  66736.98017719 70439.6047592  70474.78239772 71238.21621992 
        74620.75350778 71398.18416741 70620.80936843 77492.84330946 71004.28109473]
平均值: 71408.89772646272
标准差: 2712.8600596563356

Scikit-LearnK-折交叉验证功能更倾向于使用效用函数(越大越好)而不是成本函数(越小越好),所以计算分数的函数实际上负的MSE(一个负值)函数,这就是为什么上面的代码在计算平方根之前会先计算出-scores

这次的决策树模型好像不如之前的表现得好,事实上,它看起来简直比线性回归模型还要糟糕。请注意,交叉验证不仅可以得到一个模型性能的评估值,还可以衡量该评估的精准度(即其标准差)。这里该决策树得到的评分约为71407,上下浮动±2439。如果你只使用了一个验证集,就收不到这样的结果信息。交叉验证的代价就是要多次训练模型,因此也不是永远都行得通。

保险起见,让我们也计算一下线性回归模型的评分:

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)
分  数: [66782.73843989 66960.118071 70347.95244419 74739.57052552 68031.13388938 
        71193.84183426 64969.63056405 68281.61137997 71552.91566558 67665.10082067]
平均值: 69052.46136345083
标准差: 2731.674001798347

没错,决策树模型的确严重过拟合了,以至于表现得比线性回归模型还要糟糕。

4.1.3、RndomForestRegressor 随机森林模型

我们再来试试最后一个模型RndomForestRegressor。随机森林的工作原理:通过对特征的随机子集进行许多个决策树的训练,然后对其预测取平均。在多个模型的基础之上建立模型,称之为集成学习,这是进一步推动机器学习算法的好方法。这里我们将跳过大部分代码,因为与其他模型基本相同:

from sklearn.ensemble import RandomForestRegressor

forest_reg = RandomForestRegressor()
forest_reg.fit(housing_prepared, housing_labels)
RandomForestRegressor()
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)
18725.06655956781
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)
分  数: [49809.66295035 47362.11725625 50097.32716715 51971.44001152 49498.75378409 
        53481.17484005 49051.91408781 48402.93749135 52812.15210493 50385.42811085]
平均值: 50287.290780434654
标准差: 1842.3191312235808

当前数据看起来是目前对好的。但是,请注意,训练集上的分数(18725)仍然远低于验证集(50287),这意味着该模型仍然对训练集过拟合。过拟合的可能解决方案包括:

  1. 简化模型
  2. 约束模型(即使其正规化)
  3. 或获得更多的训练数据

不过在深入探索随机森林之前,你应该先尝试一遍各种机器学习算法的其他模型(几种具有不同内核的支持向量机,比如神经网络模型等),但记住,别花太多时间去调整超参数,我们的目的是筛选出几个(2~5个)有效的模型。

每一个尝试过的模型都应该妥善的保存,以便将来可以轻松回顾。通过Pythonpickle模块或joblib库,你可以轻松保存Scikit-Learn模型,这样可以更有效地将大型NumPy数组序列号。

你可能感兴趣的:(机器学习,python,人工智能)