第一部分 字典学习以及稀疏表示的概要
字典学习(Dictionary Learning)和稀疏表示(Sparse Representation)在学术界的正式称谓应该是稀疏字典学习(Sparse Dictionary Learning)。该算法理论包含两个阶段:字典构建阶段(Dictionary Generate)和利用字典(稀疏的)表示样本阶段(Sparse coding with a precomputed dictionary)。这两个阶段(如下图)的每个阶段都有许多不同算法可供选择,每种算法的诞生时间都不一样,以至于稀疏字典学习的理论提出者已变得不可考。笔者尝试找了Wikipedia和Google Scolar都无法找到这一系列理论的最早发起人。

这里有两个问题是必须要预先解释清楚:
问题1:我们为什么需要字典学习?
回答这个问题实际上就是要回答“稀疏字典学习 ”中的字典是怎么来的。做一个比喻,句子是人类社会最神奇的东西,人类社会的一切知识无论是已经发现的还是没有发现的都必然要通过句子来表示出来(从某种意义上讲,公式也是句子)。这样说来,人类懂得的知识可要算是极为浩繁的。有人统计过人类每天新产生的知识可以装满一个2T(2048G)大小的硬盘。但无论有多少句子需要被书写,对于一个句子来说它最本质的特征是什么呢?毫无疑问,是一个个构成这个句子的单词(对英语来说)或字(对汉语来说)。所以我们可以很傲娇的这样认为,无论人类的知识有多么浩繁,也无论人类的科技有多么发达,一本长不过20厘米,宽不过15厘米,厚不过4厘米的新华字典或牛津字典足以表达人类从古至今乃至未来的所有知识,那些知识只不过是字典中字的排列组合罢了!直到这里,我相信相当一部分读者或许在心中已经明白了字典学习的第一个好处——它实质上是对于庞大数据集的一种降维表示。第二,正如同字是句子最质朴的特征一样,字典学习总是尝试学习蕴藏在样本背后最质朴的特征(假如样本最质朴的特征就是样本最好的特征),这两条原因同时也是这两年深度学习之风日盛的情况下字典学习也开始随之升温的原因。题外话:现代神经科学表明,哺乳动物大脑的初级视觉皮层干就事情就是图像的字典表示。
问题2:我们为什么需要稀疏表示?
回答这个问题毫无疑问就是要回答“稀疏字典学习”中稀疏两字的来历。不妨再举一个例子。相信大部分人都有这样一种感觉,当我们在解涉及到新的知识点的数学题时总有一种累心(累脑)的感觉。但是当我们通过艰苦卓绝的训练将新的知识点牢牢掌握时,再解决与这个知识点相关的问题时就不觉得很累了。这是为什么呢?意大利罗马大学的Fabio Babiloni教授曾经做过一项实验,他们让新飞行员驾驶一架飞机并采集了他们驾驶状态下的脑电,同时又让老飞行员驾驶飞机并也采集了他们驾驶状态下的脑电。如下图所示:
 
 

随后Fabio教授计算出了两类飞行员的大脑的活跃状态,如下图:
 

左图是新飞行员(不熟练的飞行员)的大脑。图中黄色的部分,是被认为活跃的脑区。右图是老飞行员(熟练的飞行员)的大脑,黄色区域相比左边的图有明显的减少。换言之,针对某一特定任务(这里是飞行),熟练者的大脑可以调动尽可能少的脑区消耗尽可能少的能量进行同样有效的计算(所以熟悉知识点的你,大脑不会再容易觉得累了),并且由于调动的脑区很少,大脑计算速度也会变快,这就是我们称熟练者为熟练者的原理所在。站在我们所要理解的稀疏字典学习的角度上来讲就是大脑学会了知识的稀疏表示
 
稀疏表示的本质:用尽可能少的资源表示尽可能多的知识,这种表示还能带来一个附加的好处,即计算速度快。
 
在懂得“字典”和“稀疏”各自的那点事儿以后,我们还要再讲讲稀疏和字典共同的那点儿事。或许在大脑中“字典”和“稀疏”是两个不怎么想干的阶段,毕竟“字典”涉及初级视觉皮层,而“稀疏”涉及前额叶皮层。但是在计算机中,“字典”和“稀疏”却是一堆孪生兄弟。在学习样本字典之初的时候,稀疏条件就已经被加入了。我们希望字典里的字可以尽能的少,但是却可以尽可能的表示最多的句子。这样的字典最容易满足稀疏条件。也就是说,这个“字典”是这个“稀疏”私人订制的。
 
第二部分 稀疏字典学习的Python实现
 
用Python实现稀疏字典学习需要三个前提条件
1.安装NumPy
2.安装SciPy
3.安装Python机器学习工具包sklearn
为了避免过于麻烦的安装,这里我干脆建议诸位读者安装Python的商业发行版Anaconda,内含python集成开发环境和数百个常用的python支持包。具体安装过程和使用细节参见我的博客附录D Python接口大法
 
样例一:图片的稀疏字典学习
这段代码来源于Python的Dictionary Learning的官方文献教材,主要用途是教会用户通过字典学习对图片进行滤波处理。
step1:首先是各种工具包的导入和测试样例的导入
  1. from time import time
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. import scipy as sp
  5. from sklearn.decomposition import MiniBatchDictionaryLearning
  6. from sklearn.feature_extraction.image import extract_patches_2d
  7. from sklearn.feature_extraction.image import reconstruct_from_patches_2d
  8. from sklearn.utils.testing import SkipTest
  9. from sklearn.utils.fixes import sp_version
  10. if sp_version < (0, 12):
  11. raise SkipTest("Skipping because SciPy version earlier than 0.12.0 and "
  12. "thus does not include the scipy.misc.face() image.")
  13. try:
  14. from scipy import misc
  15. face = misc.face(gray=True)
  16. except AttributeError:
  17. # Old versions of scipy have face in the top level package
  18. face = sp.face(gray=True)
 
第1行:导入time模块,用于测算一些步骤的时间消耗
第3~5行:导入Python科学计算的基本需求模块,主要包括NumPy(矩阵计算模块)、SciPy(科学计算模块)和matplotlib.pyplot模块(画图)。有了这三个模块,Python俨然已是基础版的Matlab。
第7~11行:导入稀疏字典学习所需要的函数,下面分行解释
第7行:导入MiniBatchDictionaryLearning,MiniBatch是字典学习的一种方法,这种方法专门应用于大数据情况下字典学习。当数据量非常大时,严格对待每一个样本就会消耗大量的时间,而MiniBatch通过降低计算精度来换取时间利益,但是仍然能够通过大量的数据学到合理的词典。换言之,普通的DictionaryLearning做的是精品店,量少而精,但是价格高。MiniBatchDictionaryLearning做的是批发市场,量大不精,薄利多销。
第8行:导入碎片提取函数extract_patches_2d。调用该函数将一张图片切割为一个一个的pitch。如果一张图片相当于一篇文章的话,那么该函数的目标就是把文章中的每个句子都找到,这样才方便提取蕴藏在每个句子中的字。图片和pitch的关系如下图所示:
整张头像的照片是个图片,通过对图片的分割可以将图片分割为一个一个的小块,也就是一个个Pitch。如果对pitch仍然不了解,只好请你看这个:http://blog.csdn.net/zouxy09/article/details/8775488
第9行:导入图片复原函数reconstruct_from_patches_2d,它可以通过pitch复原一整张图片。
第10行:导入测试工具nose下的异常抛出函数SkipTest
第11行:导入SciPy版本检测函数sp_version用于检测版本高低,版本低于0.12的SciPy没有我们需要的样本测试用例
第13~15行:检测SciPy版本,如果版本太低就抛出一个异常。程序运行结束
第16~21行:尝试打开样本测试用例,如果打不开就抛出一个异常。
 
step2:通过测试样例计算字典V
  1. # Convert from uint8 representation with values between 0 and 255 to
  2. # a floating point representation with values between 0 and 1.
  3. face = face / 255.0
  4. # downsample for higher speed
  5. face = face[::2, ::2] + face[1::2, ::2] + face[::2, 1::2] + face[1::2, 1::2]
  6. face = face / 4.0
  7. height, width = face.shape
  8. # Distort the right half of the image
  9. print('Distorting image...')
  10. distorted = face.copy()
  11. distorted[:, width // 2:] += 0.075 * np.random.randn(height, width // 2)
  12. # Extract all reference patches from the left half of the image
  13. print('Extracting reference patches...')
  14. t0 = time()
  15. patch_size = (7, 7)
  16. data = extract_patches_2d(distorted[:, :width // 2], patch_size)
  17. data = data.reshape(data.shape[0], -1)
  18. data -= np.mean(data, axis=0)
  19. data /= np.std(data, axis=0)
  20. print('done in %.2fs.' % (time() - t0))
  21. print('Learning the dictionary...')
  22. t0 = time()
  23. dico = MiniBatchDictionaryLearning(n_components=100, alpha=1, n_iter=500)
  24. V = dico.fit(data).components_
  25. dt = time() - t0
  26. print('done in %.2fs.' % dt)
  27. plt.figure(figsize=(4.2, 4))
  28. for i, comp in enumerate(V[:100]):
  29. plt.subplot(10, 10, i + 1)
  30. plt.imshow(comp.reshape(patch_size), cmap=plt.cm.gray_r,
  31. interpolation='nearest')
  32. plt.xticks(())
  33. plt.yticks(())
  34. plt.suptitle('Dictionary learned from face patches\n' +
  35. 'Train time %.1fs on %d patches' % (dt, len(data)),
  36. fontsize=16)
  37. plt.subplots_adjust(0.08, 0.02, 0.92, 0.85, 0.08, 0.23)#left, right, bottom, top, wspace, hspace
 
第3行:读入的face大小在0~255之间,所以通过除以255将face的大小映射到0~1上去
第6~7行:对图形进行采样,把图片的长和宽各缩小一般。记住array矩阵的访问方式      array[起始点:终结点(不包括):步长]
第8行:图片的长宽大小
第12行:将face的内容复制给distorted,这里不用等号因为等号在python中其实是地址的引用。
第13行:对照片的右半部分加上噪声,之所以左半部分不加是因为教材想要产生一个对比的效果
第17行:开始计时,并保存在t0中
第18行:tuple格式的pitch大小
第19行:对图片的左半部分(未加噪声的部分)提取pitch
第20行:用reshape函数对data(94500,7,7)进行整形,reshape中如果某一位是-1,则这一维会根据(元素个数/已指明的维度)来计算这里经过整形后data变成(94500,49)
第21~22行:每一行的data减去均值除以方差,这是zscore标准化的方法
第26行:初始化MiniBatchDictionaryLearning类,并按照初始参数初始化类的属性
第27行:调用fit方法对传入的样本集data进行字典提取,components_返回该类fit方法的运算结果,也就是我们想要的字典V
第31~41行:画出V中的字典,下面逐行解释
第31行:figsize方法指明图片的大小,4.2英寸宽,4英寸高。其中一英寸的定义是80个像素点
第32行:循环画出100个字典V中的字
第41行:6个参数与注释后的6个属性对应
运行程序,查看输出结果:
step3:画出标准图像和真正的噪声,方便同之后字典学习学到的噪声相比较
  1. def show_with_diff(image, reference, title):
  2. """Helper function to display denoising"""
  3. plt.figure(figsize=(5, 3.3))
  4. plt.subplot(1, 2, 1)
  5. plt.title('Image')
  6. plt.imshow(image, vmin=0, vmax=1, cmap=plt.cm.gray,
  7. interpolation='nearest')
  8. plt.xticks(())
  9. plt.yticks(())
  10. plt.subplot(1, 2, 2)
  11. difference = image - reference
  12. plt.title('Difference (norm: %.2f)' % np.sqrt(np.sum(difference ** 2)))
  13. plt.imshow(difference, vmin=-0.5, vmax=0.5, cmap=plt.cm.PuOr,
  14. interpolation='nearest')
  15. plt.xticks(())
  16. plt.yticks(())
  17. plt.suptitle(title, size=16)
  18. plt.subplots_adjust(0.02, 0.02, 0.98, 0.79, 0.02, 0.2)
  19. show_with_diff(distorted, face, 'Distorted image')
程序输出如下图所示:
step4:测试不同的字典学习方法和参数对字典学习的影响
  1. print('Extracting noisy patches... ')
  2. t0 = time()
  3. data = extract_patches_2d(distorted[:, width // 2:], patch_size)
  4. data = data.reshape(data.shape[0], -1)
  5. intercept = np.mean(data, axis=0)
  6. data -= intercept
  7. print('done in %.2fs.' % (time() - t0))
  8. transform_algorithms = [
  9. ('Orthogonal Matching Pursuit\n1 atom', 'omp',
  10. {'transform_n_nonzero_coefs': 1}),
  11. ('Orthogonal Matching Pursuit\n2 atoms', 'omp',
  12. {'transform_n_nonzero_coefs': 2}),
  13. ('Least-angle regression\n5 atoms', 'lars',
  14. {'transform_n_nonzero_coefs': 5}),
  15. ('Thresholding\n alpha=0.1', 'threshold', {'transform_alpha': .1})]
  16. reconstructions = {}
  17. for title, transform_algorithm, kwargs in transform_algorithms:
  18. print(title + '...')
  19. reconstructions[title] = face.copy()
  20. t0 = time()
  21. dico.set_params(transform_algorithm=transform_algorithm, **kwargs)
  22. code = dico.transform(data)
  23. patches = np.dot(code, V)
  24. patches += intercept
  25. patches = patches.reshape(len(data), *patch_size)
  26. if transform_algorithm == 'threshold':
  27. patches -= patches.min()
  28. patches /= patches.max()
  29. reconstructions[title][:, width // 2:] = reconstruct_from_patches_2d(
  30. patches, (height, width // 2))
  31. dt = time() - t0
  32. print('done in %.2fs.' % dt)
  33. show_with_diff(reconstructions[title], face,
  34. title + ' (time: %.1fs)' % dt)
  35. plt.show()
 
第3行:提取照片中被污染过的右半部进行字典学习。
第10~16行:四中不同的字典表示策略
第23行:通过set_params对第二阶段的参数进行设置
第24行:transform根据set_params对设完参数的模型进行字典表示,表示结果放在code中。code总共有100列,每一列对应着V中的一个字典元素,所谓稀疏性就是code中每一行的大部分元素都是0,这样就可以用尽可能少的字典元素表示回去。
第25行:code矩阵乘V得到复原后的矩阵patches
第28行:将patches从(94500,49)变回(94500,7,7)
第32行:通过reconstruct_from_patches_2d函数将patches重新拼接回图片
 
该程序输出为四中不同转换算法下的降噪效果:
 
 

Dictionary Learning(字典学习、稀疏表示以及其他)的更多相关文章

  1. 稀疏编码(sparse code)与字典学习(dictionary learning)

    Dictionary Learning Tools for Matlab. 1. 简介 字典 D∈RN×K(其中 K>N),共有 k 个原子,x∈RN×1 在字典 D 下的表示为 w,则获取较为 ...

  2. 学习人工智能的第五个月[字典学习[Dictionary Learning,DL]]

    摘要: 大白话解释字典学习,分享第五个月的学习过程,人生感悟,最后是自问自答. 目录: 1.字典学习(Dictionary Learning,DL) 2.学习过程 3.自问自答 内容: 1.字典学习( ...

  3. 字典学习(Dictionary Learning, KSVD)详解

    注:字典学习也是一种数据降维的方法,这里我用到SVD的知识,对SVD不太理解的地方,可以看看这篇博客:<SVD(奇异值分解)小结 >. 1.字典学习思想 字典学习的思想应该源来实际生活中的 ...

  4. 字典学习(Dictionary Learning)

    0 - 背景 0.0 - 为什么需要字典学习? 这里引用这个博客的一段话,我觉得可以很好的解释这个问题. 回答这个问题实际上就是要回答“稀疏字典学习 ”中的字典是怎么来的.做一个比喻,句子是人类社会最 ...

  5. 机器学习(Machine Learning)&深度学习(Deep Learning)资料【转】

    转自:机器学习(Machine Learning)&深度学习(Deep Learning)资料 <Brief History of Machine Learning> 介绍:这是一 ...

  6. 机器学习(Machine Learning)&深度学习(Deep Learning)资料汇总 (上)

    转载:http://dataunion.org/8463.html?utm_source=tuicool&utm_medium=referral <Brief History of Ma ...

  7. 联合CRF和字典学习的自顶向下的视觉显著性-全文解读

    top-down visual saliency via joint CRF anddictionary learning 自顶向下的视觉显著性是使用目标对象的可判别表示和一个降低搜索空间的概率图来进 ...

  8. 论文阅读笔记(十九)【ITIP2017】:Super-Resolution Person Re-Identification With Semi-Coupled Low-Rank Discriminant Dictionary Learning

    Introduction (1)问题描述: super resolution(SP)问题:Gallery是 high resolution(HR),Probe是 low resolution(LR). ...

  9. 论文阅读笔记(六)【TCSVT2018】:Semi-Supervised Cross-View Projection-Based Dictionary Learning for Video-Based Person Re-Identification

    Introduction (1)Motivation: ① 现实场景中,给所有视频进行标记是一项繁琐和高成本的工作,而且随着监控相机的记录,视频信息会快速增多,因此需要采用半监督学习的方式,只对一部分 ...

随机推荐

  1. 关于数组去重的几种方法-------javascript描述

    第一种方法:借助json对象来实现,若json对象中无该属性则添加,否则不添加,最后返回json对象的属性,时间复杂度为O(n) function deleteArrayRepeat(arr) { v ...

  2. bzoj4555题解

    我们计算$f(i)=\sum_{j=1}^i S(i,j)\times 2^j\times (j!)$,容(o)易(e)知(i)道(s)$f(i)$的指数生成函数为$\frac{1}{3-2\time ...

  3. Eclipse使用Maven tomcat:run命令启动web项目时修改默认端口

  4. U3D学习笔记1: HelloWorld

    Unity 版本: 5.3.5.f1 Hello World工程 1.新建工程 HelloWorld U3D可选2D和3D游戏   2.新建C#脚本文件 在project栏的assets目录右键-&g ...

  5. CentOS 6.3下Samba服务器的安装与配置方法(图文详解)

    这篇文章主要介绍了CentOS 6.3下Samba服务器的安装与配置方法(图文详解),需要的朋友可以参考下   一.简介  Samba是一个能让Linux系统应用Microsoft网络通讯协议的软件, ...

  6. Python之mmap内存映射模块(大文本处理)说明

    背景: 通常在UNIX下面处理文本文件的方法是sed.awk等shell命令,对于处理大文件受CPU,IO等因素影响,对服务器也有一定的压力.关于sed的说明可以看了解sed的工作原理,本文将介绍通过 ...

  7. @RequestMapping 用法详解之地址映射

    @RequestMapping 用法详解之地址映射 引言: 前段时间项目中用到了RESTful模式来开发程序,但是当用POST.PUT模式提交数据时,发现服务器端接受不到提交的数据(服务器端参数绑定没 ...

  8. Alipay秘钥问题

    有三种秘钥一个是应用公钥 一个是支付宝公钥 p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco } span.s1 { text-d ...

  9. 最终版的Web(Python实现)

    天啦,要考试了,要期末考试了,今天把最终版的Python搭建Web代码先写这里记下了.详细的过程先不写了. 这次是在前面的基础上重写 HTTPServer 与 BaseHTTPRequestHandl ...

  10. PowerDisner15 关于生成表带双""号问题

    我们可以尝试在DBMS配置文件中修改相应的格式来解决. 在PowerDesigner中 选择 Database->Edit current database->Script->Sql ...