UFLDL深度学习笔记 (七)拓扑稀疏编码与矩阵化

主要思路

  前面几篇所讲的都是围绕神经网络展开的,一个标志就是激活函数非线性;在前人的研究中,也存在线性激活函数的稀疏编码,该方法试图直接学习数据的特征集,利用与此特征集相应的基向量,将学习得到的特征集从特征空间转换到样本数据空间,这样可以用特征集重构样本数据。

​ 数据集、特征集、基向量分别表示为\(x、A、s\).构造如下目标代价函数,对估计误差的代价采用二阶范数,对稀疏性因子的惩罚代价采用一阶范数。原文中没有对误差项在数据集上做平均,真实情况下都会除以数据集个数\(m\).

\[J(A,s)= \frac 1m||As-x||_2^2+\lambda||s||
\]

接下来,原文中解释说为了增强稀疏性约束,避免取\(A\)的缩放值也能获得相同的代价,稀疏性惩罚需要考虑特征集的数值,进一步改进代价函数为

\[J(A,s)= \frac 1m||As-x||_2^2+\lambda||s||+\gamma ||A||_2^2
\]

代价函数仍然存在L1范数的0点不可微问题,通过近似平滑解决,定义常量值平滑参数\(\epsilon\), 将代价函数变成

\[J(A,s)= \frac 1m||As-x||_2^2+\lambda \sum_k \sqrt{s_k^2+\epsilon} +\gamma ||A||_2^2
\]

由于本代价函数非凸,而固定任意一个变量之后,代价函数是凸函数,所以可以通过交替固定\(A,s\)来求最优化代价的\(A,s\). 理论上对上式最优化取得的特征集与通过稀疏自编码学习得到的特征集差不多,人类视觉神经具有一种特点,大脑皮层 V1 区神经元能够按特定的方向对边缘进行检测,同时,这些神经元(在生理上)被组织成超柱(hypercolumns),在超柱中,相邻神经元以相似的方向对边缘进行检测,一个神经元检测水平边缘,其相邻神经元检测到的边缘就稍微偏离水平方向。为了使算法达到这种 拓扑性 ,也就是说相邻的特征激活具有一定连续性、平滑性,我们将惩罚项也改造成考虑相邻特征值,在2X2分组情况下,把原来 \(\sqrt{s_{1,1}^2+\epsilon}\)这一项换成 \(\sqrt{s_{1,1}^2+s_{1,2}^2+s_{2,1}^2 +s_{2,2}^2+ \epsilon}\) 。得到拓扑稀疏编码的代价函数为

\[J(A,s)= \frac 1m||As-x||_2^2+\lambda \sum_{all G} \sqrt{ \sum_{s \in G}s^2+\epsilon} +\gamma ||A||_2^2
\]

进一步用分组矩阵G来表示邻域分组规则,\(G_{r,c}=1\)表示第r组包含第c个特征,目标函数重写为

\[J(A,s)= \frac 1m||As-x||_2^2+\lambda \sum \sqrt{ Vss^T+\epsilon} +\gamma ||A||_2^2
\]

矩阵化推导

以上符号都是非常抽象意义上的变量,矩阵化实现时就需要考虑清楚每行每列的操作是不是按照预设的每一项运算规则实现的,原文中没有这部分内容,我也花费了一番功夫推导。

按照前文所说的交替求\(A,s\)最优化策略,我们需要先推导代价函数对\(A,s\)的偏导。设定矩阵表示展开为\(A=[_{Wj,f}]_{visibleSize \times featureSize}\). \(s=[S_{Wj,f}]_{featureSize\times m}\). 令\(V=visibleSize, F=featureSize\).

固定\(s\)求解\(A\)的梯度与最优取值

代价的一阶范数项对\(A\)求偏导为0.

\[\frac {\nabla J(A,s)} {W_{j,f}} =\frac 1 m \sum _i^m 2[W_{j,1}S_{1,i}+W_{j,2}S_{2,i}+…W_{j,F}S_{F,i} -x_{j,i}]S_{f,i}+ 2\gamma W_{j,f}
\]

单向合并成矩阵表示为

\[\frac {\nabla J(A,s)} {A} = \frac 2 m (As-x)s^T +2\gamma A
\]

同时我们发现此表达式为一阶方程,可以得到代价函数取极小值时的\(A\)。可得s固定时使代价函数最小的\(A\)为

即$$min J(A,s) \Leftrightarrow A = \frac {xs^T} {ssT+m \gamma I}; $$ .

固定\(A\)求解\(s\)的梯度

展开代价函数并对\(s\)求解,

\[\begin{align} \frac {\nabla J(A,s)} { S_{f,i}} &= \frac 1 m \sum _j^V 2[W_{j,1}S_{1,i}+W_{j,2}S_{2,i}+…W_{j,F}S_{F,i} -x_{j,i}]W_{j,f}+ \frac {\nabla \lambda \sum_f^F \sum_i^m \sqrt {Gss^T+\epsilon }} {\nabla S_{f,i}} \\ &= \frac 1 m \sum _j^V 2[W_{j,1}S_{1,i}+W_{j,2}S_{2,i}+…W_{j,F}S_{F,i} -x_{j,i}]W_{j,f} + \lambda S_{f,i}\sum_l^F{\frac {g_{l,f}} {S\_smooth_{x,f}}} \end{align}
\]

其中\(G=[g_{l,f}]_{F \times F}\) ,\(g_{l,f}=1\)表示第\(l\)组包含第f个特征。 S_smooth表示根据拓扑编码要求,对特征值的邻域进行平滑后的特征矩阵。

进行矩阵化改写,可以得到,两个求和式可以分别写成矩阵乘法:

\[\frac {\nabla J(A,s)} S = \frac 2 m A^T(As-x) + \lambda S \cdot (G^T {(1./ S\_smooth)})
\]

这个矩阵表达式不能得到使代价函数最小的\(S\)解析式,这个最优化过程需要使用迭代的方式获得,可以使用梯度下降这类最优化方法。

至此我们得到了编写代码需要的所有矩阵化表达。

代码实现

本节实践实例中,主文件是 sparseCodingExercise.m ,对\(A,s\)的代价梯度计算模块分别是 sparseCodingWeightCost.m、sparseCodingFeatureCost.m. 按照上述矩阵推导分别填充其中的公式部分,全部代码见https://github.com/codgeek/deeplearning

分别固定\(A,s\)进行最优化的步骤在sparseCodingExercise.m中,有几条需要注意的地方,否则将会很难训练出结果。

  • 每次交替开始前,不能随机设定特征值,而是设定为 featureMatrix = weightMatrix'*batchPatches;
  • 加载原始图像的函数sampleIMAGES.m中不能调用归一化normalizeData。和稀疏自编码不同。
  • 前面推导的固定\(s\)时最优化\(A\)表示中千万不能漏掉单位矩阵,是\(\gamma\)乘以单位矩阵,不能直接加\(\gamma\)。公式为weightMatrix = (batchPatches*(featureMatrix'))/(featureMatrix*(featureMatrix')+gamma*batchNumPatches*eye(numFeatures));.

两个梯度公式代码如下。

function [cost, grad] = sparseCodingWeightCost(weightMatrix, featureMatrix, visibleSize, numFeatures,  patches, gamma, lambda, epsilon, groupMatrix)
%sparseCodingWeightCost - given the features in featureMatrix,
% computes the cost and gradient with respect to
% the weights, given in weightMatrix
% parameters
% weightMatrix - the weight matrix. weightMatrix(:, c) is the cth basis
% vector.
% featureMatrix - the feature matrix. featureMatrix(:, c) is the features
% for the cth example
% visibleSize - number of pixels in the patches
% numFeatures - number of features
% patches - patches
% gamma - weight decay parameter (on weightMatrix)
% lambda - L1 sparsity weight (on featureMatrix)
% epsilon - L1 sparsity epsilon
% groupMatrix - the grouping matrix. groupMatrix(r, :) indicates the
% features included in the rth group. groupMatrix(r, c)
% is 1 if the cth feature is in the rth group and 0
% otherwise.
if exist('groupMatrix', 'var')
assert(size(groupMatrix, 2) == numFeatures, 'groupMatrix has bad dimension');
else
groupMatrix = eye(numFeatures);
end numExamples = size(patches, 2); weightMatrix = reshape(weightMatrix, visibleSize, numFeatures);
featureMatrix = reshape(featureMatrix, numFeatures, numExamples); % -------------------- YOUR CODE HERE --------------------
% Instructions:
% Write code to compute the cost and gradient with respect to the
% weights given in weightMatrix.
% -------------------- YOUR CODE HERE --------------------
linearError = weightMatrix * featureMatrix - patches;
normError = sum(sum(linearError .* linearError))./numExamples;% 公式中代价项是二阶范数的平方,所以不用在开方
normWeight = sum(sum(weightMatrix .* weightMatrix)); topoFeature = groupMatrix*(featureMatrix.*featureMatrix);
smoothFeature = sqrt(topoFeature + epsilon);
costFeature = sum(sum(smoothFeature));% L1 范数为sum(|x|),对x加上平滑参数后,sum(sqrt(x2+epsilon)).容易错写为sqrt(sum(x2+epsilon))实际是L2范数 % cost = normError + gamma.*normWeight;
cost = normError + lambda.*costFeature + gamma.*normWeight;
grad = 2./numExamples.*(linearError*featureMatrix') + (2*gamma) .* weightMatrix;
% grad = 2.*(weightMatrix*featureMatrix - patches)*featureMatrix' + 2.*gamma*weightMatrix;
grad = grad(:); end
function [cost, grad] = sparseCodingFeatureCost(weightMatrix, featureMatrix, visibleSize, numFeatures, patches, gamma, lambda, epsilon, groupMatrix)
%sparseCodingFeatureCost - given the weights in weightMatrix,
% computes the cost and gradient with respect to
% the features, given in featureMatrix
% parameters
% weightMatrix - the weight matrix. weightMatrix(:, c) is the cth basis
% vector.
% featureMatrix - the feature matrix. featureMatrix(:, c) is the features
% for the cth example
% visibleSize - number of pixels in the patches
% numFeatures - number of features
% patches - patches
% gamma - weight decay parameter (on weightMatrix)
% lambda - L1 sparsity weight (on featureMatrix)
% epsilon - L1 sparsity epsilon
% groupMatrix - the grouping matrix. groupMatrix(r, :) indicates the
% features included in the rth group. groupMatrix(r, c)
% is 1 if the cth feature is in the rth group and 0
% otherwise. if exist('groupMatrix', 'var')
assert(size(groupMatrix, 2) == numFeatures, 'groupMatrix has bad dimension');
else
groupMatrix = eye(numFeatures);
end numExamples = size(patches, 2); weightMatrix = reshape(weightMatrix, visibleSize, numFeatures);
featureMatrix = reshape(featureMatrix, numFeatures, numExamples); linearError = weightMatrix * featureMatrix - patches;
normError = sum(sum(linearError .* linearError))./numExamples;
normWeight = sum(sum(weightMatrix .* weightMatrix));
topoFeature = groupMatrix*(featureMatrix.*featureMatrix);
smoothFeature = sqrt(topoFeature + epsilon);
costFeature = sum(sum(smoothFeature));% L1 范数为sum(|x|),对x加上平滑参数后,sum(sqrt(x2+epsilon)).容易错写为sqrt(sum(x2+epsilon))实际是L2范数 cost = normError + lambda.*costFeature + gamma.*normWeight;
grad = 2./numExamples.*(weightMatrix' * linearError) + lambda.*featureMatrix.*( (groupMatrix')*(1 ./ smoothFeature) );% 不止(f,i)本项偏导非零,(f-1,i)……,groupMatrix第f列不为0的所有行对应项都有s(f,i)的偏导
grad = grad(:);
end

训练结果

数据来源还是稀疏自编码一节所用的图片, 设定特征层包含121个节点,输入层为8X8patch即64个节点,拓扑邻域为3X3的方阵,运行200次训练,

当输入值为对应特征值时,每个激活值会有最大响应,所以把A矩阵每一行的64个向量还原成8*8的图片patch,也就是特征值了,每个隐藏层对应一个,总共121个。结果如下图. 可看出在当前参数下,相同迭代次数,cg算法的图片特征更加清晰。

lbfgs cg

为了看到更精细的训练结果,增加特征层以及输入层节点数,特征层采用256个节点,输入层分别试验了14X14以及15X15,相应需要增加拓扑邻域的大小,采用5X5的方阵。迭代算法采用cg。特征的清晰程度以及拓扑结构的完整性已经和示例中的结果无差别。边缘特征有序排列。而当把输入节点个数增加到16X16, 训练效果出现恶化,边缘特征开始变得模糊,原因也可以理解,特征层已经不再大于输入层,超完备基的条件不成立了,得到的训练效果也相对变差。

14X14输入节点,拓扑5X5 15X15输入节点,拓扑5X5

增加输入节点的结果:

16X16输入节点,拓扑3X3 16X16输入节点,拓扑5X5

UFLDL深度学习笔记 (七)拓扑稀疏编码与矩阵化的更多相关文章

  1. UFLDL深度学习笔记 (二)SoftMax 回归(矩阵化推导)

    UFLDL深度学习笔记 (二)Softmax 回归 本文为学习"UFLDL Softmax回归"的笔记与代码实现,文中略过了对代价函数求偏导的过程,本篇笔记主要补充求偏导步骤的详细 ...

  2. UFLDL深度学习笔记 (一)反向传播与稀疏自编码

    UFLDL深度学习笔记 (一)基本知识与稀疏自编码 前言 近来正在系统研究一下深度学习,作为新入门者,为了更好地理解.交流,准备把学习过程总结记录下来.最开始的规划是先学习理论推导:然后学习一两种开源 ...

  3. UFLDL深度学习笔记 (五)自编码线性解码器

    UFLDL深度学习笔记 (五)自编码线性解码器 1. 基本问题 在第一篇 UFLDL深度学习笔记 (一)基本知识与稀疏自编码中讨论了激活函数为\(sigmoid\)函数的系数自编码网络,本文要讨论&q ...

  4. UFLDL深度学习笔记 (六)卷积神经网络

    UFLDL深度学习笔记 (六)卷积神经网络 1. 主要思路 "UFLDL 卷积神经网络"主要讲解了对大尺寸图像应用前面所讨论神经网络学习的方法,其中的变化有两条,第一,对大尺寸图像 ...

  5. UFLDL深度学习笔记 (四)用于分类的深度网络

    UFLDL深度学习笔记 (四)用于分类的深度网络 1. 主要思路 本文要讨论的"UFLDL 建立分类用深度网络"基本原理基于前2节的softmax回归和 无监督特征学习,区别在于使 ...

  6. UFLDL深度学习笔记 (三)无监督特征学习

    UFLDL深度学习笔记 (三)无监督特征学习 1. 主题思路 "UFLDL 无监督特征学习"本节全称为自我学习与无监督特征学习,和前一节softmax回归很类似,所以本篇笔记会比较 ...

  7. (转)Qt Model/View 学习笔记 (七)——Delegate类

    Qt Model/View 学习笔记 (七) Delegate  类 概念 与MVC模式不同,model/view结构没有用于与用户交互的完全独立的组件.一般来讲, view负责把数据展示 给用户,也 ...

  8. Google TensorFlow深度学习笔记

    Google Deep Learning Notes Google 深度学习笔记 由于谷歌机器学习教程更新太慢,所以一边学习Deep Learning教程,经常总结是个好习惯,笔记目录奉上. Gith ...

  9. Learning ROS for Robotics Programming Second Edition学习笔记(七) indigo PCL xtion pro live

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS forRobotics Pro ...

随机推荐

  1. sqlsever 和oracle的参数

    StringBuilder strSql = new StringBuilder(); strSql.Append("insert into YXZY_TSDQWH("); str ...

  2. apache去掉目录浏览

    apache去掉目录浏览 apache默认开启目录浏览的,这样大大降低了我们网站的安全,下面是关闭浏览目录: 要禁止 Apache 显示目录结构列表,只需将 Option 中的 Indexes 去掉即 ...

  3. 6、Python模块

    最常用的两个模块: os    #可以允许python调用执行系统命令,如shell sys    #处理与python程序本身的事情   Python自带200多个常用模块 Python官网收集了2 ...

  4. Linux内核锁与中断处理

    Linux内核锁 在Linux内核里面,一般采用了如下几种锁的机制,来保证多线程的同步与互斥: (1)原子操作 atomic_t v: void atomic_set(atomic_t *v, int ...

  5. Linux使用nginx部署Laravel

    问题描述 Laravel是PHP下当今最受欢迎的web应用开发框架,github上start数远超第二名Symfony,以前我用这个框架做项目的时候通常就是扔到apache里面,然后配置.htacce ...

  6. GridView后台绑定数据列表方法

    在很多时候数据绑定都是知道了数据表中的表字段来绑定GridView控件的,那时候我就有个想法希望通过表明来查询数据库中的字段来动态的绑定GirdView控件数据并提供了相关的操作列,在网上找了一些资料 ...

  7. 解决dubbo问题:forbid consumer(1)

    原因: 1.dubbo服务没有起动起来 2.dubbo链接的地址出现异常 3.dubbo服务端更新了服务接口,没有发布 如果已上都没有问题,那么还有一个原因就是 “ 别人的代码有问题 阻碍了 你的程序 ...

  8. 不在JPA 的 persistence.xml 文件里配置Entity class的解决的方法

     在Spring 集成 Hibernate 的JPA方式中,须要在persistence配置文件里定义每个实体类.这样很地不方便.2种方法能够解决此问题: 这2种方式都能够实现不用在persist ...

  9. iOS开发:解决UIScrollView不滚动的问题

    照着书上的Demo(iOS 5.0的教程),在- (void)viewDidLoad里设置scrollView的contentsize,让它大于屏幕的高度,却发现在模拟器中没用,还是不能滚.经过 一翻 ...

  10. WebView简单使用

    public class MainActivity extends Activity { WebView webView; @Override protected void onCreate(Bund ...