2016-04-21 89 views
1

我試圖在MNIST數據集上執行PCA,作爲我需要生成特徵向量並可視化頂部特徵的過程的一部分。以下是我的算法:MNIST Python numpy特徵向量可視化錯誤

  1. 加載圖像
  2. 減意味着
  3. 生成協方差矩陣
  4. 派生特徵向量和特徵值

這是相當簡單的算法來運行;我的第一個任務是將前10個特徵向量可視化爲圖像。以下是代碼,我迄今爲止:

__author__  = "Ajay Krishna Teja Kavuri" 


import numpy as np 
import random 
from mnist import MNIST 
import matplotlib.pylab as plt 

class PCAMNIST: 


    #Initialization 
    def __init__(self): 
     #Load MNIST datset 
     mnistData = MNIST('./mnistData') 
     self.imgTrain,self.lblTrain=mnistData.load_training() 
     self.imgTrainSmpl=self.imgTrain[:60000] 
     np.seterr(all='warn') 


    #1. Subtract the mean because the PCA will work better 
    def subMean(self): 
     try: 
      self.sumImg = np.empty([784,]) 
      #calculate the sum 
      for img in self.imgTrainSmpl: 
       imgArr = np.asarray(img) 
       self.sumImg = np.add(imgArr,self.sumImg) 

      #Calculate the mean array 
      self.meanImg = self.sumImg/(len(self.imgTrainSmpl)) 
      self.meanImg = np.nan_to_num(self.meanImg) 

      #subtract it out 
      index=0 
      for img in self.imgTrainSmpl: 
       imgArr = np.asarray(img) 
       self.imgTrainSmpl[index] = np.subtract(imgArr,self.meanImg).tolist() 
       index += 1 

      #for img in self.imgTrainSmpl: 
       #print img 
     except: 
      print Exception 


    #2. get the covaraince matrix for each digit 
    def getCov(self): 
     self.imgCov=[] 
     dgtArr = np.asarray(self.imgTrainSmpl).T 
     dgtCov = np.cov(dgtArr) 
     self.imgCov.append(dgtCov) 
     #for img in self.imgCov: 
      #print img 

    #3. get the eigen vectors from the covariance matrix 
    def getEigen(self): 
     self.eigVec=[] 
     self.eigVal=[] 
     dgtArr = np.asarray(self.imgCov) 
     tmpEigVal,tmpEigVec=np.linalg.eig(dgtArr) 
     self.eigVal.append(tmpEigVal.tolist()) 
     self.eigVec.append(tmpEigVec.tolist()) 

     #print "\nEigen values:\n" 
     #for img in self.eigVal: 
      #print img 

     #print "\nEigen vectors:\n" 
     #for img in self.eigVec: 
      #print img 


    def sortEV(self): 
     self.eigValArr = np.asarray(self.eigVal[0][0]) 
     self.eigVecArr = np.asarray(self.eigVec[0][0]) 
     self.srtdInd = np.argsort(np.abs(self.eigValArr)) 
     self.srtdEigValArr = self.eigValArr[self.srtdInd] 
     self.srtdEigVecArr = self.eigVecArr[self.srtdInd] 
     self.srtdEigVec = self.srtdEigVecArr.real.tolist() 
     #print self.srtdEigValArr[0] 
     print len(self.srtdInd.tolist()) 
     #print self.eigVec[self.srtdInd[0]] 
     #print np.asarray(self.srtdEigVec).shape 
     #for img in self.srtdEigVecArr: 
      #print img 
     #self.drawEig() 

    def plotVal(self): 
     """ 
     plt.figure() 
     plt.scatter(np.asarray(self.eigVal).real) 
     plt.show() 
     """ 

    def drawEig(self): 
     for vec in self.srtdEigVec[:10]: 
      self.drawEigV(vec) 


    def drawEigV(self,digit): 
     plt.figure() 
     fig=plt.imshow(np.asarray(digit).reshape(28,28),origin='upper') 
     fig.set_cmap('gray_r') 
     fig.axes.get_xaxis().set_visible(False) 
     fig.axes.get_yaxis().set_visible(False) 
     plt.savefig(str(random.randint(0,10000))+".png") 
     #plt.show() 
     plt.close() 



    def drawChar(self,digit): 
     plt.figure() 
     fig=plt.imshow(np.asarray(digit).reshape(28,28),clim=(-1,1.0),origin='upper') 
     fig.set_cmap('gray_r') 
     fig.axes.get_xaxis().set_visible(False) 
     fig.axes.get_yaxis().set_visible(False) 
     plt.show() 
     plt.close() 


    def drawSmpl(self): 
     for img in self.imgTrainSmpl: 
      self.drawChar(img) 


    def singleStep(self): 
     self.val, self.vec = np.linalg.eig(np.cov(np.array(self.imgTrainSmpl).transpose())) 
     self.srtd = np.argsort(self.val)[::-1] 
     print self.val 


#asnmnt4=PCAMNIST() 
#asnmnt4.singleStep() 
asnmnt4=PCAMNIST() 
asnmnt4.subMean() 
asnmnt4.getCov() 
asnmnt4.getEigen() 
asnmnt4.sortEV() 
asnmnt4.drawEig() 
#asnmnt4.plotVal() 
""" 
asnmnt4.getSorted() 
asnmnt4.printTopEigenVal() 
""" 

儘管上述代碼運行完全和所有的數組大小的給定的數據集匹配,則生成以下的圖像的特徵向量: Eigen vectors as images

顯然特徵向量沒有意義,因爲它們必須表示數據集的特徵,在這種情況下應該是數字。任何幫助表示讚賞。如果您試圖運行此代碼,則可能需要安裝MNIST軟件包並從鏈接下載數據。

+0

你是否有任何理由用手而不是使用scikit-learn這樣的工具?下面是一個不同數字數據集上的PCA示例:http://scikit-learn.org/stable/tutorial/statistical_inference/putting_together.html – jakevdp

+0

只是爲了學習它艱難的方式。 – PseudoAj

回答

2

您正在繪製特徵向量矩陣的。特徵向量位於矩陣的中,如您在np.linalg.eig documentation中所見。

你應該改變

self.eigVec.append(tmpEigVec.tolist()) 

self.eigVec.append(np.transpose(tmpEigVec).tolist()) 

,我相信如預期它會奏效。

+0

另一位用戶指出了這一點,他刪除了他的解決方案,因爲它以奇怪的方式附加到列表中,形成(1,784,784,1)形狀,其結果爲數組值錯誤。但感謝您指出它,任何備用解決方案表示讚賞。 – PseudoAj

+0

好的 - 可能有更好的解決方案,但我相信問題的根源在於我在這裏提到:特徵向量在列中而不是行。 – jakevdp

1

正如指出的幾個用戶的問題是與特徵向量,使其工作,而不是改變追加邏輯,只需修改繪製函數爲:

def drawEig(self): 
     for vec in self.srtdEigVecArr.T[:10]: 
      self.drawEigV(vec) 

現在,特徵向量意義: enter image description here