您當前的位置:首頁 > 舞蹈

偏最小二乘判別PLS-DA的python實現(基於sklearn,附完整程式碼實現)

作者:由 賣藝伊風 發表于 舞蹈時間:2021-05-22

偏最小二乘判別PLS-DA的python實現(基於sklearn,附完整程式碼實現)

前兩天收到了論文的拒稿意見,其中一條是“PLSDA的表示錯誤,應為PLS-DA”,好吧,以後都寫PLS-DA!虛心接受專家意見。

由於之前偷懶,都是用PLS toolbox完成相關偏最小二乘法的資料分析工作,藉此機會,就把PLS-DA的python實現好好嘮嘮。查過不少資料中,沒有詳細說調包sklearn實現的,廢話不多說,進入正題。

sklearn中的偏最小二乘函式為PLSRegression(),這是一個迴歸函式,如果直接拿來做分類,顯然得不到想要的結果。呼叫格式如下:

from sklearn。cross_decomposition import PLSRegression

model = PLSRegression()

解決方法是:把標籤矩陣(比如0,1,2,3,4的一個列向量)使用get_dummies()函式轉換為類別矩陣,拿我的資料舉例:

import numpy as np

from sklearn。cross_decomposition import PLSRegression

from sklearn。model_selection import train_test_split

from sklearn。preprocessing import MinMaxScaler #歸一化

from sklearn。metrics import confusion_matrix,recall_score,classification_report,accuracy_score

import pandas as pd

import matplotlib。pyplot as plt

import seaborn as sns

from sklearn。model_selection import GridSearchCV

import warnings

from sklearn。model_selection import validation_curve

from sklearn。model_selection import KFold

#讀取特徵矩陣

spec = pd。read_excel(‘correct_spec。xlsx’)

x = np。array(spec)

#我這裡的特徵x形狀: (939, 150)

#做一個標籤向量,標籤y形狀: (939,)

y1 = np。zeros((189,1))

y2 = 1*np。ones((188,1))

y3 = 2*np。ones((185,1))

y4 = 3*np。ones((188,1))

y5 = 4*np。ones((189,1))

y = np。vstack((y1,y2,y3,y4,y5))

y = y。ravel()

#先做一個數據集的劃分

train_X,test_X, train_y, test_y = train_test_split(x, y, test_size=0。2)

#然後對y進行轉換

train_y = pd。get_dummies(train_y)

#建模

model = PLSRegression(n_components=8)

model。fit(train_X,train_y)

#預測

y_pred = model。predict(test_X)

#將預測結果(類別矩陣)轉換為數值標籤

y_pred = np。array([np。argmax(i) for i in y_pred])

#模型評價

print(‘測試集混淆矩陣為:\n’,confusion_matrix(test_y,y_pred))

print(‘平均分類準確率為:\n’,accuracy_score(test_y,y_pred))

接下里的問題就是函式中

主成分數n_components的取值

,如果直接使用網格搜尋函式GridSearchCV()對n_components的值在一個範圍內進行搜尋,比如(1,20)一般情況下是行不通的,會發生過擬合,直接搜尋到指定範圍內的最大值。

這時候想到的是使用validation_curve()函式繪製驗證曲線,來選擇這個超引數,但是依然會報錯,原因大致是:這是一個迴歸函式,我們用它來做分類,y值不連續,所以我就要報錯了,叭叭叭叭······ 即使按照上述方法事先轉換y的型別,再呼叫validation_curve依然不行······

所以這裡只能自己寫一個驗證函式用來調參,選取原則就是訓練集和驗證集的得分最高時候對應的主成分數,且驗證集的得分不能高於訓練集。

def accuracy_component(xc,xv,yc,yv,component,n_fold):

k_range = np。linspace(1, component,component)

kf=KFold(n_splits=n_fold,random_state=None, shuffle=True)

accuracy_validation=np。zeros((1,component))

accuracy_train=np。zeros((1,component))

for j in range(component):

p=0

acc=0

model_pls=PLSRegression(n_components=j+1)

model_pls。fit(xc,yc_labels)

y_pred = model_pls。predict(xv)

y_pred = np。array([np。argmax(i) for i in y_pred])

accuracy_train[:,j]=accuracy_score(yv,y_pred)

for train_index, test_index in kf。split(xc):

X_train, X_test = xc[train_index], xc[test_index]

y_train, y_test = yc[train_index], yc[test_index]

YC_labels = pd。get_dummies(y_train)

YV_labels=pd。get_dummies(y_test)

model_1=PLSRegression(n_components=j+1)

model_1。fit(X_train,YC_labels)

Y_pred = model_1。predict(X_test)

Y_pred = np。array([np。argmax(i1) for i1 in Y_pred])

acc=accuracy_score(y_test,Y_pred)+acc

p=p+1

accuracy_validation[:,j]=acc/p

print(accuracy_validation)

plt。plot(k_range, accuracy_validation。T, ‘o-’,label=“Training”,color=“r”)

plt。plot(k_range, accuracy_train。T, ‘o-’,label=“Cross-validation”,color=“b”)

plt。xlabel(“N components”)

plt。ylabel(“Score”)

plt。legend(loc=“best”)

plt。rc(‘font’,family=‘Times New Roman’)

plt。rcParams[‘font。size’] = 10

plt。show()

return accuracy_validation,accuracy_train

得到最佳主成分n_components,重複上述過程,對模型進行訓練即可,於是直接調包又香了

標簽: train  test  np  accuracy  pred