Python - ошибка анализа главных компонентов (PCA)


Я пытаюсь сделать анализ главных компонентов (PCA) с помощью python. Вот мой код:

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)

Кто-нибудь может мне помочь?
1 3

1 ответ:

Если вы изменяете на 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

EDIT

Вы, если хотите, можете также конвертировать содержимое файлов в numpy при чтении их.

Для записей, это numpy.asarray.