注:字典学习也是一种数据降维的方法,这里我用到SVD的知识,对SVD不太理解的地方,可以看看这篇博客:《SVD(奇异值分解)小结 》;数据集:https://pan.baidu.com/s/1ZmpUSIscy4VltcimwwIWew

1、字典学习思想

字典学习的思想应该源来实际生活中的字典的概念。字典是前辈们学习总结的精华,当我们需要学习新的知识的时候,不必与先辈们一样去学习先辈们所有学习过的知识,我们可以参考先辈们给我们总结的字典,通过查阅这些字典,我们可以大致学会到这些知识。

为了将上述过程用准确的数学语言描述出来,我们需要将“总结字典”、“查阅字典”做出一个更为准确的描述。就从我们的常识出发:

  1. 我们通常会要求的我们的字典尽可能全面,也就是说总结出的字典不能漏下关键的知识点。
  2. 查字典的时候,我们想要我们查字典的过程尽可能简洁,迅速,准确。即,查字典要快、准、狠。
  3. 查到的结果,要尽可能地还原出原来知识。当然,如果要完全还原出来,那么这个字典和查字典的方法会变得非常复杂,所以我们只需要尽可能地还原出原知识点即可。

注: 以上内容,完全是自己的理解,如有不当之处,欢迎各位拍砖。

下面,我们要讨论的就是如何将上述问题抽象成一个数学问题,并解决这个问题。

2、字典学习数学模型

2.1 数学描述

我们将上面的所提到的关键点用几个数学符号表示一下:

  • “以前的知识”,更专业一点,我们称之为原始样本,用矩阵\(\mathbf{Y}\)表示;
  • “字典”,我们称之为字典矩阵,用\(\mathbf{D}\)表示,“字典”中的词条,我们称之为原子(atom),用列向量\(\mathbf{d}_k\)表示;
  • “查字典的方法”,我们称为稀疏矩阵,用\(\mathbf{X}\);
  • “查字典的过程”,我们可以用矩阵的乘法来表示,即\(\mathbf{DX}\)。

用数学语言描述,字典学习的主要思想是,利用包含\(K\)个原子\(\mathbf{d}_k\)的字典矩阵\(\mathbf{D}\in \mathbf{R}^{m \times K}\),稀疏线性表示原始样本\(\mathbf{Y} \in \mathbf{R}^{m \times n}\)(其中\(m\)表示样本数,\(n\)表示样本的属性),即有\(\mathbf{Y=DX}\)(这只是我们理想的情况),其中\(\mathbf{X} \in \mathbf{R}^{K \times n}\)为稀疏矩阵,可以将上述问题用数学语言描述为如下优化问题

\[\min_{\mathbf{D,\ X}}{\|\mathbf{Y}-\mathbf{DX}\|^2_F},\quad \text{s.t.}\ \forall i,\ \|\mathbf{x}_i\|_0 \le T_0
\tag{2-1}
\]

或者

\[\min_{\mathbf{D,\ X}}\sum_i\|\mathbf{x}_i\|_0,
\quad \text{s.t.}\ \min_{\mathbf{D,\ X}}{\|\mathbf{Y}-\mathbf{DX}\|^2_F} \le \epsilon,
\tag{2-2}
\]

上式中\(\mathbf{X}\)为稀疏编码的矩阵,\(\mathbf{x}_i\,\ (i=1,2,\cdots,K)\)为该矩阵中的行向量,代表字典矩阵的系数。

注: \(\|\mathbf{x}_i\|_0\)表示零阶范数,它表示向量中不为0的数的个数。

2.2 求解问题

式(2-1)的目标函数表示,我们要最小化查完的字典与原始样本的误差,即要尽可能还原出原始样本;它的限的制条件\(\|\mathbf{x}_i\|_0 \le T_0\),表示查字典的方式要尽可能简单,即\(\mathbf{X}\)要尽可能稀疏。式(2-2)同理。

式(2-1)或式(2-2)是一个带有约束的优化问题,可以利用拉格朗日乘子法将其转化为无约束优化问题

\[\min_{\mathbf{D,\ X}}{\|\mathbf{Y}-\mathbf{DX}\|^2_F}+\lambda\|\mathbf{x}_i\|_1
\tag{2-3}
\]

注: 我们将\(\|\mathbf{x}_i\|_0\)用\(\|\mathbf{x}_i\|_1\)代替,主要是\(\|\mathbf{x}_i\|_1\)更加便于求解。

这里有两个优化变量\(\mathbf{D,\ X}\),为解决这个优化问题,一般是固定其中一个优化变量,优化另一个变量,如此交替进行。式(2-3)中的稀疏矩阵\(\mathbf{X}\)可以利用已有经典算法求解,如Lasso(Least Absolute Shrinkage and Selection Operator)、OMP(Orthogonal Matching Pursuit),这里我重点讲述如何更新字典\(\mathbf{D}\),对更新\(\mathbf{X}\)不多做讨论。

假设\(\mathbf{X}\)是已知的,我们逐列更新字典。下面我们仅更新字典的第\(k\)列,记\(\mathbf{d}_k\)为字典\(\mathbf{D}\)的第\(k\)列向量,记\(\mathbf{x}^k_T\)为稀疏矩阵\(\mathbf{X}\)的第\(k\)行向量,那么对式(2-1),我们有

\[\begin{aligned}
{\|\mathbf{Y}-\mathbf{DX}\|^2_F}
=&\left\|\mathbf{Y}-\sum^K_{j=1}\mathbf{d}_j\mathbf{x}^j_T\right\|^2_F \\
=&\left\|\left(\mathbf{Y}-\sum_{j\ne k}\mathbf{d}_j\mathbf{x}^j_T\right)-\mathbf{d}_k\mathbf{x}^k_T\right\|^2_F\\
=&\left\|\mathbf{E}_k - \mathbf{d}_k\mathbf{x}_T^k \right\|^2_F
\end{aligned}
\tag{2-4}
\]

上式中残差\(\mathbf{E}_k=\mathbf{Y}-\sum_{j\ne k}\mathbf{d}_j\mathbf{x}^j_T\),

此时优化问题可描述为

\[\min_{\mathbf{d}_k,\ \mathbf{x}^k_T}\left\|\mathbf{E}_k - \mathbf{d}_k\mathbf{x}_T^k \right\|^2_F
\]

因此我们需要求出最优的\(\mathbf{d}_k,\ \mathbf{x}_T^k\),这是一个最小二乘问题,可以利用最小二乘的方法求解,或者可以利用SVD进行求解,这里利用SVD的方式求解出两个优化变量。

但是,在这里我人需要注意的是,不能直接利用\(\mathbf{E}_k\)进行求解,否则求得的新的\(\mathbf{x}_k^T\)不稀疏。因此我们需要将\(\mathbf{E}_k\)中对应的\(\mathbf{x}_T^k\)不为0的位置提取出来,得到新的\(\mathbf{E}_k^{'}\),这个过程如图2-1所示,这样描述更加清晰。

图2-1 提取部分残差

如上图,假设我们要更新第0列原子,我们将\(\mathbf{x}_T^k\)中为零的位置找出来,然后把\(\mathbf{E}_k\)对应的位置删除,得到\(\mathbf{E}_k^{'}\),此时优化问题可描述为

\[\min_{\mathbf{d}_k,\ \mathbf{x}^k_T}\left\|\mathbf{E}_k^{'} - \mathbf{d}_k\mathbf{x{'}}_T^{k} \right\|^2_F
\tag{2-5}
\]

因此我们需要求出最优的\(\mathbf{d}_k,\ \mathbf{x^{'}}_T^k\)

\[\mathbf{E}_k^{'}=U\Sigma V^T
\tag{2-6}
\]

取左奇异矩阵\(U\)的第1个列向量\(\mathbf{u}_1=U(\cdot,1)\)作为\(\mathbf{d}_k\),即\(\mathbf{d}_k=\mathbf{u}_1\),取右奇异矩阵的第1个行向量与第1个奇异值的乘积作为\(\mathbf{x{'}}_T^k\),即\(\mathbf{x{'}}^k_T=\Sigma(1,1)V^T(1,\cdot)\)。得到\(\mathbf{x{'}}^k_T\)后,将其对应地更新到原\(\mathbf{x}_T^k\)。

注: 式(2-6)所求得的奇异值矩阵\(\Sigma\)中的奇异值应从大到小排列;同样也有\(\mathbf{x{'}}^k_T=\Sigma(1,1)V(\cdot,1)^T\),这与上面\(\mathbf{x{'}}^k_T\)的求法是相等的。

2.3 字典学习算法实现

据2.2小节,利用稀疏算法求解得到稀疏矩阵\(\mathbf{X}\)后,逐列更新字典,有如下算法1.1。

算法1.1:字典学习(K-SVD)

输入:原始样本,字典,稀疏矩阵

输出:字典,稀疏矩阵

  1. 初始化: 从原始样本\(Y \in \mathbf{R}^{m \times n}\)随机取\(K\)个列向量或者取它的左奇异矩阵的前\(K\)个列向量\(\{\mathbf{d}_1,\mathbf{d}_2,\cdots,\mathbf{d}_K\}\)作为初始字典的原子,得到字典\(\mathbf{D}^{(0)} \in \mathbf{R}^{m \times K}\)。令\(j=0\),重复下面步骤2-3,直到达到指定的迭代步数,或收敛到指定的误差:

  2. 稀疏编码: 利用字典上一步得到的字典\(\mathbf{D}^{(j)}\),稀疏编码,得到\(\mathbf{X}^{(j)}\in\mathbf{R}^{K \times n}\)。

  3. 字典更新: 逐列更新字典\(\mathbf{D}^{(j)}\),字典的列\(\mathbf{d}_k \in \{\mathbf{d}_1,\mathbf{d}_2,\cdots,\mathbf{d}_K\}\)

    • 当更新\(\mathbf{d}_k\)时,计算误差矩阵\(\mathbf{E}_k\)

      \[\mathbf{E}_k=\mathbf{Y}-\sum_{j\ne k}\mathbf{d}_j\mathbf{x}^j_T.
      \]

    • 取出稀疏矩阵第\(k\)个行向量\(\mathbf{x}^k_T\)不为0的索引的集合\(\omega_k = \{i|1\le i\le n,\ \mathbf{x}_T^k(i) \ne 0\}\),\(\mathbf{x'}_T^{k} = \{\mathbf{x}_T^k(i)|1\le i\le n,\ \mathbf{x}_T^k(i) \ne 0\}\)

    • 从\(\mathbf{E}_k\)取出对应\(\omega_k\)不为0的列,得到\(\mathbf{E}_k^{'}\).

    • 对\(\mathbf{E}_k^{'}\)作奇异值分解\(\mathbf{E}_k=U\Sigma V^T\),取\(U\)的第1列更新字典的第\(k\)列,即\(\mathbf{d}_k=U(\cdot,1)\);令\(\mathbf{x'}^k_T=\Sigma(1,1)V(\cdot,1)^T\),得到\(\mathbf{x{'}}^k_T\)后,将其对应地更新到原\(\mathbf{x}_T^k\)。

    • \(j = j + 1\)

3、字典学习Python实现

以下实验的运行环境为python3.6+jupyter5.4

载入数据

  1. import numpy as np
  2. import pandas as pd
  3. from scipy.io import loadmat
  4. train_data_mat = loadmat("../data/train_data2.mat")
  5. train_data = train_data_mat["Data"]
  6. train_label = train_data_mat["Label"]
  7. print(train_data.shape, train_label.shape)

注: 上面的数据集,可以随便使用一个,也可以随便找一个张图片。

初始化字典

  1. u, s, v = np.linalg.svd(train_data)
  2. n_comp = 50
  3. dict_data = u[:, :n_comp]

字典更新

  1. def dict_update(y, d, x, n_components):
  2. """
  3. 使用KSVD更新字典的过程
  4. """
  5. for i in range(n_components):
  6. index = np.nonzero(x[i, :])[0]
  7. if len(index) == 0:
  8. continue
  9. # 更新第i列
  10. d[:, i] = 0
  11. # 计算误差矩阵
  12. r = (y - np.dot(d, x))[:, index]
  13. # 利用svd的方法,来求解更新字典和稀疏系数矩阵
  14. u, s, v = np.linalg.svd(r, full_matrices=False)
  15. # 使用左奇异矩阵的第0列更新字典
  16. d[:, i] = u[:, 0]
  17. # 使用第0个奇异值和右奇异矩阵的第0行的乘积更新稀疏系数矩阵
  18. for j,k in enumerate(index):
  19. x[i, k] = s[0] * v[0, j]
  20. return d, x

注: 上面代码的16~17需要注意python的numpy中的普通索引和花式索引的区别,花式索引会产生一个原数组的副本,所以对花式索引的操作并不会改变原数据,因此不能像第10行一样,需利用直接索引更新x。

迭代更新求解

可以指定迭代更新的次数,或者指定收敛的误差。

  1. from sklearn import linear_model
  2. max_iter = 10
  3. dictionary = dict_data
  4. y = train_data
  5. tolerance = 1e-6
  6. for i in range(max_iter):
  7. # 稀疏编码
  8. x = linear_model.orthogonal_mp(dictionary, y)
  9. e = np.linalg.norm(y - np.dot(dictionary, x))
  10. if e < tolerance:
  11. break
  12. dict_update(y, dictionary, x, n_comp)
  13. sparsecode = linear_model.orthogonal_mp(dictionary, y)
  14. train_restruct = dictionary.dot(sparsecode)

字典学习(Dictionary Learning, KSVD)详解的更多相关文章

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

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

  2. RFC2544学习频率“Learning Frequency”详解—信而泰网络测试仪实操

    在RFC2544中, 会有一个Learning Frequency的字段让我们选择, 其值有4个, 分别是learn once, learn Every Trial, Learn Every Fram ...

  3. [深入学习Web安全](5)详解MySQL注射

    [深入学习Web安全](5)详解MySQL注射 0x00 目录 0x00 目录 0x01 MySQL注射的简单介绍 0x02 对于information_schema库的研究 0x03 注射第一步—— ...

  4. Shell学习之Bash变量详解(二)

    Shell学习之Bash变量详解 目录 Bash变量 Bash变量注意点 用户自定义变量 环境变量 位置参数变量 预定义变量 Bash变量 用户自定义变量:在Bash中由用户定义的变量. 环境变量:这 ...

  5. Asp.Net MVC学习总结之过滤器详解(转载)

    来源:http://www.php.cn/csharp-article-359736.html   一.过滤器简介 1.1.理解什么是过滤器 1.过滤器(Filters)就是向请求处理管道中注入额外的 ...

  6. Linux学习之用户配置文件详解(十四)

    Linux学习之用户配置文件详解 目录 用户信息文件/etc/password 影子文件/etc/shadow 组信息文件/etc/group 组密码文件/etc/gshadow 用户信息文件/etc ...

  7. [转载]springmvc学习之@ModelAttribute运用详解

    spring学习之@ModelAttribute运用详解 链接

  8. expect学习笔记及实例详解【转】

    1. expect是基于tcl演变而来的,所以很多语法和tcl类似,基本的语法如下所示:1.1 首行加上/usr/bin/expect1.2 spawn: 后面加上需要执行的shell命令,比如说sp ...

  9. Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)

    [Android布局学习系列]   1.Android 布局学习之——Layout(布局)详解一   2.Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)   3.And ...

  10. Activiti工作流学习之流程图应用详解

    Activiti工作流学习之流程图应用详解 1.目的  了解Activiti工作流是怎样应用流程图的. 2.环境准备2.1.相关软件及版本    jdk版本:Jdk1.7及以上 IDE:eclipse ...

随机推荐

  1. SQLServer 2008(R2)如何开启数据库的远程连接

    SQL Server 2008 R2如何开启数据库的远程连接 by:授客 QQ:1033553122 SQL Server 2008默认是不允许远程连接的,如果想要在本地用SSMS连接远程服务器上的S ...

  2. 【疑难杂症04】EOFException异常详解

    最近线上的系统被检测出有错误日志,领导让我检查下问题,我就顺便了解了下这个异常. 了解一个类,当然是先去看他的API,EOFException的API如下: 通过这个API,我们可以得出以下信息: 这 ...

  3. MySQL缓存机制详解(一)

    本文章拿来学习用||参考资料:http://www.2cto.com/database/201308/236361.html 对MySql查询缓存及SQL Server过程缓存的理解及总结   一.M ...

  4. Java 装饰器模式详解

    转载请注明出处:http://blog.csdn.net/zhaoyanjun6/article/details/56488020 前言 在上面的几篇文章中,着重介绍了Java 中常见的 IO 相关知 ...

  5. 机器学习实战(Machine Learning in Action)学习笔记————05.Logistic回归

    机器学习实战(Machine Learning in Action)学习笔记————05.Logistic回归 关键字:Logistic回归.python.源码解析.测试作者:米仓山下时间:2018- ...

  6. SQL Server 2014 新特性——内存数据库(转载)

    目录 SQL Server 2014 新特性——内存数据库 简介: 设计目的和原因: 专业名词 In-Memory OLTP不同之处 内存优化表 内存优化表的索引 并发能力的提升 和竞争对手相比几点 ...

  7. Oracle数据库 插入数据格式,简单查询

    操作练习代码,知识点往下翻 TRUNCATE TABLE hehe1111; select * from hehe1111; desc hehe1111; ,'); ,'); ,'); ,'); ,' ...

  8. od 转储 二进制文件常用命令

    od :  NAME od - dump files in octal and other formats 常用命令: ➜ Downloads od -t x1 -Ax /etc/ld.so.cach ...

  9. security/pam_appl.h:没有那个文件或目录

    在编译开源库时, 提示 pam.h:4:10: 致命错误:security/pam_appl.h:没有那个文件或目录 #include <security/pam_appl.h> 解决方法 ...

  10. react native环境搭建(含错误处理)

    1.  Python 2  注意,不要选择3.0及以上的,还不成熟 安装过程中一直 next就可以了,但是注意下图,勾选添加到系统环境变量 安装完之后cmd输入 python 查看是否安装成功. 补充 ...