3

我正在尝试使用 python 进行主成分分析(PCA)。这是我的代码:

import os
from PIL import Image
import numpy as np
import glob
from matplotlib.mlab import PCA

#Step1: put database images into a 3D array
filenames = glob.glob('C:\\Users\\Karim\\Downloads\\att_faces\\New folder/*.pgm')
filenames.sort()
img = [Image.open(fn).convert('L') for fn in filenames]
images = np.dstack([np.array(im) for im in img])    

# Step2: create 2D flattened version of 3D input array
d1,d2,d3 = images.shape
b = np.zeros([d1,d2*d3])
for i in range(len(images)):
  b[i] = images[i].flatten()

#Step 3: PCA
results = PCA(b)
results.Wt

但我收到一个错误RuntimeError: we assume data in a is organized with numrows>numcols

我试着用b = np.zeros([d1,d2*d3])b = np.zeros([d2*d3, d1])得到了ValueError: could not broadcast input array from shape (2760) into shape (112)

谁能帮我?

4

1 回答 1

2

如果您更改为,b = np.zeros([d2*d3, d1])您还应该在之后更改循环,否则您尝试将一个d1维度数组放入d2*d3一个。

你应该摆脱这样做的第二个错误

您可以简单地转置b

# Step2: create 2D flattened version of 3D input array
d1,d2,d3 = images.shape
b = np.empty([d1,d2*d3])  #if you know that you are filling the whole array it's faster that using np.zeros or np.ones
for i, im in enumerate(images): 
    b[i,:] = im.flatten()

#Step 3: PCA
results = PCA(b.T)

我还用我认为更好的版本替换了您的 for 循环:在您的实现中,您首先找到 的维度images,在其上创建一个整数列表循环,然后重新访问images. enumerate返回带有一对(索引,值)的迭代器。优点是它只返回您需要的元素,然后您不必images直接在循环中访问。

可能您也不需要创建images,但我不知道PIL,所以我无法帮助您。在这种情况下,您可以简单地使用类似

d1,d2,d3 = len(img), img[0].shape

编辑

如果你愿意,你也可以在阅读文件时将文件的内容转换为 numpy。

对于记录,这是numpy.asarray.

于 2013-04-09T07:49:00.037 回答