• 机器学习(十八)应用实例:照片OCR



    Log

    2022.08.12开始学习最后一章!
    2022.08.13继续学习
    2022.08.14继续学习
    2022.08.15继续学习
    2022.08.16继续学习
    2022.08.18继续学习。结束十八章!


    • 本章将会介绍一种机器学习的应用实例,或者说在机器学习应用历史中一种叫做照片OCR(Photo OCR) 的技术。我想介绍它的原因有 3 3 3 个:
      • 首先,我想向你展示一个复杂的机器学习系统是如何被组合起来的;
      • 第二,我想介绍一下机器学习流水线的有关概念,以及如何分配资源来对下一步计划作出决定,这既可以适用于自己开发一个复杂的机器学习应用,也可以适用于一个开发团队共同开发机器学习应用;
      • 最后,我想通过介绍照片 O C R \rm OCR OCR 问题来告诉你机器学习中许多有用的想法和概念,其中之一就是如何将机器学习应用到计算机视觉问题中,而另一个就是人工数据合成的概念。

    一、问题描述与流水线(Problem description and pipeline)

    • 照片 O C R \rm OCR OCR 全称为照片光学字符识别(Photo Optical Character Recognition),随着数码摄影的发展,以及智能手机拍照功能的成熟,我们现在会有很多各个地方拍摄的照片,一个吸引了众多开发者们的问题就是如何让计算机更好地理解这些照片的环境。照片OCR问题注重的问题是如何让计算机读出图片中的文字信息。

    1. 问题描述(The Photo OCR problem)

    • 假设现在有这样一张照片:
      在这里插入图片描述

    • 我们希望计算机能够读出照片中的文字,这样一来,如果我们之后想找到这张照片,我们就只需要输入照片中的文字: L U L A    B ′ s    A N T I Q U E    M A L L \rm LULA\ \ B's\ \ ANTIQUE\ \ MALL LULA  Bs  ANTIQUE  MALL,计算机就能自动找出这张图片,这样我们就不用花大量时间把相册翻个底朝天,从千百张照片中把它找出来了。

    • O C R \rm OCR OCR 所要做的事情有如下几个步骤:

      • 首先,给定某张图片,它将图片扫描一遍,然后找出照片中的文字信息;
        在这里插入图片描述

      • 在成功找出文字以后,它将重点关注这些文字区域,并对区域中的文字进行识别,当它正确读出这些文字以后,它会将这些文字内容显示并记录下来。
        在这里插入图片描述

    • 虽然现在 O C R \rm OCR OCR (或者说光学文字识别)对于扫描文档来说已经是一个比较简单的问题了,但对于数码照片来说,现在还是一个很难的机器学习问题,如果能够成功实现它,不仅可以帮助计算机更好地理解图像中的内容,还可以开发出一些比如能够帮助盲人的应用,举个例子,可以为盲人提供一种相机,该相机可以看出来它们前面有什么东西,然后直接告诉他们,他们前面有个路牌,现在也有研究人员将照片 O C R \rm OCR OCR 技术应用到汽车导航系统中,比如说我们的车能读出街上的路牌,帮我们导航到目的地。

    2. 流水线(Photo OCR pipeline

    1.   T e x t    d e t e c t i o n 2.   C h a r a c t e r    s e g m e n t a t i o n 3.   C h a r a c t e r    c l a s s i f i c a t i o n 1. Text  detection2. Character  segmentation3. Character  classification 1. Text  detection2. Character  segmentation3. Character  classification

    • 为了实现照片 O C R \rm OCR OCR ,这是我们能做的:

      • 首先我们要扫描图像,并找出有文字的图像区域,比如这就是一个 O C R \rm OCR OCR 系统可能识别到的一个文字区域(下图);
        在这里插入图片描述

      • 然后它会得到这个矩形区域,然后进行文字分离,通过这个文本框它会识别出 A N T I Q U E    M A L L \rm ANTIQUE\ \ MALL ANTIQUE  MALL,然后将其分割成一个个独立的字符区域;
        在这里插入图片描述

      • 分割好这些独立的字符后,我们用一个分类器,它会对这些可见的字符进行识别,然后识别出第一个字母是 A \rm A A,第二个字母是 N \rm N N,第三字母是 T \rm T T 等等,做完这些之后,可能我们就能计算出这句话是 L U L A    B ′ s    A N T I Q U E    M A L L \rm LULA\ \ B's\ \ ANTIQUE\ \ MALL LULA  Bs  ANTIQUE  MALL,然后图片中其它有文字的地方也是一样的方法。
        在这里插入图片描述

    • 实际上有一些照片 O C R \rm OCR OCR 系统会做一些更复杂的事情,比如最后会进行拼写校正,举个例子,假如我们的字符分割和分类系统识告诉我们它识别到的字符是 C 1 e a n i n g C\red 1eaning C1eaning,然后一些拼写修正系统就会告诉我们这应该是单词 C l e a n i n g C\red leaning Cleaning,我们的字符分类算法把字母 l l l 识别成了数字 1 1 1,不过由于本节暂时不考虑这些东西,所以忽略掉最后一步,我们只关注系统的前三步:文字检测(Text detection)文字分割(Character segmentation)以及字符分类(Character classification)

    Image
    Text detection
    Character
    segmentation
    Character
    recognition
    • 那么像这样的一个系统,我们把它称之为机器学习流水线(machine learning pipeline),具体来说,这幅图所表示的就是 O C R \rm OCR OCR 的流水线(上流程图),首先我们有一副图像,然后把它传给文字检测系统,识别出文字区域以后,然后我们将文本区域中的单个字符分割出来,最后我们对这些单个字母进行识别。
    • 在很多复杂的机器学习系统中,这种流水线形式非常普遍,在流水线中会有多个不同的模块,比如在本例中有三个模块,我们有文字检查、字符分割以及字母识别模块,每一个模块都是一个机器学习组件,可能有时候它不是一个机器学习组件,但是它有一系列的连接在一起的模块,并在一系列数据上执行,最终得出我们希望的结果,在照片 O C R \rm OCR OCR 的例子中就是最终识别到的图片中的文字信息。
    • 如果我们要设计一个机器学习系统,我们要作出的最重要的决定之一就是我们要怎样设计这个流水线的各个模块,或者说在这个照片 O C R \rm OCR OCR 问题中,我们应该如何将这个问题分成一系列不同的模块,我们需要设计整个流水线以及我们的流水线中的每一个模块,这通常会影响到算法最终的表现。
    • 如果我们有一个工程师团队在进行同样类似的任务,我们可以让不同的人来完成不同的模块,我们大概可以估计出文字检测这个模块需要大概 1 1 1 5 5 5 个人,字符分割部分需要 1 1 1 5 5 5 个人,字母识别部分还需要 1 1 1 5 5 5 个人。因此使用这样的流水线可以让我们很自然地把工作分配给不同的组员去完成。当然,所以这些工作也可以只由一个人来完成,如果我们想的话。
    • 在复杂的机器学习系统中,流水线的概念已经渗透到各种应用中,我们刚才看到的只是照片 O C R \rm OCR OCR 流水线的具体运作过程。接下来的几节我们将介绍更多关于流水线的信息,并且我们还会继续使用这个例子来介绍其它很重要的机器学习的概念。

    二、滑动窗口(Sliding windows)

    • 上一节我们讨论了 O C R \rm OCR OCR 流水线及其工作原理,在 O C R \rm OCR OCR 中我们取一张图,然后把这张图传递到一些列的机器学习组件来读取出图片上的文字。本节我们将会介绍一些关于流水线中每个独立的组件的工作原理,本节我们主要要讲一种叫做滑动窗口分类器(Sliding windows classifier) 的东西。

    1. 行人检测(Pedestrian detection)

    ①文字识别与行人检测(Text detection & Pedestrian detection)

    • 图像 O C R \rm OCR OCR 流水线的第一步是文字识别,比如我们看这样一张图(下图左), 然后尝试找到图片上文字出现的区域:
      在这里插入图片描述

    • 文字识别在计算机视觉中是一个比较难的问题,因为根据我们找到的这些文字区域,它们对应的矩形具有不同的长宽比例,所以为了讲述如何在图片中检测它们,我们首先从一个简单点的例子开始,即行人检测,之后我们再将做行人检测的思路应用到文字识别中去。

    • 在行人检测中,我们有一张类似这样的图片(上图右),我们要找出图片中的各个行人,我们会依次找到六个行人,这个问题与文字识别相比,简单的地方在于我们要识别的东西具有相似的长宽比,仅用一个具有固定长宽比(fixed aspect ratio) 的矩形就可以了(长宽比的意思就是矩形长度和宽度之间的比例),这些行人们的长宽比都是差不多的。对于文字来说,不同位置的文字具有不同的比例;对于行人检测,尽管不同行人距离摄像头的距离可能不同,所以这些矩形的高度根据不同行人的位置也会不一样,但比例还是不变的。

    ②应用监督学习的行人检测(Supervised learning for pedestrian detection)

    • 为了建立一个行人检测系统,我们需要这么做,例如我们决定要把比例的标准定为 82 × 36 82×36 82×36,当然我们也可以选择其他的相近的数字,比如 80 × 40 80×40 80×40,或者 82 × 36 82×36 82×36 也可以,我们将要做的是从数据集中收集一些正样本和负样本,这里是一些 82 × 36 82×36 82×36 的图片样本,其中包含了整个行人,还有一些不包含行人的图片:
      在这里插入图片描述

    • 上图我们展示了 12 12 12 y = 1 y=1 y=1 的正样本,还有 12 12 12 y = 0 y=0 y=0 的负样本。在一个更典型的行人检测应用中我们可能会有 1000 1000 1000 个到 10000 10000 10000 个数目的样本,甚至更多,如果我们能得到更大的数据集的话,然后我们可以在我们的网络中训练或者使用其它学习算法,向其中输入一个 82 × 36 82×36 82×36 的图块,来对 y y y 进行分类,来划分每个图块是否包含一个行人,于是这给了我们一个应用监督学习的方法来对一个图块进行处理判断其是否包含有行人。

    ③滑动窗口检测(Sliding window detection)

    • 现在假设我们得到一张新图,比如这样的一张测试集图片(下图),我们尝试在图片中找到一个行人,首先在图片中选取一个矩形块,像这样的(下图左上绿色方块)一个 82 × 36 82×36 82×36 的图块:
      在这里插入图片描述

    • 我们把这个图块传递给我们的分类器,来检测图块中是否有行人,这时我们的分类器应该会返回 y = 0 y=0 y=0,因为上面没有行人,接下来将绿色的矩形稍稍移动一点,再把这个图块传递给我们的分类器判断是否是行人,在这之后,我们再次将窗口向右滑动一些,再传给分类器进行分类判断。这个绿色矩形每次移动的距离是一个参数,一般称之为步长(the step size of the parameter),有时也被称为滑动参数(the slide parameter),如果我们一次移动一个像素,那么步长就为 1 1 1,一般这个步长表现最好,但是计算成本较高。一般来说,把步长设为 4 4 4 像素或 8 8 8 像素或更大的数是比较常见的。这就意味着矩形每次都会移动一些。继续这个过程,继续向右移动矩形,每次都移动一点,每次移动都使用分类器对图块进行分类,一直这样下去,直到在图中各个位置都过一遍(下方动图),首先从第一行开始,再移动到图像的下一行,就这样遍历图中所有不同的位置并且通过分类器进行分类。
      在这里插入图片描述

    • 它是一个很小的矩形,且它只会检测某个特定大小的行人,接下来我们要做的是使用更大的图块,进行和使用小图块时相同的操作,我们所说的用更大的图块实际上意思是:当我们选取完这样的图块之后我们要做的是把这个图块调整到 82 × 36 82×36 82×36 的大小,所以把这个大的图块调整为一个更小的图片,然后把调整后的图片传递给我们的分类器中,然后判断是否有行人。
      在这里插入图片描述

    • 最后我们还可以使用更大尺寸的窗口来把图像过一遍。经过这一系列过程后,算法便能够检测出图中各个地方是否出现行人(上图)。

    • 这就是我们如何训练一个监督学习分类器,然后使用一个滑动窗口分类器或者说滑动窗口检测器来找出图中的所有行人。

    2. 文本检测(Text detection)

    ①文字检测(Text detection)

    • 让我们回到文本检测的例子,谈谈 O C R \rm OCR OCR 流水线中的这个阶段,也就是如何找出图中的文字区域,与行人检测类似,拿出一系列包含正样本和负样本的训练集,其中正样本代表的是对应的区域有文字出现,之前我们做的是行人检测,但是现在我们要尝试做文本检测,所以正样本代表的是含有文字的图块,负样本表示的是没有文字的图块。
      在这里插入图片描述

    • 训练完之后,我们可以将其应用在一个新的测试集中的图片上,这是我们刚才作为例子所用的图片(下图1),现在我们在这个图片上来运行算法,我们将使用一个固定比例的滑动窗口来进行讲解。
      在这里插入图片描述

    • 这里我们将只使用一个固定大小的矩形,假如说,我们在这些图块上使用这样的(上图1左上绿色方块)滑动窗口分类器,这样的话,我们就会得到这样的结果(上图2、3),其中白色区域表示检测系统发现了文本,黑色区域表示分类器没有发现文字。同时我们发现,有很多白色的区域,这表示分类器在这些位置上发现了文本,我们在图2中所做的操作是用白色表示分类器认为有文字的地方,而这些深浅不同的灰色对应的是分类器认为该处有文字的概率,所以这些灰色阴影意味着分类器认为它可能找到了文本,但是概率不高,而这些亮白色的区域表示分类器输出了一个很高的概率,也就是该处有文字的概率。

    • 但到这里还没有结束,我们真正想做的是在所有文字周围绘制矩形,然后更进一步将这些分类器的输出应用到一种叫做放大算子(expansion operator) 的东西上,它所做的是取这里的图,它把每个白色方块或者说是白色区域,然后扩大这些白色区域,我们可以用数学方式来实现它,如果我们观察图3,构造这个图像的方法,就是对图2的每个像素判断其一定范围内是否存在白色的像素,如果某个像素,它周围 5 5 5 10 10 10 个像素的范围内,如果存在其它的白色像素,那么就在上图中把整个范围内的像素都变成白色,这样做的效果是,把上上图中的每个白色区块都扩大一些,都增长一些,通过检查像素附近是否存在白色像素,然后把这一范围内都变成白色。

    • 在完成之后,现在我们看看图3的关联部分,也就是白色区域,然后在其周围绘制边框。如果观察所有白色区域,我们想用一个简单的方法来排除那些比例很奇怪的矩形,因为我们知道文本周围的框宽度应该远大于高度,所以如果我们忽略瘦高的矩形,类似这些(上图3蓝色标注),我们丢弃这些太高太窄的矩形,我们在那些长宽比例正常的文字区域周围画上矩形,即文字区域周围的这些框框(上图3红色方框),对应商场的招牌 L U L A    B ′ s    A N T I Q U E    M A L L \rm LULA\ \ B's\ \ ANTIQUE\ \ MALL LULA  Bs  ANTIQUE  MALL L U L A    B ′ s \rm LULA\ \ B's LULA  Bs 标志以及 O p e n \rm Open Open 的标志,这个例子中其实遗漏了一段文字,虽然很难看出来,但这里是有一块文字的(上图1紫色标注),它对应的是这个区域(上图3紫色标注),但它的长宽比看起来是错的,所以被我们丢弃了。

    • 看起来效果还不错,但是在该例中,我们的分类器还是遗漏了一段文字,它很难被看出来,因为这些文字写在了透明的窗户上。这就是使用了滑动窗口的文本检测系统,通过找出这些包含文字的矩形,现在可以把这些区域剪切出来,然后进入流水线的下个阶段,也就是识别文本。

    ②使用一维窗口进行文字分割(1D Sliding window for character segmentation)

    • 现在回一下流水线的第二步是字符分割,给定下图所示的图片,我们如何分割出图像中的单个字符?我们要做的是再次使用监督学习算法,用一些正样本和一些负样本。
      在这里插入图片描述

    • 现在我们观察这些图块,然后判断出图块中是否存在文字分割的地方,所以对于初始的正样本,对于第一个样本,即这个图块(上图1),看起来它和中间确实存在两个字符分割的地方;第二个样本看起来也是一个正样本(上图2),如果我们在正中间放一条线来分割字符好像是可以的,所以这些都是正样本(上图左),它们的中间代表两个字符之间的分隔。对于负样本,我们不需要把字符从中间分成两个,所以这些都是负样本(上图右),因为它们并不表示两个字符的分割。

    • 所以我们要做的是训练一个分类器,可能会用到新的网络,也可能使用不同的学习算法,来尝试将正样本和负样本进行区分,训练完这样的分类器后,我们可以将它运行在文字检测系统输出的这些文本中。我们先来看看这个矩形(上图3对应绿框),我们可能会问,它看起来像是绿框的中间部分吗,它看起来像是两个字符的分割吗?这时分类器会说不,然后我们移动矩形,这时一个一维的窗口分类器,因为我们只在一条直线上滑这个窗口,简单地从左向右,只有这一行而没有其他行,但是分类器到这个位置时(上图4对应蓝框),这时我们问,我们是否应该分开这两个字符,或者说我们是否应该对矩形中间进行分割呢,分类器将会输出 y = 1 y=1 y=1,这种情况下我们会决定在中间合适的位置画一条线来分割这两个字符,然后再次移动窗口,不断地重复该过程,判断正负样本,我们每移动一次就使用一次分分类器,它会告诉我们应该在哪里对字符进行分割,直到把图像全部分成单独的字符。再次重复一下,这是一维的滑动窗口用来进行字符分割。
      在这里插入图片描述

    • 这就是 O C R \rm OCR OCR 识别流水线的全部,在本节中我们已经谈到了文本检测步骤,其中我们使用滑动窗口检测文本,我们也使用一个一维的滑动窗口来做字符分割,将这张图片(上图中)分割成单个文字,那么流水线的最后一步就是文字识别,可能你早已经熟悉这一步了,因为在之前监督学习的章节中你已经能应用一个标准的监督学习算法到你的网络或者其它东西中了。为了能处理输入的图片,训练一个分类器,可以分类 26 26 26 个字母,或者我们可能有 36 36 36 个字符,如果包含数字的话,这是一个多分类问题,即输入一个包含文字的图片,它能判断图片中的字符。

    • 这就是图片 O C R \rm OCR OCR 流水线以及使用类似于滑动窗口这样的思想来组合这些不同的组件开发出图片 O C R \rm OCR OCR 系统。接下来的章节中,将继续研究图片 O C R \rm OCR OCR 问题,将围绕构建一个这样的应用来探索一些有趣的问题。

    三、获取大量数据:人工数据合成(Getting lots of data: Artificial data synthesis)

    • 一个最可靠的得到高性能机器学习系统的方法,是使用一个低偏差机器学习算法,并且使用庞大的训练集去训练它。不过我们该从哪里获取这么多训练数据呢?实际上,机器学习中有一个很棒的概念,叫做人工数据合成(Artificial data synthesis),它并不适用于所有问题,而且将其运用于特定问题时,经常需要思考改进并且深入了解它,但是假如这个想法适用于我们的机器学习问题,有时它能为我们的学习算法轻松得到大规模的训练集。
    • 人工数据合成主要有两种形式:第一种实际上是自己创造数据,即从零开始创造新数据;第二种是我们已经有小的标签训练集,然后以某种方式扩充训练集,就是将较小的训练集转化为一个较大的训练集。在本节中,我们将学习这两种方法。

    1. 从零开始 - 随机使用字体(using random fonts)

    • 为了引入人工数据合成这个概念,我们用字符识别这个例子来讲解,也就是照片光学字符识别 O C R \rm OCR OCR 的一部分,我们输入图像,就能识别出字符。
      在这里插入图片描述

    • 假如我们收集到了一个大的标签数据集(下图左),在本例中,我们选用了一个正方形的长宽比,所以我们要对正方形图像块进行识别,目标是输入一个图像块然后识别出图像块中央的字符。为了简化操作,我们会将这些图像处理成灰度图像而不是彩色图像,实际上,使用彩色图像对这个具体问题而言帮助不大。
      在这里插入图片描述

    • 给定这个图像块(上图1蓝色标注),希望机器能识别出 T \rm T T,对于这个图像块(上图2绿色标注),希望能识别出 S \rm S S,对于这个图像块(上图3紫色标注),我们希望能识别出 I \rm I I,等等。这里所有例子都是真实图像,我们怎样才能得到一个更大的训练集呢?现代计算机通常有一个庞大的字体库,假如我们使用一个文字处理软件,不同的文字处理软件可能有所有这些字体,并且还有更多内置字体。事实上,如果我们去浏览不同网站,网上还有庞大的免费字体库,我们能下载许多不同类型的字体,有上百种甚至是上千种不同的字体。

    • 所以,假如我们想要更多的训练样本,一个方法是用不同的字体生成字符(take characters from different fonts),然后将其粘贴到任意不同的背景中,比如说,我们可以将这个字母 C \rm C C 粘贴在任意背景中(上图红色标注),操作完成后,我们现在就有了一个字符 C \rm C C 的图像训练样本,在完成一些相同的操作之后,要想合成能以假乱真的数据的确需要花一番功夫,但做完这些工作之后,我们就会得到像这样的人造训练集(下图右),里面的每一个图像,实际上都是一个合成图像,它是用一个字体,可能是从网上下载的字体,我们将这种字体的一个字符图像或是多个字符图像粘贴到另一个任意背景图中,然后可以应用一点模糊算子(blurring operations)或者仿射变换(affine distortions),仿射的意思是进行等分缩放和一些旋转操作。完成这些操作后,我们会得到一个人工合成训练集。
      在这里插入图片描述

    • 这要花费一些功夫,为了使合成的数据更逼真,我们需要在操作中花些心思。如果我们在创造人工数据时做的不好,那使用效果就不好。我们看一下上图右侧这些合成数据,它实际上与真实数据非常相似,那么使用合成的数据,我们实际上能为我们的人工训练合成提供无限的训练数据样本。因此,如果我们使用这种合成数据,我们就会有无限的标签数据来为字符识别问题生成一个监督学习算法。

    • 在这个人工数据合成的例子中,我们基本上是从零开始生成新数据的,也就是从零开始产生新的图像。

    2. 基于已有 - 人工拉伸(artificial warpings)

    • 另一个主要的生成人工数据的方法是使用现有的样本生成数据。
      在这里插入图片描述

    • 我们拿一个真实的样本,可能来自一张真的图片,然后生成一些其它的数据以扩充训练集。这是一张字符 A \rm A A 的图像(上图左),它取自一张真实图像,而不是合成图像,我们在上面覆盖了网格线,只是为了便于说明,实际上不会有网格线。接下来要做的是,对这个字母,这张图进行人工拉伸(artificial warpings),或者说人工扭曲(artificial distortions),这样就可以将这个图 A \rm A A 变成 16 16 16 个新的样本。采用这种办法,我们就能将一个小的标签训练集扩充为一个更大的训练集。同样的,这个应用中,为了得到这种效果,确实要花些心思,并且需要深入理解来解决哪些扭曲是合理的,哪些操作能够用来扩充以及增加我们的训练集。对于字符识别这一特定例子引入这些拉伸看起来是个很自然的选择,但是对于其他机器学习应用来说,可能其它类型的失真将会更合理,我们举一个不同领域的例子,即语音识别(speech recognition),对语音识别而言,假定我们有一些音频片段,然后我们想从中学习来识别语音片段中出现的单词。
      ⊲ ) )   O r i g i n a l    a u d i o ⊲ ) )   A u d i o    o n    b a d    c e l l p h o n e    c o n n e c t i o n ⊲ ) )   N o i s y    b a c k g r o u n d :    C r o w d ⊲ ) )   N o i s y    b a c k g r o u n d :    M a c h i n e r y )) Original  audio)) Audio  on  bad  cellphone  connection)) Noisy  background:  Crowd)) Noisy  background:  Machinery )) Original  audio)) Audio  on  bad  cellphone  connection)) Noisy  background:  Crowd)) Noisy  background:  Machinery

    • 假定有一个带标签的训练样本,它是某个人说的一些词,我们想尝试应用一个学习算法来识别出那个人说的单词,那么,我们该如何扩充数据集呢?我们能做的是引入额外的语音失真到数据集中,这里我们加入背景音,来模拟手机通话信号不好的情况,我们会听到蜂鸣声,它实际上是音轨的一部分,而不是扬声器的问题,这个声音可以作为另一个有用的训练样本;另一个例子则是嘈杂的背景音,背景音中有汽车经过、行人走过的的声音。

    • 我们拿原来的 “ 干净 ” 的音频自动合成这些其他的训练样本,从一个训练样本生成四种不同的训练样本。因此,仅通过一个标签样本,只需要花功夫收集一个标签样本,通过人工添加失真,引入不同的背景声音,我们现在很容易将一个样例扩充为更多的样本,即自动化添加这些不同的背景声音到 “ 干净 ” 的音频中。

    3. 引入具有代表性的失真

    在这里插入图片描述

    • 提醒一点,在引入失真合成数据时,如果我们试图自己完成,那么引入的失真应该具有代表性,这些噪音或扭曲是有可能出现在测试集中的,所以对于字符识别例子来说,我们引入的扭曲实际上是合理的,因为像这样的 A \rm A A 的图像可能会出现在测试集中(上图1),可能会有这种笔画较粗的 A \rm A A,而右上角的那张图(上图2)也是很有可能见到的。对于音频而言,现实中的确会出现连接信号很差的情况,或者不同的背景噪音,因此对于音频问题,我们也需要合成有代表性的、我们想要正确分类或识别的样本。
    • 相反,如果只是将随机的无意义的噪声加入到数据中,并没有多大帮助。这个例子中(上图下),我们将原来的这张图(上图3)变成了它右侧的 4 4 4 张图,其中每个像素随机加入一些高斯噪声,即改变每个像素的亮度,如果只是随机加入一些高斯噪声到每个像素中,就只是完全没有意义的噪声。因此,除非觉得有可能在测试集中看到这种像素级的噪音,那么这种纯随机的无意义噪声很可能是无用的。
    • 这种人工数据合成的过程也需要一点技巧,有时候就是需要试一下,看看行不行。但是当我们在决定该添加哪种失真时,认真考虑一下添加什么样的失真才是有意义的,怎样才能使我们生成的训练样本至少有一定代表性是有可能在测试集中见到的样本。

    4. 生成训练样本前的工作和获得更多数据的方法

    • 最后我们再提几点有关通过人工数据合成来生成大量数据。
      1.   M a k e    s u r e    y o u    h a v e    a    l o w    b i a s    c l a s s i f i e r    b e f o r e    e x p e n d i n g    t h e     e f f o r t .    ( P l o t    l e a r n i n g    c u r v e s ) .    E . g .    k e e p    i n c r e a s i n g    t h e    n u m b e r     o f    f e a t u r e s / n u m b e r    o f    h i d d e n    u n i t s    i n    n e u r a l    n e t w o r k    u n t i l     y o u    h a v e    a    l o w    b i a s    c l a s s i f i e r . 1. Make  sure  you  have  a  low  bias  classifier  before  expending  the   effort.  (Plot  learning  curves).  E.g.  keep  increasing  the  number   of  features/number  of  hidden  units  in  neural  network  until   you  have  a  low  bias  classifier. 1. Make  sure  you  have  a  low  bias  classifier  before  expending  the   effort.  (Plot  learning  curves).  E.g.  keep  increasing  the  number   of  features/number  of  hidden  units  in  neural  network  until   you  have  a  low  bias  classifier.
    • 首先,像之前相同,在花大力气想办法生成人工训练样本之前,通常最好先确保我们的分类器偏差较低,这样的话,更多的训练数据才会真正起作用。
    • 标准的做法是绘制一个学习曲线来确保我们有一个低偏差,高方差的分类器;如果我们的分类器偏差太高,那么我们可以尝试持续增加分类器的特征数量或增加神经网络隐藏单元的数量,直到偏差值降低,然后再花精力到生成大量的人工训练集上,所以我们真正要避免的是花一整个星期或者是几个月解决如何获取大量人工合成数据,却又发现实现后学习算法性能提升并不是很大,即使我们使用了庞大的训练集。所以我们通常建议先用测试确保需要用到大量训练数据,再花精力去生成训练样本
      2.  “ H o w    m u c h    w o r k    w o u l d    i t    b e    t o    g e t    10 x    a s    m u c h    d a t a    a s    w e     c u r r e n t l y    h a v e ? ”     − A r t i f i c i a l    d a t a    s y n t h e s i s     − C o l l e c t / l a b e l    i t    y o u r s e l f     − “ C r o w d    s o u r c e ”   ( E . g .    A m a z o n    M e c h a n i c a l    T u r k ) 2. How  much  work  would  it  be  to  get  10x  as  much  data  as  we   currently  have?   Artificial  data  synthesis   Collect/label  it  yourself   Crowd  source  (E.g.  Amazon  Mechanical  Turk) 2. “How  much  work  would  it  be  to  get  10x  as  much  data  as  we   currently  have?   Artificial  data  synthesis   Collect/label  it  yourself   “Crowd  source”  (E.g.  Amazon  Mechanical  Turk)
    • 其次,就是在研究机器学习问题时,我们经常问的一个问题,就是获得我们当前拥有的数据的 10 10 10 倍的数据量需要花费多少努力,问题的答案通常是,其实没有那么困难,可能最多花上几天的工作,就可以获得现有的 10 10 10 倍数据,对于一个机器学习应用来说。并且通常假如我们能得到当前数据的 10 10 10 倍数据,那么这就能使我们的算法运行地更好。
    • 因此,有几个方法来得到更多数据,本节中我们主要着眼于人工数据合成的方法,其中包括从零开始生成数据的随机使用字体等等;以及第二种方法,利用现有的样本,引入一些失真来增加扩大训练集;别的一些获得更多数据的方法的例子还有自己收集数据或是添加标签。我们经常会做,而且很有用的一个计算是,获得一定数量的样本需要多少分钟、多少小时,实际上是坐下来估计一下,假如给一个样本加标签需要 10 10 10 多秒,然后再假设在我们的应用中当前有 1000 1000 1000 个标注样本(所以 m = 1000 m=1000 m=1000),然后坐下来自问一下实际收集一个样本并添加标签需要多少时间。有时它可能会花费我们 10 10 10 秒来标记一个新样本,因此如果我们需要 10 10 10 倍多的样本,我们就会做一个计算,假如我们需要 10 10 10 秒来得到一个训练样本,如果我们需要 10 10 10 倍多数据,即我们需要 10 , 000 10,000 10,000 个样本,所以做一下计算这会花费我们多少时间来手工对 10 , 000 10,000 10,000 个样本加标签,如果给 1 1 1 个样本加标签需要 10 10 10 秒。实际上工作量是非常之小的,有时只是几天的时间,有时只是少数的几周,许多小组都会吃惊于获得更多的数据需要的工作是多么少,这样做能显著提高机器学习应用的性能;最后一个,有时用来获得更多数据的方法叫做众包(crowd sourcing),如今,有些网站或是一些服务商,能为我们提供网上雇人的服务,并且能以相对低廉的价格为我们标记大量的训练集,这种众包的方法或者叫众包数据标记(crowd sourced data labeling),有学术文献专门研究它,它有它的复杂之处,例如标记人员的可靠性,因为可能有成千上万的世界各地的标记员以相对低廉的价格为我们的数据加标签。我们刚才所说的也只是一个备选方案,可能 A m a z o n    M e c h a n i c a l    T u r k \rm Amazon\ \ Mechanical\ \ Turk Amazon  Mechanical  Turk 系统是当下最流行的众包选择,如果我们想要高质量的标签的话,通常来说工作量不小,不过这还是一个值得考虑的选择,如果你想尝试在网上以相对低廉的价格雇佣很多人为你标记大量数据的话。
    • 在本节中我们讨论了人工数据合成的两种方法,从零开始生成新数据,例如利用任意字体生成样本,或是扩充一个已有的训练集,通过将现有的标注样本引入一些失真以生成额外的标注样本。最后,希望大家能够记住的一点是,假如我们遇到一个机器学习问题,有两件事是值得做的,一个就是用学习曲线做一个合理检验,看更多的数据是否真的有用,第二个就是,假如情况是这样,我们通常会坐下来并且扪心自问大概要花多少资源才能获取到 10 10 10 倍于当前拥有的数据,同时有时候你会惊讶于实现它其实很简单,可能是几天或者几周的工作,并且这是一个很好的方法来大幅提高我们的机器学习算法性能。

    四、上限分析:下一步要做的工作是什么(Ceiling analysis: What part of the pipeline to work on next )

    • 在前面的章节中,我们不止一次地说过,当我们开发机器学习系统时,我们最宝贵的资源就是我们的时间。作为一个开发者,你需要正确选择下一步的工作,或者也许你有一个开发团队,或者一个工程师小组共同开发一个机器学习系统,同样,最宝贵的还是开发系统所花费的时间,你需要尽量避免你、你的同事或者你的朋友花费了大量时间在某一个模块上,在几周甚至几个月的努力以后才意识到所有这些付出的劳动都对你最终系统的表现并没有太大的帮助。
    • 本节我们将介绍一下关于上限分析(ceiling analysis) 的内容,当你自己或者你跟你的团队,在设计某个机器学习系统工作流时,这种方式通常能提供一个很有价值的信号,很好地指导你在你的工作流中哪一部分最值得你花时间去研究。

    1. 实例一:照片 OCR

    • 为了讲解上限分析,我们将继续使用之前用过的照片 O C R \rm OCR OCR 工作流的例子:
    Image
    Text detection
    Character
    segmentation
    Character
    recognition
    • 之前的课程中我们讲过这些方框,文本检测、字符分割和字符识别。这里每个方框都可能需要一个小团队来完成,当然也可以你一个人来构建整个系统,问题是你应该怎样分配资源呢?也就是说这些模块中哪一个、或者哪两个或者说所有的这三个哪些是最值得你花费精力去改善它的效果的,这便是上限分析要做的事,跟其它机器学习系统的开发过程一样,为了决定如何开发这个系统,一个有效的方法是对学习系统使用一个数值评价量度,假如我们用字符准确度作为这个度量,给定一个测试样本图像,那么这个数值就表示我们对测试图像中的文本识别正确的比例,或者我们也可以选择其他的某个数值评价度量值,假设不管选择什么评价度量值,我们得到整个系统目前的准确率为 72 % 72\% 72%
    ComponentAccuracy
    Overall system72%
    Text detection89%
    Character segmentation90%
    Character recognition100%
    • 换句话说,我们有一些测试集图像,并且对测试集中的每一幅图像,我们都对其分别运行文本检测、字符分割然后字符识别,然后我们发现在测试集上整个系统的总的准确率为 72 % 72\% 72%,不管我们用什么度量值来度量,下面是上限分析的主要思想:
      • 首先,我们关注这个机器学习工作流中的第一个模块——文本检测,而我们要做的实际上是在给测试集样本捣点儿乱,对于测试集,对于每一个测试样本,都给它提供一个正确的文本检测结果。换句话说,我们要遍历每个测试集样本,然后人为地告诉算法,每一个测试样本中文本的位置。因此换句话说,我们是要仿真出,如果是 100 % 100\% 100% 正确地检测出图片中的文本信息应该是什么样的。当然,要做到这个是很容易的,现在不用我们的学习算法来检测图像中的文本了,我们只需要找到对应的图像,然后人为地识别出测试集图像中出现文本的区域,让这个模块输出正确的结果,把这些真实的文本位置的标签作为输出的文本集合,然后用这些真实的标签传给工作流的下一个阶段,传给字符分割模块。在文本检测部分,我们想要做的是遍历我们的测试集,直接给出正确答案、正确的标签来给工作流的文本检测部分,这样的话我们就会有一个非常棒的文本检测系统。
      • 然后我们要做的是继续运行完接下来的几个模块,也就是字符分割和字符识别,然后使用与之前一样的评价量度指标来测量整个系统总的准确率。如果用这个完美的文本检测,系统的表现会有所提升,假如说提升到了 89 % 89\% 89%
      • 下一步我们继续进行,接着进入工作流的下一个阶段——字符分割,同前面一样,还是去找出我们的测试集,现在我们不仅用准确的文本检测结果,我们还同时用标准的字符分割结果,还是遍历测试样本,人工地把文本准确地标记成单个的字符,然后看看这有没有用。假如我们这样做以后整个系统准确率提高到 90 % 90\% 90%,这里说的准确率是指整个系统的准确率,所以无论字符识别模块给出的最终输出是什么,无论整个工作流最后输出结果是什么,我们都是测出的整个系统的准确率。
      • 最后我们执行最后一个模块——字符识别,同样也是人工给出这一模块的正确标签,这样做以后,理所当然得到100%准确率。
    • 进行上限分析的一个好处就是,我们现在理解了,如果对每一个模块进行改善,它们各自的上升空间是多大。如果我们有完美的文本检测模块,那么整个系统的准确率将从 72 % 72\% 72% 上升到 89 % 89\% 89%,因此效果的增益是 17 % 17\% 17%,这就意味着如果我们在现有系统的基础上花费时间和精力改善文本检测模块的效果,这就意味着可以提高系统 17 % 17\% 17% 的性能,看起来这还挺值得。
    • 相反,文本检测模块之后,即使我们用了完美的字符分割模块,性能只提高了 1 % 1\% 1%,这个信息更值得关注,这就意味着,不管投入多大精力在字符分割上,系统效果的潜在上升空间也都可能很小,或许就不会让一个比较大的工程师团队花时间忙于字符分割模块,通过这种分析我们就知道,即使把字符分割模块做的更好,我们的性能只能提升 1 % 1\% 1%,这就估计出了性能的上限,或者说研究一个模块,我们的系统性能提升的上界是多少。最后,对于字符,当我们有更好的字符识别模块时,系统性能可以提高 10 % 10\% 10%,我们可以决定对于 10 % 10\% 10% 的性能提高值得我们投入多少的精力,这表明如果花费更多的精力,在工作流的最后一个阶段,我们也可以提升系统的性能。
    • 也可以考虑这个方法,通过这种分析我们可以知道,提升每个模块的潜在效果如何,或者说如果一个模块近乎完美时,系统性能增益多少,这就像是给系统表现加上了一个提升的上限值。上限分析的概念是很重要的,下面我们再用一个稍微复杂一点的例子再阐述一下上限分析的方法。

    2. 实例二:人脸识别

    ①工作流

    • 假如你用图片做人脸识别,并且你想看这个照片,然后识别这个照片里的人是不是你的朋友,希望辨识出图像中的人,这是一个偏人工智能的例子,当然这并不是现实中的人脸识别技术,但是我想通过这个例子展示一个工作流,给你一个关于上限分析的实例。
    • 假如我们有张照片,我们设计了如下的工作流:
    Camera
    Image
    Preprocess
    (remove background)
    Face detection
    Eyes segmentation
    Nose segmentation
    Mouth segmentation
    Logistic regression
    label
    • 假如我们第一步要做的是图像预处理,假如就用这张图片(下图1),现在我们想要把背景去掉,那么经过预处理背景就被去掉了(下图2)。下一步我们希望检测出人脸的位置,这通常通过一个学习算法来实现,我们会运行一个滑动窗分类器,在人脸上画一个框(下图3)。
      在这里插入图片描述

    • 在检测到脸部以后,如果我们想要识别出这个人,那么眼睛是一个很重要的线索,事实上,要辨认出你的朋友你通常会看眼睛,这是个比较重要的线索,所以我们需要运行另一个分类器来检测人的眼睛,分割出眼睛,这样就提供了识别出一个人的很重要的特征,然后继续找出脸上其他重要的部位,比如分割出鼻子分割出嘴巴(上图4)。这样找出了眼睛、鼻子、嘴巴,所有这些都是非常有用的特征,可以被输入给某个逻辑回归的分类器,然后这个分类器的任务就是给出最终的标签,辨识出这个人是谁。这是一个稍微复杂一些的流水线,如果你真的想识别出人的话,可能实际的工作流比这个还要复杂,但这是一个很好的例子用来弄清楚上限分析。

    ②上限分析

    • 对这个流水线,怎么进行上限分析呢?我们还是每次关注一个步骤,假如说你的整个系统的准确率达到了 85 % 85\% 85%,首先还是找到测试集,然后人工地给它真实的标签,前景和背景的分割效果,找到测试集,然后用 P h o t o s h o p \rm Photoshop Photoshop 或者别的工具标记出哪些区域是背景,然后手动把背景删掉,真实的标签去掉这些背景,然后观察准确率提高多少。
    ComponentAccuracy
    Overall system85%
    Preprocess (remove background)85.1%
    Face detection91%
    Eyes segmentation95%
    Nose segmentation96%
    Mouth segmentation97%
    Logistic regression100%
    • 假设在这个例子中准确率提高了0.1%,这是个很明显的信号,它告诉我们即便我们把背景分割做得很好,完全去除了背景图案,但整个系统的表现也并不会提高多少,所以似乎不值得花太多精力在预处理或者背景移除上;接下来,再遍历测试集,给出正确的脸部识别图案,接下来还是依次运行眼睛、鼻子和嘴巴的分割,选择一种顺序就行了,给出眼睛的正确位置、鼻子的正确位置、嘴巴的正确位置。最后,再给出最终的正确标签,准确率提高到 100 % 100\% 100%
    • 随着一步步经过系统给越来越多的模块测试集里的真实标签,整个系统的性能逐步提升,这样我们就能很清楚地看到不同的步骤系统性能上升了多少,比如,有了完美的脸部识别,整个系统的表现似乎提高了 5.9 % 5.9\% 5.9%,这算是比较大的提高了,这告诉我们也许在脸部检测上多做点努力是值得的,眼睛识别提高了 4 % 4\% 4%,鼻子和嘴巴识别都是提高 1 % 1\% 1%,逻辑回归这一步提高 3 % 3\% 3%
    • 从整体上看,最值得付出努力的模块排在最前的是脸部检测,系统表现提高了 5.9 % 5.9\% 5.9%,给它完美的眼部分割系统表现提高 4 % 4\% 4%,最终是我们的逻辑回归分类器提高大约 3 % 3\% 3%,因此这很清楚地指出了哪一个模块是最值得花精力去完善的
    • 总结一下,工作流是非常常用却又很复杂的机器学习应用,当我们在开发某个大型的机器学习应用的时候,作为一个开发者,时间是相当宝贵的,所以真的不要花时间去做一些到头来没意义的事情。因此,这节介我们绍了上限分析的概念,我经常觉得上限分析是个很有用的工具,可以用来衡量模块,当你想花精力到某个模块上时,你可以确定这样做会不会有效果,整个系统的表现会不会产生明显的提高。我们不应该更多地去相信自己的直觉,相反地,如果要解决某个机器学习问题,最好能把问题分成多个模块,然后做一下上限分析,这通常给我们更可靠更好的方法,来为我们决定该把劲儿往哪儿使,该提高哪个模块的效果,这样我们就会非常确认把这个模块最好就能提高最后总体的性能。

    总结

    • 本篇文章主要介绍了一种机器学习的应用实例,叫做照片OCR(Photo OCR) 的技术,它的全称为照片光学字符识别(Photo Optical Character Recognition)。照片 O C R \rm OCR OCR 问题注重的问题是如何让计算机更好地理解这些照片的环境,如何让计算机读出图片中的文字信息,随后我们介绍了流水线的概念,它已经在复杂的机器学习系统中渗透到各种应用中。同时也介绍了该系统的前三步:文字检测、文字分割以及字符分类。
    • 滑动窗口中通过行人检测和文本检测的例子来说明滑动窗口的作用,我们使用一个滑动窗口,从图像的第一行开始逐行移动,就这样遍历图中所有不同的位置并且通过分类器进行分类。
    • 人工数据合成中我们讨论了人工数据合成的两种方法,从零开始生成新数据,例如利用任意字体生成样本,或是扩充一个已有的训练集,通过将现有的标注样本引入一些失真以生成额外的标注样本。同时也介绍了我们遇到一个机器学习问题两件值得做的事,一个是用学习曲线做一个合理检验,看更多的数据是否真的有用,第二个是,我们应当坐下来并且扪心自问大概要花多少资源才能获取到 10 10 10 倍于当前拥有的数据,同时实现它其实很简单,可能是几天或者几周的工作,并且这是一个很好的方法来大幅提高我们的机器学习算法性能。
    • 上限分析是个很有用的工具,可以用来衡量模块,当你想花精力到某个模块上时,你可以确定这样做会不会有效果,整个系统的表现会不会产生明显的提高。我们不应该更多地去相信自己的直觉,相反地,如果要解决某个机器学习问题,最好能把问题分成多个模块,然后做一下上限分析,这通常给我们更可靠更好的方法,来为我们决定该把劲儿往哪儿使,该提高哪个模块的效果,这样我们就会非常确认把这个模块最好就能提高最后总体的性能。
  • 相关阅读:
    MaxKey单点登录认证系统v3.5.10GA发布
    SIT1145AQ收发器芯片CAN FD Passive功能详解(摘自官网)
    JavaScript重点知识总结二
    Pytorch学习task02_待补
    腾讯云4核8G12M带宽服务器支持多少人同时在线?
    基于ATmega16单片机和GPS的多用途定位仪设计
    从事黑客工作十余年,究竟如何成为一名高级的安全工程师?
    Python绘图系统24:添加辅助坐标轴
    鼓起勇气做事情
    动态内存和指针变量
  • 原文地址:https://blog.csdn.net/weixin_53312629/article/details/126131664