《機器學習實戰 學習筆記》(三):練習題(第2章 端到端的機器學習項目)

第2章練習題

1.使用不同的超參數,如kernel=“linear”(具有C超參數的多種值)或kernel=“rbf”(C超參數和gamma超參數的多種值),嘗試一個支持向量機迴歸器,不用擔心現在不知道這些超參數的含義。最好的SVR預測期是如何工作的?

from sklearn.model_selection import GridSearchCV

param_grid = [
        {'kernel': ['linear'], 'C': [10., 30., 100., 300., 1000., 3000., 10000., 30000.0]},
        {'kernel': ['rbf'], 'C': [1.0, 3.0, 10., 30., 100., 300., 1000.0],
         'gamma': [0.01, 0.03, 0.1, 0.3, 1.0, 3.0]},
    ]

svm_reg = SVR()
grid_search = GridSearchCV(svm_reg, param_grid, cv=5, scoring='neg_mean_squared_error', verbose=2, n_jobs=4)
grid_search.fit(housing_prepared, housing_labels)
   提醒:搜尋最佳參數時間有點慢~

在這裏插入圖片描述

negative_mse = grid_search.best_score_
rmse = np.sqrt(-negative_mse)
rmse
grid_search.best_params_

在這裏插入圖片描述
在這裏插入圖片描述

   分析: 通過網格搜索可以看出,線性核的SVR比rbf核更適合。而且需要注意的是C的值是候選參數中最大的,所以我們可以嘗試更大的C值,因爲C越大越好。

2. 嘗試用RandomizedSearchCV替換GridSearchCV

scipy統計分析庫(含各種概率分佈函數)

from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import expon, reciprocal

# scipy統計分析庫: https://docs.scipy.org/doc/scipy/reference/stats.html
# 有關於 `expon()` and `reciprocal()` 文檔 和 更多概率分佈函數.

# 注意: 當 kernel 是線性時忽略gamma
param_distribs = {
        'kernel': ['linear', 'rbf'],
        'C': reciprocal(20, 200000),
        'gamma': expon(scale=1.0),
    }

svm_reg = SVR()
rnd_search = RandomizedSearchCV(svm_reg, param_distributions=param_distribs,
                                n_iter=50, cv=5, scoring='neg_mean_squared_error',
                                verbose=2, n_jobs=4, random_state=42)
rnd_search.fit(housing_prepared, housing_labels)

在這裏插入圖片描述

negative_mse = rnd_search.best_score_
rmse = np.sqrt(-negative_mse)
rmse

在這裏插入圖片描述

   這個值更接近於隨機森林了。看一下最好的參數:
rnd_search.best_params_

在這裏插入圖片描述

   我們的C和gamma分別是用reciprocal分佈和指數分佈去採樣的。模擬採樣過程:
expon_distrib = expon(scale=1.)
samples = expon_distrib.rvs(10000, random_state=42)
plt.figure(figsize=(10, 4))
plt.subplot(121)
plt.title("Exponential distribution (scale=1.0)")
plt.hist(samples, bins=50)
plt.subplot(122)
plt.title("Log of this distribution")
plt.hist(np.log(samples), bins=50)
plt.show()

在這裏插入圖片描述

   C的選取是從給定範圍的均勻分佈內選取的,所以2張圖看起來差別不是很大。當不知道目標比例時,這種分佈非常有用。
reciprocal_distrib = reciprocal(20, 200000)
samples = reciprocal_distrib.rvs(10000, random_state=42)
plt.figure(figsize=(10, 4))
plt.subplot(121)
plt.title("Reciprocal distribution (scale=1.0)")
plt.hist(samples, bins=50)
plt.subplot(122)
plt.title("Log of this distribution")
plt.hist(np.log(samples), bins=50)
plt.show()

在這裏插入圖片描述

   如上圖,reciprocal 分佈是一個典型的對數均勻分佈。當已經知道超參數的範圍大小時,指數分佈是最好的。

3. 嘗試再準備流水線中添加一個轉換器,從而只選出最重要的屬性。

   首先,實現選擇TopK的方法。
from sklearn.base import BaseEstimator, TransformerMixin

def indices_of_top_k(arr, k):
    return np.sort(np.argpartition(np.array(arr), -k)[-k:])

class TopFeatureSelector(BaseEstimator, TransformerMixin):
    def __init__(self, feature_importances, k):
        self.feature_importances = feature_importances
        self.k = k
    def fit(self, X, y=None):
        self.feature_indices_ = indices_of_top_k(self.feature_importances, self.k)
        return self
    def transform(self, X):
        return X[:, self.feature_indices_]
   如果已經以某種方式計算了特徵重要度(比如RF中),那麼再用TopFeatureSelector.fit()會降低網格/隨機搜索的速度,除非實現緩存。
k=5
top_k_feature_indices = indices_of_top_k(feature_importances, k)
top_k_feature_indices
np.array(attributes)[top_k_feature_indices]

在這裏插入圖片描述
在這裏插入圖片描述

sorted(zip(feature_importances, attributes), reverse=True)[:k]

在這裏插入圖片描述

   其次,加入到pipeline中。

preparation_and_feature_selection_pipeline = Pipeline([
    ('preparation', full_pipeline),
    ('feature_selection', TopFeatureSelector(feature_importances, k))
])
housing_prepared_top_k_features = preparation_and_feature_selection_pipeline.fit_transform(housing)
   查看前3特徵,並校驗正確性
housing_prepared_top_k_features[0:3] # 查看
housing_prepared[0:3, top_k_feature_indices]#校驗

在這裏插入圖片描述
在這裏插入圖片描述

4.嘗試創建一個覆蓋完整的數據準備和最終預測的流水線

prepare_select_and_predict_pipeline = Pipeline([
    ('preparation', full_pipeline),
    ('feature_selection', TopFeatureSelector(feature_importances, k)),
    ('svm_reg', SVR(**rnd_search.best_params_))
])
prepare_select_and_predict_pipeline.fit(housing, housing_labels)

在這裏插入圖片描述

some_data = housing.iloc[:4]
some_labels = housing_labels.iloc[:4]

print("Predictions:\t", prepare_select_and_predict_pipeline.predict(some_data))
print("Labels:\t\t", list(some_labels))

在這裏插入圖片描述

   流程沒問題,但是預測效果不理想,如果用RF會好很多。

5.使用GridSearchCV自動搜索一些準備選線。

param_grid = [{
    'preparation__num__imputer__strategy': ['mean', 'median', 'most_frequent'],
    'feature_selection__k': list(range(1, len(feature_importances) + 1))
}]

grid_search_prep = GridSearchCV(prepare_select_and_predict_pipeline, param_grid, cv=5,
                                scoring='neg_mean_squared_error', verbose=2, n_jobs=4)
grid_search_prep.fit(housing, housing_labels)

在這裏插入圖片描述


grid_search_prep.best_params_

在這裏插入圖片描述

6.總結

   這個練習題部分感覺還是比較實用的,開闊了自己的視野,也比較有參考意義,繼續努力。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章