山东大学数据结构课程设计 —— KNN分类器应用于手写数字识别、数据结构KD树的实现以及其K近邻搜索

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

  1. 考虑众多机器学习的模型的训练需要一个强大的计算环境,所以本次项目将算法模型的实现数据的处理样本数据集的训练均放在了服务端。

  2. 将项目部署到Linux系统之后,方便向其他人展示功能,其他人也可以实时参与系统的测试使用。

  3. 本次数据结构课设,不适合采用CS(Customer-Server)架构,因为项目本身不大,将项目部署到云服务器之后,用户使用浏览器访问即可。

开发平台、技术栈


开发语言:Java、JavaScript

其中算法设计、数据结构实现使用Java, 数据可视化、图形化编程使用JavaScript;

后端:SpringBoot、SpringMVC;

前端:vue、canvas、echarts;

服务器: 云服务器实例、Ubuntu镜像、服务器Nginx;

IDE:IntelliJ IDEA、WebStorm

算法设计

====================================================================

KNN(K nearest neighbors)


这部分内容,放在了这篇博客详细介绍了。

点击传送门

交叉验证法优化超参数K的取值


交叉验证(Cross-validation)主要用于建模应用中,例如PCR、PLS回归建模中。在给定的建模样本中,拿出大部分样本进行建模型,留小部分样本用刚建立的模型进行预报,并求这小部分样本的预报误差,记录它们的平方加和。

交叉验证法的思想

交叉验证(Cross Validation),有的时候也称作循环估计(Rotation Estimation),是一种统计学上将数据样本切割成较小子集的实用方法,该理论是由Seymour Geisser提出的。

交叉验证的基本思想, 把在某种意义下将原始数据(dataset)进行分组,一部分做为训练集(train set),另一部分做为验证集(validation set or test set),

首先用训练集对分类器进行训练, 再利用验证集来测试训练得到的模型(model),以此来做为评价分类器的性能指标。

在给定的建模样本中,拿出大部分样本进行建模型,留小部分样本用刚建立的模型进行预报,并求这小部分样本的预报误差,记录它们的平方的和。这个过程一直进行,直到所有的样本都被预报了一次而且仅被预报一次。把每个样本的预报误差平方求和,称为PRESS(predicted Error Sum of Squares)

K-fold cross-validation

K-fold cross-validation

K折交叉验证,初始采样分割成K个子样本,一个单独的子样本被保留作为验证模型的数据,其他K-1个样本用来训练。交叉验证重复K次,每个子样本验证一次,平均K次的结果或者使用其它结合方式,最终得到一个单一估测。这个方法的优势在于,同时重复运用随机产生的子样本进行训练和验证,每次的结果验证一次,10折交叉验证是最常用的。

如下图:

在这里插入图片描述

K折验证的一种特殊形式 —— 留一验证正如名称所建议, 留一验证(LOOCV)意指只使用原本样本中的一项来当做验证资料, 而剩余的则留下来当做训练资料。

这个步骤一直持续到每个样本都被当做一次验证资料。 事实上,这等同于和K-fold 交叉验证是一样的,其中K为原本样本个数。

在某些情况下是存在有效率的演算法,如使用kernel regression 和Tikhonov regularization。

K折验证法选取超参数 k

为了选取最优的超参数k,在构造KNN分类器时,我们可以使用上文提及的10折交叉验证法,

这个算法流程如下图。

在这里插入图片描述

值得一提的是,k的迭代步长如何确定。

在上面的分析中:

K的选取一般来源于经验,一般选取一个较小的大于1的奇数,一般在 ( 1 , n ) (1,\sqrt n) (1,n ​)。

  1. n较小时,n取 ( 1 , 10 ) (1,10) (1,10)中的奇数;
  1. n较大时,n取 ( 1 , n / 2 ) (1,\sqrt n/2) (1,n ​/2)中的奇数;

并且考虑到,k的值对预测结果的敏感程度,所以在k较小的时候,步数尽可能小;在 k取值较大的时候,步数可以适量增大。

假定样本容量为 n n n, n n n的量级大概在 1 0 6 10^6 106自由,

所以 k k k不超过 n / 2 \sqrt n/2 n ​/2,也就是500。

所以,k的步长可以这样设计,

从3开始,为了保证k的取值是偶数,

  1. 1~10内,步长为2;

  2. 10~30内,步长为4;

  3. 30~60,步长为6;

  4. 60~100,步长为8;

  5. 100~500, 步长为40;

如此,既减少了模型训练、测试样本的时间,又在一定程度上表现了随着k的变化,对分类正确率的影响

图像特征的数字化


本次实现的KNN分类器的最终目标是实现一个建议的手写字体识别器。

因此,对图像数字特征的提取工作就变得尤为关键。

下面介绍几个常见的 图像特征提取算法

暴力算法

将图像的每一个像素点都作为特征向量的一个维度,很明显。

这样做的缺点是非常明显的,甚至可以说毫无优点。

  • 特征维度提取不精确

有一些并属于图像的像素也被作为特征维度,相当于成了噪声点 —— 也 就是说并没有很好的体现图像的拓扑学关系。

  • 维度太高

向量的维度太高,会带来一系列问题。内存占用太多,计算量迅速增大,并且对于高维向量的检索KD树表现的很差(几乎接近暴力的线性扫描的复杂度)。

以下内容均来自这篇文章

SIFT

SIFT:Scale-Invariant Feature Taransform,尺度不变特征变换

  • 尺度空间的极值检测:搜索所有尺度空间上的图像,通过高斯微分函数来识别潜在的对尺度和旋转鲁棒性较强的点。

  • 特征点定位:在每个候选位置上,通过一个拟合精细模型(尺度空间DoG函数进行曲线拟合)来确定位置尺度,关键点的选取依据他们的稳定程度。

特征方向赋值:基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向,后续的所有操作都是对于关键点的方向、尺度和位置进行变换,从而提供这些特征的不变性。

  • 特征点描述:在每个特征点周围的领域内,在选定的尺度上测量图像的局部梯度,计算块内梯度直方图,生成具有独特性的向量。

HOG

HOG:Histogram of Oriented Gradient,方向梯度直方图

  • 颜色空间归一化:为了减少光照因素的影响, 首先需要将整个图像归一化。因为颜色信息作用不大,通常先转化为灰度图。

  • 梯度计算:计算图像横坐标和纵坐标方向的梯度,并据此计算每个像素位置的梯度+ 方向值;求导操作不仅能捕获轮廓,还能进一步弱化光照的影响。

  • 梯度方向直方图:将图像分成若干个cell,对cell内每个像素用梯度方向在直方图中进行加权投影(映射到固定的角度范围),就可以得到这个cell的梯度直方图。

将每几个cell组成一个block(例如3*3个cell/block),一个block内所有cell的特征descriptor串联起来便得到该block的HOG特征descriptor。

组成特征:将图像image内的所有block的HOG特征descriptor串联起来就可以得到该image(你要检测的目标)的HOG特征descriptor。

LBP

LBP:Local Binary Pattern,局部二值模式

原始的LBP算子定义在像素3_3的邻域内,以邻域中心像素为阈值,相邻的8个像素的灰度值与邻域中心的像素值进行比较,若周围像素大于中心像素值,则该像素点的位置被标记为1,否则为0。这样,3_3邻域内的8个点经过比较可产生8位二进制数,将这8位二进制数依次排列形成一个二进制数字,这个二进制数字就是中心像素的LBP值,LBP值共有28种可能,因此LBP值有256种。中心像素的LBP值反映了该像素周围区域的纹理信息。

值得一提的是,即使暴力法有诸多不好,但是很多机器学习的教材上仍然将它作为特征提取的一种方法,原因是图像的特征解析已经和机器学习的内容关系不大了,

所以对初学者使用暴力法即可。

而本次任务是实现KNN算法,并且用KD树进行优化。

数据结构设计

======================================================================

这部分内容,放在了这篇博客详细介绍了。

传送门

应用程序设计

======================================================================

功能模块


下面介绍在此次课程设计中根据功能解耦拆分出来的功能模块。

如下。

画图模块

画图模块,使用JavaScript 和 canvas 标签完成。

完成的功能很简单,按住鼠标左键的同时移动鼠标,然后开始作图。

下方有两个按钮,清空按钮和识别按钮。

在这里插入图片描述

解析图形模块

这部分已经在上文的

图像特征的数字化

详细介绍过了,这里略去不谈。

样本数据加载模块

因为本次识别使用到了OpenCV官方给的数据集,而OpenCV官给的手写数字的数据集是用IDX文件格式的存储的。

而这样的文件格式虽然最高效的存储了图片信息,但是对于java来解析它,却绝非易事,所以样本数据加载模块的功能就是解析idx文件,

即可以生成可视化的图片,也生成以矩阵或者向量形式呈现出来的图片。

在处理IDX文件之前,必须对它的存储有一定了解。

有关IDX文件格式的信息: IDX文件格式是各种数值类型的向量和多维矩阵的简单格式. 基本格式是:

magic number size in dimension 0 size in dimension 1 size in

dimension 2 … size in dimension N data

幻数是一个整数(MSB优先).前2个字节始终为0.

第三个字节编码数据的类型:

0x08: unsigned byte 0x09: signed byte 0x0B: short (2 bytes) 0x0C:

int (4 bytes) 0x0D: float (4 bytes) 0x0E: double (8 bytes)

第4个字节编码向量/矩阵的维数:1表示向量,2表示矩阵….

每个维度的大小为4字节整数(MSB优先,高端,与大多数非英特尔处理器一样).

数据存储在C数组中,即最后一维中的索引变化最快.

在这里插入图片描述

idx文件解析完之后加载之后,可以看到官方给的手写字体的图片。

(图片大小为28*28)

在这里插入图片描述

浮点算法:

G r a y = R ∗ 0.3 + G ∗ 0.59 + B ∗ 0.11 Gray=R*0.3+G*0.59+B*0.11 Gray=R∗0.3+G∗0.59+B∗0.11

依次提取出每个像素的点的RGB值之后,根据灰度公式

G r a y = R ∗ 0.3 + G ∗ 0.59 + B ∗ 0.11 Gray=R*0.3+G*0.59+B*0.11 Gray=R∗0.3+G∗0.59+B∗0.11

提取出图片的矩阵呈现形式。由于矩阵太大,无法全部显示出来。

这里将其缩放乘8*8的图片并以灰度矩阵的形式展示出来。

分类器模块

  • 训练模型的构建

将样本数据集标准化,然后

  • 超参数k的选取

这部分内容在上面以及详细介绍过,此处略去。

测试模块

控制变量法研究不同因素的对分类器效率的影响。

这个模块会在下面详细介绍,这里就略去不谈了。

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

测试模块

控制变量法研究不同因素的对分类器效率的影响。

这个模块会在下面详细介绍,这里就略去不谈了。

[外链图片转存中…(img-xpNO4xog-1715458368501)]
[外链图片转存中…(img-IjIzM51i-1715458368501)]
[外链图片转存中…(img-NDAFJYsj-1715458368501)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值