機(jī)器學(xué)習(xí)項(xiàng)目流程及模型評(píng)估驗(yàn)證

4.9日到現(xiàn)在一直在做Udacity的P1項(xiàng)目——波士頓房?jī)r(jià)預(yù)測(cè)。這個(gè)項(xiàng)目讓我收獲最大的就是理清了機(jī)器學(xué)習(xí)解決問題的整體流程,搭起一個(gè)框架,學(xué)會(huì)了尋找模型的最優(yōu)參數(shù)以及模型的評(píng)估和驗(yàn)證方法。

機(jī)器學(xué)習(xí)項(xiàng)目流程思維導(dǎo)圖.JPG

numpy簡(jiǎn)單的統(tǒng)計(jì)分析整理

import numpy as np
a = np.array([1,2,3,4,5])
# 最小值
minimum_a = np.min(a)
# 最大值
maximum_a = np.max(a)
# 平均值
mean_a = np.mean(a)
# 中位數(shù)
median_a = np.median(a)
# 標(biāo)準(zhǔn)差
std_a = np.std(a)
# 方差
var_a = np.var(a)
# 和
sum_a = np.sum(a)

pandas讀取處理csv數(shù)據(jù)

目前主要用的就是讀取csv,然后從表中移除目標(biāo)列,提取特征列。panda讀出來之后是一個(gè)DataFrame。

data = pd.read_csv('xxx')
outcome = data['XXX'] # outcome是目標(biāo)列
features = data.drop('XXX', axis = 1) # features是移除目標(biāo)列后剩下的特征

模型評(píng)估驗(yàn)證

誤差來源

模型誤差常見來源:因模型無法表示基本數(shù)據(jù)的復(fù)雜度造成的偏差(bias)或者因模型對(duì)訓(xùn)練它所用的有限數(shù)據(jù)過度敏感造成的方差(Variance)

偏差影響模型的正確性(欠擬合),方差影響模型的不確定性(過擬合)。
sklearn的學(xué)習(xí)曲線learning_curve可以找到偏差和方差

評(píng)估驗(yàn)證

模型的評(píng)估驗(yàn)證分兩步,首先選擇性能指標(biāo),然后測(cè)試模型表現(xiàn)。機(jī)器學(xué)習(xí)有分類問題和回歸問題兩大類,這兩類有不同的性能指標(biāo),分類問題的指標(biāo)有accuracy、precision、recall、F1分?jǐn)?shù);回歸問題有誤差指標(biāo)和分?jǐn)?shù)指標(biāo),其中誤差指標(biāo)包括平均絕對(duì)誤差和均方誤差,分?jǐn)?shù)指標(biāo)包括R2分?jǐn)?shù)和可釋方差分?jǐn)?shù),誤差指標(biāo)越接近0越好,分?jǐn)?shù)指標(biāo)越接近1越好。

分類問題

準(zhǔn)確率(accuracy)

在分類中,準(zhǔn)確率被描述為特定類的所有項(xiàng)中正確分類的數(shù)量。

準(zhǔn)確率 = 正確識(shí)別的items數(shù)量 / 所有items數(shù)量

準(zhǔn)確率的缺陷在于不適用于skewed class,skewed class是指有很多數(shù)據(jù)點(diǎn),大部分屬于一個(gè)類,其余的小部分屬于一個(gè)類,比如titanic生還問題,猜測(cè)全部死亡,accuracy也不會(huì)很低,一些算法算出來可能還不猜測(cè)全部死亡準(zhǔn)確率高,同理猜測(cè)全部存活,accuracy就會(huì)很低,可能再怎么進(jìn)行下一步判斷也依然提高不了多少。
sklearn有專門計(jì)算accuracy的函數(shù):

import numpy as np
from sklearn.metrics import accuracy_score
y_pred = [0,2,1,3]
y_true = [0,1,2,3]
accuracy_score = accuracy_score(y_true, y_pred)
print(accuracy_score) # 0.5
accuracy_score = accuracy_score(y_true, y_pred, normalize=False)
print(accuracy_score) # 2
精確率(precision)

precision = true_positives / (true_positives + false_positives)

精確率就是正確歸為此類的占(正確歸為此類的+誤歸為此類的)百分比。
sklearn有專門計(jì)算precision的函數(shù):

>>> from sklearn.metrics import precision_score
>>> y_true = [0, 1, 2, 0, 1, 2]
>>> y_pred = [0, 2, 1, 0, 0, 1]
>>> precision_score(y_true, y_pred, average='macro')  
0.22...
>>> precision_score(y_true, y_pred, average='micro')  
0.33...
>>> precision_score(y_true, y_pred, average='weighted')
... 
0.22...
>>> precision_score(y_true, y_pred, average=None)  
array([ 0.66...,  0.        ,  0.        ])
召回率(recall)

recall = true_positives / (true_positives + false_negtives)

召回率就是正確歸為此類的占(正確歸為此類的+本來是此類但是沒有歸為此類的)百分比。
sklearn有專門計(jì)算precision的函數(shù):

>>> from sklearn.metrics import recall_score
>>> y_true = [0, 1, 2, 0, 1, 2]
>>> y_pred = [0, 2, 1, 0, 0, 1]
>>> recall_score(y_true, y_pred, average='macro')  
0.33...
>>> recall_score(y_true, y_pred, average='micro')  
0.33...
>>> recall_score(y_true, y_pred, average='weighted')  
0.33...
>>> recall_score(y_true, y_pred, average=None)
array([ 1.,  0.,  0.])
F1分?jǐn)?shù)

F1 分?jǐn)?shù)會(huì)同時(shí)考慮精確率和召回率,以便計(jì)算新的分?jǐn)?shù)??蓪?F1 分?jǐn)?shù)理解為精確率和召回率的加權(quán)平均值,其中 F1 分?jǐn)?shù)的最佳值為 1、最差值為 0:
F1 = 2 x (精確率 x 召回率) / (精確率 + 召回率)

>>> from sklearn.metrics import f1_score
>>> y_true = [0, 1, 2, 0, 1, 2]
>>> y_pred = [0, 2, 1, 0, 0, 1]
>>> f1_score(y_true, y_pred, average='macro')  
0.26...
>>> f1_score(y_true, y_pred, average='micro')  
0.33...
>>> f1_score(y_true, y_pred, average='weighted')  
0.26...
>>> f1_score(y_true, y_pred, average=None)
array([ 0.8,  0. ,  0. ])

回歸問題

平均絕對(duì)誤差

將各個(gè)樣本的絕對(duì)誤差匯總,然后根據(jù)數(shù)據(jù)點(diǎn)數(shù)量求出平均誤差。通過將模型的所有絕對(duì)值加起來,可以避免因預(yù)測(cè)值比真實(shí)值過高或或低抵消誤差,并能獲得用戶評(píng)估模型的整體誤差指標(biāo)。

>>> from sklearn.metrics import mean_absolute_error
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> mean_absolute_error(y_true, y_pred)
0.5
>>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
>>> y_pred = [[0, 2], [-1, 2], [8, -5]]
>>> mean_absolute_error(y_true, y_pred)
0.75
>>> mean_absolute_error(y_true, y_pred, multioutput='raw_values')
array([ 0.5,  1. ])
>>> mean_absolute_error(y_true, y_pred, multioutput=[0.3, 0.7])
... 
0.849...
均方誤差

與絕對(duì)誤差相比,殘差(預(yù)測(cè)值與真實(shí)值的差值)被求平方。對(duì)殘差求平方的一些好處是,自動(dòng)將所有的誤差轉(zhuǎn)為正數(shù)、注重較大的誤差而不是較小的誤差以及在微積分中是可微單(可讓我們找到最大值和最小值)。

>>> from sklearn.metrics import mean_squared_error
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> mean_squared_error(y_true, y_pred)
0.375
>>> y_true = [[0.5, 1],[-1, 1],[7, -6]]
>>> y_pred = [[0, 2],[-1, 2],[8, -5]]
>>> mean_squared_error(y_true, y_pred)  
0.708...
>>> mean_squared_error(y_true, y_pred, multioutput='raw_values')
... 
array([ 0.416...,  1.        ])
>>> mean_squared_error(y_true, y_pred, multioutput=[0.3, 0.7])
... 
0.824...
R2分?jǐn)?shù)
>>> from sklearn.metrics import r2_score
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> r2_score(y_true, y_pred)  
0.948...
>>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
>>> y_pred = [[0, 2], [-1, 2], [8, -5]]
>>> r2_score(y_true, y_pred, multioutput='variance_weighted')  
0.938...
>>> y_true = [1,2,3]
>>> y_pred = [1,2,3]
>>> r2_score(y_true, y_pred)
1.0
>>> y_true = [1,2,3]
>>> y_pred = [2,2,2]
>>> r2_score(y_true, y_pred)
0.0
>>> y_true = [1,2,3]
>>> y_pred = [3,2,1]
>>> r2_score(y_true, y_pred)
-3.0
可釋方差分?jǐn)?shù)
>>> from sklearn.metrics import explained_variance_score
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> explained_variance_score(y_true, y_pred)  
0.957...
>>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
>>> y_pred = [[0, 2], [-1, 2], [8, -5]]
>>> explained_variance_score(y_true, y_pred, multioutput='uniform_average')
... 
0.983...

網(wǎng)格搜索和交叉驗(yàn)證

在Udacity的Reviewer督促下,終于搞懂了網(wǎng)格搜索和交叉驗(yàn)證以及它們是如何工作的。

機(jī)器學(xué)習(xí)的很多算法需要尋找最優(yōu)參數(shù),進(jìn)行模型改進(jìn),網(wǎng)格搜索可以找到算法的最有參數(shù)。
網(wǎng)格搜索會(huì)遍歷傳入的參數(shù)字典中參數(shù)的所有可能情況,根據(jù)傳入的scoring對(duì)參數(shù)進(jìn)行打分,返回一個(gè)網(wǎng)格搜索類的對(duì)象,至于要用該對(duì)象的哪個(gè)值就視需要而定了。

交叉驗(yàn)證可以讓網(wǎng)格搜索在不碰測(cè)試集的前提下進(jìn)行模型驗(yàn)證。交叉驗(yàn)證有很多種,比如k折交叉驗(yàn)證,它將訓(xùn)練集平均分成k份,其中1份做測(cè)試集,其余k-1份做訓(xùn)練集,運(yùn)行k次,得出一個(gè)平均分作為打分。網(wǎng)格搜索結(jié)合交叉驗(yàn)證的思路就是:把網(wǎng)格搜索找到的所有參數(shù)在k份驗(yàn)證集上跑一遍,將分?jǐn)?shù)最好的作為最優(yōu)參數(shù)。用交叉驗(yàn)證最大的好處就是不碰測(cè)試集。

下面代碼是我在做Udacity的波士頓房?jī)r(jià)預(yù)測(cè)后面的可選問題——北京房?jī)r(jià)預(yù)測(cè)的代碼。用的是k折交叉驗(yàn)證和網(wǎng)格搜索。

def fit_model_k_fold(X, y):
    """ Performs grid search over the 'max_depth' parameter for a 
        decision tree regressor trained on the input data [X, y]. """
    
    # Create cross-validation sets from the training data
    # cv_sets = ShuffleSplit(n_splits = 10, test_size = 0.20, random_state = 0)
    k_fold = KFold(n_splits=10)
    
    # TODO: Create a decision tree regressor object
    regressor = DecisionTreeRegressor(random_state=80)

    # TODO: Create a dictionary for the parameter 'max_depth' with a range from 1 to 10
    params = {'max_depth':range(1,11)}

    # TODO: Transform 'performance_metric' into a scoring function using 'make_scorer' 
    scoring_fnc = make_scorer(performance_metric)

    # TODO: Create the grid search object
    grid = GridSearchCV(regressor, param_grid=params,scoring=scoring_fnc,cv=k_fold)

    # Fit the grid search object to the data to compute the optimal model
    grid = grid.fit(X, y)

    # Return the optimal model after fitting the data
    return grid.best_estimator_


reg_k_fold = fit_model_k_fold(X_train, y_train)
print "k_fold Parameter 'max_depth' is {} for the optimal model.".format(reg_k_fold.get_params()    ['max_depth'])
# Show predictions
for i, price in enumerate(reg_k_fold.predict(client_data)):
     print "k_fold Predicted selling price for Client {}'s home: ¥{:,.2f}萬".format(i+1, price)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容