我正在尝试使用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)
任何人都可以帮助我吗?
答案 0 :(得分: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
的维度,创建一个整数循环列表,然后重新访问{{ 1}}。 images
返回带有一对(索引,值)的迭代器。优点是它只返回您需要的元素,然后您不必直接在循环中访问enumerate
。
也许您也不需要创建images
,但我不知道images
,所以我无法帮助您。在这种情况下,您可以使用类似
PIL
修改强>
如果你愿意,你也可以在阅读时将文件内容转换为numpy。
对于记录,这是numpy.asarray
。