k-近邻算法实现手写数字识别系统

2023-05-16

k-近邻算法实现手写数字识别系统

一、实验介绍

1.1 实验内容

本实验将会从电影题材分类的例子入手,详细讲述k-近邻算法的原理。在这之后,我们将会使用该算法实现手写数字识别系统。

1.2 课程来源

本课程源自 图灵教育 的 《机器学习实战》 书籍第2章,感谢 图灵教育 授权实验楼发布。如需系统的学习本书,请购买《机器学习实战》。

为了保证可以在实验楼环境中完成本次实验,我们在原书内容基础上补充了一系列的实验指导,比如实验截图,代码注释,帮助您更好得实战。

如果您对于实验有疑惑或者建议可以随时在讨论区中提问,与同学们一起探讨。

1.3 实验知识点

  • k近邻分类算法
  • 从文本文件中解析和导入数据
  • 使用Matplotlib创建扩散图
  • 归一化数值

1.4 实验环境

  • python 2.7
  • numpy 模块
  • Xfce 终端

1.5 适合人群

本课程属于中等难度级别,适合具有 Python 基础的用户,如果对 numpy 了解能够更好的上手本课程。

1.6 代码获取

你可以通过下面命令将代码下载到实验楼环境中,作为参照对比进行学习。

$ wget http://labfile.oss.aliyuncs.com/courses/777/lab3_0930.zip
$ unzip lab3_0930.zip

二、实验原理

众所周知,电影可以按照题材分类,然而题材本身是如何定义的?由谁来判定某部电影属于哪个题材?也就是说同一题材的电影具有哪些公共特征?这些都是在进行电影分类时必须要考虑的问题。没有哪个电影人会说自己制作的电影和以前的某部电影类似,但我们确实知道每部电影在风格上的确有可能会和同题材的电影相近。那么动作片具有哪些共有特征,使得动作片之间非常类似,而与爱情片存在着明显的差别呢?动作片中也会存在接吻镜头,爱情片中也会存在打斗场景,我们不能单纯依靠是否存在打斗或者亲吻来判断影片的类型。但是爱情片中的亲吻镜头更多,动作片中的打斗场景也更频繁,基于此类场景在某部电影中出现的次数可以用来进行电影分类。本章第一节基于电影中出现的亲吻、打斗出现的次数,使用k近邻算法构造程序,自动划分电影的题材类型。我们首先使用电影分类讲解k近邻算法的基本概念,然后学习如何在其他系统上使用k近邻算法。

本章介绍第一个机器学习算法:k近邻算法,它非常有效而且易于掌握。首先,我们将探讨k近邻算法的基本理论,以及如何使用距离测量的方法分类物品;接着,我们将使用Python从文本文件中导入并解析数据;然后,本书讨论了当存在许多数据来源时,如何避免计算距离时可能碰到的一些常见错误;最后,利用实际的例子讲解如何使用k近邻算法完成手写数字识别系统。

2.1 k-近邻算法概述

简单地说,k近邻算法采用测量不同特征值之间的距离方法进行分类。

k-近邻算法

  • 优点:精度高、对异常值不敏感、无数据输入假定。
  • 缺点:计算复杂度高、空间复杂度高。 适用数据范围:数值型和标称型。

本书讲解的第一个机器学习算法是k-近邻算法(kNN),它的工作原理是:存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。

现在我们回到前面电影分类的例子,使用k近邻算法分类爱情片和动作片。有人曾经统计过很多电影的打斗镜头和接吻镜头,图2-1显示了6部电影的打斗和接吻镜头数。假如有一部未看过的电影,如何确定它是爱情片还是动作片呢?我们可以使用kNN来解决这个问题。

此处输入图片的描述

首先我们需要知道这个未知电影存在多少个打斗镜头和接吻镜头,图2-1中问号位置是该未知电影出现的镜头数图形化展示,具体数字参见表2-1。

表2-1 每部电影的打斗镜头数、接吻镜头数以及电影评估类型

电影名称 打斗镜头 接吻镜头 电影类型
California Man 3 104 爱情片
He’s Not Really into Dudes 2 100 爱情片
Beautiful Woman 1 81 爱情片
Kevin Longblade 101 10 动作片
Robo Slayer 3000 99 5 动作片
Amped II 98 2 动作片
? 18 90 未知

即使不知道未知电影属于哪种类型,我们也可以通过某种方法计算出来。首先计算未知电影与样本集中其他电影的距离,如表2-2所示。此处暂时不要关心如何计算得到这些距离值,使用Python实现电影分类应用时,会提供具体的计算方法。

表2-2 已知电影与未知电影的距离

电影名称 与未知电影的距离
California Man 20.5
He’s Not Really into Dudes 18.7
Beautiful Woman 19.2
Kevin Longblade 115.3
Robo Slayer 3000 117.4
Amped II 118.9

现在我们得到了样本集中所有电影与未知电影的距离,按照距离递增排序,可以找到k个距离最近的电影。假定k=3,则三个最靠近的电影依次是He’s Not Really into DudesBeautiful WomanCalifornia Man。k近邻算法按照距离最近的三部电影的类型,决定未知电影的类型,而这三部电影全是爱情片,因此我们判定未知电影是爱情片。

本章主要讲解如何在实际环境中应用k近邻算法,同时涉及如何使用Python工具和相关的机器学习术语。按照1.5节开发机器学习应用的通用步骤,我们使用Python语言开发k近邻算法的简单应用,以检验算法使用的正确性。

k近邻算法的一般流程

  1. 收集数据:可以使用任何方法。
  2. 准备数据:距离计算所需要的数值,最好是结构化的数据格式。
  3. 分析数据:可以使用任何方法。
  4. 训练算法:此步骤不适用于k近邻算法。
  5. 测试算法:计算错误率。
  6. 使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。

2.2 准备:使用Python导入数据

首先,创建名为kNN.py的Python模块,本章使用的所有代码都在这个文件中。读者可以按照自己的习惯学习代码,既可以按照本书学习的进度,在自己创建的Python文件中编写代码,也可以直接从本书的源代码中复制kNN.py文件。我推荐读者从头开始创建模块,按照学习的进度编写代码。

我们打开 Xfce 终端,创建实验文件夹KNN

cd Code
mkdir KNN
cd KNN
touch kNN.py

然后我们先来安装 NumPy 模块。

sudo pip install numpy

随后我们就可以使用 vim 或者 sublime 对我们的 kNN.py文件进行编辑。在kNN.py文件中增加下面的代码:

    from numpy import *
    import operator

    def createDataSet():
        group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
        labels = ['A','A','B','B']
        return group, labels

在上面的代码中,我们导入了两个模块:第一个是科学计算包NumPy;第二个是运算符模块,k近邻算法执行排序操作时将使用这个模块提供的函数,后面我们将进一步介绍。

然后保存kNN.py文件,确保我们在 kNN.py 文件的路径下(/home/shiyanlou/Code/KNN),在 Xfce 终端内输入ipython,进入Python交互式开发环境。

进入Python开发环境之后,输入下列命令导入上面编辑的程序模块:

    >>> import kNN

上述命令导入kNN模块。为了确保输入相同的数据集,kNN模块中定义了函数createDataSet,在Python命令提示符下输入下列命令:

    >>> group,labels = kNN.createDataSet()

上述命令创建了变量grouplabels,在Python命令提示符下输入下列命令,输入变量的名字以检验是否正确地定义变量:

    >>> group
    array([[ 1. , 1.1],
           [ 1. , 1. ],
           [ 0. , 0. ],
           [ 0. , 0.1]])
    >>> labels
    ['A', 'A', 'B', 'B']

这里有4组数据,每组数据有两个我们已知的属性或者特征值。上面的group矩阵每行包含一个不同的数据,我们可以把它想象为某个日志文件中不同的测量点或者入口。由于人类大脑的限制,我们通常只能可视化处理三维以下的事务。因此为了简单地实现数据可视化,对于每个数据点我们通常只使用两个特征。

向量labels包含了每个数据点的标签信息,labels包含的元素个数等于group矩阵行数。这里我们将数据点(1, 1.1)定义为类A,数据点(0, 0.1)定义为类B。为了说明方便,例子中的数值是任意选择的,并没有给出轴标签,图2-2是带有类标签信息的四个数据点。

此处输入图片的描述

现在我们已经知道Python如何解析数据,如何加载数据,以及kNN算法的工作原理,接下来我们将使用这些方法完成分类任务。

2.3 如何测试分类器

在上文中我们提到使用 kNN 算法能够判断出一个电影是动作片还是爱情片,即我们使用 kNN 算法能够实现一个分类器。我们需要检验分类器给出的答案是否符合我们的预期。读者可能会问:“分类器何种情况下会出错?”或者“答案是否总是正确的?”答案是否定的,分类器并不会得到百分百正确的结果,我们可以使用多种方法检测分类器的正确率。此外分类器的性能也会受到多种因素的影响,如分类器设置和数据集等。不同的算法在不同数据集上的表现可能完全不同,这也是本部分的6章都在讨论分类算法的原因所在。

为了测试分类器的效果,我们可以使用已知答案的数据,当然答案不能告诉分类器,检验分类器给出的结果是否符合预期结果。通过大量的测试数据,我们可以得到分类器的错误率——分类器给出错误结果的次数除以测试执行的总数。错误率是常用的评估方法,主要用于评估分类器在某个数据集上的执行效果。完美分类器的错误率为0,最差分类器的错误率是1.0,在这种情况下,分类器根本就无法找到一个正确答案。读者可以在后面章节看到实际的数据例子。

上一节介绍的例子已经可以正常运转了,但是并没有太大的实际用处。接下来本书将使用手写识别系统的测试程序检测k近邻算法的效果。

三、开发准备

本节我们一步步地构造使用k近邻分类器的手写识别系统。为了简单起见,这里构造的系统只能识别数字0到9,参见图2-6。需要识别的数字已经使用图形处理软件,处理成具有相同的色彩和大小 1:宽高是32像素x32像素的黑白图像。尽管采用文本格式存储图像不能有效地利用内存空间,但是为了方便理解,我们还是将图像转换为文本格式。

1.该数据集合修改自"手写数字数据集的光学识别"一文中的数据集合,该文登载于2010年10月3日的UCI机器学习资料库中

http://archive.ics.uci.edu/ml。作者是土耳其伊斯坦布尔海峡大学计算机工程系的E. Alpaydin与C. Kaynak。


此处输入图片的描述

下面下载实验所需资料:

$ cd /home/shiyanlou
$ wget http://labfile.oss.aliyuncs.com/courses/777/lab3_0930.zip
$ unzip lab3_0930.zip

将测试数据拷贝到我们自己的目录:(KNN是我们在上文中创建的实验目录,如果没有创建的话,请看 2.2 节的指导)

$ cd Code/KNN
$ cp -a /home/shiyanlou/lab3_0930/digits ./

digits 目录下有两个文件夹,分别是:

  • trainingDigits:训练数据,1934个文件,每个数字大约200个文件。
  • testDigits:测试数据,946个文件,每个数字大约100个文件。

每个文件中存储一个手写的数字,文件的命名类似0_7.txt,第一个数字0表示文件中的手写数字是0,后面的7是个序号。

我们使用目录trainingDigits中的数据训练分类器,使用目录testDigits中的数据测试分类器的效果。两组数据没有重叠,你可以检查一下这些文件夹的文件是否符合要求。根据这些数据我们开始实现KNN算法。

我们需要打开一个 Xfce 终端,输入 ipython 进入到交互式模式来边写代码边测试。

四、项目文件结构

此处输入图片的描述

五、实验步骤

5.1 准备数据:将图像转换为测试向量

为了使用前面两个例子的分类器,我们必须将图像格式化处理为一个向量。我们将把一个32x32的二进制图像矩阵转换为1x1024的向量,这样前两节使用的分类器就可以处理数字图像信息了。

我们首先编写一段函数img2vector,将图像转换为向量:该函数创建1x1024的NumPy数组,然后打开给定的文件,循环读出文件的前32行,并将每行的头32个字符值存储在NumPy数组中,最后返回数组。我们在 kNN.py中加入如下代码:

from numpy import *

def img2vector(filename):
    # 创建向量
    returnVect = zeros((1,1024))

    # 打开数据文件,读取每行内容
    fr = open(filename)

    for i in range(32):
        # 读取每一行
        lineStr = fr.readline()

        # 将每行前32字符转成int存入向量
        for j in range(32):
            returnVect[0,32*i+j] = int(lineStr[j])

    return returnVect

在iPython命令行中输入下列命令测试img2vector函数,然后与文本编辑器打开的文件进行比较:(因为 kNN.py 文件经过了更新,需要reload 这个模块)

    >>> reload(kNN)
    >>> testVector = kNN.img2vector('digits/testDigits/0_1.txt')
    >>> testVector[0,0:31]

测试结果如下:

此处输入图片的描述

我们用 vim 和 gedit 打开 Code/KNN/digits/testDigits/0_1.txt

此处输入图片的描述

准备数据部分没有问题了。

5.2 分析数据

k-近邻(k-NN)算法我们在理论学习部分已经有所了解,本节内容将实现这个算法的核心部分:计算“距离”。

当我们有一定的样本数据和这些数据所属的分类后,输入一个测试数据,我们就可以根据算法得出该测试数据属于哪个类别,此处的类别为0-9十个数字,就是十个类别。

算法实现过程:

  1. 计算已知类别数据集中的点与当前点之间的距离;
  2. 按照距离递增次序排序;
  3. 选取与当前点距离最小的k个点;
  4. 确定前k个点所在类别的出现频率;
  5. 返回前k个点出现频率最高的类别作为当前点的预测分类。

算法实现为函数 classify0(),函数的参数包括:

  1. inX:用于分类的输入向量
  2. dataSet:输入的训练样本集
  3. labels:样本数据的类标签向量
  4. k:用于选择最近邻居的数目

我们在 kNN.py 中加入如下代码

import operator

def classify0(inX, dataSet, labels, k):
    # 获取样本数据数量
    dataSetSize = dataSet.shape[0]

    # 矩阵运算,计算测试数据与每个样本数据对应数据项的差值
    diffMat = tile(inX, (dataSetSize,1)) - dataSet

    # sqDistances 上一步骤结果平方和
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)

    # 取平方根,得到距离向量
    distances = sqDistances**0.5

    # 按照距离从低到高排序
    sortedDistIndicies = distances.argsort()     
    classCount={}          

    # 依次取出最近的样本数据
    for i in range(k):
        # 记录该样本数据所属的类别
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1

    # 对类别出现的频次进行排序,从高到低
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)

    # 返回出现频次最高的类别
    return sortedClassCount[0][0]

我们使用欧氏距离公式,计算两个向量点xA和xB之间的距离:

此处输入图片的描述

例如,点(0, 0)与(1, 2)之间的距离计算为:

此处输入图片的描述

如果数据集存在4个特征值,则点(1, 0, 0, 1)与(7, 6, 9, 4)之间的距离计算为:

此处输入图片的描述

计算完所有点之间的距离后,可以对数据按照从小到大的次序排序。然后,确定前k个距离最小元素所在的主要分类,输入k总是正整数;最后,将classCount字典分解为元组列表,然后使用程序第二行导入运算符模块的itemgetter方法,按照第二个元素的次序对元组进行排序。此处的排序为逆序,即按照从最大到最小次序排序,最后返回发生频率最高的元素标签。

为了预测数据所在分类,在Python提示符中输入下列命令:

    >>> reload(kNN)
    >>> group,labels = kNN.createDataSet()
    >>> kNN.classify0([0,0], group, labels, 3)

输出结果应该是B,大家也可以改变输入[0, 0]为其他值,测试程序的运行结果。

到现在为止,我们已经构造了第一个分类器,使用这个分类器可以完成很多分类任务。从这个实例出发,构造使用分类算法将会更加容易。

5.3 测试算法:使用k近邻算法识别手写数字

上节我们已经将数据处理成分类器可以识别的格式,本节我们将这些数据输入到分类器,检测分类器的执行效果。程序清单2-6所示的自包含函数handwritingClassTest()是测试分类器的代码,将其写入kNN.py文件中。在写入这些代码之前,我们必须确保将from os import listdir写入文件的起始部分,这段代码的主要功能是从os模块中导入函数listdir,它可以列出给定目录的文件名。

测试的步骤:

  1. 读取训练数据到向量(手写图片数据),从数据文件名中提取类别标签列表(每个向量对应的真实的数字)
  2. 读取测试数据到向量,从数据文件名中提取类别标签
  3. 执行KNN算法对测试数据进行测试,得到分类结果
  4. 与实际的类别标签进行对比,记录分类错误率
  5. 打印每个数据文件的分类数据及错误率作为最终的结果
from os import listdir

def handwritingClassTest():
    # 样本数据的类标签列表
    hwLabels = []

    # 样本数据文件列表
    trainingFileList = listdir('digits/trainingDigits')
    m = len(trainingFileList)

    # 初始化样本数据矩阵(M*1024)
    trainingMat = zeros((m,1024))

    # 依次读取所有样本数据到数据矩阵
    for i in range(m):
        # 提取文件名中的数字
        fileNameStr = trainingFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        hwLabels.append(classNumStr)

        # 将样本数据存入矩阵
        trainingMat[i,:] = img2vector('digits/trainingDigits/%s' % fileNameStr)

    # 循环读取测试数据
    testFileList = listdir('digits/testDigits')

    # 初始化错误率
    errorCount = 0.0
    mTest = len(testFileList)

    # 循环测试每个测试数据文件
    for i in range(mTest):
        # 提取文件名中的数字
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])

        # 提取数据向量
        vectorUnderTest = img2vector('digits/testDigits/%s' % fileNameStr)

        # 对数据文件进行分类
        classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)

        # 打印KNN算法分类结果和真实的分类
        print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr)

        # 判断KNN算法结果是否准确
        if (classifierResult != classNumStr): errorCount += 1.0

    # 打印错误率
    print "\nthe total number of errors is: %d" % errorCount
    print "\nthe total error rate is: %f" % (errorCount/float(mTest))

在程序清单2-6中,将trainingDigits目录中的文件内容存储在列表中,然后可以得到目录中有多少文件,并将其存储在变量m中。接着,代码创建一个m行1024列的训练矩阵,该矩阵的每行数据存储一个图像。我们可以从文件名中解析出分类数字。该目录下的文件按照规则命名,如文件9_45.txt的分类是9,它是数字9的第45个实例。然后我们可以将类代码存储在hwLabels向量中,使用前面讨论的img2vector函数载入图像。在下一步中,我们对testDigits目录中的文件执行相似的操作,不同之处是我们并不将这个目录下的文件载入矩阵中,而是使用classify0()函数测试该目录下的每个文件。

在Python命令提示符中输入kNN.handwritingClassTest(),测试该函数的输出结果。依赖于机器速度,加载数据集可能需要花费很长时间,然后函数开始依次测试每个文件,输出结果如下所示: (记得要 reload(kNN) )

    >>> reload(kNN)
    >>> kNN.handwritingClassTest()
    the classifier came back with: 0, the real answer is: 0 
    the classifier came back with: 0, the real answer is: 0
    .
    .
    the classifier came back with: 7, the real answer is: 7 
    the classifier came back with: 7, the real answer is: 7 
    the classifier came back with: 8, the real answer is: 8 
    the classifier came back with: 8, the real answer is: 8 
    the classifier came back with: 8, the real answer is: 8 
    the classifier came back with: 6, the real answer is: 8
    .
    .


    the total number of errors is: 12

    the total error rate is: 0.012685

k-近邻算法识别手写数字数据集,错误率为1.2%。改变变量k的值、修改函数handwritingClassTest随机选取训练样本、改变训练样本的数目,都会对k近邻算法的错误率产生影响,感兴趣的话可以改变这些变量值,观察错误率的变化。

最后我们在kNN.py文件的末尾加上

handwritingClassTest()

就可以直接在命令行中来直接运行我们的手写字符判别系统。

kNN效果

六、实验总结

k-近邻算法是分类数据最简单有效的算法。k-近邻算法是基于实例的学习,使用算法时我们必须有接近实际数据的训练样本数据。k-近邻算法必须保存全部数据集,如果训练数据集很大,必须使用大量的存储空间。此外,由于必须对数据集中的每个数据计算距离值实际使用是可能非常耗时。是否存在一种算法减少存储空间和计算时间的开销呢?k决策树就是k近邻算法的优化版,可以节省大量的计算开销。

七、扩展阅读

本课程源自 图灵教育 的 《机器学习实战》 第2章,再次感谢 图灵教育 授权实验楼发布。

如果学完本课程,对书籍其他内容感兴趣欢迎点击以下链接购买书籍:

  • 立即购买《机器学习实战》
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

k-近邻算法实现手写数字识别系统 的相关文章

  • Git基础教程(三)

    Git分支 在git中使用分支非常简单 xff0c 只需要使用Git branch命令即可 xff1a git branch test 新建test分支 此时使用git branch查看一下分支 xff1a 此时的确多了一个分支 xff0c
  • Git基础教程(四)

    工作做到一半需要临时切换到别的任务 1 先commit当前的进度 简单的做法先保存当前的修改 然后切换到有问题的分级 xff0c 先完成别的功能 xff0c 然后切换回原来做到一半的develop分支 xff0c 执行reset命令 xff
  • jupyter notebook matplotlib绘制动态图并显示在notebook中

    有些时候matplotlib 的绘图没法显示在notebook中 xff0c 或者显示不了 这与backend有关 首先启动你的notebook xff0c 输入 pylab 查看你的matplotlib后端 xff0c 我的输出为 xff
  • 主机连接wifi,如何设置虚拟机上网方式

    主机是windows系统 xff08 win7 xff0c win10 xff09 xff0c 如果使用wifi上网 xff0c 虚拟机如何设置 xff1f xff1f 首先打开主机网络 xff08 如下所示 xff09 xff1a 1 点
  • VS2015断点调试方法

    备注 xff1a 部分图片 xff08 打马赛克的 xff09 转自百度 xff0c 侵删 xff01 果真被和谐了 xff0c 大家还是看这个网页吧 xff1a https jingyan baidu com album e75057f2
  • FreeRTOS 源代码的编程标准与命名约定

    一 编程标准 xff08 Coding Standard xff09 FreeRTOS 源代码遵守 MISRA Motor Industry Software Reliability Association 规范 与 MISRA 标准有出入
  • 特征匹配中OpenCV Dmatch类的用法解析以及非常详细的ORB特征提取与匹配解析

    首先说明一点 xff0c 在SLAM中进行特征提取和匹配时 xff0c 需要注意使用的OpenCV版本 xff0c 在使用OpenCV2 x版本时 xff0c 可以创建特征对象如下所示 xff08 省略了参数表 xff09 xff1a OR
  • 单目视觉里程计的尺度问题的疑问?

    SLAM是个坑 经过一段时间对SLAM的了解 xff0c 原来是我理解有错误 xff0c 得到的尺度已经是统一的 xff0c 只是不知道它的真实尺度是多少 贴一个不错的视觉里程计简介的链接 xff1a https blog csdn net
  • 使用ORB_SLAM2的方式进行特征检测和提取

    比较opencv默认的方式和ORB SLAM2中对opencv进行重写的方式 xff0c 两个方法对图像特征提取结果的对比 为方便比较 xff0c 写在同一个文件中 主函数如下 xff1a include lt iostream gt in
  • 什么是归一化的平面坐标

    所谓的归一化的成像平面 xff0c 就是将三维空间点的坐标都除以Z 所有空间点坐标都转到了相机前单位距离处 xff0c 这个平面就叫归一化的平面 xff0c 之后再乘以焦距 f f f xff0c 让归一化平面回到成像平面 以一张别的博主做
  • 无人机编程实战第1讲——无人机简介

    目录 前言 一 飞控是什么 xff1f 二 扫盲行动 xff01 xff01 xff01 1 微控制器 2 传感器 3 处理 xff1f 4 无人机飞行姿态 总结 前言 随着开源无人机飞行控制器的不断发展 xff0c 越来越多优秀的代码与算
  • 阿里云Serverless kubernetes服务购买体验

    阿里云Serverless kubernetes服务购买体验 Serverless kubernetes是什么优点缺点体验步骤价格ECI的价格 xff1a ECS的价格 阿里云Serverless Kubernetes支持列表总结 Serv
  • python修改xml文件内容,不废话,拿来即用

    XML 被设计用来传输和存储数据 HTML 被设计用来显示数据 XML 指可扩展标记语言 xff08 eXtensible Markup Language xff09 可扩展标记语言 xff08 英语 xff1a Extensible Ma
  • mysql如何删除数据表,被关联的数据表如何删除呢

    删除数据表的时候 xff0c 表的定义和表中所有的数据均会被删除 因此 xff0c 在进行删除操作前 xff0c 最好对表中的数据做一个备份 xff0c 以免造成无法挽回的后果 mysql删除数据表分为两种情况 xff1b mysql删除没
  • mysql8.0新特性-自增变量的持久化

    在mysql8 0之前 xff0c 自增主键AUTO INCREMENT的值如果大于max primay key 43 1 xff0c 在mysql重启后 xff0c 会重置AUTO INCREMENT 61 max primay key
  • 双系统重装Ubuntu20.04及系统基本配置

    文章目录 前言Ubuntu20 04换源安装chrome浏览器安装OneNote安装Wechat QQ Dingtalk参考 前言 笔者从2019年9月份去长沙智能驾驶研究院开始接触ubuntu18 04 在2020年4月份做本科毕业设计的
  • 视觉 SLAM 十四讲 —— 第十三讲 建图

    视觉 SLAM 十四讲 第十三讲 建图 在前端和后端中 xff0c 我们重点关注同时估计相机运动轨迹与特征点空间位置的问题 然而 xff0c 在实际使用 SLAM 时 xff0c 除了对相机本体进行定位之外 xff0c 还存在许多其他的需求
  • mysql中数据表的基本操作很难嘛,由这个实验来带你从头走一遍

    mysql表中数据表的各种操作 xff0c 创建表 添加各类约束 查看表结构 修改和删除表 这次带你捋清楚 xff0c 从头再走一遍 实验目的 创建 修改和删除表 xff0c 掌握数据表的基本操作 实验结果 创建数据库company xff

随机推荐

  • nginx自动摘除和恢复后端服务,进行自动检测

    主动地健康检查 xff0c nginx定时主动地去ping后端的服务列表 xff0c 当发现某服务出现异常时 xff0c 把该服务从健康列表中移除 xff0c 当发现某服务恢复时 xff0c 又能够将该服务加回健康列表中 nginx自带的u
  • nginx中配置root和alias的区别

    在nginx中 xff0c root和alias都可以代理静态资源 xff0c 那么他们两个有什么区别呢 xff1f 在什么情况下使用什么呢 初识 xff1a root和alias都可以在定义在location模块中 xff0c 都是用来请
  • 史上最全的mysql数据类型汇总-(上)

    mysql支持多种数据类型 xff0c 主要有数值类型 日期 时间类型以及字符串类型 整数类型 数值型数据类型主要用来存储数字 xff0c mysql提供了多种数值数据类型 xff0c 不同的数据类型提供不同的取值范围 xff0c 可以存储
  • 史上最全的mysql数据类型汇总(下)

    接着上文继续来梳理 xff0c 上文我们写到了日期与时间类型中的time类型 xff0c 然后我们接着来写日期与时间类型中的date类型 date类型 date类型用在仅需要日期值时 xff0c 没有时间部分 xff0c 在存储时需要3字节
  • mysql中的字段如何选择合适的数据类型呢?

    前面两篇我们介绍了很多种数据类型 xff0c 那么有没有看花眼呢 xff0c 我们在mysql中创建数据表的时候 xff0c 到底应该选择哪一种数据类型呢 xff1f 这次我们就来简单的梳理一下子把 准则 我们不论要如何创建数据表 xff0
  • mysql中的四大运算符种类汇总20多项,用了三天三夜来整理的,还不赶快收藏

    运算符连接表达式中的各个操作数 xff0c 他的作用是用来指明对数据表中的操作数所进行的运算 运用运算法有什么好处呢 xff1f 运用运算符可以更加灵活的使用表中的数据 xff0c 我们可以通过使用运算符来解决我们的很多问题 xff0c 大
  • mysql函数汇总之数学函数

    什么是mysql函数 xff1f 61 61 61 61 61 61 61 61 61 61 61 61 61 61 函数表示对输入参数值返回一个具有特定关系的值 xff0c mysql提供了大量丰富的函数 xff0c 在进行数据库管理以及
  • mysql函数汇总之字符串函数

    字符串函数主要用来处理数据库中的字符串数据 mysql中的字符串函数有计算字符串长度函数 字符串合并函数 字符串替换函数 字符串比较函数 查找指定字符串位置函数等 计算字符串字符数的函数 CHAR LENGTH str 函数计算字符串str
  • mysql函数汇总之日期和时间函数

    日期和时间函数主要用来处理日期和时间值 xff0c 一般的日期函数除了使用date类型的参数外 xff0c 也可以使用datetime或者timestamp类型的参数 xff0c 但会忽略这些值的时间部分 获取当前日期的函数 curdate
  • [ Ubuntu 使用技巧 ] 在当前工作目录打开 Terminal

    1 General Purposes Why I wrote this 在 Ubuntu 系统开发最舒服的一点就是可以开心地使用 Terminal 这是个好东西 xff0c 尤其当你熟悉大部分的常用命令之后 xff0c 对日常的代码工作还有
  • mysql函数汇总之条件判断函数

    条件判断函数也被称为控制流程函数 xff0c 根据满足的不同条件 xff0c 执行响应的流程 mysql中进行条件判断的函数有if ifunll和case等 IF expr v1 v2 函数 IF expr v1 v2 xff1a 如果表达
  • mysql函数汇总之系统信息函数

    mysql的系统信息有数据库的版本号 当前用户名和连接数 系统字符集 最后一个自动生成的ID值等 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
  • mysql数据库中的数据如何加密呢?mysql8.0自带新特性

    61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
  • mysql还有哪些自带的函数呢?别到处找了,看这个就够了。

    格式化函数FPRMAT x n format x n 将数字x进行格式化 xff0c 并以四舍五入的方式保留小数点后n位 xff0c 结果以字符串的形式返回 如果n为0 xff0c 则返回结果函数不含小数部分 mysql gt select
  • mysql中还有窗口函数?这是什么东西?

    什么是窗口函数 xff1f 在mysql8 0的版本中 xff0c 新增了一个窗口函数 xff0c 用他可以实现很多新的查询方式 窗口函数类似于sun count 那样的集合函数 xff0c 但它并不会将多行查询结果合并为一行 xff0c
  • 记一次mysql查询慢的优化历程

    有一个项目 xff0c 代称cc xff0c 用了我们公司的产品 xff0c 单表数据量在200万左右 在做业务操作的时候 xff0c 点击一下按钮 xff0c 需要等待2 3分钟 及其难以忍受 xff0c 特此让我们修改 PS xff1a
  • configure: error: No curses library functions found

    centos上编译程序报错如下 xff1a configure error No curses library functions found 这个错误是因为缺少 curses 库导致的 在CentOS 7中 xff0c 可以通过以下命令安
  • STM32使用内部RC振荡器作为系统时钟开发项目--内晶振启动模板工程

    STM32使用内部RC振荡器时 xff0c OSC32 IN xff0c OSC32 OUT接法 xff1a 1 xff09 对于100脚或144脚的产品 xff0c OSC IN应接地 xff0c OSC OUT应悬空 2 xff09 对
  • 项目笔记(6):阿里云的Iot Studio和web可视化

    项目笔记 xff08 4 xff09 阿里云物联网的自定义主题和物联网模型
  • k-近邻算法实现手写数字识别系统

    k 近邻算法实现手写数字识别系统 一 实验介绍 1 1 实验内容 本实验将会从电影题材分类的例子入手 xff0c 详细讲述k 近邻算法的原理 在这之后 xff0c 我们将会使用该算法实现手写数字识别系统 1 2 课程来源 本课程源自 图灵教