天天看點

PCA等降維算法真的能提升分類任務的性能嗎?

       對于深度學習中的圖像處理任務來說,很多研究人員都會用到降維處理技術,比如主成分分析(PCA)、稀疏自動編碼器(SAE)、随機鄰近嵌入(SNE)等,每種降維方法都有各自的側重點,根據相應的任務需求選擇合适的降維算法。在圖像處理任務中,使用降維技術的原因主要有以下兩個,一方面是通過降維能夠降低計算複雜度,另外一方面受限于輸入圖像尺寸的大小,需要對其進行一些預處理,比如常用的卷積神經網絡模型(CNN),輸入圖像的尺寸一般都不大。降維算法一般是選擇最能代表資料集中的特征進而減少特征的數量,那麼,降維算法能否對圖像分類任務的性能有所提升?畢竟降維算法處理後的特征并不能完全表征圖像的全部資訊,下面就讓我們一窺究竟吧。

降維算法

       本文主要以PCA降維算法為例分析,在直接編寫代碼驗證之前,先來談談降維算法。維數降低一般有兩種主要算法:一種是線性判别分析(LDA),另外一種是主成分分析(PCA)。二者之間的主要差別在于,LDA使用類别資訊來查找新特征,以便最大化類别的可分性,而PCA使用每個特征的方差來做到這一點。在這種情況下,LDA可以被認為是有監督算法,而PCA是無監督算法。

談談PCA算法

       PCA的想法很簡單,就是找到一組能概括資料集的低維坐标集。為什麼我們需要概況資料呢?舉一個例子:假設有一個包括一組汽車屬性的資料集,這些屬性通過其尺寸、顔色、形狀、緊湊度、車身半徑、座椅數量、門數以及行李箱尺寸等參數來描述每輛車。但是,許多屬性之間是由關聯的,所有部分屬性是多餘的。是以,我們應該根據描述每輛車的能力的高低來删除這些備援屬性,這就是PCA的目标。例如,考慮将車輪數量作為汽車和公共汽車的特征,幾乎每個類别中每個樣例都有四個輪子,是以,這個特征的差異度很小(一些罕見的公共汽車有六個輪子),是以這個特征無法區分公共汽車和汽車,但兩種車輛實際上是非常不同。現在,考慮将高度作為特征,汽車和公共汽車具有不同的屬性值,并且從最低的汽車到最高的公共汽車二者的高度差異具有很大的範圍。顯然,車輛的高度可以作為分離它們的良好特征。PCA算法不考慮類别的資訊,它隻是檢視每個特征的方差,因為可以合理地假設,呈現高方差的特征更有可能在類别之間進行良好的區分。

       通常,人們會有一個誤解,認為PCA算法會從資料集中選擇某些特征并丢棄其他特征。實際上,該算法是基于舊的屬性來組合構造新的屬性集。從數學上講,PCA執行線性變換,将原始特征集變換到由主成分組成的新空間。這些新特征對我們來說并沒有任何的實際意義,隻具有代數意義,是以不要認為PCA能夠找到之前從未想過存在的新特征。許多人仍然相信機器學習算法是神奇的,他們直接将數以千計的輸入投入到算法中,并希望機器學習算法能夠為其業務找到所有的見解和解決方案,在這裡聲明一點,不要被一些誇張的報道所欺騙,機器學習目前的能力有限,資料科學家的工作是通過使用機器學習算法作為一組工具而并不是魔術棒,智能通過對資料進行良好的探索性分析來找到對業務的見解。

主成分空間

       在新的特征空間中,我們正在尋找一些在類别中存在很大差異的屬性。正如之前舉得例子所示,一些呈現出低方差的屬性作用不大,無法很好的區分樣例。另一方面,PCA尋找的屬性可以盡可能多地顯示類别,以建構出主成分空間。該算法使用方差矩陣、協方差矩陣、特征向量和特征值對的概念來實作PCA算法,進而提供一組特征向量及其各自的特征值。

那麼,我們應該如何處理特征值和特征向量呢?答案非常簡單,特征向量表示主成分空間的新坐标系,特征值帶有每個特征向量具有的方差資訊。是以,為了減小資料集的維數,将選擇具有方內插補點大的那些特征向量,并丢棄具有方內插補點小的那些特征向量,具體實作步驟可以網上找下相關資源。下面将通過具體的例子和代碼展示PCA算法是如何工作的。

實驗代碼

       本部分内容是比較有趣的部分,現在讓我們看看PCA算法是否真的改善了分類任務的結果。

       為了驗證它,采取的政策是在資料集上應用神經網絡并檢視其初始結果。之後,我将在分類之前執行PCA降維,之後在降維後得到的資料集上應用相同的神經網絡,最後比較兩個結果。

       該資料集源自名為“Statlog資料集”的UCI機器學習庫,該資料集存儲了四個車輛輪廓的一些度量,用于分類。它由946個示例和18個度量(屬性)所有數值組成,可以

在此連結

中檢視更多詳細資訊。神經網絡結構是一個多層感覺機,其具有四個隐藏節點和一個輸出節點,所有的激活函數選擇sigmoid函數,PCA的處理是通過R資料包完成。

準備資料集

       首先,準備二進制分類的資料集,僅從兩個類别中選擇示例以構成二進制分類。這些例子來自“bus(公共汽車)”和“saab(薩博汽車)”類。類别“saab”用類别0替換,類别“bus”用類别1替換。下一步是将資料集劃分為訓練資料集和測試資料集,其比例分别為占總類示例的60%和40%。

       在資料集準備好之後,一次性使用所有特征建構神經網絡模型,然後對其應用測試資料集,看其性能。

# 加載庫
library( dplyr )

# 讀取資料集
data = read.csv( "../dataset/vehicle.csv", stringsAsFactor = FALSE )

# 變換資料格式
dataset = data %>% 
            filter( class == "bus" | class == "saab" ) %>%
            transform( class = ifelse( class == "saab", 0, 1 ) )
dataset = as.data.frame( sapply( dataset, as.numeric ) )

# 将資料集劃分為訓練集和測試集
index = sample( 1:nrow( dataset ), nrow( dataset ) * 0.6, replace = FALSE ) 

trainset = dataset[ index, ]
test = dataset[ -index, ]
testset = test %>% select( -class )

# 建構神經網絡模型 (NN)
library( neuralnet )
n = names( trainset )
f = as.formula( paste( "class ~", paste( n[!n %in% "class"], collapse = "+" ) ) )
nn = neuralnet( f, trainset, hidden = 4, linear.output = FALSE, threshold = 0.01 )

plot( nn, rep = "best" )           
PCA等降維算法真的能提升分類任務的性能嗎?

多層感覺機神經網絡

# 測試結果輸出
nn.results = compute( nn, testset )

results = data.frame( actual = test$class, prediction = round( nn.results$net.result ) )

# 混淆矩陣
library( caret )
t = table( results )
print( confusionMatrix( t ) )

## 輸出結果
## 
##         prediction
## actual  0  1
##      0   79  0
##      1   79 16
##                                                 
##                Accuracy : 0.545977              
##                  95% CI : (0.4688867, 0.6214742)
##     No Information Rate : 0.908046              
##     P-Value [Acc > NIR] : 1                     
##                                                 
##                   Kappa : 0.1553398             
##  Mcnemar's Test P-Value : < 0.0000000000000002   
##                                                 
##             Sensitivity : 0.5000000             
##             Specificity : 1.0000000             
##          Pos Pred Value : 1.0000000             
##          Neg Pred Value : 0.1684211             
##              Prevalence : 0.9080460             
##          Detection Rate : 0.4540230             
##    Detection Prevalence : 0.4540230             
##       Balanced Accuracy : 0.7500000             
##                                                 
##        'Positive' Class : 0                     
##           

無PCA處理的結果

       從上面的結果中首先可以看到,混淆矩陣(Confusion Matrix)表示有多少例子被分類,主對角線顯示正确分類的示例,次對角線顯示錯誤分類。這個結果中,分類器表示自己十分困惑,因為幾乎所有來自“saab”類别的例子都被正确分類,但它也将大多數“bus”類别的樣例分類為“saab”類别。此外,可以看出其精度值(Accuracy)約為50%,這對于分類任務來說是一個非常糟糕的結果,分類器本身就有一半一半的機率将新樣例分類為“saab”或“bus”類别。是以,由神經網絡構成的該分類器性能不好。

PCA處理後的結果

       現在,對資料集進行主成分分析PCA處理,得到特征值和特征向量。實際上,你會看到R資料包中的PCA函數提已經供了一組按降序排序的特征值,這意味着第一個分量是方差最大的一個,第二個分量是方差第二大的特征向量,以此類推。下面的代碼展示了如何選擇特征值的特征向量。

# PCA
pca_trainset = trainset %>% select( -class )
pca_testset = testset
pca = prcomp( pca_trainset, scale = T )

# 方差
pr_var = ( pca$sdev )^2 

# 方差占比
prop_varex = pr_var / sum( pr_var )

# 畫出曲線
plot( prop_varex, xlab = "Principal Component", 
                  ylab = "Proportion of Variance Explained", type = "b" )           
PCA等降維算法真的能提升分類任務的性能嗎?

主成分

# 畫出方差累積
plot( cumsum( prop_varex ), xlab = "Principal Component", 
                            ylab = "Cumulative Proportion of Variance Explained", type = "b" )           
PCA等降維算法真的能提升分類任務的性能嗎?

方差累積和

       來自R資料包中的“prcomp”函數執行PCA,該函數傳回所需的所有特征值和特征向量。上面的第一張圖顯示每個特征的方差百分比。從圖中可以看到,第一成分具有最高的方差,值約為50%,而第8個成分的方差約為0%。是以,這告訴我們。應該取其前八個元件作為主要成分。第二張圖展示了方差的另外一個視角——方差的累積和。從圖中可以看到,前八個特征值對應的方差累積和占所有方差的大約98%。實際上,這是一個非常好的數字,這意味着隻有2%的資訊丢失了,最大的好處是,從具有18維特征的空間轉換到另外一個隻有8維特征的空間,僅丢失了2%的資訊,這就是降維的力量。

       當我們知道了構成新空間的特征數量時,就可以建立出新的資料集,然後再次對其建構神經網絡模型,并用新的測試集測試其性能。

# 建立新的資料
train = data.frame( class = trainset$class, pca$x )
t = as.data.frame( predict( pca, newdata = pca_testset ) )

new_trainset = train[, 1:9]
new_testset =  t[, 1:8]

# 建構神經網絡模型 (NN)
library( neuralnet )
n = names( new_trainset )
f = as.formula( paste( "class ~", paste( n[!n %in% "class" ], collapse = "+" ) ) )
nn = neuralnet( f, new_trainset, hidden = 4, linear.output = FALSE, threshold=0.01 )

# 畫出 NN模型
plot( nn, rep = "best" )           
PCA等降維算法真的能提升分類任務的性能嗎?

新資料集的神經網絡模型

# 測試輸出
nn.results = compute( nn, new_testset )

# 結果
results = data.frame( actual = test$class, 
                      prediction = round( nn.results$net.result ) )

# 混淆矩陣
library( caret )
t = table( results ) 
print( confusionMatrix( t ) )

## 輸出結果
## 
##       prediction
## actual  0  1
##      0 76  3
##      1  1 94
##                                                 
##                Accuracy : 0.9770115             
##                  95% CI : (0.9421888, 0.9937017)
##     No Information Rate : 0.5574713             
##     P-Value [Acc > NIR] : < 0.00000000000000022 
##                                                 
##                   Kappa : 0.9535318             
##  Mcnemar's Test P-Value : 0.6170751             
##                                                 
##             Sensitivity : 0.9870130             
##             Specificity : 0.9690722             
##          Pos Pred Value : 0.9620253             
##          Neg Pred Value : 0.9894737             
##              Prevalence : 0.4425287             
##          Detection Rate : 0.4367816             
##    Detection Prevalence : 0.4540230             
##       Balanced Accuracy : 0.9780426             
##                                                 
##        'Positive' Class : 0                     
##           

       從上面可以看到,得到了非常好的結果。在這次實驗中,混淆矩陣顯示出神經網絡在兩個類别中都具有較少的錯誤分類次數,并且,出主對角線的值和精度值都在95%左右,這表明新的分類器有95%的機會正确分類一個新的樣例,這個準确率對于分類問題而言,是一個非常不錯的結果。

結論

       降維在機器學習中起着非常重要的作用,特别是當資料集具有數千種特征時。主成分分析是最優的降維算法之一,在實際項目中很容易被了解和使用。除了使得特征處理變得更加容易之外,這項技術還能夠改善分類器的結果,從文中的實驗對比來看,提升效果還是很大的。

最後,對于PCA降維算法能否提升分類任務的性能問題而言,其答案是肯定的,PCA降維算法有助于改善分類器的性能。

數十款阿裡雲産品限時折扣中,趕緊點選領劵開始雲上實踐吧!

作者資訊

Meigarom Diego Fernandes,機器學習和資料科學研究者

個人首頁:

https://www.linkedin.com/in/meigarom/

本文由阿裡雲雲栖社群組織翻譯。

文章原标題《Dimensionality Reduction — Does PCA really improve classification outcome?》,譯者:海棠,審校:Uncle_LLD。

文章為簡譯,更為詳細的内容,

請檢視原文

繼續閱讀