机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(三)

https://blog.csdn.net/fjl_csdn/a


三、开始实战 

7、选择及训练模型 

  首先尝试训练一个线性回归模型(LinearRegression)

<span style="color:#000000"><code><span style="color:#000088">from</span> sklearn.linear_model <span style="color:#000088">import</span> LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(train_housing_prepared, train_housing_labels)</code></span>
  • 1
  • 2
  • 3

  训练完成,然后评估模型,计算训练集中的均方根误差(RMSE)

<span style="color:#000000"><code>from sklearn<span style="color:#009900">.metrics</span> import mean_squared_error
housing_predictions = lin_reg<span style="color:#009900">.predict</span>(train_housing_prepared)
lin_mse = mean_squared_error(train_housing_labels, housing_predictions)
lin_rmse = np<span style="color:#009900">.sqrt</span>(lin_mse)
lin_rmse</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5

  这里写图片描述

  可以看到线性回归模型的训练集均方误差为68626

  再试试看更强大的模型,决策树模型(DecisionTreeRegressor)

<span style="color:#000000"><code>from sklearn<span style="color:#009900">.tree</span> import DecisionTreeRegressor
tree_reg = DecisionTreeRegressor()
tree_reg<span style="color:#009900">.fit</span>(train_housing_prepared, train_housing_labels)
housing_predictions = tree_reg<span style="color:#009900">.predict</span>(train_housing_prepared)
tree_mse = mean_squared_error(train_housing_labels, housing_predictions)
tree_rmse = np<span style="color:#009900">.sqrt</span>(tree_mse)
tree_rmse</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

  这里写图片描述

  可以看到决策树回归模型的的训练集均方误差竟然为0。比线性回归模型的的训练集均方误差小太多太多。

  但这是否说明了决策树回归模型比线性回归模型在此问题上好很多,当然不是,训练误差小的模型并不代表为好模型,这是因为模型可能过度地学习了训练集的数据,只是在训练集上的表现好(即过拟合),一旦测试新的数据表现就会很差。

  因此在训练的时候需要将部分的训练数据提取出来作为验证集,验证该模型是否对此问题适用。其中比较常用的就是交叉验证法。 


交叉验证法

  交叉验证的基本思想是将训练数据集分为k份,每次用k-1份训练模型,用剩余的1份作为验证集。按顺序训练k次后,计算k次的平均误差来评价模型(改变参数后即为另一个模型)的好坏。(具体做法可以看百度百科)

      这里写图片描述

  在Scikit-Learn中交叉验证对应的类为cross_val_score,下面是线性回归模型与决策树回归模型的交叉验证实例:

<span style="color:#000000"><code><span style="color:#000088">from</span> sklearn.model_selection <span style="color:#000088">import</span> cross_val_score
tree_scores = cross_val_score(tree_reg, train_housing_prepared, train_housing_labels,
scoring=<span style="color:#009900">"neg_mean_squared_error"</span>, cv=<span style="color:#006666">10</span>)
lin_scores = cross_val_score(lin_reg, train_housing_prepared, train_housing_labels,
scoring=<span style="color:#009900">"neg_mean_squared_error"</span>, cv=<span style="color:#006666">10</span>)
tree_rmse_scores = np.sqrt(-tree_scores)
lin_rmse_scores = np.sqrt(-lin_scores)

<span style="color:#000088">def</span> <span style="color:#009900">display_scores</span><span style="color:#4f4f4f">(scores)</span>:
    print(<span style="color:#009900">"Scores:"</span>, scores)
    print(<span style="color:#009900">"Mean:"</span>, scores.mean())
    print(<span style="color:#009900">"Standard deviation:"</span>, scores.std())

display_scores(tree_rmse_scores)
display_scores(lin_rmse_scores)</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

  其中参数scoring为选择一个指标,代码中选的为均方误差;参数cv是交叉验证划分的个数,这里划为为10份。

  需要注意:这里经过交叉验证求均方误差的结果为负值,所以后面求平方根前需要加负号。

  这里写图片描述

  可以看到决策树回归模型的交叉验证平均误差为71163,而线性回归模型的交叉验证平均误差为69051,这说明决策树回归模型明显是过拟合,实际上比线性回归模型要差一些。

  除了这两个简单的模型以外,还应该试验不同的模型(如随机森林,不同核的SVM,神经网络等),最终选择2-5个候选的模型。(也可以写到同一个文件下,方便以后直接调用)

保存模型

  最后介绍一下如何保存模型到本地(硬盘)与重新加载本地模型,可以使用Pickle库,也可以使用scikit-learn中的joblib库,具体代码如下:

<span style="color:#000000"><code>from sklearn<span style="color:#009900">.externals</span> import joblib
joblib<span style="color:#009900">.dump</span>(my_model, <span style="color:#009900">"my_model.pkl"</span>) <span style="color:#009900">#保存模型</span>
<span style="color:#009900"># and later...</span>
my_model_loaded = joblib<span style="color:#009900">.load</span>(<span style="color:#009900">"my_model.pkl"</span>) <span style="color:#009900">#加载模型</span></code></span>
  • 1
  • 2
  • 3
  • 4



8、模型调参

  现在已经有一些候选的模型,你需要对模型的参数进行微调,使模型表现的更好。下面介绍几种调参方法

网格搜索(Grid Search)

  scikit-learn中提供函数GridSearchCV用于网格搜索调参,网格搜索就是通过自己对模型需要调整的几个参数设定一些可行值,然后Grid Search会排列组合这些参数值,每一种情况都去训练一个模型,经过交叉验证今后输出结果。下面为随机森林回归模型(RandomForestRegression)的一个Grid Search的例子。

<span style="color:#000000"><code><span style="color:#000088">from</span> sklearn.model_selection <span style="color:#000088">import</span> GridSearchCV
param_grid = [
{<span style="color:#009900">'n_estimators'</span>: [<span style="color:#006666">3</span>, <span style="color:#006666">10</span>, <span style="color:#006666">30</span>], <span style="color:#009900">'max_features'</span>: [<span style="color:#006666">2</span>, <span style="color:#006666">4</span>, <span style="color:#006666">6</span>, <span style="color:#006666">8</span>]},
{<span style="color:#009900">'bootstrap'</span>: [<span style="color:#000088">False</span>], <span style="color:#009900">'n_estimators'</span>: [<span style="color:#006666">3</span>, <span style="color:#006666">10</span>], <span style="color:#009900">'max_features'</span>: [<span style="color:#006666">2</span>, <span style="color:#006666">3</span>, <span style="color:#006666">4</span>]},
]
forest_reg = RandomForestRegressor()
grid_search = GridSearchCV(forest_reg, param_grid, cv=<span style="color:#006666">5</span>,
scoring=<span style="color:#009900">'neg_mean_squared_error'</span>)
grid_search.fit(train_housing_prepared, train_housing_labels)</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

  例子中首先调第一行的参数为n_estimators和max_features,即有3*4=12种组合,然后再调第二行的参数,即2*3=6种组合,具体参数的代表的意思以后再讲述。总共组合数为12+6=18种组合。每种交叉验证5次,即18*5=90次模型计算,虽然运算量比较大,但运行完后能得到较好的参数。

  输出最好的参数

<span style="color:#000000"><code>grid_search<span style="color:#009900">.best</span>_params_</code></span>
  • 1

  这里写图片描述

  可以看到最好参数中30是选定参数的边缘,所以可以再选更大的数试验,可能会得到更好的模型,还可以在6附近选定参数,也可能会得到更好的模型。

  输出最好参数的模型

<span style="color:#000000"><code>grid_search<span style="color:#009900">.best</span>_params_</code></span>
  • 1

  这里写图片描述

  也可以看看每一个组合分别的交叉验证的结果

<span style="color:#000000"><code>cvres = grid_search.cv_results_
<span style="color:#000088">...</span> <span style="color:#000088">for</span> mean_score, params <span style="color:#000088">in</span> zip(cvres[<span style="color:#009900">"mean_test_score"</span>], cvres[<span style="color:#009900">"params"</span>]):
<span style="color:#000088">...</span> print(np.sqrt(-mean_score), params)</code></span>
  • 1
  • 2
  • 3

  这里写图片描述

随机搜索(Randomized Search)

  由于上面的网格搜索搜索空间太大,而机器计算能力不足,则可以通过给参数设定一定的范围,在范围内使用随机搜索选择参数,随机搜索的好处是能在更大的范围内进行搜索,并且可以通过设定迭代次数n_iter,根据机器的计算能力来确定参数组合的个数,是下面给出一个随机搜索的例子。

<span style="color:#000000"><code>from sklearn.model_selection <span style="color:#000088">import</span> RandomizedSearchCV
param_ran={<span style="color:#009900">'n_estimators'</span>:<span style="color:#000088">range</span><span style="color:#006666">(30</span><span style="color:#006666">,50</span>),<span style="color:#009900">'max_features'</span>: <span style="color:#000088">range</span><span style="color:#006666">(3</span><span style="color:#006666">,8</span>)}
forest_reg = RandomForestRegressor()
random_search = RandomizedSearchCV(forest_reg,param_ran,cv<span style="color:#006666">=5</span>,scoring=<span style="color:#009900">'neg_mean_squared_error'</span>,n_iter<span style="color:#006666">=10</span>)
random_search.fit(train_housing_prepared, train_housing_labels)</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5

分析最好的模型每个特征的重要性

  假设现在调参以后得到最好的参数模型,然后可以查看每个特征对预测结果的贡献程度,根据贡献程度,可以删减减少一些不必要的特征。

<span style="color:#000000"><code>feature_importances = grid_search.best_estimator_.feature_importances_
extr<span style="color:#4f4f4f">a_attribs</span> = [<span style="color:#009900">"rooms_per_hhold"</span>, <span style="color:#009900">"pop_per_hhold"</span>, <span style="color:#009900">"bedrooms_per_room"</span>]
cat_one_hot_attribs = list(encoder.classes_)
attributes = num_attribs + extr<span style="color:#4f4f4f">a_attribs</span> + cat_one_hot_attribs
sorted(zip(feature_importances, attributes), reverse=<span style="color:#006666">True</span>)</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5

          这里写图片描述

  可以看到ocean_proximity中的4个特征中只有一个特征是有用的,其他3个几乎没有用,所以可以考虑去除其他3个特征。

在测试集中评估

  经过努力终于得到了最终的模型,现在就差在测试集上验证这个模型的泛化能力以及准确性。测试集中的操作和训练集中的操作基本相同,唯一不同的是不需要fit(),只需要transform()就可以了,这是因为测试集不是用来训练模型,所以不用fit(),所以将fit_transform()改为transform()。

<span style="color:#000000"><code>final_model = grid_search.best_estimator_
X_test = strat_test_set.drop(<span style="color:#009900">"median_house_value"</span>, axis=<span style="color:#006666">1</span>)
y_test = strat_test_set[<span style="color:#009900">"median_house_value"</span>].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) </code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

  这里写图片描述

  可以发现,结果和交叉验证以后的结果比较相似,说明经过交叉验证后,在新的数据集上也能达到类似的效果。

  需要注意:在测试集中补缺失值,标准化等用到的值都是训练集上的中值,平均值等,而不是测试集上的。因为必须把数据放缩到同一尺度。

  最后还可以分析这个模型学习到了什么,没做到什么,作出了什么假设,有什么局限性,得到了什么结论(比如median income是最影响结果的) 

rticle/details/79019437

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值