注:資料均來源於網絡,本文只做知識分享,如侵立刪,謝謝。
PAC算法背景簡述:
在許多領域的研究與應用中,通常需要對含有多個變量的數據進行觀測,收集大量數據后進行分析尋找規律。多變量大數據集無疑會為研究和應用提供豐富的信息,但是也在一定程度上增加了數據采集的工作量。更重要的是在很多情形下,許多變量之間可能存在相關性,從而增加了問題分析的復雜性。如果分別對每個指標進行分析,分析往往是孤立的,不能完全利用數據中的信息,因此盲目減少指標會損失很多有用的信息,從而產生錯誤的結論。
因此需要找到一種合理的方法,在減少需要分析的指標同時,盡量減少原指標包含信息的損失,以達到對所收集數據進行全面分析的目的。由於各變量之間存在一定的相關關系,因此可以考慮將關系緊密的變量變成盡可能少的新變量,使這些新變量是兩兩不相關的,那么就可以用較少的綜合指標分別代表存在於各個變量中的各類信息。主成分分析與因子分析就屬於這類降維算法。
來源:https://blog.csdn.net/program_developer/article/details/80632779
類似方法包括:奇異值分解(SVD)、主成分分析(PCA)、因子分析(FA)、獨立成分分析(ICA)
Principle Component Analysis是主成分分析,簡稱PCA。它的應用場景是對數據集進行降維。降維后的數據能夠最大程度地保留原始數據的特征(以數據協方差為衡量標准)。
PCA的原理是通過構造一個新的特征空間,把原數據映射到這個新的低維空間里。PCA可以提高數據的計算性能,並且緩解"高維災難"。高維災難詳見https://www.leiphone.com/news/201706/Vy3sQDFlI82dAGFF.html
福利: 這里需要注意的一點是:經常有人把特征選擇和特征抽取弄混。特征選擇是直接對原始數據特征選擇子集,具體的實現方法會在另一篇里寫。而特征抽取會對原始數據特征進行變型,我們一般借助PCA方法來做特征抽取。
關於PCA的數學公式隆重推薦這篇https://blog.csdn.net/aspirinvagrant/article/details/39737669
用PCA進行異常檢測的原理是:PCA在做特征值分解之后得到的特征向量反應了原始數據方差變化程度的不同方向,特征值為數據在對應方向上的方差大小。所以,最大特征值對應的特征向量為數據方差最大的方向,最小特征值對應的特征向量為數據方差最小的方向。原始數據在不同方向上的方差變化反應了其內在特點。如果單個數據樣本跟整體數據樣本表現出的特點不太一致,比如在某些方向上跟其它數據樣本偏離較大,可能就表示該數據樣本是一個異常點。
具體實現步驟:
- 對於非異常label的數據取樣,進行標准化處理,即scalar
standard_scalar = StandardScaler()
centered_training_data = standard_scalar.fit_transform(training_data[all_features])
- 初始化一個pca對象,用默認參數對所有成分進行保留。對標准化后的數據進行訓練,得到基本的PCA模型。注意這里是無監督訓練。
pca = PCA()
pca.fit(centered_training_data)
- 用pca()對步驟1中取樣的數據(訓練集)進行降維,計算數據樣本在該方向上的偏離程度。
transformed_data = pca.transform(training_data)
y = transformed_data
lambdas = pca.singular_values_
M = ((y*y)/lambdas)
這里,y是降維后的數據集。雖說是降維,但因為我們在初始化PCA的時候是對所有參數進行了保留,所以這里的y可以理解為將原始的數據X映射到了一個新的空間:y=X轉換矩陣。轉換矩陣就是把特征向量按大小順序從左往右排好組成的過渡矩陣。
這里,lambdas是訓練集(training_data)的特征值集合。
M是數據樣本的偏離程度矩陣。如果原始數據是500034,M還是5000*34。只不過M里的每一行數值代表了每個樣本在重構空間里離每個特征向量的距離。
注意:這里的lambdas主要起歸一化的作用,這樣可以使得不同方向上的偏離程度具有可比性。在計算了數據樣本在所有方向上的偏離程度之后,為了給出一個綜合的異常得分,最自然的做法是將樣本在所有方向上的偏離程度加起來。
- 計算主成分和次成分的閾值。
'q' 設為可以讓前q個成分解釋數據集50%的方差
q = 5
print "Explained variance by first q terms: ", sum(pca.explained_variance_ratio_[:q])
r設為可以讓r以后的成分對應的特征值小於0.2.
q_values = list(pca.singular_values_ < .2) r = q_values.index(True)
根據r和q,對M進行切片,再對每個樣本點進行距離的計算。np.sum(major_components, axis=1)就是在算每一行(樣本)的距離加總。
major_components = M[:,range(q)]
minor_components = M[:,range(r, len(features))]
major_components = np.sum(major_components, axis=1)
minor_components = np.sum(minor_components, axis=1)
對切片后的數據集進行閾值計算
components = pd.DataFrame({'major_components': major_components, 'minor_components': minor_components}) c1 = components.quantile(0.99)['major_components'] c2 = components.quantile(0.99)['minor_components']
這里的c1, c2是人為設定的兩個閾值,如果得分大於閾值則判斷為異常。
那么問題來了,我們不僅選了前50%最重要的成分,還選取了后面特征值小於0.2的最不重要的成分。為什么要這樣做呢?原因如下:
一般而言,前幾個特征向量往往直接對應原始數據里的某幾個特征,在前幾個特征向量方向上偏差比較大的數據樣本,往往就是在原始數據中那幾個特征上的極值點。而后幾個特征向量有些不同,它們通常表示某幾個原始特征的線性組合,線性組合之后的方差比較小反應了這幾個特征之間的某種關系。在后幾個特征方向上偏差比較大的數據樣本,表示它在原始數據里對應的那幾個特征上出現了與預計不太一致的情況。到底是考慮全部特征方向上的偏差,前幾個特征向量上的偏差,還是后幾個特征向量上的偏差,在具體使用時可以根據具體數據靈活處理。
當然,根據數據的情況,也可以只考慮數據在前 k 個特征向量方向上的偏差,或者只考慮后 r 個特征向量方向上的偏差。
-
計算出訓練數據的閾值c1, c2,即上面得到的。
-
對於新的數據(測試集),用已經訓練好的pca模型和standard_scalar模型進行transform。注意這里是用訓練集的標准去tranform新的數據。
data = standard_scalar.transform(df_full[all_features])
transformed_data_test = pca.transform(data)
y_test = transformed_data
lambdas_test = pca.singular_values_
M_test = ((y*y)/lambdas)
然后r和q保持不變,還是用在訓練集上算出來的r, q來對M_test進行切片
major_components_test = M_test[:,range(q)]
minor_components_test = M_test[:,range(r, len(features))]
major_components_test = np.sum(major_components, axis=1)
minor_components_test = np.sum(minor_components, axis=1)
- 制作分類器
def classifier(major_components, minor_components): major = major_components > c1 minor = minor_components > c2 return np.logical_or(major,minor)
- 計算結果
results = classifier(major_components=major_components, minor_components=minor_components)
來源:CC思SS https://www.jianshu.com/p/e35a47913457