一個自動化解決數據科學問題的python工具
機器學習經常被吹捧為:
A field of study that gives computers the ability to learn without being explicitly programmed.
盡管這是一個常見的說法,在這個領域工作的人都知道設計有效的機器學習系統是一個乏味的過程,通常需要對機器學習算法有相當的經驗,問題領域的專業知識,以及蠻力搜索來完成。因此,與機器學習愛好者試圖讓我們相信的相反,機器學習仍然需要大量的編程。
在本文中,我們要經歷機器學習流程(pipline)設計中三個乏味的過程,但卻如此重要。之后,我們將演示工具來遍歷之前的過程,來體現智能自動化的機器學習流程設計,這樣我們就可以花時間在數據科學的更有趣的方面。
模型超參數的優化是很重要的
機器學習中最乏味的部分就是調整超參數(簡稱調參)。
支持向量機要求我們選擇理想的內核,內核的參數,和懲罰參數c .人工神經網絡需要我們調整隱藏層的數量,隱藏節點的數量,以及更多的超參數。甚至隨機森林也需要我們調整的樹的數量以使得結果最好。
所有這些超參數可以對模型的效果產生重大影響。例如,我們使用 MNIST 手寫的數字數據集來說明:
如果我們使用隨機森林分類器(scikit-learn 默認的 10個樹作為參數):
In [5]:
import pandas as pd import numpy as np from sklearn.ensemble import RandomForestClassifier from sklearn.cross_validation import cross_val_score mnist_data = pd.read_csv('https://raw.githubusercontent.com/rhiever/Data-Analysis-and-Machine-Learning-Projects/master/tpot-demo/mnist.csv.gz', sep='\t', compression='gzip') cv_scores = cross_val_score(RandomForestClassifier(n_estimators=10, n_jobs=-1), X=mnist_data.drop('class', axis=1).values, y=mnist_data.loc[:, 'class'].values, cv=10) print(cv_scores) print(np.mean(cv_scores))
[ 0.94118487 0.96159338 0.9486008 0.94043708 0.94971429 0.94056294 0.94698485 0.94197513 0.93982276 0.95683248] 0.946770856298
其交叉驗證效果達到了94.7%,如果我們將參數調整到100棵樹,效果會怎么樣呢?
cv_scores = cross_val_score(RandomForestClassifier(n_estimators=100, n_jobs=-1),X=mnist_data.drop('class', axis=1).values, y=mnist_data.loc[:, 'class'].values, cv=10) print(cv_scores) [ 0.96259814 0.97829812 0.9684466 0.96700471 0.966 0.96399486 0.97113461 0.96755752 0.96397942 0.97684391] print(np.mean(cv_scores)) 0.968585789367
這樣一個小變化,我們將交叉驗證精度的平均值從94.7%提高到了96.9%。如果我們的模型為美國郵政服務,那么這個小改善可以轉化為成千上萬的附加數字分類正確。
因此不要使用默認設置。超參數的調整對每個機器學習項目至關重要。
模型選擇是重要的
我們都希望喜歡的模型很好地運用在每個機器學習問題中,但是不同的模型更適合不同的問題。
例如,我們在一個信號處理問題時,我們需要對時間序列中的“山”或“谷”進行分類:
我們應用“tuned”隨機森林來解決問題:
import pandas as pd import numpy as np from sklearn.ensemble import RandomForestClassifier from sklearn.linear_model import LogisticRegression from sklearn.cross_validation import cross_val_score hill_valley_data = pd.read_csv('https://raw.githubusercontent.com/rhiever/Data-Analysis-and-Machine-Learning-Projects/master/tpot-demo/Hill_Valley_without_noise.csv.gz', sep='\t', compression='gzip') cv_scores = cross_val_score(RandomForestClassifier(n_estimators=100, n_jobs=-1), X=hill_valley_data.drop('class', axis=1).values, y=hill_valley_data.loc[:, 'class'].values, cv=10) print(cv_scores) [ 0.64754098 0.64754098 0.57024793 0.61983471 0.62809917 0.61983471 0.70247934 0.59504132 0.49586777 0.65289256] print(np.mean(cv_scores)) 0.617937948787
然后我們會發現隨機森林并不適合這樣的信號處理任務,其交叉驗證的精度平均水平才僅61.8%.
如果我們嘗試不同的模型,例如邏輯回歸,會怎么樣呢?
cv_scores=cross_val_score(LogisticRegression(),X=hill_valley_data.drop('class', axis=1).values,y=hill_valley_data.loc[:, 'class'].values,cv=10) print(cv_scores) [ 1. 1. 1. 0.99173554 1. 0.98347107 1. 0.99173554 1. 1. ] print(np.mean(cv_scores)) 0.996694214876
我們會發現邏輯回歸非常適合這個信號處理任務,并且很容易達到近100%交叉驗證精度同時又沒有任何超參數調優。
因此對工作中的機器學習任務嘗試各種不同的機器學習模型。嘗試——調參-不同的機器學習模型盡管乏味但確是機器學習流程設計中至關重要的一步。
特征預處理是非常重要的
正如前面的兩個例子中我們所看到的,機器學習模型的性能也受特征形式的影響。因此機器學習流程中的特征預處理,就是通過重塑特征的方式使數據集更容易被模型分類。
例如,我們用之前“山”或“谷”的一個更難一點的版本(加了噪聲)來說明:
我們使用一個'tuned'的隨機森林模型來解決這個問題:
import pandas as pd import numpy as np from sklearn.ensemble import RandomForestClassifier from sklearn.decomposition import PCA from sklearn.pipeline import make_pipeline from sklearn.cross_validation import cross_val_score hill_valley_noisy_data = pd.read_csv('https://raw.githubusercontent.com/rhiever/Data-Analysis-and-Machine-Learning-Projects/master/tpot-demo/Hill_Valley_with_noise.csv.gz', sep='\t', compression='gzip') cv_scores = cross_val_score(RandomForestClassifier(n_estimators=100, n_jobs=-1), X=hill_valley_noisy_data.drop('class', axis=1).values, y=hill_valley_noisy_data.loc[:, 'class'].values, cv=10) print(cv_scores) [ 0.52459016 0.51639344 0.57377049 0.6147541 0.6557377 0.56557377 0.575 0.575 0.60833333 0.575 ] print(np.mean(cv_scores)) 0.578415300546
我們再次發現其交叉驗證的平均值只有57.8%,令人失望。
然而,如果我們先通過主成分分析來降噪,
cv_scores = cross_val_score(make_pipeline(PCA(n_components=10),RandomForestClassifier(n_estimators=100,n_jobs=-1)),X=hill_valley_noisy_data.drop('class', axis=1).values,y=hill_valley_noisy_data.loc[:, 'class'].values,cv=10) print(cv_scores) [ 0.96721311 0.98360656 0.8852459 0.96721311 0.95081967 0.93442623 0.91666667 0.89166667 0.94166667 0.95833333] print(np.mean(cv_scores)) 0.93968579235
我們會發現其結果驚人的提高到94%。
總結: 為您的數據探索各種特征的表示方法 。機器學習不同于人類,特征表示對我們可能有意義而對機器沒有意義。
利用TPOT 自動化解決數據分析
總結一下我們目前學到的關于有效的機器學習系統設計,我們應該:
- 調整超參數
- 嘗試不同的模型
- 探索特征不同的表示方式
同時我們也考慮下面幾點:
- 每個模型都有非常多的超參數
- 機器學習的模型也很多
- 各種各樣的數據特征預處理的方法也極其豐富
這就是為什么設計有效的機器學習系統如此乏味。這也是為什么我和我的合作者TPOT創建一個開源的Python工具,智能自動化的處理整個過程。
如果您的數據集與scikit-learn兼容,那么TPOT會自動優化的進行一系列特征預處理器和模型測試,最大化數據集上的交叉驗證精度。例如,如果我們希望TPOT解決帶擾動的“山”和“谷”的分類問題:
import pandas as pd from sklearn.cross_validation import train_test_split from tpot import TPOT hill_valley_noisy_data = pd.read_csv('https://raw.githubusercontent.com/rhiever/Data-Analysis-and-Machine-Learning-Projects/master/tpot-demo/Hill_Valley_with_noise.csv.gz', sep='\t', compression='gzip') X = hill_valley_noisy_data.drop('class', axis=1).values y = hill_valley_noisy_data.loc[:, 'class'].values X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.75, test_size=0.25) my_tpot = TPOT(generations=10) my_tpot.fit(X_train, y_train) print(my_tpot.score(X_test, y_test)) 0.960352039038
根據你使用的電腦,一般10 generations的 TPOT大概要5分鐘。這期間你可以做任何你想做的事情,放松一下。
經過5分鐘的優化,TPOT會發現一種達到96%的交叉驗證準確性,比我們之前手動創建的流程更好!
如果我們想知道它具體是什么,TPOT可以自動化的導出具體的 scikit-learn 代碼:使用 export() 命令
my_tpot.export('exported_pipeline.py')
其具體結果如下:
import pandas as pd from sklearn.cross_validation import train_test_split from sklearn.linear_model import LogisticRegression # NOTE: Make sure that the class is labeled 'class' in the data file tpot_data = pd.read_csv('https://raw.githubusercontent.com/rhiever/Data-Analysis-and-Machine-Learning-Projects/master/tpot-demo/Hill_Valley_with_noise.csv.gz', sep='\t', compression='gzip') training_indices, testing_indices = train_test_split( tpot_data.index,stratify=tpot_data['class'].values,train_size=0.75,test_size=0.25) result1 = tpot_data.copy() # Perform classification with a logistic regression classifier lrc1 = LogisticRegression(C=0.0001) lrc1.fit(result1.loc[training_indices].drop('class', axis=1).values, result1.loc[training_indices, 'class'].values) result1['lrc1-classification'] = lrc1.predict(result1.drop('class', axis=1).values)
它告訴我們一個 tuned logistic 回歸也許是這個問題的最優模型。
我們設計TPOT是一個銜接完整的機器學習系統,可以作為一個替代任何您目前正在使用的scikit-learn的工作流模型。
如果TPOT聽起來像你所苦苦尋找的工具,下面幾個連接也許對你十分有用:
- TPOT repository on GitHub
- [TPOT documentation] ( http://rhiever.github.io/tpot/ )
來自: http://datartisan.com/article/detail/131.html