前言:linux
接着coursera課程:Probabilistic Graphical Models 上的實驗3,本次實驗是利用馬爾科夫網絡(CRF模型)來完成單詞的OCR識別,每一個單詞由多個字母組合,每一個字母爲16×8大小的黑白圖片。本次實驗簡化了不少內容,不須要咱們去學這些參數(已提供),不須要掌握推理的方法(也提供了),目的是讓你們對CRF模型有個感性認識。馬爾科夫網絡相比貝葉斯網絡的優勢就是不用本身去肯定那些太明確結構(好比說那些因果關係)。網絡
matlab基礎知識:函數
n = norm(X):學習
計算X的誘導2範數。若是X爲向量,則n爲它的歐式距離。若是X爲矩陣,則n爲X的最大特徵值。測試
b = nchoosek(n,k):ui
這個是計算組合數的函數,從n箇中拿出k個的拿法。spa
C = vertcat(A1,...,AN):設計
該函數是將多個矩陣A2,...,AN在垂直方向上鍊接起來獲得C.code
關於實驗的一些註釋:orm
allWords:
裏面的每個樣本都是一個單詞,單詞的長度不必定相同。句子由字母構成,而每一個字母就是一副小圖片(16×8大小,且每一個像素都是0或1)。因此對馬爾科夫網絡而言,每一個訓練樣本是多張圖片。且樣本是帶有標籤的,標籤值是一個向量,向量長度和單詞長度同樣,向量元素值表示對應字母的序號(1~26分別對應a~z)。
P = ComputeImageFactor (img, imgModel):
這個函數其實就是一個softmax分類器的實現,輸入img經過softmax後獲得一個26維的輸出(模型參數已經保存在imgModel中了),輸出值表示該圖片內容爲26個字母的機率。只是不太明白爲何imgModel中參數只有25個字母的權值,另一個權值是在softmax進行歸一化前直接默認輸出爲0的(歸一化後固然不是0了),這樣作的理由?
factors = ComputeSingletonFactors (images, imageModel):
對應的模型爲:
練習1所對應的內容。images是一個結構體向量,裏面裝了多張圖片(能夠組成多個單詞)的信息(圖片內容和標籤)。imageModel是提供好了的模型的參數,這裏只需用到softmax部分的參數。每一張圖片在用softmax輸出時都對應一個factor,因此factors也是一個結構體向量。
allFactors = BuildOCRNetwork (images, imageModel, pairwiseModel, tripletList):
該函數的做用是對一個單詞的圖片創建它的各類factor集合。由於各類factor形式所須要的參數已經給出了,好比imageModel,pairwiseModel,tripletList(固然正常狀況下,這些參數是須要經過大量的單詞圖片樣原本訓練的)。
pred = RunInference (factors):
該函數是使用CRF模型來進行推理的函數。好比說已經用BuildOCRNetwork()函數算出了某個單詞圖片的factors,直接傳入本函數,就能夠獲得這個圖片序列所預測的單詞。
wordPredictions = ComputeWordPredictions (allWords, imageModel, pairwiseModel, tripletList):
該函數的做用是計算全部單詞圖片集(allWords中含有多個單詞的圖片)在CRF模型下的預測,每一個圖片序列獲得一個預測的單詞。內部實現固然是循環調用RunInference()函數。
[charAcc, wordAcc] = ScorePredictions (words, predictions, showOutput):
該函數的做用是:用訓練好的CRF模型對words進行預測,charAcc表示字母預測準確率,wordAcc表示單詞預測準確率。
實驗1完成後執行:
[charAcc, wordAcc] = ScoreModel(allWords, imageModel, [], []);
則會發現charAcc=76.70%,wordAcc=22.00%.
factors = ComputeEqualPairwiseFactors (images, K):
images是某個單詞的圖片序列,假設這個單詞的長度爲n,則該函數返回n-1個factor的集合。其中每一個factor表中都有K*K項,且其值都設爲1.
對應的模型爲:
factors = ComputePairwiseFactors (images, pairwiseModel, K):
實驗2的內容。這個函數和上面的函數是同樣的,只不過它的每一個factor的值是用模型中給定的權值。
實驗2後完成後:首先將函數BuildOCRNetwork()中第45行註釋掉,改成不等同的pairwiseModel,而後執行:
[charAcc, wordAcc] = ScoreModel(allWords, imageModel, pairwiseModel, [])
結果爲:charAcc=80.90%,wordAcc=30.00%. 能夠發現有較大提升。
實驗3對應的模型爲:
factors = ComputeTripletFactors (images, tripletList, K):
實驗3的內容。這個函數主要是求三元組形式的factor,每一個單詞的長度爲n,則返回一個n-2長度的factor列表,每張圖片對應一個factor表,每一個factor表有K^3項,裏面的值按照tripletList裏面的對應位置的參數給,其它值默認爲1. 由於若是按照k^3來計算的話,則須要17576種組合,而其中不少種組合是不常見的,因此本次實驗只給出了最多見的2000個組合的值。
實驗3完成後執行下面語句:
[charAcc, wordAcc] = ScoreModel(allWords, imageModel, pairwiseModel, tripletList)
結果爲:charAcc=81.62% ,wordAcc=37.00%. 有提升了一些。
sim = ImageSimilarity (im1, im2):
該函數爲計算兩張圖片im1和im2之間的類似度。具體距離計算方法能夠去查閱函數的代碼,這個方法有點意思,不過主要仍是在餘弦距離上改進的。
factor = ComputeSimilarityFactor (images, K, i, j):
實驗4的內容。這個factor的計算依據是:當2張圖片很是類似時,則它們被預測爲同一個字母的機率要大,反之要小。同理若是兩張圖片的所表示的字母是同樣的,則它們之間的權重應該爲這兩張圖片的類似度。images爲一個單詞的多張圖片,i和j爲這個圖片集的某2個下標。這2張圖片只生成一個factor,factor表格大小爲K*K,若是是相同字母,則值爲二者之間的類似度,不然爲1.
factors = ComputeAllSimilarityFactors (images, K):
練習5的內容,該函數是計算一個單詞圖片序列的全部類似度factor,共有0.5*K*(K-1)個,每一個factor表格大小爲K*K. 實驗過程可直接調用前面的函數:ComputeSimilarityFactor().
factors = ChooseTopSimilarityFactors (allFactors, F):
練習6的內容。該函數的做用是在全部的factor集(由兩兩組合構成)中選出類似度最大的F個。因爲每個factor的最大值在factor表中的對角線上,且有對角線上的值相同。因此隨便取對角線上一個元素便可。
固然了,上面幾回驗證都是在類似度取top-2的狀況下獲得的,若是不考慮類似度,則運行:
[charAcc, wordAcc] = ScoreModel(allWords, imageModel, pairwiseModel, tripletList)
結果爲:
charAcc=80.03% ,wordAcc=34.00%.
那麼若是採用top-4效果會不會考些呢?
依舊運行下面程序:
[charAcc, wordAcc] = ScoreModel(allWords, imageModel, pairwiseModel, tripletList)
則結果爲:charAcc=81.77% ,wordAcc=36.00%.比top-2時小效果還要稍微低一點,也就是說並非top數越高越好。另外,若是你將top數設置太大,則計算量太大,很容易電腦就內存不夠掛掉。
實驗總結:
由本次實驗可知,在真正使用CRF時,咱們須要學習imageModel, pairwiseModel, tripletList這些參數,這固然是經過大量訓練樣原本學習的,且類似度超參數top-F中的F也是須要手動去調的。另外,即便已經學習到了這些模型的參數,在用CRF對測試樣本進行預測時也是須要不少步驟的。而在本次實驗中,參數的學習以及模型的預測使用方法都是已知的,老師在該實驗設計時簡化了很多內容。不過在後續的實驗過程當中會陸續的補上。
若是遇到下列錯誤:
dlopen: cannot load any more object with static TLS
解決方法是:在matlab下,依次進入Preferences > General > Java-Heap Memory.增長這個內容,具體我也不知道該要用多少,因此我乾脆土豪了一把,拉到最大了。而後重啓matlab,若是還不行就重啓電腦。
若是在linux下,上面的方法可能不奏效,解決這個bug的方法能夠參考官方的bug解法方法,下載那個.zip並解壓後獲得libiomp5.so文件,而後替換matlab按照目錄下的~/R2013b/sys/os/glnxa64/libiomp5.so,重啓matlab便可。
The doinference command failed. Look at the file inf.log to diagnose the cause.
跟蹤定位到出錯的那一句,發現是在函數RunInference()裏面,由於有使用系統命令語句:
[retVal, output] = system(command);
而該語句是要使目錄下的文件doinference-linux,該文件不具備可執行權限,所以先用chmod對該文件設置爲可執行後就ok了。
參考資料: