1. 程式人生 > >Coursera概率圖模型(Probabilistic Graphical Models)第三週程式設計作業分析

Coursera概率圖模型(Probabilistic Graphical Models)第三週程式設計作業分析

Markov Networks for OCR

光學字元識別的馬爾科夫網路

 

說到光學字元識別(OCR),此前筆者首先想到的會是卷積神經網路,而單詞識別則會考慮使用遞迴神經網路。而本週的作業則基於馬爾科夫網路構建了一個較為基礎OCR系統,目的也主要是讓我們對馬爾科夫網路有個感性的認知。網路所需要的的所有引數題目都已經訓練完畢,而一些字元識別中的核心演算法如影象間的相似度計算題目也都直接提供了……

 

筆者在剛讀本科的時候,有幸看過一本《科學美國人》的《數學遊戲》專欄集結本,其中《變佳作為夢囈》一文就提到了將莎士比亞名著中字元出現的頻率以及字元之間的連線關係進行學習,形成字元間的概率表(基本等同於我們這一週學的馬爾科夫網路╮(╯▽╰)╭),再由概率表生成一段乍看上去有點意思仔細一讀狗屁不通的文章……原文還提到了對Basic語言的程式碼進行學習,再由所得的概率表自動生產一段Basic程式碼……學習的效果如下圖所示,大家自行體會:

 

 

 

當然,上面的結果已經是上古時代先賢們探索時期的產物了。但這篇文章直接讓筆者對馬爾科夫網路有了一個最基本的印象:能夠較為自然地反映事物之間的聯絡。而英文單詞的字元之間,也正是存在著一定的聯絡,比如xzw這種字元組合在英文單詞中基本見不到,而ing的組合出現頻率則較高。我們平時在記憶英語單詞的時候,也大多會採用詞根詞綴記憶法(我覺得能聽懂這門課的同學英語都不會太差……畢竟這課程基本沒有中文字幕……)。因此,馬爾科夫網路在字元識別上的確有較為優秀的表現。

 

1.構建基礎光學字元識別網路

 

聽過吳恩達大神的機器學習課程的同學們都知道,機器學習課程的第三次作業也是將神經網路的引數全部訓練完畢,只要我們完成基本網路的構架即可,第四次作業才是構建完成的神經網路,完成引數訓練的工作。鑑於Koller和吳恩達同事多年,我感覺這個套路他們是有溝通過的……

 

ComputeSingletonFactors.m 計算單獨因子

 

我們開啟ComputeImageFactor.m檔案,仔細看一下的話,不難發現這就是一個softmax分類器……這裡也主要是考慮對單個字元影象的識別問題。

 

因子factors的結構及意義如下:

var:表示字元圖片的編號。

card:表示字元圖片的總分類數,26個小寫字母。

val:表示字元圖片對應各分類的置信度,由ComputeImageFactor計算得出。

 

參考程式碼如下:

% Your code here:

for ii = 1 : n

    factors(ii).var = ii;

    factors(ii).card = imageModel.K;

    factors(ii).val = ComputeImageFactor(images(ii).img, imageModel);

end

2.擴充套件網路

 

只考慮對字元影象的識別的話,和馬爾科夫網路其實也沒有什麼關係……馬爾科夫網路的牛逼之處也正是在於其能夠通過字元間的概率關係來提升識別的效果。

 

ComputeEqualPairwiseFactors.m 計算相同成對因子

 

這個函式是ComputePairwiseFactors.m函式的前身,建立因子的基本結構,而將因子的val全部置1即可。

 

因子factors的結構及意義如下:

var:表示兩個字元圖片的編號。

card:表示兩個字元圖片各自可能的取值數量,即[26, 26]。

val:表示相應字元組合的置信度,這裡直接全部取1。

 

參考程式碼如下:

% Your code here:

for ii = 1 : n - 1

    factors(ii).var = [ii, ii + 1];

    factors(ii).card = [K, K];

    factors(ii).val = ones(K * K, 1);

end

 

ComputePairwiseFactors.m 計算成對因子

 

相比上面的函式,這裡的置信度由pairwiseModel給出而非直接置1。

 

因子factors的結構及意義如下:

var:表示兩個字元圖片的編號。

card:表示兩個字元圖片各自可能的取值數量,即[26, 26]。

val:表示相應字元組合的置信度,由pairwiseModel直接給出。

 

 

參考程式碼如下:

% Your code here:

for ii = 1 : n - 1

    factors(ii).var = [ii, ii + 1];

    factors(ii).card = [K, K];

    factors(ii).val = reshape(pairwiseModel, K * K, 1);

end

 

 

ComputeTripletFactors.m 計算三聯因子

 

題目也提供了三聯表tripletList,用來描述連續三個字母的出現頻率。三聯表中不存在的組合的val值置1。

 

因子factors的結構及意義如下:

var:表示三個字元圖片的編號。

card:表示三個字元圖片各自可能的取值數量,即[26, 26, 26]。

val:表示相應字元組合的置信度,由tripletList直接給出。

 

參考程式碼如下:

% Your code here:

val = ones(K * K * K, 1);

for ii = 1 : length(tripletList)

    indices = AssignmentToIndex(tripletList(ii).chars, [K, K, K]);

    val(indices) = tripletList(ii).factorVal;

end



for ii = 1 : n - 2

    factors(ii).var = [ii, ii + 1, ii + 2];

    factors(ii).card = [K, K, K];

    factors(ii).val = val;

end

 

以上因子主要是描述字元標籤之間的關聯性,與字元影象本身還沒啥關係。下面則通過對同一單詞中不同字元影象之間的相似性關係,來構建因子進一步提升識別準確率。

 

===============================分割線================================

 

ComputeSimilarityFactor.m 計算相似因子

 

這個函式的邏輯是:如果兩個字元影象在之前被識別出是相同的字母,則由ImageSimilarity函式計算出它們之間的相似度,不然將它們之間的相似度置1。

 

因子factors的結構及意義如下:

var:表示兩個字元圖片在整個單詞中的位置編號。

card:表示兩個字元圖片各自可能的取值數量,即[26, 26]。

val:表示字元圖片之間的相似度,由ImageSimilarity函式計算得出。

 

參考程式碼如下:

% Your code here:

factor.var = [i, j];

factor.card = [K, K];

factor.val = ones(K * K, 1);

for ii = 1 : K

    index = AssignmentToIndex([ii, ii], [K, K]);

    factor.val(index) = ImageSimilarity(images(i).img, images(j).img);

end

 

ComputeAllSimilarityFactors.m 計算全部相似因子

 

基於上邊的ComputeSimilarityFactor函式,計算單詞中所有兩個字母組合的相似因子。

 

參考程式碼如下:

% Your code here:

kk = 1;

for ii = 1 : n

    for jj = ii + 1 : n

        factors(kk) = ComputeSimilarityFactor(images, K, ii, jj);

        kk = kk + 1;

    end

end

 

ChooseTopSimilarityFactors.m 選擇最優相似因子

 

在ComputeAllSimilarityFactors.m的基礎上,選擇相似度最高的F個因子。這裡我們注意相似因子val的任一對角元素即可反映兩圖片之間的相似性即可。

 

參考程式碼如下:

% Your code here:

SimilarityScore = zeros(length(allFactors), 1);

for ii = 1 : length(allFactors)

    SimilarityScore(ii) = allFactors(ii).val(1);

end

[~, indeces] = sort(SimilarityScore, 'descend');



factors = repmat(struct('var', [], 'card', [], 'val', []), F, 1);

for ii = 1 : F

    factors(ii) = allFactors(indeces(ii));

end

 

由於筆者的電腦無法執行ScoreModel 函式,所以也沒辦法直觀的判斷出不同網路模組對分類正確率的貢獻,反正根據題目pdf文件的說法是單詞的識別正確率會從22%上升到37%,同時字元識別率也會從76.7%上升到81.62%。

 

附上交作業的截圖:

 

 

下週也要繼續加油~fighting~