第二章——機器學習項目完整案例(End-to-End Machine Learning Project)


本章通過一個例子,介紹機器學習的整個流程。

2.1 使用真實數據集練手(Working with Real Data)

國外一些獲取數據的網站:

  • Popular open data repositories:
  1. UC Irvine Machine Learning Repository
  2. Kaggle datasets
  3. Amazon’s AWS datasets
  • Meta portals (they list open data repositories):
  1. http://dataportals.org/
  2. http://opendatamonitor.eu/
  3. http://quandl.com/
  • Other pages listing many popular open data repositories:
  1. Wikipedia’s list of Machine Learning datasets
  2. Quora.com question
  3. Datasets subreddit

國內的一些數據源:

 本章選擇了加州房價數據集,代碼可以從https://github.com/ageron/handson-ml獲取。

2.2 分析整體情況(Look at the Big Picture)

我們的目的是使用加州的人口普查數據,建立模型,預測加州各區域的房價中位數。

訓練數據的特征包括加州各區域的人口、收入中位數、房價中位數等。

2.2.1 問題構建(Frame the Problem,提出問題,給出框架,提出假設)

首先問清楚老板的商業目的,以及當前的解決方案(如果有的話)。比如,了解到了當前方案的錯誤率大概15%,我們就要奮斗目標了。

接下來就可以分析,這是一個有監督學習、無監督學習、還是增強學習?分類任務還是回歸任務,或者別的什么?應該使用批量學習(batch learning)還是在線學習(online learning)?

如果數據量巨大,可以使用MapReduce技術,將數據分給多個服務器處理。也可是使用在線學習。

2.2.2 選擇性能衡量指標(Select a Performance Measure) 

回歸問題典型的衡量指標選擇均方根誤差(Root Mean Square Error,RMSE),它揭示了預測值的標准偏差(standard deviation)。

\begin{align*}
RMSE(X,h) = \sqrt{\frac{1}{m}\sum_{i=1}^{m}(h(X^{(i)}) - y^{(i)})^2}
\end{align*}

有時候樣本中存在很多離群點(outlier) ,我們可能就會使用絕對誤差(Mean Absolute Error,MAE)。

\begin{align*}
RMSE(X,h) = \frac{1}{m}\sum_{i=1}^{m}\left | h(x^{(i)}) - y^{(i)} \right |
\end{align*}

RMSE和MAE都是向量距離的度量方式(預測值向量和目標值向量)。向量的距離,也可以為稱為向量的模(norm),有以下性質:

  • RMSE對應於歐氏距離,也被稱作$l_2$距離,記做$\left \| \cdot  \right \|_2$(或$\left \| \cdot  \right \|$)。
  • MAE對應於$l_1$距離,記做$\left \| \cdot  \right \|_1$。
  • 一般的,具有$n$的元素的向量$v$,$l_k$距離定義為$\left \| v \right \|_k = (\left | v_1 \right |^k + \left | v_2 \right |^k + \cdots + \left | v_n \right |^k)^{\frac{1}{k}}$。$l_0$僅僅給出向量的基數(比如非零元素的個數),$l_\infty$給出向量中最大元素的絕對值。
  • 指數k最大,向量中最大元素的貢獻就越大。這就是為什么相對於MAE,RMSE對離群點更敏感。但如果誤差是指數級稀少(exponentially rare)的,例如鍾形曲線(bell-shaped curve),RMSE的表現很好,也是通常的選擇。

2.2.3 檢查假設(Check the Assumptions) 

我們最好跟同事確認一下假設。例如,我們的房價預測值是給下游系統使用的。如果下游系統要把價格轉換為類別(例如高、中、低),那么我們的問題就成了分類。

2.3 獲取數據(Get the Data)

下面就開始動手操作了,代碼位於https://github.com/ageron/handson-ml

2.3.1 創建工作空間(Create the Workspace)

安裝Python、安裝Jupyter Notebook

2.3.2 下載數據

fetch_housing_data函數負責,代碼里面有。

2.3.3 瀏覽數據(Take a Quick Look at the Data Structure)

介紹了pandas DataFrame里面的一些函數:head()、info()、describe()、value_counts()(針對類別屬性,列出各個類別,以及類別數量)。

Matplotlib里面的hist()函數繪制直方圖。

我們可以從直方圖中發現以下幾點:

  1. 收入中位數(median income)並不是以美元為單位的,而是經過了預處理。最高一致被設置為了大概15(高於某一值的數據,都被設置為了15,即使它可能是25),最低值被設置為0.5(低於某一值的都被設置為0.5)。這在機器學習中很常見,也沒什么問題。
  2. 房齡中位數(housing median age)和房價中位數(median house value)也被處理過了。例如后者,房價高於500,000的,都被設置為500,000,即使真實房價800,000。這就是為什么它們所對應的直方圖,最右列突然增高。但由於房價中位數是我們的目標屬性,如果我們需要預測真實的房價,可能會高於500,000,這就存在問題了。那么有兩種主要的解決方案:a、收集真實的房價。b、丟掉房價高於500,000的樣本。
  3. 這些屬性具有不同的取值范圍。這將在下文探索特征縮放是進行討論。
  4. 本多直方圖呈現重尾分布(tail heavy):左側距離中位數要遠於右側。這不利於一些機器學習算法進行模式識別(tail heavy)。后面將進行轉換,使這些屬性更符合鍾形分布(bell-shaped distributions)。

2.3.4 創建測試集(Create a Test Set)

在進一步分析數據之前, 應該創建一個測試集,並將其丟在一邊,不去分析。

這是為了防止過擬合,防止數據探測法偏見(data snooping bias)。

只需要隨機選擇20%的數據作為測試集即可。

具體怎么隨機選擇,作者介紹了很多實踐經驗比如可以用如下代碼實現:

from sklearn.model_selection import train_test_split
# random_state = 42 to make this notebook's output identical at every run
train_set, test_set = train_test_split(housing, test_size=0.2, random_state=42)

 然后作者又介紹了為什么要分層抽樣(stratified sampling)。

2.4 數據的探索和可視化(Discover and Visualize the Data to Gain Insights)

這是對數據進一步的探索,寫一步不能考慮測試集,只分析訓練集。

2.4.1 地理數據可視化(Visualizing Geographical Data)

使用散點圖,分析了地理位置、人口、人均收入跟房價的關系。

2.4.2 相關性探索(Looking for Correlations)

計算相關系數(standard correlation coefficient)矩陣,分析其它屬性跟房價的相關系數。

相關系數取值-1到1,解決1時說明是正相關,接近-1時說明是負相關。接近0說明非線性相關。下圖顯示了一些標准數據集的相關系數:

相關系數只能度量線性相關(例如:“如果$x$增長,$y$通常增長/減少。”),這會完全地錯過非線性相關(例如:“如果$x$趨近於0,$y$通常增長。”)。例如上圖的第三行,這些數據相關系數為0,但它們顯然不獨立,存在非線性關系。

2.4.3 嘗試屬性組合(Experimenting with Attribute Combinations)

例如可以增加以下三個屬性:

housing["rooms_per_household"] = housing["total_rooms"]/housing["households"]
housing["bedrooms_per_room"] = housing["total_bedrooms"]/housing["total_rooms"]
housing["population_per_household"]=housing["population"]/housing["households"]

然后可以計算它們跟房價均值的相關系數。

2.5  為機器學習算法准備數據(Prepare the Data for Machine Learning Algorithms)

2.5.1 數據清洗(Data Cleaning)

大部分機器學習算法都無法處理存在控制的屬性。前面已經注意到total_bedrooms存在缺失值。修復這一問題有三個選擇:

  • 去掉相應的樣本
  • 去掉這一屬性
  • 使用其它值對缺失值進行填充(0、均值、中位數等等)

這可以通過DataFrame的dropna(), drop(), and fillna()方法實現:

housing.dropna(subset=["total_bedrooms"]) # option 1
housing.drop("total_bedrooms", axis=1) # option 2
median = housing["total_bedrooms"].median()
housing["total_bedrooms"].fillna(median) # option 3  

作者也介紹了怎么通過Scikit-Learn的Imputer實現這一目的。

2.5.2 處理文本和類型屬性(Handling Text and Categorical Attributes)

ocean_proximity是一個無法計算中位數的文本屬性。而大部分機器學習算法智能處理數字,這就需要將文本轉為數字。

可以使用Scikit-Learn的LabelEncoder:

>>> from sklearn.preprocessing import LabelEncoder
>>> encoder = LabelEncoder()
>>> housing_cat = housing["ocean_proximity"]
>>> housing_cat_encoded = encoder.fit_transform(housing_cat)
>>> housing_cat_encoded
array([1, 1, 4, ..., 1, 0, 3])

這將['<1H OCEAN' 'INLAND' 'ISLAND' 'NEAR BAY' 'NEAR OCEAN']五個文本值編碼為了0-4。但這樣編碼存在一個問題:ML算法會假設,靠近的兩個數字比間隔遠的兩個數字更相似。未解決這一問題,可以采用one-hot編碼。

2.5.3 自定義轉換函數(Custom Transformers)

這一小節作者講述了如何自定義Scikit-Learn的轉換器(transformers)。

2.5.4 特征歸一化(Feature Scaling)

最大最小歸一化(min-max scaling)和標准化(Standardization)兩個方法。前者比后者更容易收到離群點的影響。

2.5.5 轉換流水線(Transformation Pipelines)

sklearn提供了一個類Pipeline,使得上述步驟可以進行流水操作。

2.6 選擇模型並訓練(Select and Train a Model)

作者選擇了線性回歸、決策樹、隨機森林三個模型。又介紹了交叉驗證。

2.7 模型調整(Fine-Tune Your Model)

2.7.1 網格搜索(Grid Search)

介紹了如何使用Scikit-Learn’s GridSearchCV進行網格搜索,選取最優超參數。

另外,需要注意的是,我們可以把數據預處理階段的一些操作視為超參數,並使用網格搜索找到最優方案。例如作者定義的CombinedAttributesAdder函數,有一個超參數add_bedrooms_per_room。相似的,使用網格搜索,可以自動尋找處理離群點、缺失值、特征選擇等等問題的最優解決方案。

2.7.2 隨機搜索(Randomized Search)

如果超參數的組合太少,隨機搜索是網格搜索的一個不錯的替代方案,也就是RandomizedSearchCV。與GridSearchCV搜索所有可能的參數組合不同,RandomizedSearchCV每次迭代的超參數都隨機選取。這有兩個好處:

  • 如果使用隨機搜索迭代1000次,這將對每個超參數探索1000個不同值(網格搜索對每個超參數只會探索很少的幾個值)。
  • 通過設置迭代次數,就可以方便地控制運算量。

2.7.3 模型融合(Ensemble Methods)

三個臭皮匠頂個諸葛亮,隨機森林也好過單獨的決策樹。由於不同的模型錯誤類型也可能不同,所有我們可以訓練多個模型,將預測結果進行融合。細節將在第7章介紹。

2.7.4 分析最優模型與其錯誤(Analyze the Best Models and Their Errors)

訓練好模型后,可以查到每個屬性的重要性,這就可以去掉一些不重要,與目標值不相關的屬性。

2.7.5 在測試集上進行評估(Evaluate Your System on the Test Set)

2.8 系統上線、監控、維護(Launch, Monitor, and Maintain Your System)

上線之后,需要定期檢查系統表現, 以及在崩潰是可以引發警報。不僅要檢測到突發情況,還有檢測到系統退化。因為隨着時間的推移,系統退化是很常見側,除非模型經常被最新的數據重新訓練。

系統表現評估,可以對系統的預測隨機采樣並進行評估。一般這是需要人工分析的。可能是領域專家,也可能是眾包平台(例如亞馬遜的Mechanical Turk或者CrowdFlower)的工作者。無論如何,都要在系統中增加人工處理流水線。

同時要確保輸入數據的質量。最好在數據輸入時,就監控到異常數據。在線學習上這一點尤其重要。

最后,應該經常使用最新的數據訓練模型,這一操作自動化程度越高越好。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM