系列文章目錄
“光晰本質(zhì),譜見(jiàn)不同”,光譜作為物質(zhì)的指紋,被廣泛應(yīng)用于成分分析中。伴隨微型光譜儀/光譜成像儀的發(fā)展與普及,基于光譜的分析技術(shù)將不只停留于工業(yè)和實(shí)驗(yàn)室,即將走入生活,實(shí)現(xiàn)萬(wàn)物感知,見(jiàn)微知著。本系列文章致力于光譜分析技術(shù)的科普和應(yīng)用
前言
典型的光譜分析模型(以近紅外光譜作為示意,可見(jiàn)光、中遠(yuǎn)紅外、熒光、拉曼、高光譜等分析流程亦相似)建立流程如下所示,在建立過(guò)程中,需要使用算法對(duì)訓(xùn)練樣本進(jìn)行選擇,然后使用預(yù)處理算法對(duì)光譜進(jìn)行預(yù)處理,或?qū)庾V的特征進(jìn)行提取,再構(gòu)建校正模型實(shí)現(xiàn)定量分析,最后針對(duì)不同測(cè)量?jī)x器或環(huán)境,進(jìn)行模型轉(zhuǎn)移或傳遞。因此訓(xùn)練樣本的選擇、光譜的預(yù)處理、波長(zhǎng)篩選、校正模型、模型傳遞以及上述算法的參數(shù)都影響著模型的應(yīng)用效果。

針對(duì)光譜分析流程所涉及的常見(jiàn)的訓(xùn)練樣本的劃分、光譜的預(yù)處理、波長(zhǎng)篩選、校正模型算法建立了完整的算法庫(kù),名為OpenSA(OpenSpectrumAnalysis)。整套算法庫(kù)的架構(gòu)如下所示。

樣本劃分模塊提供隨機(jī)劃分、SPXY劃分、KS劃分三種數(shù)據(jù)集劃分方法,光譜預(yù)處理模塊提供常見(jiàn)光譜預(yù)處理,波長(zhǎng)篩選模塊提供Spa、Cars、Lars、Uve、Pca等特征降維方法,分析模塊由光譜相似度計(jì)算、聚類、分類(定性分析)、回歸(定量分析)構(gòu)建,光譜相似度子模塊計(jì)算提供SAM、SID、MSSIM、MPSNR等相似計(jì)算方法,聚類子模塊提供KMeans、FCM等聚類方法,分類子模塊提供ANN、SVM、PLS_DA、RF等經(jīng)典化學(xué)計(jì)量學(xué)方法,亦提供CNN、AE、Transformer等前沿深度學(xué)習(xí)方法,回歸子模塊提供ANN、SVR、PLS等經(jīng)典化學(xué)計(jì)量學(xué)定量分析方法,亦提供CNN、AE、Transformer等前沿深度學(xué)習(xí)定量分析方法。模型評(píng)估模塊提供常見(jiàn)的評(píng)價(jià)指標(biāo),用于模型評(píng)估。自動(dòng)參數(shù)優(yōu)化模塊用于自動(dòng)進(jìn)行最佳的模型設(shè)置參數(shù)尋找,提供網(wǎng)格搜索、遺傳算法、貝葉斯概率三種最優(yōu)參數(shù)尋找方法。可視化模塊提供全程的分析可視化,可為科研繪圖,模型選擇提供視覺(jué)信息??赏ㄟ^(guò)幾行代碼快速實(shí)現(xiàn)完整的光譜分析及應(yīng)用(注: 自動(dòng)參數(shù)優(yōu)化模塊和可視化模塊暫不開(kāi)源,等畢業(yè)后再說(shuō))
本篇針對(duì)OpenSA的光譜波長(zhǎng)篩選模塊進(jìn)行代碼開(kāi)源和使用示意。
一、光譜數(shù)據(jù)讀入
提供兩個(gè)開(kāi)源數(shù)據(jù)作為實(shí)列,一個(gè)為公開(kāi)定量分析數(shù)據(jù)集,一個(gè)為公開(kāi)定性分析數(shù)據(jù)集,本章僅以公開(kāi)定量分析數(shù)據(jù)集作為演示。
1.1 光譜數(shù)據(jù)讀入
# 分別使用一個(gè)回歸、一個(gè)分類的公開(kāi)數(shù)據(jù)集做為example
def LoadNirtest(type):
if type == "Rgs":
CDataPath1 = './/Data//Rgs//Cdata1.csv'
VDataPath1 = './/Data//Rgs//Vdata1.csv'
TDataPath1 = './/Data//Rgs//Tdata1.csv'
Cdata1 = np.loadtxt(open(CDataPath1, 'rb'), dtype=np.float64, delimiter=',', skiprows=0)
Vdata1 = np.loadtxt(open(VDataPath1, 'rb'), dtype=np.float64, delimiter=',', skiprows=0)
Tdata1 = np.loadtxt(open(TDataPath1, 'rb'), dtype=np.float64, delimiter=',', skiprows=0)
Nirdata1 = np.concatenate((Cdata1, Vdata1))
Nirdata = np.concatenate((Nirdata1, Tdata1))
data = Nirdata[:, :-4]
label = Nirdata[:, -1]
elif type == "Cls":
path = './/Data//Cls//table.csv'
Nirdata = np.loadtxt(open(path, 'rb'), dtype=np.float64, delimiter=',', skiprows=0)
data = Nirdata[:, :-1]
label = Nirdata[:, -1]
return data, label
1.2 光譜可視化
#載入原始數(shù)據(jù)并可視化
data, label = LoadNirtest('Rgs')
plotspc(data, "raw specturm")
采用的開(kāi)源光譜如圖所示:

二、光譜波長(zhǎng)篩選
2.1 光譜預(yù)處理模塊
提供常見(jiàn)的UVE、Cars、SPA、LARS、PCA等波長(zhǎng)篩選算法,并進(jìn)行了相應(yīng)的封裝,使用者僅需要改變名字,即可選擇對(duì)應(yīng)的光譜波長(zhǎng)篩選算法,滿足論文快速?gòu)?fù)現(xiàn)、算法快速建模,下面是光譜篩選模塊的核心代碼
第一種波長(zhǎng)篩選算法,無(wú)信息變量選擇算法(UVE)
class UVE:
def __init__(self, x, y, ncomp=1, nrep=500, testSize=0.2):
'''
X : 預(yù)測(cè)變量矩陣
y :標(biāo)簽
ncomp : 結(jié)果包含的變量個(gè)數(shù)
testSize: PLS中劃分的數(shù)據(jù)集
return :波長(zhǎng)篩選后的光譜數(shù)據(jù)
'''
self.x = x
self.y = y
# The number of latent components should not be larger than any dimension size of independent matrix
self.ncomp = min([ncomp, rank(x)])
self.nrep = nrep
self.testSize = testSize
self.criteria = None
self.featureIndex = None
self.featureR2 = np.full(self.x.shape[1], np.nan)
self.selFeature = None
def calcCriteria(self):
PLSCoef = np.zeros((self.nrep, self.x.shape[1]))
ss = ShuffleSplit(n_splits=self.nrep, test_size=self.testSize)
step = 0
for train, test in ss.split(self.x, self.y):
xtrain = self.x[train, :]
ytrain = self.y[train]
plsModel = PLSRegression(min([self.ncomp, rank(xtrain)]))
plsModel.fit(xtrain, ytrain)
PLSCoef[step, :] = plsModel.coef_.T
step += 1
meanCoef = np.mean(PLSCoef, axis=0)
stdCoef = np.std(PLSCoef, axis=0)
self.criteria = meanCoef / stdCoef
def evalCriteria(self, cv=3):
self.featureIndex = np.argsort(-np.abs(self.criteria))
for i in range(self.x.shape[1]):
xi = self.x[:, self.featureIndex[:i + 1]]
if i<self.ncomp:
regModel = LinearRegression()
else:
regModel = PLSRegression(min([self.ncomp, rank(xi)]))
cvScore = cross_val_score(regModel, xi, self.y, cv=cv)
self.featureR2[i] = np.mean(cvScore)
def cutFeature(self, *args):
cuti = np.argmax(self.featureR2)
self.selFeature = self.featureIndex[:cuti+1]
if len(args) != 0:
returnx = list(args)
i = 0
for argi in args:
if argi.shape[1] == self.x.shape[1]:
returnx[i] = argi[:, self.selFeature]
i += 1
return returnx
def SpctrumFeatureSelcet(method, X, y):
"""
:param method: 波長(zhǎng)篩選/降維的方法,包括:Cars, Lars, Uve, Spa, Pca
:param X: 光譜數(shù)據(jù), shape (n_samples, n_features)
:param y: 光譜數(shù)據(jù)對(duì)應(yīng)標(biāo)簽:格式:(n_samples,)
:return: X_Feature: 波長(zhǎng)篩選/降維后的數(shù)據(jù), shape (n_samples, n_features)
y:光譜數(shù)據(jù)對(duì)應(yīng)的標(biāo)簽, (n_samples,)
"""
if method == "None":
X_Feature = X
if method== "Cars":
Featuresecletidx = CARS_Cloud(X, y)
X_Feature = X[:, Featuresecletidx]
elif method == "Lars":
Featuresecletidx = Lar(X, y)
X_Feature = X[:, Featuresecletidx]
elif method == "Uve":
Uve = UVE(X, y, 7)
Uve.calcCriteria()
Uve.evalCriteria(cv=5)
Featuresecletidx = Uve.cutFeature(X)
X_Feature = Featuresecletidx[0]
elif method == "Spa":
Xcal, Xval, ycal, yval = train_test_split(X, y, test_size=0.2)
Featuresecletidx = SPA().spa(
Xcal= Xcal, ycal=ycal, m_min=8, m_max=50, Xval=Xval, yval=yval, autoscaling=1)
X_Feature = X[:, Featuresecletidx]
elif method == "Pca":
X_Feature = Pca(X)
else:
print("no this method of SpctrumFeatureSelcet!")
return X_Feature, y
2 .2 光譜波長(zhǎng)篩選的使用
在example.py文件中,提供了光譜波長(zhǎng)篩選模塊的使用方法,具體如下,僅需要兩行代碼即可實(shí)現(xiàn)所有常見(jiàn)的光譜預(yù)處理。
示意:利用OpenSA實(shí)現(xiàn)UVE無(wú)信息變量選擇進(jìn)行波長(zhǎng)篩選
#載入原始數(shù)據(jù)并可視化
#載入原始數(shù)據(jù)并可視化
data, label = LoadNirtest('Rgs')
plotspc(data, "raw specturm")
# #波長(zhǎng)特征篩選并可視化
SpectruSelected, y = SpctrumFeatureSelcet('Uve', data, label)
可以看到通過(guò)OpenSA一行代碼,原始波長(zhǎng)655個(gè)維度,經(jīng)過(guò)Uve波長(zhǎng)篩選后后,得到了70個(gè)關(guān)鍵數(shù)據(jù)點(diǎn)(相關(guān)篩選波長(zhǎng)維度可以通過(guò)改變Uve對(duì)應(yīng)參數(shù)修改)

總結(jié)
利用OpenSA可以非常簡(jiǎn)單的實(shí)現(xiàn)對(duì)光譜的預(yù)處理,完整代碼可從獲得GitHub倉(cāng)庫(kù) 如果對(duì)您有用,請(qǐng)點(diǎn)贊!
代碼現(xiàn)僅供學(xué)術(shù)使用,若對(duì)您的學(xué)術(shù)研究有幫助,請(qǐng)引用本人的論文,同時(shí),未經(jīng)許可不得用于商業(yè)化應(yīng)用,歡迎大家繼續(xù)補(bǔ)充OpenSA中所涉及到的算法,如有問(wèn)題,微信:Fu_siry