Sklearn 损失函数如何应用到_Sklearn全复习(下)(持续更新)
這是一篇根據我個人需要的復習筆記 本來想一篇寫下的結果發現太多了自己找起來都好累 干脆分成兩半 上半部分包括:Decision Tree/Random Forest/Preprocessing and Feature Engineering/PCA/Logistic Regression/Kmeans. 下半部分從SVM開始 還在整理中。
七、SVM
非常強(強學習器,線性分類非線性分類都能做、二分類多分類都能做、連續型變量的回歸也能做、無監督的聚類也能做)
它在手寫識別數字和人臉識別中應用廣泛,在文本和超 文本的分類中舉足輕重,因為SVM可以大量減少標準歸納(standard inductive)和轉換設置(transductive settings)中對標記訓練實例的需求。除此之外,生物學和許多其他科學都是SVM的青睞者,SVM現在已經廣泛被用于蛋白質分類,現 在化合物分類的業界平均水平可以達到90%以上的準確率。從學術的角度來看,SVM是最接近深度學習的機器學習算法。線性SVM可以看成是神經網絡的單個神經元(雖然損失函數與神經網絡不同),非線性的SVM則與兩層的神經網絡相當,非線性的SVM中如果添加多個核函數,則可以模仿多層的神經網絡。
SVM在干嘛?---選擇一條margin最大的decision boundary。(擁有更大邊際的決策邊界在分類中的泛化誤差更小,這邊際很小的情況,是一種模型在訓練集上表現很好,卻在測試集上表現糟糕的情況,所以會“過擬合”。)過程分為:1)損失函數;2)用拉格朗日對偶函數求解系數
圖片來自菜菜的sklearn公開課svm里面的class除了特別表明是線性的兩個類LinearSVC和LinearSVR之外,其他的所有類都是同時支持線性和非線性的。 NuSVC和NuSVC可以手動調節支持向量的數目,其他參數都與最常用的SVC和SVR一致。注意OneClassSVM是無監督的類。
class sklearn.svm.SVC (C=1.0, kernel=’rbf’, degree=3, gamma=’auto_deprecated’, coef0=0.0, shrinking=True, probability=False, tol=0.001, cache_size=200, class_weight=None, verbose=False, max_iter=-1, decision_function_shape=’ovr’, random_state=None)
先看decision boundary: 。在一組數據下,給定固定的w和b,
這個式子就可以是一條固定直線,在w和b不確定的狀況下,這個表達式就可以代表平面上的任意一條直線。在SVM中,我們就使用這個表達式來表示我們的決策邊界。我們的目標是求解能夠讓邊際最大化的決策邊界,所以我們要求解參數向量w和截距b。參數向量w的方向必然是垂直于我們的決策邊界。以下黑不拉幾的圖來自我們鴨絨教授的notebook(我覺得很清楚)從MMC講起
linear 的classification的原理maximal margin classifierMMC的損失函數在MMC基礎上加penalty變成了SVCAs the penalty increases:Margin decreases;The number of support vectors decreases- from sklearn import svm
- clf = svm.SVC(kernel='linear',C=10**10)
- clf.fit(df[['X1','X2']], df['class'])
- clf.predict([[3., 3.] , [-3., -3.]])
- beta1,beta2 = clf.coef_[0]
- beta0 = clf.intercept_[0]
- M = 1/np.sqrt(beta1**2 + beta2**2) #Margin
- clf.support_ #support vectors indexes
- P = clf.decision_function(xy).reshape(axisx.shape) #重要接口decision_function,返回每個輸入的樣本所對應的到決策邊界的距離
- 用plt里面contour畫 decision boundary
*PS. 畫decision boundary的函數: matplotlib.axes.Axes.contour([X, Y,] Z, [levels]) Contour是我們專門用來繪制等高線的函數。等高線,本質上是在二維圖像上表現三維圖像的一種形式,其中兩維X和Y是兩條坐標軸上的取值,而Z表示高度。Contour就是將由X和Y構成平面上的所有點中,高度一致的點連接成線段的函數. 要注意的是,我們畫線需要重新創建網格,用網格上的點,并不是用樣本點。制作網格用到函數meshgrid()
SVC的clf的接口
- Clf.predict(X)#根據決策邊界,對X中的樣本進行分類,返回的結構為n_samples
- clf.score(X,y)#返回給定測試數據和標簽的平均準確度
- clf.support_vectors_#返回支持向量
- clf.n_support_#返回每個類中支持向量的數目
下一個問題?非線性可分數據怎么辦?
升維-Extended feature space-映射至多維空間再找decision boundary--核變換--kernel (比如rbf:高斯徑向基核函數,本質就是根據原有 feature創建出新的feature來升維)
進入對偶問題和核函數。K()在這里是linear kernel 其實就是向量點積這實際上是一個rbf kernel的例子Kernel: a measure of the similarity of two observations(也就是兩個vector)
2.將損失函數的形態轉換為拉格朗日乘數形態
拉格朗日函數求解目標原理解釋來自菜菜sklearn我們求解的參數和以及求解的超平面的存在,只與支持向量相關,與其他樣本都無關。
目標函數的最終形態對于新的樣本點的決策函數,點是向量點積。鴨老師的筆記鴨老師的筆記3.非線性SVM與核函數
核技巧”(Kernel Trick),是一種能夠使用數據原始空間中的向量計算來表示升維后的空間中的點積結果的數學方式。具體表現為K(u,v) =
。而這個原始空間中的點積函數,K(u,v)就被叫做“核函數”(Kernel Function)。畫對比圖的代碼不同的核函數在不同的數據集上的表現效果4. 什么時候選擇哪一個核函數?核函數在不同的數據集上的表現怎樣?
線性核函數和多項式核函數在非線性數據上表現會浮動,如果數據相對線性可分,則表現不錯,如果是像環形數據那樣徹底不可分的,則表現糟糕。在線性數據集上,線性核函數和多項式核函數即便有擾動項也可以表現不錯,可見多項式核函數是雖然也可以處理非線性情況,但更偏向于線性的功能。Sigmoid核函數就比較尷尬了,它在非線性數據上強于兩個線性核函數,但效果明顯不如rbf,它在線性數據上完全比不上線性的核函數們,對擾動項的抵抗也比較弱,所以它功能比較弱小,很少被用到。rbf,高斯徑向基核函數基本在任何數據集上都表現不錯,屬于比較萬能的核函數。根據經驗,無論如何先試試看高斯徑向基核函數,它適用于核轉換到很高的空間的情況,在各種情況下往往效果都很不錯,如果rbf效果不好,那我們再試試看其他的核函數。另外,多項式核函數多被用于圖像處理之中。
值得提到的是量綱問題:雖然SVM不能說是完全的距離類模型,但是它嚴重受到數據量綱的影響。尤其是poly和rbf。所以要先進行數據的無量綱化。
5.調參
參數gamma就是表達式中的γ:γ越大,每個點的影響隨distance下降越快(影響范圍越小),“everyone becomes support vector”,會導致overfitting。(鴨老師的話我記得超清楚啊)
degree就是多項式核函數的次數,參數coef0就是常數項。其中,高斯徑向基核函數受到gamma的影響,而多項式核函數受到全部三個參數的影響。
我們往往直接使用學習曲線或者網格搜索來幫助我們查找最佳的參數組合。
soft margins: 在不完全linear separable的數據上 allow points to be on the wrong side of the margin/separating hyperplane,并且懲罰分錯的程度(點到它應該所屬那一方的margin的距離),C就是懲罰系數,用于權衡”訓練樣本的正確分類“與”決策函數的邊際最大化“兩個不可同時完成的目標,希望找出一個平衡點來讓模型的效果最佳。
這時候誰是support vector呢?在兩條margin上以及中間,還有那些training error的點,都是support vector。
從左到右C在變大,對training error的懲罰加重,training error的數目減少,support vector會減少,Margin decreases。能看出來隨著C變大,accuracy是先增大后減小的,通過學習曲線調參。multi-classification:
- clf = svm.SVC(kernel='linear',C=1,decision_function_shape='ovo')#one versus one
- clf = svm.SVC(kernel='linear',C=1,decision_function_shape='ovr') # one versus rest
八、SVM(下)
unbalanced是個挺大的問題,其一多數標簽的學習效果更好,但往往我們關注的少數類別;其二模型的accuracy會失去意義。對于SVM來說,增加樣本總量并不合適(第一影響速度,第二其實你增加了很多對無意義的點)
使用SVC的參數:class_weight(本質上這個權重加在了C身上,對兩類的懲罰就不一樣了,對少數類的懲罰小,對多數類的懲罰大,因此決策邊界就會被拉向少數類那一邊。用dictionary規定權重或者“balanced”模式)。或者使用fit的參數sample_weight(每個樣本在fit時的權重)。這兩個用一個就好。通常給少數樣本賦更大的權重,就是少數類被分錯的懲罰更大,為避免懲罰,decision boundary就會移動。
例如: wclf = svm.SVC(kernel='linear', class_weight={1: 10}) 少數類是1多數類是10.
加權重之后可以很好的捕捉到少數類。但是加了不同權重以后,accuracy會下降。因為為了更準確低捕捉到少數類,會誤傷多數類。如果我們的目的是模型整體的準確率,那我們就要拒絕樣本平衡,使用class_weight被設置之前的模型。然而在現實中,將少數類判錯(沒有捕捉到)這個代價是巨大的,我們希望不惜一切代價來捕獲少數類,或者希望捕捉出盡量多的少數類,那我們就必須使用class_weight設置后的模型。
下一個問題是評估指標,單純地追求捕捉出少數類,就會成本太高,而不顧及少數類,又會無法達成模型的效果。所以在現實中,我們往往在尋找捕獲少數類的能力和將多數類判錯后需要付出的成本的平衡。如果一個模型在能夠盡量捕獲少數類的情況下,還能夠盡量對多數類判斷正確才是完美。We need Confusion Matrix.(略了 太熟悉了)
這里面True是少數類- Precision:”將多數類判錯后所需付出成本“的衡量。我們抓少數抓的有多準確(實際為真/預測為真)
- Recall/Sensitivity/TPR:在所有的少數類里面,我們抓住了多少
- 追求Precision還是Recall取決于,究竟是誤傷多數類的成本更高,還是無法捕捉少數類的代價更高。
- F-score:為了兼顧Precision和Recall。
- TNR:Specificity
- FPR:1-Specificity
Recall增加的時候,Precision的下降,表示更多的多數類被誤判了。我們希望理解,我每判斷正確一個少數類,就有多少個多數類會被判斷錯誤。FPR(因為它分母是總共的多數類個數)正好可以幫助我們衡量這個能力的變化。我們可以使用Recall和FPR之間的平衡,來替代Recall和Precision之間的平衡,讓我們衡量模型在不同閾值下,盡量捕捉少數類的時候,誤傷多數類的情況如何變化,這就是我們的ROC曲線。
clf_proba = svm.SVC(kernel="linear",C=1.0,probability=True).fit(X,y) 這樣設置以后,我們就可以返回predict_proba,也就是概率預測,我們就可以改變閾值來改變預測的分類了。
ROC曲線代表隨著Recall的不斷增加,FPR如何增加。我們希望隨著Recall的不斷提升,FPR增加得越慢越好,這說明我們可以盡量高效地捕捉出少數類,而不會將很多地多數類判斷錯誤。所以,我們希望看到的圖像是,縱坐標急速上升,橫坐標緩慢增長,也就是在整個圖像左上方的一條弧線。這代表模型的效果很不錯,擁有較好的捕獲少數類的能力。ROC曲線通常是凸型的,所以越靠近左上角越好,也就是線下面積AUC越大。那么最好的閾值在哪呢?其實是Recall和FPR差距最大的點,就是ROC曲線上面離左上角最近的點。這個點,又叫做約登指數。
- from sklearn.metrics import roc_curve
- FPR, recall, thresholds = roc_curve(y,clf_proba.decision_function(X), pos_label=1)
- from sklearn.metrics import roc_auc_score as AUC
- area = AUC(y,clf_proba.decision_function(X))
- 然后畫圖就好 比如:plt.plot(FPR, recall, color='red',label='ROC curve (area = %0.2f)' % area)
class sklearn.svm.LinearSVC (penalty=’l2’, loss=’squared_hinge’, dual=True, tol=0.0001, C=1.0, multi_class=’ovr’,fit_intercept=True, intercept_scaling=1, class_weight=None, verbose=0, random_state=None, max_iter=1000) 線性支持向量機其實與SVC類中選擇"linear"作為核函數的功能類似,但是其背后的實現庫是liblinear而不是libsvm,這使得在線性數據上,linearSVC的運行速度比SVC中的“linear”核函數要快,不過兩者的運行結果相似。
九、Linear Regression
首先,線性回歸的核心是預測連續型變量,源于統計分析。以下理解基于矩陣/線代角度。
- 損失函數:殘差平方和 RSS(Residual Sum of Squares)
- 求解方法:最小二乘法(RSS對參數矩陣求導一階導=0)(無偏估計需要y服從正態分布)
- 線性回歸的性能,往往取決于數據本身,而并非是我們的調參能力,線性回歸也因此對數據有著很高的要求。
- from sklearn.linear_model import LinearRegression as LR
- reg = LR().fit(Xtrain, Ytrain)
- yhat = reg.predict(Xtest)
2. 模型評估指標
(1)預測數值
- 均方誤差MSE(Mean Squared error)用MSE類或者cross_val_score
- from sklearn.metrics import mean_squared_error as MSE
- MSE(yhat,Ytest)
- cross_val_score(reg,X,y,cv=10,scoring="neg_mean_squared_error")
- 絕對均值誤差MAE(Mean Absolute error)用法和MSE基本一致
(2)擬合信息
- R方:我們捕獲到的信息量/y所含有的信息總量
- from sklearn.metrics import r2_score
- r2_score(yhat,Ytest) ####要注意輸入的順序
- 或者r2 = reg.score(Xtest,Ytest)
- 或者cross_val_score(reg,X,y,cv=10,scoring="r2").mean()
當MSE不高,但是我們的R方也不高的時候,說明我們的模型比較好地擬合了一部分數據的數值,卻沒有能正確擬合數據的分布。如果有更多的數據進入我們的模型,那數據標簽被預測錯誤的可能性是非常大的。
3. 解決多重共線性問題:Ridge與Lasso
我們都知道多重共線性毀掉回歸。原因非滿秩矩陣無法求逆,會毀掉最小二乘法。精確相關關系和高度相關關系并稱為"多重共線性"。在多重共線性下,模型無法建立,或者模型不可用。一個矩陣如果要滿秩,則要求矩陣中每個向量之間不能存在多重共線性,這也構成了線性回歸算法對于特征矩陣的要求。
A:精確相關 B:高度相關 C:就還挺正常那么想要解決多重共線性的問題,最常用的辦法就是在原有的線性回歸的基礎上進行改進,就有了嶺回歸,Lasso和彈性網。
1) Ridge: 嶺回歸在多元線性回歸的損失函數上加上了正則項,表達為系數的L2范式(即系數的平方項)乘以正則化系數α。這時只要α取值ok,那么逆矩陣永遠存在,也就是有解。如此,正則化系數就非常爽快地避免了”精確相關關系“帶來的影響,至少最小二乘法在存在的情況下是一定可以使用了。對于存在”高度相關關系“的矩陣,我們也可以通過調α,從而讓逆矩陣變小,以此控制參數向量的偏移。當α越大,模型越不容易受到共線性的影響。
用于判斷有無多重共線性---我們在看到較低的擬合程度時,在統計學中,我們會通過VIF或者各種檢驗來判斷數據是否存在共線性,然而在機器學習中,我們可以使用模型來判斷——如果一個數據集在嶺回歸中使用各種正則化參數取值下模型表現沒有明顯上升(比如出現持平或者下降),則說明數據沒有多重共線性,頂多是特征之間有一些相關性。反之,如果一個數據集在嶺回歸的各種正則化參數取值下表現出明顯的上升趨勢,則說明數據存在多重共線性。
- from sklearn.linear_model import Ridge, LinearRegression, Lasso
- reg = Ridge(alpha=1).fit(Xtrain,Ytrain)
- reg.score(Xtest,Ytest)
- eg加利福尼亞房價數據集上的學習曲線:嶺回歸的結果(比線性回歸)輕微上升,隨后驟降。可以說,加利佛尼亞房屋價值數據集帶有很輕微的一部分共線性,這種共線性被正則化參數消除后,模型的效果提升了一點點,但是對于整個模型而言是杯水車薪。在過了控制多重共線性的點后,模型的效果飛速下降,顯然是正則化的程度太重,擠占了參數本來的估計空間。從這個結果可以看出,加利佛尼亞數據集的核心問題不在于多重共線性,嶺回歸不能夠提升模型表現。
- 如何選取合適的α?第一種方法是嶺跡圖。每一條線是一個系數w,嶺跡圖認為,線條交叉越多,則說明特征之間的多重共線性越高。我們應該選擇系數較為平穩的喇叭口所對應的取值作為最佳取值。
- 但是現實中使用更多的是使用交叉驗證來選擇最佳的正則化系數:class sklearn.linear_model.RidgeCV (alphas=(0.1, 1.0, 10.0), fit_intercept=True, normalize=False, scoring=None,cv=None, gcv_mode=None, store_cv_values=False)
- Ridge_ = RidgeCV(alphas=np.arange(1,1001,100),store_cv_values=True).fit(X, y)
- Ridge_.score(X,y) #無關交叉驗證的嶺回歸結果
- Ridge_.cv_values_.shape #調用所有交叉驗證的結果
- Ridge_.cv_values_.mean(axis=0) #進行平均后可以查看每個正則化系數取值下的交叉驗證結果
- Ridge_.alpha_ #查看被選擇出來的最佳正則化系數
2)Lasso:Lasso無法解決特征之間”精確相關“的問題。當我們使用最小二乘法求解線性回歸時,如果線性回歸無解或者報除零錯誤,換Lasso不能解決任何問題。Lasso核心作用還是特征選擇。
- from sklearn.linear_model import Ridge, LinearRegression, Lasso
- lasso_ = Lasso(alpha=0.01).fit(Xtrain,Ytrain)
- (lasso_.coef_*100).tolist()
- 比起嶺回歸,Lasso所帶的L1正則項對于系數的懲罰要重得多(敏感很多!),并且它會將系數壓縮至0,因此可以被用來做特征選擇。也因此,我們往往讓Lasso的正則化系數α在很小的空間中變動,以此來尋找最佳的正則化系數。
- from sklearn.linear_model import LassoCV
- alpharange = np.logspace(-10, -2, 200,base=10) #自己建立Lasso進行alpha選擇的范圍,其實是形成10為底的指數函數,#10**(-10)到10**(-2)次方
- lasso_ = LassoCV(alphas=alpharange #自行輸入的alpha的取值范圍,cv=5 #交叉驗證的折數).fit(Xtrain, Ytrain)
- lasso_.alpha_ #查看被選擇出來的最佳正則化系數
- lasso_.coef_ #最佳正則化系數下獲得的模型的系數結果
- lasso_.score(Xtest,Ytest) #MSE
4. 非線性問題:多項式回歸
概括一下,對于回歸問題,數據若能分布為一條直線,則是線性的,否則是非線性。對于分類問題,數據分布若能使用一條直線來劃分類別,則是線性可分的,否則數據則是線性不可分的
對于分類模型來說,這是我們判斷模型是線性還是非線性的重要評判因素:線性模型的決策邊界是平行的直線,非線性模型的決策邊界是曲線或者交叉的直線。對分類問題而言,如果一個分類模型的決策邊界上自變量的最高次方為1,則我們稱這個模型是線性模型。
當我們獲取數據時,我們往往希望使用線性模型來對數據進行最初的擬合(線性回歸用于回歸,邏輯回歸用于分類),如果線性模型表現良好,則說明數據本身很可能是線性的或者線性可分的,如果線性模型表現糟糕,那毫無疑問我們會投入決策樹,隨機森林這些模型的懷抱,就不必浪費時間在線性模型上了。不過,我們有多種手段來處理線性回歸無法擬合非線性問題的問題:比如使用分箱或者多項式
分箱:
- from sklearn.preprocessing import KBinsDiscretizer
- enc = KBinsDiscretizer(n_bins=10 #分幾類?,encode="onehot") #ordinal
- X_binned = enc.fit_transform(X) #encode模式"onehot":使用做啞變量方式做離散化,之后返回一個稀疏矩陣(m,n_bins),每一列是一個分好的類別,對每一個樣本而言,它包含的分類(箱子)中它表示為1,其余分類中它表示為0
- 使用分箱數據進行建模
- LinearR_ = LinearRegression().fit(X_binned, y)
- TreeR_ = DecisionTreeRegressor(random_state=0).fit(X_binned, y)
- 學習曲線找最優的箱子數目
多項式變化:這是一種通過增加自變量上的次數,而將數據映射到高維空間的方法,只要我們設定一個自變量上的次數(大于1),就可以相應地獲得數據投影在高次方的空間中的結果。
當interaction_only為True的時候,只生成交互項,減輕共線性???(我猜的- from sklearn.preprocessing import PolynomialFeatures
- poly = PolynomialFeatures(degreee=2) #include_bias最好設成0?
- X = poly.fit_transform(X)
summary:都是圍繞著原始的線性回歸進行的拓展和改進。其中嶺回歸和Lasso是為了解決多元線性回歸中使用最小二乘法的各種限制,主要用途是消除多重共線性帶來的影響并且做特征選擇,而多項式回歸解決了線性回歸無法擬合非線性數據的明顯缺點,核心作用是提升模型的表現。
十、Naive Bayes
- 先驗概率,后驗概率,類的條件概率,機器學習中,X表示特征,Y表示label的分類。
- 貝葉斯假設特征之間是有條件獨立的,即 因此在特征之間有較多相關性的數據集上表現不佳。
- 分母P(X)可以用全概率公式求得。
- Naive Bayes是一個不建模的算法。
2. 如何對連續型特征變量求解概率呢
當一個特征下有無數種可能發生的事件時,這個特征的取值就是連續型的。當特征為連續型時,隨機取到某一個事件發生的概率就為0. 但是我們可以畫概率密度曲線(PDF)。我們就將求解連續型變量下某個點取值的概率問題,轉化成了求解一個函數f(x)在點xi上的取值的問題.
在現實中,我們往往假設我們的是滿足某種統計學中的分布的,最常見的就是高斯分布,常用的還有伯努利分布,多項式分布。這些分布對應著不同的貝葉斯算法,每個都對應著一系列需要我們去估計的參數,因此在貝葉斯中,我們的fit過程其實是在估計對應分布的參數,predict過程是在該參數下的分布中去進行概率預測。
3. sklearn中實現
1)GaussianNB
假設P(xi|Y)服從正態分布,來估計每個特征下每個類別上的條件概率(以給樣本分類別)。對于任意一個Y的取值,貝葉斯都以求解最大化的P(xi|Y)為目標,這樣我們才能夠比較在不同標簽下我們的樣本究竟更靠近哪一個取值。以最大化P(xi|Y)為目標,高斯樸素貝葉斯會為我們求解公式中的參數σ和μ。求解出參數后,帶入一個xi的值,就能夠得到一個P(xi|Y)的概率取值。
- from sklearn.naive_bayes import GaussianNB
- gnb = GaussianNB().fit(Xtrain,Ytrain)
- acc_score = gnb.score(Xtest,Ytest)
- Y_pred = gnb.predict(Xtest)
- prob = gnb.predict_proba(Xtest)
- 適合什么樣的數據集?高斯樸素貝葉斯的決策邊界是曲線,可以是環形也可以是弧線,所以盡管貝葉斯本身更加擅長線性可分的二分數據,但樸素貝葉斯在環形數據和月亮型數據上也可以有遠遠勝過其他線性模型的表現。但是樸素貝葉斯有一個很嚴格的假設:特征之間相互獨立,所以現實中的效果不會這樣好。
2)貝葉斯的擬合特點總結:貝葉斯是速度很快,但分類效果一般,并且初次訓練之后的結果就很接近算法極限的算法,幾乎沒有調參的余地。也就是說,如果我們追求對概率的預測,并且希望越準確越好,那我們應該先選擇邏輯回歸。如果數據十分復雜,或者是稀疏矩陣,那我們堅定地使用貝葉斯。如果我們分類的目標不是要追求對概率的預測,那我們完全可以先試試看高斯樸素貝葉斯的效果(反正它運算很快速,還不需要太多的樣本),如果效果很不錯,我們就很幸運地得到了一個表現優秀又快速的模型。如果我們沒有得到比較好的結果,那我們完全可以選擇再更換成更加復雜的模型。
首先從運行速度來看,貝葉斯與決策樹差不多(3s),而且領先其他很多,下一個等級的是SVM和隨機森林(20s),最慢的是邏輯回歸(50s)。決策樹快的原因是因為每一層選擇特征的時候不會遍歷全部特征,而是抽幾個進行遍歷,但是隨著樣本量和特征量增加,決策樹的速度必然會降低,而且你敢把少部分樣本量用貝葉斯去train(因為效果夠好),但是你不敢用決策樹在一小部分的樣本上面train。邏輯回歸按理來說應該挺快的,這里面是因為特征太多了,收到稀疏矩陣的影響而很慢。
然后是學習能力,貝葉斯是一個天生學習很弱的算法,而且沒有什么參數可以調,樣本量一變大人家學習的成果都突飛猛進接近100%,只有可憐貝葉斯本來就不咋好,還一直下降。所以少量樣本量考慮考慮貝葉斯還行。
再來看過擬合問題,決策樹的過擬合一直都很嚴重,在這張圖里面,1400樣本量對它還不夠。第二是對于過擬合的解決辦法,只有貝葉斯是通過降低訓練集的效果來減輕過擬合的。
3)使用sklearn中的learning_curve類來畫學習曲線(樣本數量與模型效果的關系)
- train_sizes,train_scores,test_scores=learning_curve(clf, X, y, cv=cv, n_jobs = n_jobs)
- cv可以是一個數,也可是一種模式:
- cv = ShuffleSplit(n_splits = 50, test_size = 0.2, random_state = 0)
4)概率類模型評估指標
布里爾分數Brier Score:
- 類似于均方誤差,可以用于任何可以使用predict_proba接口調用概率的模型
- from sklearn.metrics import brier_score_loss
- brier_score_loss(Ytest, prob[:,1], pos_label=1)
- 它是對于多分類的每一個類別下的標簽取值進行計算的
- 例子中svc最差,邏輯回歸最好。(Svc.decision.function(Xtest)返回置信度:點到決策邊界的距離,越遠說明越自信)其實svc是強行使用sigmoid函數來壓縮概率,所以svc產出的概率結果不怎么可靠。
對數似然log_loss:
里面的第二個參數y_pred只接受概率不接受標簽,如下,log_loss在svc和邏輯回歸上面會天生表現較好,現實中用做概率模型的評價指標更加常用。適合于:多分類標簽/多個模型的比較/
Reliability Curve可靠性曲線/調節概率的校準程度: 一條以預測概率為橫坐標,真實標簽為縱坐標的曲線。越靠近對角線越好。calibration_curve可用,與ROC類似,用了分箱的做法,給我們橫縱坐標。
分箱:
參數:
n_bins取不同的值:10比較合適,3沒什么用,100波動太大
依舊在不同的分類器上面嘗試:LR/SVC/Bayes,注意LR和Bayes都可以直接返回概率,但是SVC返回的是decision_function接口的置信度,因此要歸一化一下。Hasattr(obj,name)這個函數查看類obj中是否存在名為name的接口。下圖看出:邏輯回歸真的是天生對于概率預測很強。而貝葉斯表現不夠好的原因還是特征之間沒有相互獨立。SVC在于它本身是天生置信度不足的分類器,概率上不是很自信,大部分樣本的預測概率都是0.5左右。
預測概率的直方圖:
高斯樸素貝葉斯與SVC相反,它最自信,但是過度自信,不準。
概率校準:如何校準可靠性曲線?(如何讓它接近對角線)等近似回歸。Sklearn中的CalibratedClassifierCV(model, cv, method) 返回校準之后的預測結果。下圖看出bayes+isotonic等滲回歸校正的效果最好。那么準確率呢?準確率稍稍降低,與布里爾的值相悖了。(太復雜了…但還是以準確率為準)對于SVC來說,兩種概率校準辦法都很有效。
多項式樸素貝葉斯MultinomialNB
源于多項式實驗,它假設特征變量服從一個簡單的多項式分布,意義一般為:次數,頻數,是否出現等等(離散正整數)。多項式分布擅長的是分類型變量,P(xi|Y)的概率是離散的,并且不同xi之下的概率互相獨立。所以它的特征矩陣一般是稀疏矩陣,很多會和TF-IDF相結合。如果要處理連續型變量,我們用KbinsDiscretizer類進行分箱,生成一系列啞變量(是否在第i個箱子里的一堆dummy)。
MultinomialNB的參數:
1)α是一個平滑系數,避免θ=0出現。把矩陣想象成term frequency matrix,每一個樣本是大Corpus里面的一個document,每個特征都是一個詞。參數θ就代表一個概率。
2)fit_prior: 是否學習先驗概率,false的話就用統一先驗概率,比如擲色子。
3)class_prior: 給它每個class的先驗概率(有點像提前賦上class weight),如果不給它就自己學習。
如果特征矩陣中有負值 考慮歸一化。
返回接口:
_mnb.class_log_prior_返回先驗概率,查看是否有unbalanced情況
_mnb.feature_log_prob_返回log(P(xi|Y))
伯努利樸素貝葉斯BernoulliNB
假設特征們服從多元二項分布(即這個特征所代表的事件發生與否/存在與否,比較適合文本分類數據,尤其是較短的文檔)
參數:α;binarize(二值化,填閾值或None,但是一次性二值化所有的特征);fit_prior; class_prior
貝葉斯的Unbalanced問題
分箱+onehot可以同時解決二項式和多項式分布,二項式貝葉斯在unbalanced的數據集上面recall的表現最好,但是現實中不會強行將所有特征二值化,需要一個一個判斷閾值,但這樣就很低效率了。
改進后的多項式NB:complementNB
計算權重,避免某一些特征取值較多的樣本占更大的權重,會對參數估計起到支配作用。預測規則如下:
Y不等于c的概率越小,=c的概率就越大,樣本就屬于標簽c。
參數:α;norm(是否使用L2范式來規定權重的大小);fit_prior; class_prior
complementNB在unbalanced上面的效果:CNB犧牲了部分整體的精確度和布里爾指數,但是得到了非常高的recall,說明捕捉少數類很優秀,同時AUC也保持很高,因此如果目標是盡可能地捕捉少數類,那么CNB是第一選擇。
一個小例子:Bayes Classifier做文本分類。
- 單詞向量計數編碼:
- sample = ["Machine learning is fascinating, it is wonderful","Machine learning is a sensational technology","Elsa is a popular character"]
- from sklearn.feature_extraction.text import CountVectorizer
- vec = CountVectorizer()
- X = vec.fit_transform(sample)
- X:特征矩陣(稀疏矩陣)
- Vec. get_feature_names()查看都有什么單詞向量
- #注意稀疏矩陣是無法輸入pandas的,要先toarray()
- CVresult = pd.DataFrame(X.toarray(),columns = vec.get_feature_names())
問題1:越長的句子(樣本),對于θ的估計影響越大。因此補集貝葉斯讓每個特征的權重除以自己的L2范式。
問題2:沒什么實際意義的詞,比如is。因此有了TF-IDF來平衡權重。
- from sklearn.feature_extraction.text import TfidfVectorizer as TFIDF
- vec = TFIDF()
- X = vec.fit_transform(sample)
from sklearn.datasets import fetch_20newsgroups 包含約20000篇新聞,20分類的語料庫
十一、Xgboost
Xgboost由GBDT梯度提升樹發展而來。所以首先要搞懂GBDT在干嘛。
原始的boosting是在每一步訓練的模型中 為每一個樣本賦權重. 最后將N個分類器組合。Gradient Boosting與Boosting區別在于,每一計算的是為了減少上一次的殘差,下一個模型主要在殘差減少的梯度方上建立模型,使得殘差往梯度方向上減少。
k棵樹的集成結果y是所有樹的葉子權重的累加,持續迭代找到讓損失函數最小的y。迭代的單位是新的那棵樹,(原理類比邏輯回歸的梯度下降)yi(k+1) = yi(k)+ηf(k+1)(xi) 。η類比α步長。
GBDT一些重要參數:
- 尋找最佳的n_estimator: 學習曲線畫誰(偏差r方,方差,和泛化誤差)找的是泛化誤差最小的點
- subsample:隨機抽樣時的抽樣比例(0,1] 這里要注意如果本身訓練集就很小,而且因訓練集小而處于過擬合,就不要再抽樣了直接用全部trainset
- eta(η):迭代步長(shrinkage),又叫學習率(learning rate),類比邏輯回歸里面的α,用于控制迭代速度,越大就越快。太大太小都不好,xgb庫中eta默認0.3,sklearn中learning_rate默認0.1。要和n_estimator放在一起用GridSearch調參。如果說經驗之談,η在[0.01,0.2]區間內,而且我們不依賴調整η去提升模型,而還是對樹進行操作比如剪枝。
以上參數都是xgboost中與GBDT過程相關的函數。GBDT可以理解為由三個重要部分組成:(1)一個能夠衡量集成算法效果的損失函數Obj;(2)每次迭代往上加的弱評估器fk(x);(3)集成手段(迭代方法/抽樣方法/樣本加權方法/…)
而xgboost就是從以上三方面進行改進,拓展,重新定義,來實現更強大的功能。
葉子得分xgboost參數:
- booster(xgb庫中叫xgb_model): 選擇弱評估器,gbtree/gblinear/dart
- objective(xgb庫中叫obj,兩個庫里面默認值不同):目標函數/迭代過程中想要min的東西=傳統損失函數(mse/log_loss)+模型復雜度(樹的結構),可以看作是對模型方差與偏差的平衡,也就是在min泛化誤差。
Xgb庫的調用:
- 1. 用DMatrix同時傳入X matrix和y label
- 2. 寫Param,dictionary格式,注意num_round要單獨寫 不在param里面
- 3. Train
- 4. Predict
如何求解xgboost的目標函數:
1.轉化目標函數:偏差和方差都用fk(x)表示,也就是樹的結構。因為我們求解的是樹的結構。這里有泰勒展開和刨除已知常數。
2.樹結構參數化
fk(xi)表示樣本xi在第k棵樹的葉子權重/得分,f就代表這
使用葉子節點數量T來代表模型復雜度:Ω(f) = γT+正則項 (α和λ(類比lasso和ridge)正則化強度
3.區別:GBDT的目標函數不含正則項的
4.求解w(每片葉子的葉子得分)與T(葉子數量):最小化結構分數來求解樹結構:貪婪算法(控制局部最優來達到全局最優)類比Decision Tree的信息增益,
γ參數:復雜性控制,讓樹停止生長,防止過擬合。定義:在樹 的葉節點上進行進一步分枝所需的最小的目標函數減少量(如果比γ還要小,那gain就小于0了)。γ通過后剪枝的方式防止過擬合。
xgboost.cv類:
通過控制訓練集上面的訓練來提高泛化能力--不讓你學習的那么具體Xgboost應用(要記住它也是天生過擬合):剪枝參數與回歸模型調參
1.Max_depth(與γ用處差不多 一般調一個就可,調好一個以后,再調另外一個怎么調都看不到到大的效果的)
2.隨機抽樣:colsample_bytree/bysample/bynode這里是指抽取特征(注意區分這里和subsample的區別:subsample是每次建樹時抽取部分樣本來防止過度學習)會縮短時間,對于大的數據集,調這三個可能都會有反應。
3.調參思路:通過gridsearch找出最優的n_estimators和eta的組合,然后使用gamma和max_depth觀察模型處于什么樣的狀態(over/under fitting,應該往左還是往右推),最后調整正則化參數(λ和α)和抽樣參數。通常來說xgboost大多數時候時需要剪枝的,使用xgb.cv這個類(通過看train和test效果的曲線/就是上面的紅黃或者藍綠曲線)來進行剪枝調參,以調整出一組泛化能力很強的參數。(ps不建議直接把全部參數放進網格搜索,起碼要先確定大致范圍)(pps 分類的問題一般使用方差和偏差曲線,回歸問題使用MSE曲線)
默認參數:
默認參數通過cv的在train和test上面的曲線來看調參的效果Python中保存和調用模型的方法:
1)pickle:
- import pickle
- Pickle.dump(model,open(‘wenjianming.dat’,’wb’))
- Import sys
- Sys.path現有目錄
- Loaded_model=Pickle.load(model,open(‘wenjianming.dat’,’rb’))
- 然后就可以就可以直接做預測了:ypreds = Loaded_model.predict(test)
2)joblib:
- joblib.dump(model, ‘wenjianming.dat’)
- loaded_model = joblib.load(model, ‘wenjianming.dat’)
- ypreds = Loaded_model.predict(test)
Xgboost做classification的例子:
1)unbalanced問題解決
之前的random forest/svm/LR里面都有class_weight參數,xgboost中類似參數為scale_pos_weight,輸入負樣本量和正樣本量之比。
2)sklearn的predict返回分類,xgboost的predict返回概率
十二、nnet
‘黑箱算法’,是深度學習的基礎,多用于人工智能而不太適用于商業環境,因為無法解釋,只告訴你結果,你的調參也是結果導向
基本原理:基于感知機提出:
感知機三個組成部分:
- 每個輸入的特征被匹配的參數w
- 線性關系Z
- 激活函數sign
Nnet就是感知機的集成。隱藏層之間是嵌套關系,是激活函數σ的嵌套。
首先理解參數w,每一條神經鍵有一個w,他們之間沒有關系相互獨立。
理解w理解σ嵌套總結
以上是生活随笔為你收集整理的Sklearn 损失函数如何应用到_Sklearn全复习(下)(持续更新)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: struts2导入excel模板_「微干
- 下一篇: python导入自己的模块_python