SVM与KNN掌纹识别算法对比

SVM与KNN掌纹识别算法对比

一. 题目

本次研究课题为:SVM与KNN掌纹识别算法对比。

二. 数据库介绍

本次研究所使用的数据集为1006张掌纹的ROI图像库,每张图片的大小为128128,数据集的所有图片都已经提取出了感兴趣区域。因数据集涉及保密,故不公开。

三. 任务选择

本次研究任务选择为分别使用SVM与KNN进行掌纹识别。

四. 评价指标

本次研究选用识别率来作为评价指标,识别率的公式为:

在这里插入图片描述

五. 编程语言

本次研究采用python语言进行算法的对比研究,其中用到的库有python-opencv,numpy,sklearn等等。

六. 算法原理

本次所使用的算法有俩个,一个是SVM,一个是KNN,这;这俩个算法在sklearn库里面已经全部实现好了,在需要调用里面的函数即可。下面简单介绍以下俩个算法的算法原理**。**

(1) SVM算法原理

SVM(支持向量机)算法原理可以概括为以下几点:

  1. SVM是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机;SVM还包括核技巧,这使它成为实质上的非线性分类器。
  2. SVM的学习策略就是求解使间隔最大化的最优化问题,可形式化为一个求解凸二次规划的问题,也等价于正则化的合页损失函数的最小化问题。
  3. SVM的的学习算法就是求解凸二次规划的最优化算法。

(2) KNN算法原理

KNN(K-Nearest Neighbor)算法原理是通过测量不同特征值之间的距离进行分。对于一个新输入的样本,KNN算法会在训练数据集中找到与该样本最邻近的K个样本,这K个样本的大多数属于哪个类别,新输入的样本就被归类到哪个类别。

七. 程序框架

本次研究是用jupyter notebook来进行实验,Jupyter Notebook是一个非常强大和灵活的工具,特别适合进行数据分析和处理工作。本次研究的主要流程如下:

加载数据—à特征提取—à数据处理—à模型训练—à算法对比

八. 实验过程和结果分析

(一)实验过程

在进行掌纹识别前,我们需要对数据集进行简单的处理。

1.加载数据,代码如下:

#加载数据
def load_dataset():
   X = []  # 特征
   y = []  # 标签
   
   for i in range(100):
       for j in range(1,7):
           path="E:\\palmbases\\"+"p_"+str(i)+"_"+str(j)+".bmp"
           img = cv2.imread(path)
           # 提取Gabor特征
           #features = extract_gabor_features(img)
           gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
           features = gray_img.flatten()
           # 从文件名中提取类别标签
           category = i

           X.append(features)
           y.append(category)
   return X,y


2.划分数据集,这里先以4:2的比例进行分层抽样,代码如下:

#分层抽样划分数据集,每6张前4张做训练后俩张做测试
def data_split(x,y):
   X_train=[]
   X_test=[]
   y_train=[]
   y_test=[]
   j=1#标记变量
   for i in x:
       if j<=4:
           X_train.append(i)
           j+=1
       else:
           X_test.append(i)
           j+=1
           if j==7:
               j=1
   j=1
   for i in y:
       if j<=4:
           y_train.append(i)
           j+=1
       else:
           y_test.append(i)
           j+=1
           if j==7:
               j=1
   return np.array(X_train),np.array(X_test),np.array(y_train),np.array(y_test)

3.不做处理,直接跑模型测试,这里选择svm模型,代码如下:

# 加载数据集
X, y = load_dataset()
#划分数据集
X_train, X_test, y_train, y_test=data_split(X,y)
# 初始化SVM分类器
clf = svm.SVC(kernel='rbf')

# 训练SVM模型
clf.fit(X_train, y_train)

# 在测试集上进行预测
y_pred = clf.predict(X_test)

# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"Test Accuracy: {accuracy}")

上面代码需要导入的包如下,也是下面代码所需要的:

import os
import cv2
import numpy as np
from sklearn import svm
from sklearn.decomposition import PCA
from sklearn.metrics import accuracy_score

最终svm跑出的准确率为0.96.

4.数据处理与训练

接下来我们试试对数据进行处理并训练看看结果。

(1)对数据进行降维,并利用循环遍历得出最佳维度,先观察以下数据的信息,代码如下:

X_train.shape

结果显示:(400, 16384)

降维函数如下:

def pca_transform(X_train,X_test, n_components):  
   # 使用PCA降维  
   pca = PCA(n_components=n_components)  
   train = pca.fit_transform(X_train)
   test=pca.transform(X_test)
   return train,test 

根据上面结果看到维度高达16384维,下面是挑选最佳维度代码:

#获取最佳维度和准确率,利用svm计算
def pca_best(X_train,X_test):
   acc=[]#各维度准确率集合
   nlist=[]#各维度集合
   a=10
   acc1=0
   for n in range(10,300,10):#先到300维看看,如果波动比较大再加
               # 对训练数据和测试数据进行PCA降维  
       X_train_pca, X_test_pca = pca_transform(X_train,X_test,n)  
       # 初始化SVM分类器
       clf = svm.SVC(kernel='rbf')
       # 训练SVM模型
       clf.fit(X_train_pca, y_train)
       # 在测试集上进行预测
       y_pred = clf.predict(X_test_pca)
       # 计算准确率
       accuracy = accuracy_score(y_test, y_pred)
       if accuracy==1:
           return n,accuracy
       acc.append(accuracy)
       nlist.append(n)
       #打印各维度对应的准确率,看看波动情况,如果准确率越来越平稳,则不用测试300维以后的维度,否之则不然
       print("维度为:",n)
       print("准确率为:",accuracy)
       print("\n")
   #获取最佳维度和准确率
   for i in range(len(nlist)):
       if acc1<acc[i]:
           acc1=acc[i]
           a=nlist[i]
   return a,acc1

运行代码如下:

#前面已经划分好数据集
n,acc=pca_best(X_train,X_test)
print("最佳维度为:",n)
print("准确率为:",acc)

运行结果为:

最佳维度为: 70
准确率为: 0.985

(2)利用gabor滤波对数据进行处理

gabor滤波代码如下:

#建立gabor滤波器
def gabor_filter(img, frequency, theta):
   kernel = cv2.getGaborKernel((21, 21), 5.0, theta, 10.0, 1.0, 0, ktype=cv2.CV_32F)
   filtered_img = cv2.filter2D(img, cv2.CV_8UC3, kernel)
   return filtered_img

#图像滤波
def extract_gabor_features(image):
   #因为加载数据时已经进行过灰度转换了,所以下面一行注释掉
   #gray_img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
   gray_img=image
   filtered_img = gabor_filter(gray_img, frequency=0.6, theta=1.0)
   flattened_features = filtered_img.flatten()
   return flattened_features

计算gabor后的准确率,代码如下:

def gabor_image(x):#将加载的数据集进行滤波
   x_gabor=[]
   for i in x:
       features = extract_gabor_features(i)
       x_gabor.append(features)
   return x_gabor
#滤波
x_gabor=gabor_image(X)
#划分数据集
X_train, X_test, y_train, y_test=data_split(x_gabor,y)

# 初始化SVM分类器
clf = svm.SVC(kernel='rbf')

# 训练SVM模型
clf.fit(X_train, y_train)
# 在测试集上进行预测
y_pred = clf.predict(X_test)

# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"Test Accuracy: {accuracy}")

结果显示为:

Test Accuracy: 0.94

可以发现准确率相比没有滤波时下降了,我们参考下面论文:

D. Zhang, W. K. Kong, J. You, M. Wong. Online palmprint identification[J]. IEEETransactions on Pattern Analysis and Machine Intelligence,2003,25(9):1041-1050

知道了一些原因,并且可以尝试使用2D Gabor相位编码。这里暂时不做处理,我还不会。

下面使用其他算法来进行模型测试。

5.使用knn算法来进行分类识别

代码如下:

from sklearn.neighbors import KNeighborsClassifier  
from sklearn.metrics import accuracy_score 
#加载数据代码(上面有)
#划分数据代码(上面有)
# 使用KNN算法进行训练和预测  
knn = KNeighborsClassifier(n_neighbors=1)  # 设置K值为1,可根据需求进行调整  
knn.fit(X_train, y_train)  
predictions = knn.predict(X_test)  
# 计算准确率  
accuracy = accuracy_score(y_test, predictions)  
print("Accuracy:", accuracy)

加载数据和划分数据集的代码用之前的。

结果为:

Accuracy: 0.97

我们修改k值看看,这里因为训练集每个类最多只有4张图片,所以k最多设置为4,我们要用下面代码遍历看看结果:

def knn_test():
   for n in range(1,5):
       # 使用KNN算法进行训练和预测  
       knn = KNeighborsClassifier(n_neighbors=n) 
       knn.fit(X_train, y_train)  
       predictions = knn.predict(X_test)  
       # 计算准确率  
       accuracy = accuracy_score(y_test, predictions)
       print("K值为:",n)
       print("Accuracy:", accuracy)
       print("\n")
knn_test()

结果为:

K值为: 1
Accuracy: 0.97


K值为: 2
Accuracy: 0.83


K值为: 3
Accuracy: 0.765


K值为: 4
Accuracy: 0.76

结果表示k为1时结果最高。

接下来我们对数据进行降维后再利用knn分类,并利用循环得出最佳维度(与之前降维代码类似):

#获取最佳维度和准确率,利用knn计算
def pca_best(X_train,X_test):
   acc=[]#各维度准确率集合
   nlist=[]#各维度集合
   a=10
   acc1=0
   for n in range(10,300,10):#先到300维看看,如果波动比较大再加
               # 对训练数据和测试数据进行PCA降维  
       X_train_pca, X_test_pca = pca_transform(X_train,X_test,n)  
       # 使用KNN算法进行训练和预测  
       knn = KNeighborsClassifier(n_neighbors=1)  # 设置K值为1,可根据需求进行调整  
       knn.fit(X_train_pca, y_train)  
       predictions = knn.predict(X_test_pca)  
       # 计算准确率  
       accuracy = accuracy_score(y_test, predictions)  
       #print("Accuracy:", accuracy)
       if accuracy==1:
           return n,accuracy
       acc.append(accuracy)
       nlist.append(n)
       #打印各维度对应的准确率,看看波动情况,如果准确率越来越平稳,则不用测试300维以后的维度,否之则不然
       print("维度为:",n)
       print("准确率为:",accuracy)
       print("\n")
   #获取最佳维度和准确率
   for i in range(len(nlist)):
       if acc1<acc[i]:
           acc1=acc[i]
           a=nlist[i]
   return a,acc1
#前面已经划分好数据集
n,acc=pca_best(X_train,X_test)
print("最佳维度为:",n)
print("准确率为:",acc)

结果为:

最佳维度为: 20
准确率为: 0.975

下面我们对数据进行gabor滤波后再进行knn分类看看结果:

#建立gabor滤波器
def gabor_filter(img, frequency, theta):
   kernel = cv2.getGaborKernel((21, 21), 5.0, theta, 10.0, 1.0, 0, ktype=cv2.CV_32F)
   filtered_img = cv2.filter2D(img, cv2.CV_8UC3, kernel)
   return filtered_img

#图像滤波
def extract_gabor_features(image):
   #因为加载数据时已经进行过灰度转换了,所以下面一行注释掉
   #gray_img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
   gray_img=image
   filtered_img = gabor_filter(gray_img, frequency=0.6, theta=1.0)
   flattened_features = filtered_img.flatten()
   return flattened_features


def gabor_image(x):#将加载的数据集进行滤波
   x_gabor=[]
   for i in x:
       features = extract_gabor_features(i)
       x_gabor.append(features)
   return x_gabor
#滤波
x_gabor=gabor_image(X)
#划分数据集
X_train, X_test, y_train, y_test=data_split(x_gabor,y)
knn = KNeighborsClassifier(n_neighbors=1)  # 设置K值为1,可根据需求进行调整  
knn.fit(X_train, y_train)  
predictions = knn.predict(X_test)  
# 计算准确率  
accuracy = accuracy_score(y_test, predictions) 
print("准确率为:",accuracy)

结果为:

准确率为: 0.955

(二)结果分析

通过以上实验过程可以发现,在不对数据进行如何处理的情况下,KNN的识别率要高于SVM,当对数据进行降维后,本研究选择俩个算法的最佳维度来进行识别度比较,SVM的最佳维数为70,识别率为0.985,KNN的最佳维数为20,识别率为0.975,对数据不做进行gabor滤波后,俩者识别率都有所下降,但SVM下降的百分点更多。本次研究还对数据集划分做了测试,发现训练集与测试集的比例越高,识别率就越高。

一. 结论和心得体会

(一)本次实验主要有以下结论:

(1) 在训练集与测试集的划分方面,本研究按3:3,4:2,5:1的比例分别利用SVM来进行测试,发现训练集与测试集的比例越高,识别率就越高。

(2) 本研究对SVM进行了一定程度的调参,本研究使用SVM的径向基函数与线性核函数分别进行模型训练,经过对比测试发现,在不对数据做如何处理的情况下,使用径向基函数来进行模型训练的识别率要高一点。

(3) 本研究对KNN算法进行了不同K值情况下,识别率的对比研究,发现在K值为1时识别率是最高的,这与我们的一般认知K值越高,识别率越高有所差别。

(4) 本研究在对数据进行降维时,根据算法的不同,分别进行了最佳维数的选择,本研究,从10个维度开始,按照步长为10来进行循环计算得出不同维度下的识别率,发现在利用SVM进行模型训练时,最佳维度为70,识别率为0.985,在利用KNN进行模型训练时,最佳维度为20,识别率为0.975.

(5) 本研究发现在对数据进行gabor滤波后,俩个算法的识别率都有所下降,但SVM算法的识别率下降更多。

(二)心得体会

本次研究主要是SVM与KNN掌纹识别算法对比研究,主要从原理,参数调整,降维,滤波,数据集划分的方面进行研究对比,俩种算法的识别率都很可观,在不对数据做如何处理的情况下,俩个算法的识别率都高达0.95以上,这里也有一部分原因是数据集过少,在不对数据进行降维的情况下,KNN的识别率都要高于SVM,但降维后,最佳的识别率反而是SVM更高。本次研究各方面都还有所不足,还有许多方面有待研究考证。

  • 30
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值