python3的sklearn庫中有偏最小二乘法。
可以參見下面的庫說明:http://scikit-learn.org/stable/modules/generated/sklearn.cross_decomposition.PLSRegression.html
對下面的程序進行改寫,可以在python3中運行了
程序來源:來源:https://blog.csdn.net/li_huifei/article/details/78467689 經過修改可以在python3上運行
我的數據A.csv
我的數據RON.csv
# -*- coding: utf-8 -*- #看來這個程序適合的是python2版本的。來源:https://blog.csdn.net/li_huifei/article/details/78467689 #這個目前也可以用了,主要還是在第60行的數據轉換,,,不太清楚怎樣去做裝換。主要是因為數據類型不清楚,所以用了最笨的方法,不知道結果正不正確。????【這個是錯誤的】 #PLSR3經過摸索,第68行,還是因為數據結構類型不對,之后把array類型的數組轉換成了list,,,這樣方便在外面套一個[],,之后運行沒有問題,但是結果的正確與否,還有待驗證。 #導入庫的部分 import csv from sklearn import preprocessing from sklearn.cross_validation import train_test_split from sklearn.decomposition import RandomizedPCA from sklearn.cross_decomposition import PLSRegression #偏最小二乘法的實現, 在這里是可以跳進 PLSRegression 里面的 import numpy as np import math import matplotlib.pyplot as plt #導入數據的部分 A = np.loadtxt('A.csv',delimiter=',') #讀入數據 這里的A就是y的矩陣 #讀了這么多的數據???哪個是x,,哪個又是y呢??? print (A.shape) RON = np.loadtxt('RON.csv',delimiter=',') #這里的RON就是x的矩陣 print (RON.shape) #暫且在這里設置全局變量吧。 x_train_st_i=[] #定義全局函數的部分。 def error(y_predict,y_test): #定義計算誤差平方和函數,,,傳入的是估算出的值,和測試值,,這里僅僅是用來定義的,方便后面的調用。 errs = [] for i in range(len(y_predict)): e = (y_predict[i]-y_test[i])**2 errs.append(e) return sum(errs) #偏最小二乘法的實現部分。 x_train, x_test, y_train, y_test = train_test_split(RON,A,test_size=0.5) #划分訓練集測試集,,,這個是一個庫函數?? ,,,,這里能夠看出是A和RON進行建模的。 x_train_st = preprocessing.scale(x_train) #數據標准化,這個是內置函數 y_train_st = preprocessing.scale(y_train) #數據標准化,,這一句是我仿照上面的一句改寫的。 n_components = 0 #這個應該是保存主成分的個數。 while n_components<x_train_st.shape[1]: n_components=n_components+1 #在第一遍的時候n_components是1,第二遍循環的時候是2,,,第n遍循環是n,,最大是x的列數,也就是特征的個數, pls2 = PLSRegression(n_components=n_components) #計算SS (SS這個是全建模 , PRESS是減去一個進行建模,,,,在python里建模很簡單,設置好參數,調用一下函數就能建模了) #這個不是偏最小二乘法嗎???,,這里是循環計算主成分的個數,直到達到滿意的精度。 pls2.fit(x_train_st, y_train) #fit也是一個函數,,,兩個參數,第一個參數是訓練集,第二個參數是目標。 y_predict0 = pls2.predict(x_train_st) #predict也是一個內置的函數,,,,這個是不是用建好的模型去做預測,,,,把參數訓練集輸入進去,得到的是預測的值。 SS = error(y_predict0,y_train) #這里是預測的值和真正的值之間的誤差大小。 y_predict1 = [] #這是創建了一個新的變量。根據名字的意思,根據模型得到的y的預測值,實際上這個模型是留一法建立的模型。 for i in range(x_train_st.shape[0]): #計算PRESS,,,,這個是x_train_st的行數 n_components1 = n_components #但是我不明白,為什么這里還要加1,主成分不可能是0個吧,所以就從1開始了。 x_train_st1 = np.delete(x_train_st,i,0) #這里的0是行,1是列,,這個應該是刪除第i行,,,這里是標准化的數組。留一法的實現 y_train_st1 = np.delete(y_train,i,0) #這個也是刪除第i行,這里都是經過標准化的(但這個x是經過標准化的,y卻沒有用標准化的數據)。,,這個沒有用到過,是不是這里寫錯了?? pls2 = PLSRegression(n_components=n_components1) #偏最小二乘法參數的設置,,,這里面一般有5個參數,,但這里只傳入了主成分的個數。 #參數1:n_components:int ,(default 2) ,,要保留的主成分數量,默認為2 #參數2:scale:boolean,(default True),,是否歸一化數據,默認為是 #參數3:max_iter: an integer,(default 500),,使用NIPALS時的最大迭代次數 #參數4:tol: non-negative real(default 1e-06),,迭代截止條件 #參數5:copy: Boolean,(default True),, pls2.fit(x_train_st1, y_train_st1) #這里是根據前面設置好的參數建模過程,這里的建模過程是不是不太對(這里x是歸一化的,y並沒有用歸一化的),應該都是用歸一化的才行呀。??? #這里主要是進行了數據格式的轉換,因為做預測要傳進的是矩陣【格式很重要】 x_train_st_i=[] #用之前要進行清空,這個很重要。用一個參數之前要進行清空。 x_train_st_list=x_train_st[i].tolist() x_train_st_i.append(x_train_st_list) print ('the x_train_st is ',x_train_st_i) #輸出一下變量,查看格式是否正確,因為下面的predict函數需要用[[1,1,1,1,1,1]] 這種格式的數據 y_predict11 = pls2.predict(x_train_st_i) #預測函數,給定之前留一法沒有用到的樣本,進行建模,預測對應的y值。????可是已經刪除了不是嗎??? ZHE這句出了一點問題????就是數據格式有問題,需要在最外面在加一個[] y_predict1.append(y_predict11) #把所有的y值組成一個數組,便於計算誤差。,這個也是y的預測值,用它來算出另一個誤差。 PRESS = error(y_predict1,y_train) #可能錯誤:https://blog.csdn.net/little_bobo/article/details/78861578 Qh = 1-float(PRESS/SS) if Qh<0.0985: #判斷精度 模型達到精度要求,可以停止主成分的提取了。 plt.figure(1) plt.scatter(y_predict0,y_train) #畫了一個圖,這個圖是預測值,與測量值的圖??? plt.figure(2) plt.scatter(y_predict1,y_train) print ('the Qh is ',Qh) print ('the PRESS is',PRESS) print ('the SS is',SS) break #達到了上面的精度,就可以停止while的迭代了 #這下面就沒有看懂了。 print ('n_components is ',n_components+1) #這里為什么要加1???,,,難道因為計數是從0開始的?? SECs = [] errors = [] e = 100 for i in range(10): #循環測試 #print i x_train, x_test, y_train, y_test = train_test_split( RON,A, test_size=0.5) #划分訓練集與測試集,這個是一個內置的函數。 x_test_st = preprocessing.scale(x_test) #數據標准化 y_predict = pls2.predict(x_test_st) #進行預測 SECs.append(np.sqrt(error(y_predict,y_test)/(y_test.shape[0]-1))) errors.append(float(error(y_predict,y_test))) if SECs[-1]<e: y_predict_min = y_predict y_test_min = y_test print ('the prediced value is ' ,y_predict.T) #畫圖,打印結果 print ('the true value is',y_test) print ('the mean error is',float(np.mean(errors))) print ("the mean SEC is ",float(np.mean(SECs))) plt.figure(3) plt.scatter(y_predict_min,y_test_min)
摘自: