一惶楼、降維介紹
降維是對數(shù)據(jù)高維度特征的一種預(yù)處理方法秆撮。降維是將高維度的數(shù)據(jù)保留下最重要的一些特征劳曹,去除噪聲和不重要的特征捣辆,從而實現(xiàn)提升數(shù)據(jù)處理速度的目的蔬螟。在實際的生產(chǎn)和應(yīng)用中,降維在一定的信息損失范圍內(nèi)汽畴,可以為我們節(jié)省大量的時間和成本旧巾。降維也成為了應(yīng)用非常廣泛的數(shù)據(jù)預(yù)處理方法。
降維具有如下一些優(yōu)點(diǎn):
- 使得數(shù)據(jù)集更易使用
- 降低算法的計算開銷
- 去除噪聲
- 使得結(jié)果容易理解
二忍些、降維技術(shù)
2.1. 主成分分析(Principal Component Analysis鲁猩,PCA)
在PCA中數(shù)據(jù)從原來的坐標(biāo)系轉(zhuǎn)換到新的坐標(biāo)系,系坐標(biāo)系的選擇是由數(shù)據(jù)本身決定的坐昙。第一個新坐標(biāo)軸選擇的是原始數(shù)據(jù)中方差最大的方向绳匀,第二個新坐標(biāo)軸的選擇是和第一個坐標(biāo)軸正交且具有最大方差的方向。該過程一直重復(fù)炸客,重復(fù)次數(shù)為原始數(shù)據(jù)中特征的數(shù)目疾棵。我們會發(fā)現(xiàn),大部分方差都包含在最前面的幾個新坐標(biāo)軸中。因此彪蓬,我們可以忽略余下的坐標(biāo)軸烙样,即對數(shù)據(jù)進(jìn)行了降維處理。
2.2. 因子分析(Factor Analysis)
在因子分析中拟枚,我們假設(shè)在觀察數(shù)據(jù)的生成中有一些觀察不到的隱變量(latent variable)。假設(shè)觀察數(shù)據(jù)是這些隱變量和默寫噪聲的線性組合众弓。那么隱變量的數(shù)據(jù)可能比觀察數(shù)據(jù)的數(shù)目少恩溅,也就是說通過找到隱變量就可以實現(xiàn)數(shù)據(jù)的降維。
2.3.獨(dú)立成分分析(Independent Component Analysis谓娃,ICA)
ICA假設(shè)數(shù)據(jù)是從N個數(shù)據(jù)源生成的脚乡。假設(shè)數(shù)據(jù)為多個數(shù)據(jù)源的混合觀察結(jié)果,這些數(shù)據(jù)源之間在統(tǒng)計上是相互獨(dú)立的滨达。而在PCA中只假設(shè)數(shù)據(jù)是不相關(guān)的奶稠。同因子分析一樣俯艰,如果數(shù)據(jù)源的數(shù)目少于觀察數(shù)據(jù)的數(shù)目,則可以實現(xiàn)降維過程锌订。
三竹握、PCA實現(xiàn)
3.1 移動坐標(biāo)軸
考慮下圖中的大量數(shù)據(jù)點(diǎn)。如果要求畫出一條直線辆飘,這條線要盡可能覆蓋這些點(diǎn)啦辐,那么最長的線可能是哪條?從圖中看出劈猪,3條直線中B最長昧甘。
在PCA中,我們對數(shù)據(jù)的坐標(biāo)進(jìn)行了旋轉(zhuǎn)战得,該旋轉(zhuǎn)的過程取決于數(shù)據(jù)的本身充边。第一條坐標(biāo)軸旋轉(zhuǎn)到覆蓋數(shù)據(jù)的最大方差位置
,即圖中的直線B常侦。數(shù)據(jù)的最大方差給出了數(shù)據(jù)的最重要的信息浇冰。在選擇了覆蓋數(shù)據(jù)最大差異性的坐標(biāo)軸之后,我們選擇了第二條坐標(biāo)軸聋亡。假如該坐標(biāo)軸與第一條坐標(biāo)軸垂直肘习,它就是覆蓋數(shù)據(jù)次大差異性的坐標(biāo)軸。這里更嚴(yán)謹(jǐn)?shù)恼f法就是正交(orthogonal)
坡倔。當(dāng)然漂佩,在二維平面下,垂直和正交是一回事罪塔。在圖中投蝉,直線C就是第二條坐標(biāo)軸。
通過PCA進(jìn)行降維處理就可以同時獲得SVM和決策樹的優(yōu)點(diǎn):一方面征堪,得到了和決策樹一樣簡單的分類器瘩缆,同時分類間隔和SVM — 樣好〉柩粒考察下面的圖庸娱,其中的數(shù)據(jù)來自于上面的圖并經(jīng)PCA轉(zhuǎn)換之后繪制而成的。如果僅使用原始數(shù)據(jù)谐算,那么這里的間隔會比決策樹的間隔更大熟尉。另外,由于只需要考慮一維信息洲脂,因此數(shù)據(jù)就可以通過比SVM簡單得多的很容易采用的規(guī)則進(jìn)行區(qū)分臣樱。
在上圖中,我們只需要一維信息即可腮考,因為另一維信息只是對分類缺乏貢獻(xiàn)的噪聲數(shù)據(jù)雇毫。在二維平面下,這一點(diǎn)看上去微不足道踩蔚,但是如果在高維空間下則意義重大棚放。
3.2 在NumPy中實現(xiàn) PCA
全文代碼
from numpy import *
import matplotlib.pyplot as plt
def load_data_set(file_name, delim='\t'):
"""
Function:
簇繪圖函數(shù)
Parameters:
file_name - 文件名
delim - 分隔符,默認(rèn)是tab鍵'\t'
Returns:
mat(dat_arr) - 數(shù)據(jù)矩陣
Modify:
2019-1-10
"""
fr = open(file_name)
string_arr = [line.strip().split(delim) for line in fr.readlines()]
dat_arr = [list(map(float, line)) for line in string_arr]
return mat(dat_arr)
def pca(data_mat, top_n_feat=9999999):
"""
Function:
降維函數(shù)
Parameters:
data_mat - 數(shù)據(jù)集
top_n_feat - N個特征
Returns:
low_d_data_mat - 降維后的N維數(shù)據(jù)矩陣
recon_mat - 重構(gòu)原數(shù)據(jù)矩陣
Modify:
2019-1-10
"""
mean_vals = mean(data_mat, axis=0)
mean_removed = data_mat - mean_vals
# 計算協(xié)方差矩陣
cov_mat = cov(mean_removed, rowvar=0)
# eig()計算特征值
eig_vals, eig_vects = linalg.eig(mat(cov_mat))
# 對特征值從小到大排序馅闽,返回索引
eig_val_ind = argsort(eig_vals)
# 從倒數(shù)第一個(也就是最大的)往左取N個值
eig_val_ind = eig_val_ind[: -(top_n_feat + 1): -1]
# 將特征值最大的N個特征值對應(yīng)索引的特征向量提取出來飘蚯,組成壓縮矩陣
red_eig_vects = eig_vects[:, eig_val_ind]
# 將去除均值后的數(shù)據(jù)矩陣*壓縮矩陣,轉(zhuǎn)換到新的空間福也,使維度降低為N
low_d_data_mat = mean_removed * red_eig_vects
# 利用降維后的矩陣反構(gòu)出原數(shù)據(jù)矩陣(用作測試局骤,可跟未壓縮的原矩陣比對)
recon_mat = (low_d_data_mat * red_eig_vects.T) + mean_vals
return low_d_data_mat, recon_mat
def plot_pca(data_mat, recon_mat):
"""
Function:
繪制原始數(shù)據(jù)集及降維后的數(shù)據(jù)集
Parameters:
data_mat - 原數(shù)據(jù)集
recon_mat - 重構(gòu)原數(shù)據(jù)矩陣
Returns:
無
Modify:
2019-1-10
"""
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(data_mat[:, 0].flatten().A[0], data_mat[:, 1].flatten().A[0], marker='^', s=90)
ax.scatter(recon_mat[:, 0].flatten().A[0], recon_mat[:, 1].flatten().A[0], marker='o', s=50, c='red')
plt.show()
def replace_nan_with_mean():
"""
Function:
將NaN替換成平均值
Parameters:
無
Returns:
data_mat - 處理缺失值后的數(shù)據(jù)矩陣
Modify:
2019-1-10
"""
data_mat = load_data_set('./machinelearninginaction/Ch13/secom.data', ' ')
num_feat = shape(data_mat)[1]
for i in range(num_feat):
mean_val = mean(data_mat[nonzero(~isnan(data_mat[:, i].A))[0], i])
data_mat[nonzero(isnan(data_mat[:, i].A))[0], i] = mean_val
return data_mat
if __name__ == '__main__':
# data_mat = load_data_set('./machinelearninginaction/Ch13/testSet.txt')
# low_d_mat, recon_mat = pca(data_mat, 2)
# print(shape(low_d_mat))
# plot_pca(data_mat, recon_mat)
# data_mat = replace_nan_with_mean()
# mean_vals = mean(data_mat, axis=0)
# mean_removed = data_mat - mean_vals
# cov_mat = cov(mean_removed, rowvar=0)
# eig_vals, eig_vects = linalg.eig(mat(cov_mat))
# # print(eig_vals)
# for i in range(20):
# first_i_eig_vals_ratio = sum(eig_vals[0: i + 1]) / sum(eig_vals)
# print('前%d個主成分的方差值占總方差值百分比:%.2f' % (i, first_i_eig_vals_ratio))
from sklearn.decomposition import PCA
data_mat = replace_nan_with_mean()
pca = PCA(n_components=7)
pca.fit(data_mat)
print('各主成分的方差值占總方差值百分比:', pca.explained_variance_ratio_)
print('各主成分的方差值:', pca.explained_variance_)
# 轉(zhuǎn)化后的數(shù)據(jù)
trans_data = pca.transform(data_mat)
savetxt("../trans_data.txt", trans_data)
lowDMat 包含了降維之后的矩陣是個一維矩陣,將降維后的數(shù)據(jù)和原始數(shù)據(jù)一起繪制出來暴凑。
讓top_n_feat = 2
峦甩,既然沒有剔除任何特征,那么重構(gòu)之后的數(shù)據(jù)會和原始的數(shù)據(jù)重合现喳。會看到和上圖類似的結(jié)果(無直線)凯傲。
四、示例:利用PCA對半導(dǎo)體制造數(shù)據(jù)降維
我們知道嗦篱,像集成電路這樣的半導(dǎo)體冰单,成本非常昂貴。如果能在制造過程中盡早和盡快地檢測出是否出現(xiàn)瑕疵灸促,將可能為企業(yè)節(jié)省大量的成本和時間诫欠。
那么,我們在面對大規(guī)模和高維度數(shù)據(jù)集時浴栽,顯然計算損耗會很大荒叼,無疑會非常耗時。
所以吃度,如果利用 PCA 等降維技術(shù)將高維的數(shù)據(jù)特征進(jìn)行降維處理甩挫,保留那些最重要的數(shù)據(jù)特征,舍棄那些可以忽略的特征椿每,將大大加快我們的數(shù)據(jù)處理速度和計算損耗伊者,為企業(yè)節(jié)省不小的時間和成本。
現(xiàn)有一上述數(shù)據(jù)集间护,而它也比前面使用的數(shù)據(jù)集更大亦渗,包含了590個特征,并且該數(shù)據(jù)包含很多以NaN標(biāo)識的的缺失值汁尺。先嘗試對這些特征進(jìn)行降維處理法精。
對于缺失值,我們用平均值來代替缺失值,平均值根據(jù)那些非NaN得到搂蜓。
會看到一大堆值狼荞,但是其中很多值都是0。實際上帮碰,其中有超過20%的特征值都是0相味。這就意味著這些特征都是其他特征的副本,也就是說殉挽,它們可以通過其他特征來表示丰涉,而本身并沒有提供額外的信息。 最前面15個值的數(shù)量級大于105斯碌,實際上那以后的值都變得非常小一死。這就相當(dāng)于告訴我們只有部分重要特征,重要特征的數(shù)目也很快就會下降傻唾。最后投慈,我們可能會注意到有一些小的負(fù)值,它們主要源自數(shù)值誤差應(yīng)該四舍五入成0策吠。在下圖13-4中已經(jīng)給出了總方差的百分比逛裤,在開始幾個主成分之后,方差就會迅速下降猴抹。
于是带族,可以知道在數(shù)據(jù)集的前面多個主成分中所包含的信息量。我們可以嘗試不同的截斷值來檢驗它們的性能蟀给。有些人使用能包含90%信息量的主成分?jǐn)?shù)量
蝙砌,而其他人使用前20個主成分。我們無法精確知道所需要的主成分?jǐn)?shù)目跋理,必須通過在實驗中取不同的值來確定择克。
上述分析能夠得到所用到的主成分?jǐn)?shù)目,然后我們可以將該數(shù)目輸入到PCA算法中前普,最后得到約簡后數(shù)據(jù)就可以在分類器中使用了肚邢。
五、應(yīng)用scikit-learn進(jìn)行降維
在scikit-learn中拭卿,與PCA相關(guān)的類都在sklearn.decomposition包中骡湖。最常用的PCA類就是sklearn.decomposition.PCA。除了PCA類以外峻厚,最常用的PCA相關(guān)類還有KernelPCA類响蕴,,它主要用于非線性數(shù)據(jù)的降維惠桃,需要用到核技巧浦夷。另外一個常用的PCA相關(guān)類是IncrementalPCA類辖试,它主要是為了解決單機(jī)內(nèi)存限制的。此外還有SparsePCA和MiniBatchSparsePCA劈狐。他們和上面講到的PCA類的區(qū)別主要是使用了L1的正則化罐孝,這樣可以將很多非主要成分的影響度降為0,這樣在PCA降維的時候我們僅僅需要對那些相對比較主要的成分進(jìn)行PCA降維懈息,避免了一些噪聲之類的因素對我們PCA降維的影響肾档。
sklearn.decomposition.PCA的主要參數(shù)做一個介紹:
(1) n_components:這個參數(shù)可以幫我們指定希望PCA降維后的特征維度數(shù)目。最常用的做法是直接指定降維到的維度數(shù)目辫继。不輸入n_components即為默認(rèn)值,此時n_components=min(樣本數(shù)俗慈,特征數(shù))姑宽。
(2) whiten :判斷是否進(jìn)行白化。所謂白化闺阱,就是對降維后的數(shù)據(jù)的每個特征進(jìn)行歸一化炮车,讓方差都為1。對于PCA降維本身來說酣溃,一般不需要白化瘦穆。如果你PCA降維后有后續(xù)的數(shù)據(jù)處理動作,可以考慮白化赊豌。默認(rèn)值是False扛或,即不進(jìn)行白化。
(3) svd_solver:即指定奇異值分解SVD的方法碘饼,由于特征分解是奇異值分解SVD的一個特例熙兔,一般的PCA庫都是基于SVD實現(xiàn)的。默認(rèn)是auto艾恼,即PCA類會自己去在前面講到的三種算法里面去權(quán)衡住涉,選擇一個合適的SVD算法來降維。
除了這些輸入?yún)?shù)外钠绍,有兩個PCA類的成員值得關(guān)注舆声。第一個是explained_variance_,它代表降維后的各主成分的方差值柳爽。方差值越大媳握,則說明越是重要的主成分。第二個是explained_variance_ratio_泻拦,它代表降維后的各主成分的方差值占總方差值的比例毙芜,這個比例越大,則越是重要的主成分争拐。
從圖中的各主成分的方差值占總方差值的比例腋粥、方差值可以看出晦雨,sklearn.decomposition.PCA的降維結(jié)果和上面是一致的。
六隘冲、小結(jié)
降維技術(shù)使得數(shù)據(jù)變得更易使用闹瞧,并且它們往往能夠去除數(shù)據(jù)中的噪聲,使得其他機(jī)器學(xué)習(xí)任務(wù)更加精確展辞。降維往往作為預(yù)處理步驟奥邮,在數(shù)據(jù)應(yīng)用到其他算法之前清洗數(shù)據(jù)。
有很多技術(shù)可以用于數(shù)據(jù)降維罗珍,在這些技術(shù)中洽腺,獨(dú)立成分分析、因子分析和主成分分析比較流行覆旱,其中又以主成分分析應(yīng)用最廣泛蘸朋。
PCA可以從數(shù)據(jù)中識別其主要特征,它是通過沿著數(shù)據(jù)最大方差方向旋轉(zhuǎn)坐標(biāo)軸來實現(xiàn)的扣唱。
選擇方差最大的方向作為第一條坐標(biāo)軸藕坯,后續(xù)坐標(biāo)軸則與前面的坐標(biāo)軸正交。協(xié)方差矩陣上的特
征值分析可以用一系列的正交坐標(biāo)軸來獲取噪沙。