我正在尝试对MNIST数据集进行主成分分析(PCA),作为这个过程的一部分,我需要生成特征向量并可视化最重要的特征。以下是我的算法:
- 加载图像
- 减去均值
- 生成协方差矩阵
- 推导特征向量和特征值
这个算法运行起来相当简单;我的第一个任务是将前10个特征向量以图像形式可视化。以下是我目前的代码:
__author__ = "Ajay Krishna Teja Kavuri"import numpy as np import randomfrom mnist import MNISTimport matplotlib.pylab as pltclass 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()"""
尽管上述代码运行得很好,且所有数组大小都与给定数据集匹配,但它生成的特征向量图像如下:
显然,这些特征向量毫无意义,因为它们应该代表数据集的特征,在这种情况下应该是数字。任何帮助都将不胜感激。如果您尝试运行此代码,可能需要安装MNIST包并从链接中下载数据。
回答:
您正在绘制特征向量矩阵的行。特征向量位于矩阵的列中,正如您在np.linalg.eig
文档中所见。
您应该将
self.eigVec.append(tmpEigVec.tolist())
更改为
self.eigVec.append(np.transpose(tmpEigVec).tolist())
我相信这样会按预期工作。