波士頓房價預測 - 最簡單入門機器學習 - Jupyter
機器學習入門專案分享 - 波士頓房價預測
該分享源於Udacity機器學習進階中的一個mini作業專案,用於入門非常合適,刨除了繁瑣的部分,保留了最關鍵、基本的步驟,能夠對機器學習基本流程有一個最清晰的認識;
專案描述
利用馬薩諸塞州波士頓郊區的房屋資訊資料訓練和測試一個模型,並對模型的效能和預測能力進行測試;
專案分析
資料集欄位解釋:
RM
: 住宅平均房間數量;LSTAT
: 區域中被認為是低收入階層的比率;PTRATIO
: 鎮上學生與教師數量比例;MEDV
: 房屋的中值價格(目標特徵,即我們要預測的值);
其實現在回過頭來看,前三個特徵應該都是挖掘後的組合特徵,比如RM,通常在原始資料中會分為多個特徵:一樓房間、二樓房間、廚房、臥室個數、地下室房間等等,這裡應該是為了教學簡單化了;
MEDV為我們要預測的值,屬於迴歸問題,另外資料集不大(不到500個數據點),小資料集上的迴歸問題,現在的我初步考慮會用SVM,稍後讓我們看看當時的選擇;
Show Time
Step 1 匯入資料
注意點:
- 如果資料在多個csv中(比如很多銷售專案中,銷售資料和店鋪資料是分開兩個csv的,類似資料庫的兩張表),這裡一般要連線起來;
- 訓練資料和測試資料連線起來,這是為了後續的資料處理的一致,否則訓練模型時會有問題(比如用訓練資料訓練的模型,預測測試資料時報錯維度不一致);
- 觀察下資料量,資料量對於後續選擇演算法、視覺化方法等有比較大的影響,所以一般會看一下;
- pandas記憶體優化,這一點專案中目前沒有,但是我最近的專案有用到,簡單說一下,通過對特徵欄位的資料型別向下轉換(比如int64轉為int8)降低對記憶體的使用,這裡很重要,資料量大時很容易撐爆個人電腦的記憶體儲存;
上程式碼:
# 載入波士頓房屋的資料集
data = pd.read_csv('housing.csv')
prices = data['MEDV']
features = data.drop('MEDV', axis = 1)
# 完成
print "Boston housing dataset has {} data points with {} variables each.".format(*data.shape)
Step 2 分析資料
載入資料後,不要直接就急匆匆的上各種處理手段,加各種模型,先慢一點,對資料進行一個初步的瞭解,瞭解其各個特徵的統計值、分佈情況、與目標特徵的關係,最好進行視覺化,這樣會看到很多意料之外的東西;
基礎統計運算
統計運算用於瞭解某個特徵的整體取值情況,它的最大最小值,平均值中位數,百分位數等等,這些都是最簡單的對一個欄位進行了解的手段;
上程式碼:
#目標:計算價值的最小值
minimum_price = np.min(prices)# prices.min()
#目標:計算價值的最大值
maximum_price = np.max(prices)# prices.max()
#目標:計算價值的平均值
mean_price = np.mean(prices)# prices.mean()
#目標:計算價值的中值
median_price = np.median(prices)# prices.median()
#目標:計算價值的標準差
std_price = np.std(prices)# prices.std()
特徵觀察
這裡主要考慮各個特徵與目標之間的關係,比如是正相關還是負相關,通常都是通過對業務的瞭解而來的,這裡就延伸出一個點,機器學習專案通常來說,對業務越瞭解,越容易得到好的效果,因為所謂的特徵工程其實就是理解業務、深挖業務的過程;
比如這個問題中的三個特徵:
- RM:房間個數明顯應該是與房價正相關的;
- LSTAT:低收入比例一定程度上表示著這個社群的級別,因此應該是負相關;
- PTRATIO:學生/教師比例越高,說明教育資源越緊缺,也應該是負相關;
上述這三個點,同樣可以通過視覺化的方式來驗證,事實上也應該去驗證而不是隻靠主觀猜想,有些情況下,主觀感覺與客觀事實是完全相反的,這裡要注意;
Step 3 資料劃分
為了驗證模型的好壞,通常的做法是進行cv,即交叉驗證,基本思路是將資料平均劃分N塊,取其中N-1塊訓練,並對另外1塊做預測,並比對預測結果與實際結果,這個過程反覆N次直到每一塊都作為驗證資料使用過;
上程式碼:
# 提示: 匯入train_test_split
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(features, prices, test_size=0.2, random_state=RANDOM_STATE)
print X_train.shape
print X_test.shape
print y_train.shape
print y_test.shape
Step 4 定義評價函式
這裡主要是根據問題來定義,比如分類問題用的最多的是準確率(精確率、召回率也有使用,具體看業務場景中更重視什麼),迴歸問題用RMSE(均方誤差)等等,實際專案中根據業務特點經常會有需要去自定義評價函式的時候,這裡就比較靈活;
Step 5 模型調優
通過GridSearch對模型引數進行網格組合搜尋最優,注意這裡要考慮資料量以及組合後的可能個數,避免執行時間過長哈;
上程式碼:
from sklearn.model_selection import KFold,GridSearchCV
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import make_scorer
def fit_model(X, y):
""" 基於輸入資料 [X,y],利於網格搜尋找到最優的決策樹模型"""
cross_validator = KFold()
regressor = DecisionTreeRegressor()
params = {'max_depth':[1,2,3,4,5,6,7,8,9,10]}
scoring_fnc = make_scorer(performance_metric)
grid = GridSearchCV(estimator=regressor, param_grid=params, scoring=scoring_fnc, cv=cross_validator)
# 基於輸入資料 [X,y],進行網格搜尋
grid = grid.fit(X, y)
# 返回網格搜尋後的最優模型
return grid.best_estimator_
可以看到當時專案中選擇的是決策樹模型,現在看,樹模型在這種小資料集上其實是比較容易過擬合的,因此可以考慮用SVM代替,你也可以試試哈,我估計是SVM效果最好;
學習曲線
通過繪製分析學習曲線,可以對模型當前狀態有一個基本瞭解,如下圖:
可以看到,超引數max_depth為1和3時,明顯訓練分數過低,這說明此時模型有欠擬合的情況,而當max_depth為6和10時,明顯訓練分數和驗證分析差距過大,說明出現了過擬合,因此我們初步可以猜測,最佳引數在3和6之間,即4,5中的一個,其他引數一樣可以通過學習曲線來進行視覺化分析,判斷是欠擬合還是過擬合,再分別進行鍼對處理;
小結
通過以上的幾步,可以非常簡單、清晰的看到一個機器學習專案的全流程,其實再複雜的流程也是這些簡單步驟的一些擴充套件,而更難的往往是對業務的理解,沒有足夠的理解很難得到好的結果,體現出來就是特徵工程部分做的好壞,這裡就需要各位小夥伴們奮發圖強了,路漫漫啊;
專案連結
- 通篇瀏覽可以通過nbviewer來看;
- 專案原始檔、資料集檔案可以通過GitHub波士頓專案獲取,歡迎Follow、Fork、Star;
最後
大家可以到我的Github上看看有沒有其他需要的東西,目前主要是自己做的機器學習專案、Python各種指令碼工具、資料分析挖掘專案以及Follow的大佬、Fork的專案等:https://github.com/NemoHoHal