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~