1.什么是PCA呢
PCA(Principal Component Analysis)是一种常用的降维技术和数据预处理方法。它能够将高维数据映射到低维空间,同时保留原始数据中最重要的信息。
PCA的主要思想是通过线性变换将数据从原始的特征空间转换到新的特征空间,使得数据在新的特征空间中具有最大的方差。这个转换过程涉及到特征值分解或奇异值分解等数学方法。
下面是PCA的基本步骤:
数据标准化:对原始数据进行标准化处理,使得每个特征的均值为0,方差为1。这一步可以避免某些特征因为量纲不同而对PCA结果产生较大影响。
计算协方差矩阵:计算标准化后的数据的协方差矩阵。协方差矩阵描述了各个特征之间的相关性。
特征值分解:对协方差矩阵进行特征值分解或奇异值分解,得到特征值和对应的特征向量。
选择主成分:根据特征值的大小,选择最大的k个特征值对应的特征向量作为主成分,其中k是指定的目标维度。
构建转换矩阵:将选择的主成分组成一个转换矩阵。
数据转换:将原始数据乘以转换矩阵,得到降维后的数据。
PCA的主要应用包括降维、数据压缩、特征提取和可视化等。通过降低数据的维度,PCA可以减少数据的冗余信息,提高计算效率,并且有助于发现数据中的模式和结构。
2.图片在计算机中以什么样的形式存在?
通常图片在计算机中以矩阵的形式存在,下面给大家看个例子
终端的矩阵就是右边这种图片在计算机中存在的形式,因为我是以灰度图读取的只有单通道
下面给大家看以RGB的图像输入计算机中 ,会发现矩阵和刚刚不一样。
3.开始实现人脸识别
1.准备数据集
我这里准备了测试和验证集
两个文件夹都包含10个人的人脸信息
测试集中有5张,验证集则是2张
2.导入图片
因为有10个人 , 每个人 5张训练集所以range 是 1~11 和 1~6,all_data就是存放所有的训练集信息的集合矩阵
def load_data(file):
all_data = []
for i in range(1, 11):
temp_file = os.path.join(file, str(i))
for j in range(1, 6):
list = []
mark = ".tif"
new_path = os.path.join(temp_file, str(j) + mark)
temp = cv2.imread(new_path, 0)
for x in range(temp.shape[0]):
# 遍历图片每一行的每一列
for y in range(temp.shape[1]):
# 将每一处的灰度值添加至列表
list.append(temp[x, y])
all_data.append(list)
# print(all_data.__sizeof__())
return all_data
3.对训练样本开始PCA处理
各行代码什么意思我都注释在后面了,至于为什么这样做 大概就是通过 求出协方差矩阵的特征值和特征向量来达到降维的效果(作者数学不行哈哈哈哈)
file = r"Face\myuse\train"
all_data = load_data(file)
train = np.mat(all_data)
# cv2.imshow("!",train)
# cv2.waitKey()
meanFaceMat = np.mean(train, axis=0)y
normTrainFaceMat = train - meanFaceMat # 计算减去平均值后的矩阵
covariance = np.cov(normTrainFaceMat)
# 求得协方差矩阵的特征值和特征向量
eigenvalue, featurevector = np.linalg.eig(covariance)
# print(eigenvalue,featurevector)
sorted_Index = np.argsort(eigenvalue)
# print(len(sorted_Index))
# print(featurevector)
topk_evecs = featurevector[:, sorted_Index[:-10 - 1:-1]] # -10是控制维度的
eigenface = np.dot(np.transpose(normTrainFaceMat), topk_evecs) # 获得训练样本的特征脸空间
eigen_train_sample = np.dot(normTrainFaceMat, eigenface)
print(eigen_train_sample.shape)
4.导入测试样本和对测试样本降维
这里的欧氏距离其实就是KNN,PCA只是个降维算法,并不是分类算法,需要对目标进行分类我们依旧需要用到其他的分类算法。(不知道KNN是什么的可以翻一下之前写的博客也有详细的介绍)
file_test = r"Face\myuse\test"
test_data = load_data_test(file_test)
testFaceMat = np.mat(test_data)
# 这里减的meanFaceMat 和计算normTrainFaceMat 的meanFaceMat是同一个变量
normTestFaceMat = testFaceMat - meanFaceMat
# 和计算 eigen_train_sample相同,用规格化矩阵去点乘 eigenface即可。
eigen_test_sample = np.dot(normTestFaceMat, eigenface)
# 以 eigen_train_sample[0]与eigen_test_sample的欧式距离赋值 minDistance
minDistance = np.linalg.norm(eigen_train_sample[0] - eigen_test_sample)
5.得出结果
num = 1 print(eigen_train_sample.shape[0]) print(eigen_train_sample.shape) for i in range(1, eigen_train_sample.shape[0]): distance = np.linalg.norm(eigen_train_sample[i] - eigen_test_sample) #print(distance) if minDistance > distance: print(i) minDistance = distance num = i // 5 + 1 print(num)
准确率我认为还行吧,不知道是不是因为数据量太小了
4.总结
PCA算法很大程度减轻了计算机的负担,否则对于一个50x50像素的图片就要 用 50维度 的空间下进行KNN 这无疑是对算力的很大消耗,不过PCA也存在着一点问题,在降维操作的时候很容易把我们需要的特征点也过滤掉