Dictionary Learning(字典学习、稀疏表示以及其他)

2023-11-04

第一部分 字典学习以及稀疏表示的概要
字典学习(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重新拼接回图片
 
该程序输出为四中不同转换算法下的降噪效果:
 
 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐

  • JS大坑之19位数的Number型精度丢失问题详解

    这篇文章主要介绍了JS大坑之19位数的Number型精度丢失问题 文中通过示例代码介绍的非常详细 对大家的学习或者工作具有一定的参考学习价值 有兴趣的朋友们可以一起来学习探讨 最近在实现一个需求的时候 需要接入第三方的接口 先调用A接口 A
  • 关于ip5306芯片按键关机后仍然有输出

    官方手册中提到 负载自动检测时间 TloadD 负载电流持续小于 45mA 32 s时 芯片会自动进入休眠状态 实际上可能会因为个体差异 芯片空载就60ma 导致无法关机 实际上做这个芯片测试 发现了几个问题 芯片PIN5按键不可抛弃 如果
  • 计算机网络原理选择题

    1 1 电信业一般认为宽带骨干网数据传输速率应达到 d a 640kbps b 640mbps c 1gbps d 2gbps 2 异步时分多路复用 tdm 技术中的时间片分配策略是 c a 预先分配但不固定 b 预先分配固定不变 c 动态
  • 第八章 真实的谎言

    第八章 真实的谎言 我先给大家讲一个石头汤的故事 很久以前 在东欧的一个地方 发生了一次大饥荒 人们都以戒备的心理囤积起他们可以找到的任何食物 并把这些食物都藏了起来 甚至于连他们的朋友和邻居都 不告诉 有一天 一个小商贩驾着他的马车来到一
  • Ant Design与Ant Design pro入门

    一 Ant Design入门 1 什么是Ant Design Ant Design是阿里蚂蚁金服团队基于React开发的ui组件 主要用于中后台系统的使用 官网 https ant design index cn 特性 提炼自企业级中后台产
  • 网易笔试编程题-不要二

    题目描述 二货小易有一个W H的网格盒子 网格的行编号为0 H 1 网格的列编号为0 W 1 每个格子至多可以放一块蛋糕 任意两块蛋糕的欧几里得距离不能等于2 对于两个格子坐标 x1 y1 x2 y2 的欧几里得距离为 x1 x2 x1 x
  • boa服务器实现CGI功能

    CGI简介 CGI 是Web 服务器运行时外部程序的规范 按CGI 编写的程序可以扩展服务器功能 CGI 应用程序能与浏览器进行交互 还可通过数据库API 与数据库服务器等外部数据源进行通信 从数据库服务器中获取数据 格式化为HTML文档后
  • 07 Qt自定义控件

    在搭建Qt窗口界面的时候 在一个项目中很多窗口 或者是窗口中的某个模块会被经常性的重复使用 一般遇到这种情况我们都会将这个窗口或者模块拿出来做成一个独立的窗口类 以备以后重复使用 首先需要通过项目添加C 类 继承于QWidget 并在类中实
  • c++中的前置和后置加加没你想的这么简单

    1 前置 和后置 的区别1 前置是先加后赋值 后置是先赋值再加 2 前置 比后置 运行的速度快 在汇编底层中后置 会比前置 多一行 当然我这demo不是很准确毕竟也是有偶然的 但是确实是前置 快 3 作为学者的我们应该一探究竟 其实前置 是
  • 开发web系统利用路由能节省系统资源

    author skate time 2010 06 04 开发web系统利用路由能节省系统资源 今天早晨坐车来公司的时候 看见路上实时路况图 上面实时记录着每条公路的实时路况 每个非公交车司机 就可以根据实时路况图来选择最佳路线 这样不但节
  • Unity3D基础知识之Camera摄像机及其属性

    Unity3D基础知识之摄像机Camera 一 简介 Camera 附加了摄像机Camera组件的游戏对象 向玩家捕获和显示世界的设备 同时在一个场景中摄像机的数量不限 组件 Transform 变换组件 Camera摄像机 向玩家捕获和显
  • 深度学习中epoch、batch、step、iteration等神经网络参数是什么意思?

    epoch 表示将训练数据集中的所有样本都过一遍 且仅过一遍 的训练过程 在一个epoch中 训练算法会按照设定的顺序将所有样本输入模型进行前向传播 计算损失 反向传播和参数更新 一个epoch通常包含多个step batch 一般翻译为
  • goland面试题第八天

    第八天 1 关于init函数 下面说法正确的是 A 一个包中 可以包含多个 init 函数 B 程序编译时 先执行依赖包的 init 函数 再执行 main 包内的 init 函数 C main 包中 不能有 init 函数 D init
  • conda和pip都可以安装Python包,那么它们有哪些区别呢?

    文章目录 conda和pip都可以安装Python包 那么二者有什么区别呢 如果想单独了解conda可以查看这篇文章 conda详细的使用教程 不仅能够管理Python包 还能管理虚拟环境 了解pip可以查看这篇文章 Python包管理工具
  • lambda no instance(s) of type variable(s) T exist so that void conforms to R

    代码如下出现标题报错 List
  • 初学TypeScript

    TypeScript介绍 开发环境搭建 常用数据类型 1 什么是TypeScript TypeScript 是JavaScript的一个超集 支持ECMAScript 6标准 Typescript由微软开发的自由和开源的编程语言 TypeS
  • 合作搜索优化算法(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 Matlab代码实现 4 参考文献 1 概述 合作搜索算法 CSA 在问题空间中随机生成
  • flutter-使用第三方库,编译和运行版本不一致问题 2

    问题 接着上一个问题 如果是继续有问题 你讲看到这篇文章 新的问题又出现啦 如 Command xx xx develop android flutter app android gradlew app properties Finishe
  • Anaconda切换python版本

    比如 我的 已经安装好了anaconda4 即已经有了python3 5 现在想切换3 7 安装3 7 命令行运行 前提是anaconda环境变量已经配置好 创建一个名为python37的环境 指定Python版本是3 7 conda会为我
  • Dictionary Learning(字典学习、稀疏表示以及其他)

    第一部分 字典学习以及稀疏表示的概要 字典学习 Dictionary Learning 和稀疏表示 Sparse Representation 在学术界的正式称谓应该是 稀疏字典学习 Sparse Dictionary Learning 该