4.9日到現(xiàn)在一直在做Udacity的P1項(xiàng)目——波士頓房價(jià)預(yù)測盛龄。這個(gè)項(xiàng)目讓我收獲最大的就是理清了機(jī)器學(xué)習(xí)解決問題的整體流程斩启,搭起一個(gè)框架序调,學(xué)會了尋找模型的最優(yōu)參數(shù)以及模型的評估和驗(yàn)證方法。
numpy簡單的統(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)列后剩下的特征
模型評估驗(yàn)證
誤差來源
模型誤差常見來源:因模型無法表示基本數(shù)據(jù)的復(fù)雜度造成的偏差(bias)或者因模型對訓(xùn)練它所用的有限數(shù)據(jù)過度敏感造成的方差(Variance)
偏差影響模型的正確性(欠擬合)边酒,方差影響模型的不確定性(過擬合)。
sklearn的學(xué)習(xí)曲線learning_curve可以找到偏差和方差
評估驗(yàn)證
模型的評估驗(yàn)證分兩步狸窘,首先選擇性能指標(biāo)墩朦,然后測試模型表現(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)包括平均絕對誤差和均方誤差赴背,分?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)確率 = 正確識別的items數(shù)量 / 所有items數(shù)量
準(zhǔn)確率的缺陷在于不適用于skewed class便瑟,skewed class是指有很多數(shù)據(jù)點(diǎn),大部分屬于一個(gè)類番川,其余的小部分屬于一個(gè)類到涂,比如titanic生還問題脊框,猜測全部死亡,accuracy也不會很低践啄,一些算法算出來可能還不猜測全部死亡準(zhǔn)確率高浇雹,同理猜測全部存活,accuracy就會很低屿讽,可能再怎么進(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ù)會同時(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. ])
回歸問題
平均絕對誤差
將各個(gè)樣本的絕對誤差匯總履澳,然后根據(jù)數(shù)據(jù)點(diǎn)數(shù)量求出平均誤差嘶窄。通過將模型的所有絕對值加起來,可以避免因預(yù)測值比真實(shí)值過高或或低抵消誤差奇昙,并能獲得用戶評估模型的整體誤差指標(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...
均方誤差
與絕對誤差相比敌完,殘差(預(yù)測值與真實(shí)值的差值)被求平方储耐。對殘差求平方的一些好處是,自動(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)格搜索會遍歷傳入的參數(shù)字典中參數(shù)的所有可能情況哟旗,根據(jù)傳入的scoring對參數(shù)進(jìn)行打分,返回一個(gè)網(wǎng)格搜索類的對象栋操,至于要用該對象的哪個(gè)值就視需要而定了闸餐。
交叉驗(yàn)證可以讓網(wǎng)格搜索在不碰測試集的前提下進(jìn)行模型驗(yàn)證。交叉驗(yàn)證有很多種矾芙,比如k折交叉驗(yàn)證舍沙,它將訓(xùn)練集平均分成k份,其中1份做測試集剔宪,其余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)證最大的好處就是不碰測試集。
下面代碼是我在做Udacity的波士頓房價(jià)預(yù)測后面的可選問題——北京房價(jià)預(yù)測的代碼失球。用的是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)