概述
降維是機器學習中十分重要的一種思想。在機器學習中,我們會經常處理一些高維數據,而高維數據情形下,會出現 距離計算困難 , 數據樣本稀疏 等問題。這類問題是所有機器學習方法共同面臨的問題,我們也稱之為“ 維度災難 ”。在高維特征中,也容易出現特征之間存在線性相關,也就是說有的特征是冗余的,因此降維也是必要的。
降維的優點(必要性):
- 去除噪聲
- 降低算法的計算開銷(改善模型的性能)
- 使得數據更容易使用
- 使得數據更容易理解(幾百個維度難以理解,幾個維度可視化易理解)
降維的方法有很多,主要分為兩大類:
線性降維
:PCA,LDA,SVD等
非線性降維
:核方法(核+線性),二維化和張量化(二維+線性),流形學習(ISOMap,LLE,LPP)等
下面我們主要學習一下PCA降維算法。
1. 什么是降維?
降維,簡單來說就是 盡量保證數據本質 的前提下將數據維數降低。降維可以理解為一種映射關系,例如函數z = f(x,y),可以二維轉為一維。
2.什么是PCA?
PCA:principal component analysis,主成分分析,
是一種廣泛用于數據壓縮的算法(常用的降維技術)。PCA的思想是將
n維
特征映射到
k維
,這k維特征是全新的
正交特征
。這k維特征稱為
主元
,是重新構造出來的特征。在PCA中,數據從原來的坐標系轉換到新的坐標系下,新的坐標系的選擇與數據本身決定。其中,第一個新坐標軸選擇的是原始數據中方差最大的方向,第二個新坐標軸選取的是與第一個坐標軸正交且具有最大方差的方向,依次類推,我們可以取到這樣的k個坐標軸,從而構造出k個特征。
3.PCA的操作步驟
(1)去平均值,即每一維特征減去各自的平均值
(2)計算協方差矩陣
(3)計算協方差矩陣的特征值與特征向量
(4)對特征值從大到小排序
(5)保留最大的k個特征向量
(6)將數據轉換到k個特征向量構建的新空間中
具體實例:
(我們先用矩陣利器matlab工具做)
我們現在有二維數組:
dataSet
,10行2列
這個數據我們可以自己做,手動輸入到txt文檔里就可以了。
10行2列的數據,求每一維(每一列的數據均值):
dataSetMean
,1行2列
然后,原始數據每一維上的數據減去各自的均值得到
dataSetAdjust
,10行2列
計算dataSetAdjust的協方差矩陣(怎么計算一個矩陣的協方差矩陣?請點這里),得到
dataCov
,2行2列
求協方差矩陣的特征值和特征向量(怎么計算特征值和特征向量?清點這里):
特征值:D
特征向量:V
接著,對特征值進行排序,2維降1維,顯然1.4214>0.1120
我們選擇第二個特征值對應的特征向量:V_
轉換到新的空間得到降維后的數據:
FinalData
,10行1列
dataSetAdjust * V_ ,
這樣,我們就完成了,將10 × 2降維到10 × 1(2維降到1維)。
pca_SampleData_matlab.m
clc
;
clear
%
%
導入數據
dataSet
=
load
(
'data/SampleData.txt'
)
;
%
pca
k
=
1
;
%
目標維數
[
FinalData
,
reconData
]
=
PCA
(
dataSet
,
k
)
;
%
%
作圖
hold on
plot
(
dataSet
(
:
,
1
)
,
dataSet
(
:
,
2
)
,
'.'
)
;
plot
(
reconData
(
:
,
1
)
,
reconData
(
:
,
2
)
,
'.r'
)
;
hold off
PCA.m
function
[
FinalData
,
reconData
]
=
PCA
(
dataSet
,
k
)
[
m
,
n
]
=
size
(
dataSet
)
;
%
%
去除平均值
%
取平均值
dataSetMean
=
mean
(
dataSet
)
;
%
減去平均值
dataSetAdjust
=
zeros
(
m
,
n
)
;
for
i
=
1
:
m
dataSetAdjust
(
i
,
:
)
=
dataSet
(
i
,
:
)
-
dataSetMean
;
end
%
%
計算協方差矩陣
dataCov
=
cov
(
dataSetAdjust
)
;
%
%
計算協方差矩陣的特征值與特征向量
[
V
,
D
]
=
eig
(
dataCov
)
;
%
將特征值矩陣轉換成向量
d
=
zeros
(
1
,
n
)
;
for
i
=
1
:
n
d
(
1
,
i
)
=
D
(
i
,
i
)
;
end
%
%
對特征值排序
[
maxD
,
index
]
=
sort
(
d
)
;
%
%
選取前k個最大的特征值
%
maxD_k
=
maxD
(
1
,
(
n
-
k
+
1
)
:
n
)
;
index_k
=
index
(
1
,
(
n
-
k
+
1
)
:
n
)
;
%
對應的特征向量
V_k
=
zeros
(
n
,
k
)
;
for
i
=
1
:
k
V_k
(
:
,
i
)
=
V
(
:
,
index_k
(
1
,
i
)
)
;
end
%
%
轉換到新的空間
FinalData
=
dataSetAdjust
*
V_k
;
%
在原圖中找到這些點
,
數據還原
reconData
=
FinalData
*
V_k'
;
for
i
=
1
:
m
reconData
(
i
,
:
)
=
reconData
(
i
,
:
)
+
dataSetMean
;
end
end
(我們用python做)
python3代碼實現:
# -*- coding: utf-8 -*-
import
numpy
as
np
#計算均值,要求輸入數據為numpy的矩陣格式,行表示樣本數,列表示特征
def
meanX
(
dataX
)
:
return
np
.
mean
(
dataX
,
axis
=
0
)
#axis=0表示按照列來求均值,如果輸入list,則axis=1
def
pca
(
XMat
,
k
)
:
average
=
meanX
(
XMat
)
m
,
n
=
np
.
shape
(
XMat
)
avgs
=
np
.
tile
(
average
,
(
m
,
1
)
)
data_adjust
=
XMat
-
avgs
covX
=
np
.
cov
(
data_adjust
.
T
)
#計算協方差矩陣
featValue
,
featVec
=
np
.
linalg
.
eig
(
covX
)
#求解協方差矩陣的特征值和特征向量
index
=
np
.
argsort
(
-
featValue
)
#按照featValue進行從大到小排序
if
k
>
n
:
print
(
"k must lower than feature number"
)
return
else
:
#注意特征向量是列向量,而numpy的二維矩陣(數組)a[m][n]中,a[1]表示第1行值
selectVec
=
np
.
matrix
(
featVec
.
T
[
index
[
:
k
]
]
)
#所以這里需要進行轉置
finalData
=
data_adjust
*
selectVec
.
T
reconData
=
(
finalData
*
selectVec
)
+
average
return
finalData
,
reconData
#根據數據集data.txt
def
main
(
)
:
XMat
=
np
.
loadtxt
(
"data/SampleData.txt"
)
k
=
1
# 目標維數
return
pca
(
XMat
,
k
)
if
__name__
==
"__main__"
:
finalData
,
reconMat
=
main
(
)
我們依次查看運行過程求解得到的變量:
原始數據(待降維的數據集),XMat:
每列特征均值:average:
原始數據集每一維特征減去均值average,得到data_adjust:
計算data_adjust矩陣的協方差矩陣,得到covX矩陣:
計算協方差矩陣的特征值和特征向量:
特征值,feaValue:
特征向量,feaVec:
對特征值進行排序,從大到小,選取前k個特征值對應的特征向量,我們的例子是二維降一維,只需要選最大的特征值對應的特征向量(selectVec)即可,很顯然是上述矩陣的第二列。
轉換到新空間:
finalData = data_adjust * selectVec.T
python直接調用PCA模塊實現:
from
sklearn
.
decomposition
import
PCA
import
numpy
as
np
datas
=
np
.
loadtxt
(
'data/SampleData.txt'
)
# 原始數據
pca
=
PCA
(
n_components
=
1
)
# 加載PCA算法,設置降維后主成分數目為1
datas_pca
=
pca
.
fit_transform
(
datas
)
# 對樣本進行降維,data_pca降維后的數據
run result:
這樣太方便了,感覺走上了人生巔峰!!!(我們最好在明白原理,計算步驟的情況下使用,莫要成為一名調包俠啦,哈哈)
注:發現一個問題
,matlab降維和python降維結果不相同啊!它們的結果相差一個
負號
這個并不影響后面的計算。
實際上,都是對的,為什么這么說呢?
仔細閱讀你會發現,matlab和python在計算特征向量的過程中出現了差異,也就是出現了正負號的問題,第二個特征向量用matlab和python計算時,正負號不同啦。
出現的原因是什么呢?如果你學過線性代數,你會知道,一個矩陣A對應的特征值是不變的,特征值對應著特征向量,這個向量是一個通解(參數取值不同,會改變),k*p + C, 其中k和C是常數,而p是特征值對應的基礎解系。因此,在matlab和python中出現正負號的原因,是常數的取值不同,比如說,matlab中,k默認取+1,C取0,而python中k默認取-1,C取0。因此,最終的結果,是正負號不同。
我們也可以這樣理解,n維特征映射到k維,映射的方向不同(投影的方向),則出現結果符號(正負號)的差異。
如果你不是很懂,可以看我的關于求解矩陣特征值和特征向量的文章(請點這里)。
以上,是我們的個人理解,僅做參考,新手上路,勿噴啊,有錯的的地方,請指正。
總結:
PCA技術的一個很大的優點是
,
它是完全無參數限制的。在PCA的計算過程中完全不需要人為的設定參數或是根據任何經驗模型對計算進行干預,最后的結果只與數據相關,與用戶是獨立的。
但是,這一點同時也可以看作是缺點
。如果用戶對觀測對象有一定的先驗知識,掌握了數據的一些特征,卻無法通過參數化等方法對處理過程進行干預,可能會得不到預期的效果,效率也不高。
如果后期有空,源代碼放github上,供需要的人免費使用,喜歡的給我點個star,謝謝。
參考和引用:
https://www.cnblogs.com/guoyaohua/p/8855636.html
https://www.cnblogs.com/jiangxinyang/p/9291741.html
https://www.cnblogs.com/zy230530/p/7074215.html
https://blog.csdn.net/google19890102/article/details/27969459
僅用來個人學習和分享,如若侵權,留言立刪。
尊重他人知識產權,不做拿來主義者!
喜歡的可以關注我哦QAQ,
你的關注和喜歡就是我write博文的動力。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
