gpt4 book ai didi

python - 使用 python 的主成分分析 (PCA)

转载 作者:太空宇宙 更新时间:2023-11-03 11:07:08 26 4
gpt4 key购买 nike

我正在尝试使用 python 通过主成分分析 (PCA) 实现人脸识别。我正在按照本教程中的步骤操作:http://onionesquereality.wordpress.com/2009/02/11/face-recognition-using-eigenfaces-and-distance-classifiers-a-tutorial/

这是我的代码:

import os
from PIL import Image
import numpy as np
import glob
import numpy.linalg as linalg


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


#Step 2: find the mean image and the mean-shifted input images
mean_image = images.mean(axis=0)
shifted_images = images - mean_image


#Step 3: Covariance
c = np.cov(shifted_images)


#Step 4: Sorted eigenvalues and eigenvectors
eigenvalues,eigenvectors = linalg.eig(c)
idx = np.argsort(-eigenvalues)
eigenvalues = eigenvalues[idx]
eigenvectors = eigenvectors[:, idx]


#Step 5: Only keep the top 'num_eigenfaces' eigenvectors
num_components = 20
eigenvalues = eigenvalues[0:num_components].copy()
eigenvectors = eigenvectors[:, 0:num_components].copy()


#Step 6: Finding weights
w = eigenvectors.T * np.asmatrix(shifted_images)


#Step 7: Input image
input_image = Image.open('C:\\Users\\Karim\\Downloads\\att_faces\\1.pgm').convert('L').resize((90, 90))
input_image = np.asarray(input_image)


#Step 8: get the normalized image, covariance, eigenvalues and eigenvectors for input image
shifted_in = input_image - mean_image
cov = np.cov(shifted_in)
eigenvalues_in, eigenvectors_in = linalg.eig(cov)

我收到一个错误: Traceback (most recent call last):
File "C:/Users/Karim/Desktop/Bachelor 2/New folder/new3.py", line 47, in <module>
shifted_in = input_image - mean_image
ValueError: operands could not be broadcast together with shapes (90,90) (8100)

我试图删除 .flatten()来自第 1 步,但这在计算特征值和特征向量时产生了另一个错误: Traceback (most recent call last):
File "C:/Users/Karim/Desktop/Bachelor 2/New folder/new3.py", line 25, in <module>
eigenvalues,eigenvectors = linalg.eig(c)
File "C:\Python27\lib\site-packages\numpy\linalg\linalg.py", line 1016, in eig
_assertRank2(a)
File "C:\Python27\lib\site-packages\numpy\linalg\linalg.py", line 155, in _assertRank2
'two-dimensional' % len(a.shape))
LinAlgError: 4-dimensional array given. Array must be two-dimensional

我还尝试添加 .flatten()到第 7 步,但在计算输入图像的特征值和特征向量时也会产生另一个错误: Traceback (most recent call last):
File "C:/Users/Karim/Desktop/Bachelor 2/New folder/new3.py", line 49, in <module>
eigenvalues_in, eigenvectors_in = linalg.eig(cov)
File "C:\Python27\lib\site-packages\numpy\linalg\linalg.py", line 1016, in eig
_assertRank2(a)
File "C:\Python27\lib\site-packages\numpy\linalg\linalg.py", line 155, in _assertRank2
'two-dimensional' % len(a.shape))
LinAlgError: 0-dimensional array given. Array must be two-dimensional

谁能帮忙??

最佳答案

我终于看了你提供的教程,作者似乎建议你把图像展平。您现在不妨继续使用扁平化数组,因为它更适合该教程。

我相信修复它的地方是在步骤 7 中,您在该处具有输入图像的协方差。然而,输入图像的协方差矩阵将是一个标量,你无法找到它的特征值和特征向量。您可以将其投影为大小为 (1,1) 的二维矩阵,但是您的特征值将只是协方差,特征向量将为 [[1]].

也就是说,例如,

In [563]: input_image = np.random.rand(90,90).flatten()

In [564]: c = np.cov(input_image)

In [565]: c
Out[565]: array(0.08280644230318886)

In [566]: c.shape
Out[566]: ()

In [567]: c.ndim
Out[567]: 0

所以我们将 c reshape 为 2d:

In [568]: cmat = c.reshape(1,1) # equivalent to cmat = c[...,np.newaxis,np.newaxis]

In [569]: cmat
Out[569]: array([[ 0.08280644]])

In [570]: cmat.shape
Out[570]: (1, 1)

In [571]: cmat.ndim
Out[571]: 2

现在我们可以找到特征值:

In [572]: ceigval, ceigvec = linalg.eig(cmat)

但是对于单元素矩阵,只有一个特征值和一个特征向量,特征值是矩阵的元素,特征向量是长度为1的单位向量/恒等式,所以我不确定这个这真的是您想为人脸识别做的事情。

In [573]: ceigval
Out[573]: array([ 0.08280644])

In [574]: ceigvec
Out[574]: array([[ 1.]])

In [576]: np.isclose(c, ceigval)
Out[576]: True

顺便说一句,这就是为什么我们必须制作 c 2d:

In [577]: linalg.eig(c)
---------------------------------------------------------------------------
LinAlgError: 0-dimensional array given. Array must be two-dimensional

另一方面,您可以获得未展平的 input_image 的协方差,然后您将拥有 N 个特征值和 N 个特征向量:

In [582]: input_image = np.random.rand(90,90)

In [583]: c = np.cov(input_image)

In [584]: c.shape
Out[584]: (90, 90)

In [585]: ceigval, ceigvec = linalg.eig(c)

In [586]: ceigval.shape
Out[586]: (90,)

In [587]: ceigvec.shape
Out[587]: (90, 90)

关于python - 使用 python 的主成分分析 (PCA),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16018657/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com