1. 程式人生 > >機器學習專案的例項分析設計(附原始碼)

機器學習專案的例項分析設計(附原始碼)

摘要說明:

最近在學習“Hands-On Machine Learning with Scikit-Learn &TensorFlow,其中一些機器學習的思考和處理方式很具有專案級開發的特點。我在原文提供的例項基礎上,結合自己的分析,模擬了一個機器學習專案的分析和實現過程,包括專案分析,資料分析,模型分析,效能分析等,在原文的樣本程式碼基礎上,編寫了完整的可全面自動化執行的程式碼,供大家一起參考。(文章後面將提供原始碼的 github 地址)


一. 專案的總體分析

  • 業務分析
  • 內容

    分析設計

    專案名稱

    加利福尼亞房價預測

    商業背景及價值

    本公司是一家投資公司,現有一套綜合投資分析系統,將彙總各類資訊,對行政區進行全面分析後,決定是否值得進行投資。

    本專案獲得的各行政區的房價中值預測值,將提供給公司的綜合投資分析系統,作為其中的一項分析指標,幫助公司進行決策。

    目前房價中值的計算,完全依靠業務專家,通過複雜的人工推導分析後獲得,費時費力,不及時,不準確。

    本專案將實現房價中值的自動化預測計算和處理,其預測結果將影響公司投資決策的速度和準確性,從而直接影響公司的商業業績。

    業務需求

    利用加利福尼亞房價資料庫提供的統計資料,通過機器學習,從這些資料中構建模型,獲得資訊,用於預測加利福尼亞州不同行政區的房價中值

    非功能性需求

    目前採用人工分析的方法,全部計算一次所有行政區的房價中值,需要5 人天。

    本專案完成後,正常情況下,要求在1小時內完成所有計算。


  • 系統分析

內容

分析設計

基本訓練模型方案

1.     由於有明確的預測值要求,因此將使用有監督的模型(不是無監督模型);

2.     由於預測的是具體數值,不是標籤,因此屬於迴歸問題(不是分類問題,或聚類問題);

3.     根據跟專家的溝通,房價的預測將需要涉及資料集中提供的多個特徵屬性,屬於多變量回歸問題

4.     房價資料來源資訊不是實時連續變化的資料,資料量也不是特別大,完全可以裝載到記憶體後進行處理,因此採用簡單的單機批處理方式來完成。(不考慮大資料下的分散式處理及實時資料流的線上處理方式)

綜上分析,本專案將採用的基本回歸分析模型有

  • 線性迴歸模型:LinearRegression
  • 決策樹模型:DecisionTreeRegressor
  • 隨機森林樹模型: RandomForestRegressor

模型效果的測量指標

迴歸分析模型的效能,可採用的測量指標有:

  • 均方根誤差(RMSE)
  • 均方誤差(MSE)
  • 平均絕對誤差(MAE)
  • 中位值誤差
  • r方誤差

RMSE對異常資料比較敏感,若資料集的異常資料很少時(即資料分佈比較集中,像一個鐘型),用RMSE來衡量模型效果還是比較好的,


因此,本專案將採用 RMSE 指標進行模型效能的衡量比較,RMSE值越小,模型效能越好。

開發環境

Python的生態環境提供了我們完成該專案需要的機器學習函式庫,開源,通用性好,執行效能可滿足專案要求;如 numpy, pandas, scikit-Learn等,其中scikit-Learn模組中有一些流程化處理的函式,可以讓自動化處理的實現更加簡潔和優雅。


因此,本專案將採用 Python + Scikit-Learn 為主要開發平臺

自動化及可重用性

這是一個需要可重複使用的生產系統,不是一次性工具,也不是單純研究用的人機互動程式;需要儘量把處理程式碼自動化,以提高除錯優化的效率,並在生產環境中部署後自動化執行,提供必要的運維日誌資訊

前提假設

1.     加利福尼亞房價資料庫持續提供更新的房價資料

2.     公司綜合投資分析系統的資料介面保持不變,需要本專案提供的是房價的具體數值,而不是“昂貴”,“中等”,“低廉”的分類標籤。否則,本專案的學習模型將會更改為分類模型

術語說明

關於記錄集變數的定義說明如下:(括號內為全名稱)

變數名

含義

train_set

原始訓練資料集,包含標籤列,特徵列

test_set

原始資料測試集,包含標籤列,特徵列

train(train_feature)

訓練集中的特徵集,不含標籤列,簡寫成 train

train_label

 

訓練集中的標籤列

train_num(train_feature_num)

訓練集中的數值意義特徵集

train_cat(train_feature_cat)

 

訓練集中的分類意義特徵集

train_prepared (train_feature_prepared)

已經處理完成的訓練集,含所有特徵屬性,且全是數值型,將輸入給模型進行訓練使用

train_pred(train_label_pred)

 

訓練集的預測標籤值,可跟 train_label進行比較,獲得性能評分



二. 原始資料分析

  • 資料來源分析

內容

分析設計

資料來源

StatLib 庫為公開的資料庫,其中提供了自1990年以來的加利福尼亞房價資料

Github 上的映象,也可更方便地獲得該資料集

https://raw.githubusercontent.com/ageron/handson-ml/master/datasets/housing/housing.tgz

(注:本演示專案將使用github上的資料集樣本檔案)

資料內容及資料量

主要為加利福尼亞的各行政區的房價資料,下載解壓,儲存為CSV檔案後,在幾百兆左右。

資料法律義務,授權情況及訪問許可權

專案用到的資料來源,屬於對外公開的資料集,可合理使用在專案中,不需要授權,不需要承擔任何法律義務。

磁碟空間的分析

根據目前資料來源的下載量分析和資料可能的增長趨勢,5年內,資料集檔案不會超過500M,考慮系統的環境安裝,資料處理過程的需要,原始資料的備份,以及處理完的資料的備份等,該專案的磁碟空間建議預留100G以支援5年的運維。


  • 獲取資料分析

內容

分析設計

獲取資料

1.  資料來源:

https://raw.githubusercontent.com/ageron/handson-ml/master/datasets/housing/housing.tgz


2. 獲取 hoursing.tgz 檔案後,解壓出 housing.csv資料集檔案

抽取一個原始測試集

需要留一部分原始且未做任何處理的資料,來完整測試整個處理過程,並驗證訓練模型的實際效能。


該原始測試集不同於交叉驗證時測試集,交叉驗證是將已經清理乾淨的輸入學習模型的資料隨機分成訓練集,測試集;而原始測試集是未清理過的資料。


基本處理過程:

1. 將原始資料拆分為2個數據集,train_set, test_set, 分別儲存到檔案中(train_set.csv, test_set.csv),供以後重複使用

2. 裝入訓練資料集(train_set.csv),供後續的分析,清理,訓練使用

實現整個過程的自動化處理

獲取資料集,抽取原始測試集,裝載訓練集,需要自動化完成


參看程式碼: load_data.py


三. 資料特徵分析

該步驟主要是在人機互動的 Jupyter notebook中完成,需要業務專家的配合,通過分析,可以使我們瞭解清楚需要處理的資料集的基本特徵和業務特徵,為下一階段的資料清理和模型構建提供資訊。該步驟不修改資料,也沒有相應的自動化處理程式碼,需要記錄分析結果。

本文列出了一些分析檢查表,其中的分析內容和舉例僅供參考。而實際專案中,該步驟很重要,需要花費很多的時間,因為後續的處理,都將基於對資料集的全面瞭解。Jupyter notebook 檔案包含在提供的原始碼中

內容

分析設計

將資料集裝載到記憶體

import pandas as pd

import matplotlib.pyplot as plt

%matplotlib inline

 

datafilename = r"train_set.csv"

train_set_original = pd.read_csv(datafilename)

建立一個數據集的副本

 

train_set = train_set_original.copy()

 

這個資料集,是已經抽取掉原始測試集後的資料集,專門用於分析,訓練,交叉測試用的。

該資料集包含標籤列和特徵列

檢查資料集的大小

train_set.shape

(16512, 10)

一共有16512條樣本資料,每條資料有10個特徵列(其中含標籤列)

獲得資料集的所有特徵名稱及資料型別

train_set.dtypes

longitude                       float64

latitude                          float64

housing_median_age   float64

total_rooms                   float64

total_bedrooms             float64

population                     float64

households                   float64

median_income            float64

median_house_value   float64

ocean_proximity           object

 

除[ocean_proximity] 為字元型資料列(類別意義特徵屬性),其他特徵列均為數值意義特徵。

類別意義特徵需要在後續處理中,轉換為數值意義特徵,因為輸入學習訓練模型的必須是數值特徵

若為監督學習任務,需要確定標籤列

 本專案中,標籤列為 [median_house_value]

房屋價格的中值 (不是平均值)

 

明確標籤列後,可以針對性地分析瞭解特徵列跟標籤列的相關性

資料集的樣本具體內容

train_set.head()

train_set.tail()

特徵資料的分佈情況

比如:字元分類特徵列 ocean_proximity

train_set[“ocean_proximity”].value_counts()


<1H OCEAN       7341   小於1小時車程

INLAND               5227   內陸

NEAR OCEAN    2086   靠近海

NEAR BAY         1854    靠近海灣

ISLAND                   4     海島

 

分析特徵屬性的基本業務含義

需要在跟業務專家的配合下,分析主要特徵屬性的含義及對標籤列的影響程度,機器學習是用來分析和解決實際業務問題的,不單是資料處理。這裡做了簡單分析,純屬個人觀點

特徵列

分析

longitude

地理經度,用於識別位置,獲得所屬行政區的資訊。 行政區的不同,商業,政治,文化,教育環境也會不一樣,會影響房價

latitude

地理緯度, 用於識別位置,,會影響房價

housing_median_age

房屋的平均年齡,房型資訊,房齡大,房型較老,房齡小,比較新,會影響房價

total_rooms

總的房間數,房型資訊,會影響房價

total_bedrooms

臥室的房間數,房型資訊,房間多,居住會舒適,會影響房價

population

該地區的人口總數,影響供求比例,會影響房價

households

家庭數,影響供求比例,會影響房價

median_income

平均收入,影響購買力,會影響房價

ocean_proximity

跟海相關的環境分類,物以稀為貴,會影響房價

資料集的快速統計分析

train_set.isnull().sum()

train_set.info()

train_set.describe()

視覺化資料進行分析

利用各種圖表工具,對資料集進行視覺化檢視分析

 

每個列的資料直方圖

train_set.hist(bins=50,figsize=(20,15))


按地理位置的人口分佈散點圖

train_set.plot(kind='scatter',x='longitude', y='latitude', alpha=0.4, s=train_set['population']/100,label='population', c='median_house_value',cmap=plt.get_cmap("jet"),colorbar=True)

plt.legend()



資料視覺化分析很重要,涉及的內容也相對廣泛,本文不再繼續展開

分析樣本屬性之間的關係

特徵屬性跟標籤列 及 特徵屬性間的線性相關性

corr_matrix = train_set.corr()

corr_matrix

corr_matrix["median_house_value"].sort_values(ascending=False)

 

median_house_value    1.000000

median_income         0.690647

total_rooms           0.133989

housing_median_age    0.103706

households            0.063714

total_bedrooms        0.047980

population           -0.026032

longitude            -0.046349

latitude             -0.142983

 

media_income, total_rooms, housing_media_age 跟房價中值的相關性比較大

 

視覺化這些屬性的關係

from pandas.tools.plotting import scatter_matrix

attributes =

["median_house_value","median_income","total_rooms","housing_median_age"]

scatter_matrix(train_set[attributes],figsize=(12,8))


行政區的media_house_value(房價中值) 跟 media income (收入中值)的線性相關性確實比較明顯。

確認可用的額外欄位

對屬性欄位進行加工及合併的分析,以便生成新的特徵屬性,表現出更多的內部關係。

例如:

增加屬性列 population_per_household = poplation / households,  可獲得每個家庭的平均人口數

確認不需要的欄位

對預測標籤沒有任何影響的欄位,如隨機欄位等,可以標記為刪除。如日誌記錄中的隨機序列號等。

本資料集中的特徵屬性,通過分析,都跟標籤列有關係,因此,沒有需要刪除的列。

記錄所有的分析內容,用於後續的資料自動化處理

以上分析結果,我們需要進行詳細記錄。而這些只是初步的分析處理方案,在實際訓練過程中,需要根據模型效能評分多次反覆地分析,調整,才能獲得最理想的效果。


四. 特徵工程

特徵工程是在原始資料特徵分析的基礎上,對資料進行全面特徵處理和特徵提取,構建最終的特徵資料集,供學習模型進行訓練使用。提供給模型的資料和特徵,決定了機器學習的上限,可見其重要性。

該步驟需要能自動化執行,以便重複使用。分析,開發中,可以使用Jupyter進行除錯,最終,應該是可以完整執行的 Python 程式碼模組。

內容

分析設計

建立一個特徵資料集的副本

 

該步驟進行處理的資料集不包含標籤列。

上一步驟的資料集包含標籤列,是因為可以用來分析特徵列和標籤列的相關性,而清理資料時,不應該包含標籤列的,因為標籤列一般不需要進行清理或單獨進行處理。

修復或刪除異常值

任何情況都應該考慮null值,即使當前訓練集沒有,也無法保證測試集及將來的資料集都沒有。

null值的處理方式有以下幾種:

刪除行,刪除列,填充具體值等,本專案採用填充中值的方式處理null值

本專案使用 scikit-learn的轉換器 Imputer 來完成

聚合生成新的特徵

本專案將增加 population_per_household 等新特徵。

編寫自定義轉換器來完成

class CombinedAttributesAdder()

新增多項式新特徵

本專案沒有其他新特徵列

在程式碼中,提供了一個在對 pandas.DataFrame型別資料進行欄位增加的轉換器供參考。

class FeatureAdder()

刪除不需要的特徵

本專案沒有刪除特徵列

在程式碼中,提供了一個在對 pandas.DataFrame型別資料進行欄位刪除的轉換器供參考

class FeatureDeleter()

對連續特徵離散化處理

本專案沒有用到

就是把資料分段,線性值變成離散資料或分類值,如可以將population_per_household進行離散化處理

n <= 3        : 小家庭,    取值1

3 < n <= 7  : 中等家庭, 取值2

n > 7          : 大家庭,     取值3

對特徵進行歸一化處理或標準化處理

歸一化處理後,資料的業務敏感度降低,資料的分佈和方差保持不變,資料量減少,演算法更容易收斂。

本專案使用scikit-learn提供的StandardScaler,進行歸一化處理

對文字分類屬性的處理

機器學習演算法一般認為資料值越相近,則距離越近。將文字分類屬性單純用數字來代替,跟實際情況不符合,需要進行處理。

本專案採用 one-hot編碼,即為每個分類值建立一個新特徵屬性,若原分類值為對應分類列,則該列特徵值為1,否則為0

本專案使用 scikit-learn的 LabelBinarizer 轉換器,並做了相容性調整

自動化處理資料清理過程

所有轉換處理都用函式實現自動化處理,從而可快速處理新的訓練集,原始測試集。

scikit-learn 提供了一套 Pipeline 的流程化處理函式,可以讓資料清理過程按設計流程順序依次執行,很是乾淨和優雅。

 

 

 


五. 訓練模型

內容

分析設計

若資料量太大,可抽取部分資料進行快速模型分析

本專案資料量不大,將使用全部訓練集資料進行處理

訓練模型並分析效能

傳入訓練資料集,訓練模型,採用交叉驗證的方式,隨機生成訓練集,測試集,計算RMSE評分。

儲存每次測量的訓練模型,用於後續分析和預測使用,同時顯示模型訓練的效能評分,以便跟其他訓練結果進行比較


使用標準引數訓練不同的基本模型

本專案的基本訓練模型為

  • 線性迴歸模型:LinearRegression
  • 決策樹模型:DecisionTreeRegressor
  • 隨機森林樹模型: RandomForestRegressor

 

調整模型引數,進行優化

可能需要在多個模型中,使用多套引數組合方案,然後分析模型效能結果。

利用 Grid Search, 給出引數列表,然後讓系統自動構建所有組合引數進行訓練,返回效能最好的模型引數

整合多個模型,共同進行訓練

本專案暫不需要

 

比較模型效能,獲得最佳模型

需要重複以上分析步驟和過程,調整資料,調整特徵,調整模型引數等,並對每次的訓練結果進行記錄和全面分析,以獲得最佳的訓練器。


本專案採用 RMSE 指標進行模型效能的衡量比較,RMSE值越小,模型效能越好

所有訓練過程實現自動化

執行 python main.py , 完成資料獲取,清理,訓練,效能結果比較的自動化處理。

獲得最佳的訓練模型



六. 對原始測試集進行測試

內容

分析設計

對原始測試集進行預測

選用訓練獲得的最佳模型,對原始測試資料集進行測試,分析效能,並處理預測值





七. 後續工作

到目前為止,主要完成的是專案分析,設計和開發部分的工作,後續還有很多專案級的工作需要逐步配合完成,本文只做基本列舉,不再詳細描述

內容

提供專案的結果分析報告,並跟業務部門溝通分析

根據業務部門的反饋,繼續進行引數和程式碼的優化,到達最佳的業務效果

開發跟公司決策分析系統的資料介面

專案提交測試部門進行正式測試

測試通過後,進行專案的生產部署和運維管理

定期更新訓練資料,重新訓練模型,保持並提高模型的效能

專案的經驗總結(有效做法,無效做法,前提假設,侷限性及改進方案),這些都將是公司和個人在專案開發和專案管理上的寶貴財富

附錄:

該演示專案的原始碼 github 地址:

https://github.com/EdwinZhang1970/Python/tree/master/California%20Housing%20Prices