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)證方法。
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)