机器学习(十八)应用实例:照片OCR
文章目錄
- Log
- 一、問題描述與流水線(Problem description and pipeline)
- 1. 問題描述(The Photo OCR problem)
- 2. 流水線(Photo OCR pipeline)
- 二、滑動窗口(Sliding windows)
- 1. 行人檢測(Pedestrian detection)
- ①文字識別與行人檢測(Text detection & Pedestrian detection)
- ②應用監督學習的行人檢測(Supervised learning for pedestrian detection)
- ③滑動窗口檢測(Sliding window detection)
- 2. 文本檢測(Text detection)
- ①文字檢測(Text detection)
- ②使用一維窗口進行文字分割(1D Sliding window for character segmentation)
- 三、獲取大量數據:人工數據合成(Getting lots of data: Artificial data synthesis)
- 1. 從零開始 - 隨機使用字體(using random fonts)
- 2. 基于已有 - 人工拉伸(artificial warpings)
- 3. 引入具有代表性的失真
- 4. 生成訓練樣本前的工作和獲得更多數據的方法
- 四、上限分析:下一步要做的工作是什么(Ceiling analysis: What part of the pipeline to work on next )
- 1. 實例一:照片 OCR
- 2. 實例二:人臉識別
- ①工作流
- ②上限分析
- 總結
Log
2022.08.12開始學習最后一章!
2022.08.13繼續學習
2022.08.14繼續學習
2022.08.15繼續學習
2022.08.16繼續學習
2022.08.18繼續學習。結束十八章!
- 本章將會介紹一種機器學習的應用實例,或者說在機器學習應用歷史中一種叫做照片OCR(Photo OCR) 的技術。我想介紹它的原因有 333 個:
- 首先,我想向你展示一個復雜的機器學習系統是如何被組合起來的;
- 第二,我想介紹一下機器學習流水線的有關概念,以及如何分配資源來對下一步計劃作出決定,這既可以適用于自己開發一個復雜的機器學習應用,也可以適用于一個開發團隊共同開發機器學習應用;
- 最后,我想通過介紹照片 OCR\rm OCROCR 問題來告訴你機器學習中許多有用的想法和概念,其中之一就是如何將機器學習應用到計算機視覺問題中,而另一個就是人工數據合成的概念。
一、問題描述與流水線(Problem description and pipeline)
- 照片 OCR\rm OCROCR 全稱為照片光學字符識別(Photo Optical Character Recognition),隨著數碼攝影的發展,以及智能手機拍照功能的成熟,我們現在會有很多各個地方拍攝的照片,一個吸引了眾多開發者們的問題就是如何讓計算機更好地理解這些照片的環境。照片OCR問題注重的問題是如何讓計算機讀出圖片中的文字信息。
1. 問題描述(The Photo OCR problem)
-
假設現在有這樣一張照片:
-
我們希望計算機能夠讀出照片中的文字,這樣一來,如果我們之后想找到這張照片,我們就只需要輸入照片中的文字:LULAB′sANTIQUEMALL\rm LULA\ \ B's\ \ ANTIQUE\ \ MALLLULA??B′s??ANTIQUE??MALL,計算機就能自動找出這張圖片,這樣我們就不用花大量時間把相冊翻個底朝天,從千百張照片中把它找出來了。
-
OCR\rm OCROCR 所要做的事情有如下幾個步驟:
-
首先,給定某張圖片,它將圖片掃描一遍,然后找出照片中的文字信息;
-
在成功找出文字以后,它將重點關注這些文字區域,并對區域中的文字進行識別,當它正確讀出這些文字以后,它會將這些文字內容顯示并記錄下來。
-
-
雖然現在 OCR\rm OCROCR (或者說光學文字識別)對于掃描文檔來說已經是一個比較簡單的問題了,但對于數碼照片來說,現在還是一個很難的機器學習問題,如果能夠成功實現它,不僅可以幫助計算機更好地理解圖像中的內容,還可以開發出一些比如能夠幫助盲人的應用,舉個例子,可以為盲人提供一種相機,該相機可以看出來它們前面有什么東西,然后直接告訴他們,他們前面有個路牌,現在也有研究人員將照片 OCR\rm OCROCR 技術應用到汽車導航系統中,比如說我們的車能讀出街上的路牌,幫我們導航到目的地。
2. 流水線(Photo OCR pipeline)
1.Textdetection2.Charactersegmentation3.Characterclassification\begin{aligned} &1.\ \rm Text\ \ detection\\ &2.\ \rm Character\ \ segmentation\\ &3.\ \rm Character\ \ classification \end{aligned} ?1.?Text??detection2.?Character??segmentation3.?Character??classification?
-
為了實現照片 OCR\rm OCROCR ,這是我們能做的:
-
首先我們要掃描圖像,并找出有文字的圖像區域,比如這就是一個 OCR\rm OCROCR 系統可能識別到的一個文字區域(下圖);
-
然后它會得到這個矩形區域,然后進行文字分離,通過這個文本框它會識別出 ANTIQUEMALL\rm ANTIQUE\ \ MALLANTIQUE??MALL,然后將其分割成一個個獨立的字符區域;
-
分割好這些獨立的字符后,我們用一個分類器,它會對這些可見的字符進行識別,然后識別出第一個字母是 A\rm AA,第二個字母是N\rm NN,第三字母是T\rm TT 等等,做完這些之后,可能我們就能計算出這句話是 LULAB′sANTIQUEMALL\rm LULA\ \ B's\ \ ANTIQUE\ \ MALLLULA??B′s??ANTIQUE??MALL,然后圖片中其它有文字的地方也是一樣的方法。
-
-
實際上有一些照片 OCR\rm OCROCR 系統會做一些更復雜的事情,比如最后會進行拼寫校正,舉個例子,假如我們的字符分割和分類系統識告訴我們它識別到的字符是 C1eaningC\red 1eaningC1eaning,然后一些拼寫修正系統就會告訴我們這應該是單詞 CleaningC\red leaningCleaning,我們的字符分類算法把字母 lll 識別成了數字 111,不過由于本節暫時不考慮這些東西,所以忽略掉最后一步,我們只關注系統的前三步:文字檢測(Text detection)、文字分割(Character segmentation)以及字符分類(Character classification)。
segmentationCharacter
recognition
- 那么像這樣的一個系統,我們把它稱之為機器學習流水線(machine learning pipeline),具體來說,這幅圖所表示的就是 OCR\rm OCROCR 的流水線(上流程圖),首先我們有一副圖像,然后把它傳給文字檢測系統,識別出文字區域以后,然后我們將文本區域中的單個字符分割出來,最后我們對這些單個字母進行識別。
- 在很多復雜的機器學習系統中,這種流水線形式非常普遍,在流水線中會有多個不同的模塊,比如在本例中有三個模塊,我們有文字檢查、字符分割以及字母識別模塊,每一個模塊都是一個機器學習組件,可能有時候它不是一個機器學習組件,但是它有一系列的連接在一起的模塊,并在一系列數據上執行,最終得出我們希望的結果,在照片 OCR\rm OCROCR 的例子中就是最終識別到的圖片中的文字信息。
- 如果我們要設計一個機器學習系統,我們要作出的最重要的決定之一就是我們要怎樣設計這個流水線的各個模塊,或者說在這個照片 OCR\rm OCROCR 問題中,我們應該如何將這個問題分成一系列不同的模塊,我們需要設計整個流水線以及我們的流水線中的每一個模塊,這通常會影響到算法最終的表現。
- 如果我們有一個工程師團隊在進行同樣類似的任務,我們可以讓不同的人來完成不同的模塊,我們大概可以估計出文字檢測這個模塊需要大概 111 到 555 個人,字符分割部分需要 111 到 555 個人,字母識別部分還需要 111 到 555 個人。因此使用這樣的流水線可以讓我們很自然地把工作分配給不同的組員去完成。當然,所以這些工作也可以只由一個人來完成,如果我們想的話。
- 在復雜的機器學習系統中,流水線的概念已經滲透到各種應用中,我們剛才看到的只是照片 OCR\rm OCROCR 流水線的具體運作過程。接下來的幾節我們將介紹更多關于流水線的信息,并且我們還會繼續使用這個例子來介紹其它很重要的機器學習的概念。
二、滑動窗口(Sliding windows)
- 上一節我們討論了 OCR\rm OCROCR 流水線及其工作原理,在 OCR\rm OCROCR 中我們取一張圖,然后把這張圖傳遞到一些列的機器學習組件來讀取出圖片上的文字。本節我們將會介紹一些關于流水線中每個獨立的組件的工作原理,本節我們主要要講一種叫做滑動窗口分類器(Sliding windows classifier) 的東西。
1. 行人檢測(Pedestrian detection)
①文字識別與行人檢測(Text detection & Pedestrian detection)
-
圖像 OCR\rm OCROCR 流水線的第一步是文字識別,比如我們看這樣一張圖(下圖左), 然后嘗試找到圖片上文字出現的區域:
-
文字識別在計算機視覺中是一個比較難的問題,因為根據我們找到的這些文字區域,它們對應的矩形具有不同的長寬比例,所以為了講述如何在圖片中檢測它們,我們首先從一個簡單點的例子開始,即行人檢測,之后我們再將做行人檢測的思路應用到文字識別中去。
-
在行人檢測中,我們有一張類似這樣的圖片(上圖右),我們要找出圖片中的各個行人,我們會依次找到六個行人,這個問題與文字識別相比,簡單的地方在于我們要識別的東西具有相似的長寬比,僅用一個具有固定長寬比(fixed aspect ratio) 的矩形就可以了(長寬比的意思就是矩形長度和寬度之間的比例),這些行人們的長寬比都是差不多的。對于文字來說,不同位置的文字具有不同的比例;對于行人檢測,盡管不同行人距離攝像頭的距離可能不同,所以這些矩形的高度根據不同行人的位置也會不一樣,但比例還是不變的。
②應用監督學習的行人檢測(Supervised learning for pedestrian detection)
-
為了建立一個行人檢測系統,我們需要這么做,例如我們決定要把比例的標準定為 82×3682×3682×36,當然我們也可以選擇其他的相近的數字,比如 80×4080×4080×40,或者 82×3682×3682×36 也可以,我們將要做的是從數據集中收集一些正樣本和負樣本,這里是一些 82×3682×3682×36 的圖片樣本,其中包含了整個行人,還有一些不包含行人的圖片:
-
上圖我們展示了 121212 個 y=1y=1y=1 的正樣本,還有 121212 個 y=0y=0y=0 的負樣本。在一個更典型的行人檢測應用中我們可能會有 100010001000 個到 100001000010000 個數目的樣本,甚至更多,如果我們能得到更大的數據集的話,然后我們可以在我們的網絡中訓練或者使用其它學習算法,向其中輸入一個 82×3682×3682×36 的圖塊,來對 yyy 進行分類,來劃分每個圖塊是否包含一個行人,于是這給了我們一個應用監督學習的方法來對一個圖塊進行處理判斷其是否包含有行人。
③滑動窗口檢測(Sliding window detection)
-
現在假設我們得到一張新圖,比如這樣的一張測試集圖片(下圖),我們嘗試在圖片中找到一個行人,首先在圖片中選取一個矩形塊,像這樣的(下圖左上綠色方塊)一個 82×3682×3682×36 的圖塊:
-
我們把這個圖塊傳遞給我們的分類器,來檢測圖塊中是否有行人,這時我們的分類器應該會返回 y=0y=0y=0,因為上面沒有行人,接下來將綠色的矩形稍稍移動一點,再把這個圖塊傳遞給我們的分類器判斷是否是行人,在這之后,我們再次將窗口向右滑動一些,再傳給分類器進行分類判斷。這個綠色矩形每次移動的距離是一個參數,一般稱之為步長(the step size of the parameter),有時也被稱為滑動參數(the slide parameter),如果我們一次移動一個像素,那么步長就為 111,一般這個步長表現最好,但是計算成本較高。一般來說,把步長設為 444 像素或 888 像素或更大的數是比較常見的。這就意味著矩形每次都會移動一些。繼續這個過程,繼續向右移動矩形,每次都移動一點,每次移動都使用分類器對圖塊進行分類,一直這樣下去,直到在圖中各個位置都過一遍(下方動圖),首先從第一行開始,再移動到圖像的下一行,就這樣遍歷圖中所有不同的位置并且通過分類器進行分類。
-
它是一個很小的矩形,且它只會檢測某個特定大小的行人,接下來我們要做的是使用更大的圖塊,進行和使用小圖塊時相同的操作,我們所說的用更大的圖塊實際上意思是:當我們選取完這樣的圖塊之后我們要做的是把這個圖塊調整到 82×3682×3682×36 的大小,所以把這個大的圖塊調整為一個更小的圖片,然后把調整后的圖片傳遞給我們的分類器中,然后判斷是否有行人。
-
最后我們還可以使用更大尺寸的窗口來把圖像過一遍。經過這一系列過程后,算法便能夠檢測出圖中各個地方是否出現行人(上圖)。
-
這就是我們如何訓練一個監督學習分類器,然后使用一個滑動窗口分類器或者說滑動窗口檢測器來找出圖中的所有行人。
2. 文本檢測(Text detection)
①文字檢測(Text detection)
-
讓我們回到文本檢測的例子,談談 OCR\rm OCROCR 流水線中的這個階段,也就是如何找出圖中的文字區域,與行人檢測類似,拿出一系列包含正樣本和負樣本的訓練集,其中正樣本代表的是對應的區域有文字出現,之前我們做的是行人檢測,但是現在我們要嘗試做文本檢測,所以正樣本代表的是含有文字的圖塊,負樣本表示的是沒有文字的圖塊。
-
訓練完之后,我們可以將其應用在一個新的測試集中的圖片上,這是我們剛才作為例子所用的圖片(下圖1),現在我們在這個圖片上來運行算法,我們將使用一個固定比例的滑動窗口來進行講解。
-
這里我們將只使用一個固定大小的矩形,假如說,我們在這些圖塊上使用這樣的(上圖1左上綠色方塊)滑動窗口分類器,這樣的話,我們就會得到這樣的結果(上圖2、3),其中白色區域表示檢測系統發現了文本,黑色區域表示分類器沒有發現文字。同時我們發現,有很多白色的區域,這表示分類器在這些位置上發現了文本,我們在圖2中所做的操作是用白色表示分類器認為有文字的地方,而這些深淺不同的灰色對應的是分類器認為該處有文字的概率,所以這些灰色陰影意味著分類器認為它可能找到了文本,但是概率不高,而這些亮白色的區域表示分類器輸出了一個很高的概率,也就是該處有文字的概率。
-
但到這里還沒有結束,我們真正想做的是在所有文字周圍繪制矩形,然后更進一步將這些分類器的輸出應用到一種叫做放大算子(expansion operator) 的東西上,它所做的是取這里的圖,它把每個白色方塊或者說是白色區域,然后擴大這些白色區域,我們可以用數學方式來實現它,如果我們觀察圖3,構造這個圖像的方法,就是對圖2的每個像素判斷其一定范圍內是否存在白色的像素,如果某個像素,它周圍 555 到 101010 個像素的范圍內,如果存在其它的白色像素,那么就在上圖中把整個范圍內的像素都變成白色,這樣做的效果是,把上上圖中的每個白色區塊都擴大一些,都增長一些,通過檢查像素附近是否存在白色像素,然后把這一范圍內都變成白色。
-
在完成之后,現在我們看看圖3的關聯部分,也就是白色區域,然后在其周圍繪制邊框。如果觀察所有白色區域,我們想用一個簡單的方法來排除那些比例很奇怪的矩形,因為我們知道文本周圍的框寬度應該遠大于高度,所以如果我們忽略瘦高的矩形,類似這些(上圖3藍色標注),我們丟棄這些太高太窄的矩形,我們在那些長寬比例正常的文字區域周圍畫上矩形,即文字區域周圍的這些框框(上圖3紅色方框),對應商場的招牌 LULAB′sANTIQUEMALL\rm LULA\ \ B's\ \ ANTIQUE\ \ MALLLULA??B′s??ANTIQUE??MALL、LULAB′s\rm LULA\ \ B'sLULA??B′s 標志以及 Open\rm OpenOpen 的標志,這個例子中其實遺漏了一段文字,雖然很難看出來,但這里是有一塊文字的(上圖1紫色標注),它對應的是這個區域(上圖3紫色標注),但它的長寬比看起來是錯的,所以被我們丟棄了。
-
看起來效果還不錯,但是在該例中,我們的分類器還是遺漏了一段文字,它很難被看出來,因為這些文字寫在了透明的窗戶上。這就是使用了滑動窗口的文本檢測系統,通過找出這些包含文字的矩形,現在可以把這些區域剪切出來,然后進入流水線的下個階段,也就是識別文本。
②使用一維窗口進行文字分割(1D Sliding window for character segmentation)
-
現在回一下流水線的第二步是字符分割,給定下圖所示的圖片,我們如何分割出圖像中的單個字符?我們要做的是再次使用監督學習算法,用一些正樣本和一些負樣本。
-
現在我們觀察這些圖塊,然后判斷出圖塊中是否存在文字分割的地方,所以對于初始的正樣本,對于第一個樣本,即這個圖塊(上圖1),看起來它和中間確實存在兩個字符分割的地方;第二個樣本看起來也是一個正樣本(上圖2),如果我們在正中間放一條線來分割字符好像是可以的,所以這些都是正樣本(上圖左),它們的中間代表兩個字符之間的分隔。對于負樣本,我們不需要把字符從中間分成兩個,所以這些都是負樣本(上圖右),因為它們并不表示兩個字符的分割。
-
所以我們要做的是訓練一個分類器,可能會用到新的網絡,也可能使用不同的學習算法,來嘗試將正樣本和負樣本進行區分,訓練完這樣的分類器后,我們可以將它運行在文字檢測系統輸出的這些文本中。我們先來看看這個矩形(上圖3對應綠框),我們可能會問,它看起來像是綠框的中間部分嗎,它看起來像是兩個字符的分割嗎?這時分類器會說不,然后我們移動矩形,這時一個一維的窗口分類器,因為我們只在一條直線上滑這個窗口,簡單地從左向右,只有這一行而沒有其他行,但是分類器到這個位置時(上圖4對應藍框),這時我們問,我們是否應該分開這兩個字符,或者說我們是否應該對矩形中間進行分割呢,分類器將會輸出 y=1y=1y=1,這種情況下我們會決定在中間合適的位置畫一條線來分割這兩個字符,然后再次移動窗口,不斷地重復該過程,判斷正負樣本,我們每移動一次就使用一次分分類器,它會告訴我們應該在哪里對字符進行分割,直到把圖像全部分成單獨的字符。再次重復一下,這是一維的滑動窗口用來進行字符分割。
-
這就是 OCR\rm OCROCR 識別流水線的全部,在本節中我們已經談到了文本檢測步驟,其中我們使用滑動窗口檢測文本,我們也使用一個一維的滑動窗口來做字符分割,將這張圖片(上圖中)分割成單個文字,那么流水線的最后一步就是文字識別,可能你早已經熟悉這一步了,因為在之前監督學習的章節中你已經能應用一個標準的監督學習算法到你的網絡或者其它東西中了。為了能處理輸入的圖片,訓練一個分類器,可以分類 262626 個字母,或者我們可能有 363636 個字符,如果包含數字的話,這是一個多分類問題,即輸入一個包含文字的圖片,它能判斷圖片中的字符。
-
這就是圖片 OCR\rm OCROCR 流水線以及使用類似于滑動窗口這樣的思想來組合這些不同的組件開發出圖片 OCR\rm OCROCR 系統。接下來的章節中,將繼續研究圖片 OCR\rm OCROCR 問題,將圍繞構建一個這樣的應用來探索一些有趣的問題。
三、獲取大量數據:人工數據合成(Getting lots of data: Artificial data synthesis)
- 一個最可靠的得到高性能機器學習系統的方法,是使用一個低偏差機器學習算法,并且使用龐大的訓練集去訓練它。不過我們該從哪里獲取這么多訓練數據呢?實際上,機器學習中有一個很棒的概念,叫做人工數據合成(Artificial data synthesis),它并不適用于所有問題,而且將其運用于特定問題時,經常需要思考改進并且深入了解它,但是假如這個想法適用于我們的機器學習問題,有時它能為我們的學習算法輕松得到大規模的訓練集。
- 人工數據合成主要有兩種形式:第一種實際上是自己創造數據,即從零開始創造新數據;第二種是我們已經有小的標簽訓練集,然后以某種方式擴充訓練集,就是將較小的訓練集轉化為一個較大的訓練集。在本節中,我們將學習這兩種方法。
1. 從零開始 - 隨機使用字體(using random fonts)
-
為了引入人工數據合成這個概念,我們用字符識別這個例子來講解,也就是照片光學字符識別 OCR\rm OCROCR 的一部分,我們輸入圖像,就能識別出字符。
-
假如我們收集到了一個大的標簽數據集(下圖左),在本例中,我們選用了一個正方形的長寬比,所以我們要對正方形圖像塊進行識別,目標是輸入一個圖像塊然后識別出圖像塊中央的字符。為了簡化操作,我們會將這些圖像處理成灰度圖像而不是彩色圖像,實際上,使用彩色圖像對這個具體問題而言幫助不大。
-
給定這個圖像塊(上圖1藍色標注),希望機器能識別出 T\rm TT,對于這個圖像塊(上圖2綠色標注),希望能識別出 S\rm SS,對于這個圖像塊(上圖3紫色標注),我們希望能識別出 I\rm II,等等。這里所有例子都是真實圖像,我們怎樣才能得到一個更大的訓練集呢?現代計算機通常有一個龐大的字體庫,假如我們使用一個文字處理軟件,不同的文字處理軟件可能有所有這些字體,并且還有更多內置字體。事實上,如果我們去瀏覽不同網站,網上還有龐大的免費字體庫,我們能下載許多不同類型的字體,有上百種甚至是上千種不同的字體。
-
所以,假如我們想要更多的訓練樣本,一個方法是用不同的字體生成字符(take characters from different fonts),然后將其粘貼到任意不同的背景中,比如說,我們可以將這個字母C\rm CC 粘貼在任意背景中(上圖紅色標注),操作完成后,我們現在就有了一個字符C\rm CC 的圖像訓練樣本,在完成一些相同的操作之后,要想合成能以假亂真的數據的確需要花一番功夫,但做完這些工作之后,我們就會得到像這樣的人造訓練集(下圖右),里面的每一個圖像,實際上都是一個合成圖像,它是用一個字體,可能是從網上下載的字體,我們將這種字體的一個字符圖像或是多個字符圖像粘貼到另一個任意背景圖中,然后可以應用一點模糊算子(blurring operations)或者仿射變換(affine distortions),仿射的意思是進行等分縮放和一些旋轉操作。完成這些操作后,我們會得到一個人工合成訓練集。
-
這要花費一些功夫,為了使合成的數據更逼真,我們需要在操作中花些心思。如果我們在創造人工數據時做的不好,那使用效果就不好。我們看一下上圖右側這些合成數據,它實際上與真實數據非常相似,那么使用合成的數據,我們實際上能為我們的人工訓練合成提供無限的訓練數據樣本。因此,如果我們使用這種合成數據,我們就會有無限的標簽數據來為字符識別問題生成一個監督學習算法。
-
在這個人工數據合成的例子中,我們基本上是從零開始生成新數據的,也就是從零開始產生新的圖像。
2. 基于已有 - 人工拉伸(artificial warpings)
-
另一個主要的生成人工數據的方法是使用現有的樣本生成數據。
-
我們拿一個真實的樣本,可能來自一張真的圖片,然后生成一些其它的數據以擴充訓練集。這是一張字符 A\rm AA 的圖像(上圖左),它取自一張真實圖像,而不是合成圖像,我們在上面覆蓋了網格線,只是為了便于說明,實際上不會有網格線。接下來要做的是,對這個字母,這張圖進行人工拉伸(artificial warpings),或者說人工扭曲(artificial distortions),這樣就可以將這個圖 A\rm AA 變成 161616 個新的樣本。采用這種辦法,我們就能將一個小的標簽訓練集擴充為一個更大的訓練集。同樣的,這個應用中,為了得到這種效果,確實要花些心思,并且需要深入理解來解決哪些扭曲是合理的,哪些操作能夠用來擴充以及增加我們的訓練集。對于字符識別這一特定例子引入這些拉伸看起來是個很自然的選擇,但是對于其他機器學習應用來說,可能其它類型的失真將會更合理,我們舉一個不同領域的例子,即語音識別(speech recognition),對語音識別而言,假定我們有一些音頻片段,然后我們想從中學習來識別語音片段中出現的單詞。
?))Originalaudio?))Audioonbadcellphoneconnection?))Noisybackground:Crowd?))Noisybackground:Machinery\begin{aligned} &\lhd)\big)\ \rm Original\ \ audio\\ &\lhd)\big)\ \rm Audio\ \ on\ \ bad\ \ cellphone\ \ connection\\ &\lhd)\big)\ \rm Noisy\ \ background:\ \ Crowd\\ &\lhd)\big)\ \rm Noisy\ \ background:\ \ Machinery\\ \end{aligned} ??))?Original??audio?))?Audio??on??bad??cellphone??connection?))?Noisy??background:??Crowd?))?Noisy??background:??Machinery? -
假定有一個帶標簽的訓練樣本,它是某個人說的一些詞,我們想嘗試應用一個學習算法來識別出那個人說的單詞,那么,我們該如何擴充數據集呢?我們能做的是引入額外的語音失真到數據集中,這里我們加入背景音,來模擬手機通話信號不好的情況,我們會聽到蜂鳴聲,它實際上是音軌的一部分,而不是揚聲器的問題,這個聲音可以作為另一個有用的訓練樣本;另一個例子則是嘈雜的背景音,背景音中有汽車經過、行人走過的的聲音。
-
我們拿原來的 “ 干凈 ” 的音頻自動合成這些其他的訓練樣本,從一個訓練樣本生成四種不同的訓練樣本。因此,僅通過一個標簽樣本,只需要花功夫收集一個標簽樣本,通過人工添加失真,引入不同的背景聲音,我們現在很容易將一個樣例擴充為更多的樣本,即自動化添加這些不同的背景聲音到 “ 干凈 ” 的音頻中。
3. 引入具有代表性的失真
- 提醒一點,在引入失真合成數據時,如果我們試圖自己完成,那么引入的失真應該具有代表性,這些噪音或扭曲是有可能出現在測試集中的,所以對于字符識別例子來說,我們引入的扭曲實際上是合理的,因為像這樣的 A\rm AA 的圖像可能會出現在測試集中(上圖1),可能會有這種筆畫較粗的 A\rm AA,而右上角的那張圖(上圖2)也是很有可能見到的。對于音頻而言,現實中的確會出現連接信號很差的情況,或者不同的背景噪音,因此對于音頻問題,我們也需要合成有代表性的、我們想要正確分類或識別的樣本。
- 相反,如果只是將隨機的無意義的噪聲加入到數據中,并沒有多大幫助。這個例子中(上圖下),我們將原來的這張圖(上圖3)變成了它右側的 444 張圖,其中每個像素隨機加入一些高斯噪聲,即改變每個像素的亮度,如果只是隨機加入一些高斯噪聲到每個像素中,就只是完全沒有意義的噪聲。因此,除非覺得有可能在測試集中看到這種像素級的噪音,那么這種純隨機的無意義噪聲很可能是無用的。
- 這種人工數據合成的過程也需要一點技巧,有時候就是需要試一下,看看行不行。但是當我們在決定該添加哪種失真時,認真考慮一下添加什么樣的失真才是有意義的,怎樣才能使我們生成的訓練樣本至少有一定代表性是有可能在測試集中見到的樣本。
4. 生成訓練樣本前的工作和獲得更多數據的方法
- 最后我們再提幾點有關通過人工數據合成來生成大量數據。
1.Makesureyouhavealowbiasclassifierbeforeexpendingtheeffort.(Plotlearningcurves).E.g.keepincreasingthenumberoffeatures/numberofhiddenunitsinneuralnetworkuntilyouhavealowbiasclassifier.\begin{aligned} &\rm 1.\ Make\ \ sure\ \ you\ \ have\ \ a\ \ low\ \ bias\ \ classifier\ \ before\ \ expending\ \ the\\ &\ \ \ \rm effort.\ \ (Plot\ \ learning\ \ curves).\ \ E.g.\ \ keep\ \ increasing\ \ the\ \ number\\ &\ \ \ \rm of\ \ features/number\ \ of\ \ hidden\ \ units\ \ in\ \ neural\ \ network\ \ until\\ &\ \ \ \rm you\ \ have\ \ a\ \ low\ \ bias\ \ classifier.\\ \end{aligned} ?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.“Howmuchworkwoulditbetoget10xasmuchdataaswecurrentlyhave?”?Artificialdatasynthesis?Collect/labelityourself?“Crowdsource”??(E.g.AmazonMechanicalTurk)\begin{aligned} &\rm 2.\ “How\ \ much\ \ work\ \ would\ \ it\ \ be\ \ to\ \ get\ \ 10x\ \ as\ \ much\ \ data\ \ as\ \ we\\ &\ \ \ \rm currently\ \ have?”\\ &\ \ \ \rm - Artificial\ \ data\ \ synthesis\\ &\ \ \ \rm - Collect/label\ \ it\ \ yourself\\ &\ \ \ \rm - “Crowd\ \ source”\ \ (E.g.\ \ Amazon\ \ Mechanical\ \ Turk)\\ \end{aligned} ?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)? - 其次,就是在研究機器學習問題時,我們經常問的一個問題,就是獲得我們當前擁有的數據的 101010 倍的數據量需要花費多少努力,問題的答案通常是,其實沒有那么困難,可能最多花上幾天的工作,就可以獲得現有的 101010 倍數據,對于一個機器學習應用來說。并且通常假如我們能得到當前數據的 101010 倍數據,那么這就能使我們的算法運行地更好。
- 因此,有幾個方法來得到更多數據,本節中我們主要著眼于人工數據合成的方法,其中包括從零開始生成數據的隨機使用字體等等;以及第二種方法,利用現有的樣本,引入一些失真來增加擴大訓練集;別的一些獲得更多數據的方法的例子還有自己收集數據或是添加標簽。我們經常會做,而且很有用的一個計算是,獲得一定數量的樣本需要多少分鐘、多少小時,實際上是坐下來估計一下,假如給一個樣本加標簽需要 101010 多秒,然后再假設在我們的應用中當前有 100010001000 個標注樣本(所以 m=1000m=1000m=1000),然后坐下來自問一下實際收集一個樣本并添加標簽需要多少時間。有時它可能會花費我們 101010 秒來標記一個新樣本,因此如果我們需要 101010 倍多的樣本,我們就會做一個計算,假如我們需要 101010 秒來得到一個訓練樣本,如果我們需要 101010 倍多數據,即我們需要 10,00010,00010,000 個樣本,所以做一下計算這會花費我們多少時間來手工對 10,00010,00010,000 個樣本加標簽,如果給 111 個樣本加標簽需要 101010 秒。實際上工作量是非常之小的,有時只是幾天的時間,有時只是少數的幾周,許多小組都會吃驚于獲得更多的數據需要的工作是多么少,這樣做能顯著提高機器學習應用的性能;最后一個,有時用來獲得更多數據的方法叫做眾包(crowd sourcing),如今,有些網站或是一些服務商,能為我們提供網上雇人的服務,并且能以相對低廉的價格為我們標記大量的訓練集,這種眾包的方法或者叫眾包數據標記(crowd sourced data labeling),有學術文獻專門研究它,它有它的復雜之處,例如標記人員的可靠性,因為可能有成千上萬的世界各地的標記員以相對低廉的價格為我們的數據加標簽。我們剛才所說的也只是一個備選方案,可能 AmazonMechanicalTurk\rm Amazon\ \ Mechanical\ \ TurkAmazon??Mechanical??Turk 系統是當下最流行的眾包選擇,如果我們想要高質量的標簽的話,通常來說工作量不小,不過這還是一個值得考慮的選擇,如果你想嘗試在網上以相對低廉的價格雇傭很多人為你標記大量數據的話。
- 在本節中我們討論了人工數據合成的兩種方法,從零開始生成新數據,例如利用任意字體生成樣本,或是擴充一個已有的訓練集,通過將現有的標注樣本引入一些失真以生成額外的標注樣本。最后,希望大家能夠記住的一點是,假如我們遇到一個機器學習問題,有兩件事是值得做的,一個就是用學習曲線做一個合理檢驗,看更多的數據是否真的有用,第二個就是,假如情況是這樣,我們通常會坐下來并且捫心自問大概要花多少資源才能獲取到 101010 倍于當前擁有的數據,同時有時候你會驚訝于實現它其實很簡單,可能是幾天或者幾周的工作,并且這是一個很好的方法來大幅提高我們的機器學習算法性能。
四、上限分析:下一步要做的工作是什么(Ceiling analysis: What part of the pipeline to work on next )
- 在前面的章節中,我們不止一次地說過,當我們開發機器學習系統時,我們最寶貴的資源就是我們的時間。作為一個開發者,你需要正確選擇下一步的工作,或者也許你有一個開發團隊,或者一個工程師小組共同開發一個機器學習系統,同樣,最寶貴的還是開發系統所花費的時間,你需要盡量避免你、你的同事或者你的朋友花費了大量時間在某一個模塊上,在幾周甚至幾個月的努力以后才意識到所有這些付出的勞動都對你最終系統的表現并沒有太大的幫助。
- 本節我們將介紹一下關于上限分析(ceiling analysis) 的內容,當你自己或者你跟你的團隊,在設計某個機器學習系統工作流時,這種方式通常能提供一個很有價值的信號,很好地指導你在你的工作流中哪一部分最值得你花時間去研究。
1. 實例一:照片 OCR
- 為了講解上限分析,我們將繼續使用之前用過的照片 OCR\rm OCROCR 工作流的例子:
segmentationCharacter
recognition
- 之前的課程中我們講過這些方框,文本檢測、字符分割和字符識別。這里每個方框都可能需要一個小團隊來完成,當然也可以你一個人來構建整個系統,問題是你應該怎樣分配資源呢?也就是說這些模塊中哪一個、或者哪兩個或者說所有的這三個哪些是最值得你花費精力去改善它的效果的,這便是上限分析要做的事,跟其它機器學習系統的開發過程一樣,為了決定如何開發這個系統,一個有效的方法是對學習系統使用一個數值評價量度,假如我們用字符準確度作為這個度量,給定一個測試樣本圖像,那么這個數值就表示我們對測試圖像中的文本識別正確的比例,或者我們也可以選擇其他的某個數值評價度量值,假設不管選擇什么評價度量值,我們得到整個系統目前的準確率為 72%72\%72%。
| Overall system | 72% |
| Text detection | 89% |
| Character segmentation | 90% |
| Character recognition | 100% |
- 換句話說,我們有一些測試集圖像,并且對測試集中的每一幅圖像,我們都對其分別運行文本檢測、字符分割然后字符識別,然后我們發現在測試集上整個系統的總的準確率為 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. 實例二:人臉識別
①工作流
- 假如你用圖片做人臉識別,并且你想看這個照片,然后識別這個照片里的人是不是你的朋友,希望辨識出圖像中的人,這是一個偏人工智能的例子,當然這并不是現實中的人臉識別技術,但是我想通過這個例子展示一個工作流,給你一個關于上限分析的實例。
- 假如我們有張照片,我們設計了如下的工作流:
ImagePreprocess
(remove background)Face detectionEyes segmentationNose segmentationMouth segmentationLogistic regressionlabel
-
假如我們第一步要做的是圖像預處理,假如就用這張圖片(下圖1),現在我們想要把背景去掉,那么經過預處理背景就被去掉了(下圖2)。下一步我們希望檢測出人臉的位置,這通常通過一個學習算法來實現,我們會運行一個滑動窗分類器,在人臉上畫一個框(下圖3)。
-
在檢測到臉部以后,如果我們想要識別出這個人,那么眼睛是一個很重要的線索,事實上,要辨認出你的朋友你通常會看眼睛,這是個比較重要的線索,所以我們需要運行另一個分類器來檢測人的眼睛,分割出眼睛,這樣就提供了識別出一個人的很重要的特征,然后繼續找出臉上其他重要的部位,比如分割出鼻子,分割出嘴巴(上圖4)。這樣找出了眼睛、鼻子、嘴巴,所有這些都是非常有用的特征,可以被輸入給某個邏輯回歸的分類器,然后這個分類器的任務就是給出最終的標簽,辨識出這個人是誰。這是一個稍微復雜一些的流水線,如果你真的想識別出人的話,可能實際的工作流比這個還要復雜,但這是一個很好的例子用來弄清楚上限分析。
②上限分析
- 對這個流水線,怎么進行上限分析呢?我們還是每次關注一個步驟,假如說你的整個系統的準確率達到了 85%85\%85%,首先還是找到測試集,然后人工地給它真實的標簽,前景和背景的分割效果,找到測試集,然后用 Photoshop\rm PhotoshopPhotoshop 或者別的工具標記出哪些區域是背景,然后手動把背景刪掉,真實的標簽去掉這些背景,然后觀察準確率提高多少。
| Overall system | 85% |
| Preprocess (remove background) | 85.1% |
| Face detection | 91% |
| Eyes segmentation | 95% |
| Nose segmentation | 96% |
| Mouth segmentation | 97% |
| Logistic regression | 100% |
- 假設在這個例子中準確率提高了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)。照片 OCR\rm OCROCR 問題注重的問題是如何讓計算機更好地理解這些照片的環境,如何讓計算機讀出圖片中的文字信息,隨后我們介紹了流水線的概念,它已經在復雜的機器學習系統中滲透到各種應用中。同時也介紹了該系統的前三步:文字檢測、文字分割以及字符分類。
- 在滑動窗口中通過行人檢測和文本檢測的例子來說明滑動窗口的作用,我們使用一個滑動窗口,從圖像的第一行開始逐行移動,就這樣遍歷圖中所有不同的位置并且通過分類器進行分類。
- 在人工數據合成中我們討論了人工數據合成的兩種方法,從零開始生成新數據,例如利用任意字體生成樣本,或是擴充一個已有的訓練集,通過將現有的標注樣本引入一些失真以生成額外的標注樣本。同時也介紹了我們遇到一個機器學習問題兩件值得做的事,一個是用學習曲線做一個合理檢驗,看更多的數據是否真的有用,第二個是,我們應當坐下來并且捫心自問大概要花多少資源才能獲取到 101010 倍于當前擁有的數據,同時實現它其實很簡單,可能是幾天或者幾周的工作,并且這是一個很好的方法來大幅提高我們的機器學習算法性能。
- 上限分析是個很有用的工具,可以用來衡量模塊,當你想花精力到某個模塊上時,你可以確定這樣做會不會有效果,整個系統的表現會不會產生明顯的提高。我們不應該更多地去相信自己的直覺,相反地,如果要解決某個機器學習問題,最好能把問題分成多個模塊,然后做一下上限分析,這通常給我們更可靠更好的方法,來為我們決定該把勁兒往哪兒使,該提高哪個模塊的效果,這樣我們就會非常確認把這個模塊最好就能提高最后總體的性能。
總結
以上是生活随笔為你收集整理的机器学习(十八)应用实例:照片OCR的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: POJ-3386
- 下一篇: 基于FPGA的混沌信号发生器设计与实现