实验目的:
对图片进行PCA或LDA降维后,利用KNN对训练图片进行分类,并利用模型计算测试图片最可能类别,并计算准确率。
实验原理:
子空间学习:
子空间学习是一种机器学习方法,它通过在给定的数据集中找到一个最优的子空间来提高模型的预测准确性,这个最优的子空间是通过在数据集的特征空间中找到主要的方向来确定的。这种技术基于特征值分解,它可以将原始数据集的特征空间中的每一维度进行重新排序,选择具有最高方差的几个维度来构建子空间。
K最邻近分类算法:
KNN是一种基于实例的学习算法,它的基本思想是:如果一个样本在特征空间中的k个最相似的样本中的大多数属于某一个类别,则该样本也属于这个类别。KNN算法中,所选择的邻居都是已知类别样本。
实验设计:
在读取训练图片后,使用PCA或LDA进行降维,之后对所得数据使用KNN进行分类,并对测试图片进行类似操作,统计正确率。
运行环境:Python 3.10.6-64bit, numpy 1.22.4, sklearn 1.1.1,opencv 3.4.18
KNN+LDA:
import numpy as np
import cv2
import os
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from sklearn.neighbors import KNeighborsClassifier as KNN
from sklearn.metrics import accuracy_score
# 训练数据目录
train_dir = './train'
# 测试数据目录
test_dir = './test'
# 维度
n_com = 30
# KNN邻居数
n_neigh = 3
# 读取训练数据
train_data = []
train_labels = []
for label in os.listdir(train_dir):
label_dir = os.path.join(train_dir, label)
for image_file in os.listdir(label_dir):
image = cv2.imread(os.path.join(label_dir, image_file))
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
train_data.append(image.flatten())
train_labels.append(label)
# 读取测试数据
test_data = []
test_labels = []
for label in os.listdir(test_dir):
label_dir = os.path.join(test_dir, label)
for image_file in os.listdir(label_dir):
image = cv2.imread(os.path.join(label_dir, image_file))
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
test_data.append(image.flatten())
test_labels.append(label)
# 使用LDA进行降维
lda = LDA(n_components=n_com)
train_data = lda.fit_transform(train_data, train_labels)
test_data = lda.transform(test_data)
# 使用KNN进行分类
knn = KNN(n_neighbors=n_neigh)
knn.fit(train_data, train_labels)
pred_labels = knn.predict(test_data)
# 计算正确率
accuracy = accuracy_score(test_labels, pred_labels)
print('Accuracy:', accuracy)
KNN+PCA:
import numpy as np
import cv2
import os
from sklearn.decomposition import PCA
from sklearn.neighbors import KNeighborsClassifier as KNN
# 训练数据目录
train_dir = './train'
# 测试数据目录
test_dir = './test'
# 维度
n_com = 100
# KNN邻居数
n_neigh = 3
def read_images(path): # 从指定目录读取图片
images = []
labels = []
for i in os.listdir(path):
for j in os.listdir(path+'/'+i):
image = cv2.imread(path + '/' + i + '/' + j, 0)
images.append(image.flatten())
labels.append(i)
return np.array(images), np.array(labels)
# 读取训练图片
train_images, train_labels = read_images(train_dir)
# 使用PCA进行降维
pca = PCA(n_components=n_com)
pca.fit(train_images)
train_images = pca.transform(train_images)
# 使用KNN进行分类
knn = KNN(n_neighbors=n_neigh)
knn.fit(train_images, train_labels)
# 读取测试图片
test_images, test_labels = read_images(test_dir)
test_images = pca.transform(test_images)
# 计算分类准确率
accuracy = knn.score(test_images, test_labels)
print('Accuracy:', accuracy)