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. NOIP 2017 赛后反思 [补档]

    首先写一下比赛的情况: D1: T1: 之前做过类似的题目, 因而知道大致的结论, 迅速完成. T2: 貌似直接模拟就可以了, 涉及到字符串信息提取, 比较麻烦, 因而想放到最后做. T3: 非常简洁 ...

  2. 在使用springMVC时,我使用了@Service这样的注解,发现使用注解@Transactional声明的事务不起作用

    问题出现的场景: 在使用spring mvc时,我使用了@Service这样的注解, 发现使用注解@Transactional声明的事务不起作用. 我的配置如下: <mvc:annotation ...

  3. Kubernetes - 配置Nginx-Ingress 作为服务发现

    添加 Kubernetes ConfigMap配置来自定义端口与服务的映射关系 配置文件, 有二个在默认空间下web服务和api服务分别映射到自定义端口 9001, 9002 apiVersion: ...

  4. 倍福TwinCAT(贝福Beckhoff)基础教程2.2 TwinCAT常见类型使用和转换_结构体

    在DUTs文件夹上右击添加结构体,结构体中可以放基本变量类型,也可以嵌套其他结构体   使用的时候,需要声明结构体的实例,然后按照类.属性的格式来读写变量,会有代码的自动提示   你也可以声明数组,类 ...

  5. 系统封装 EasyBoot如何将WIN7安装版提取到光盘

    1 将WIN7光盘中的文件提取到Easyboot根目录,注意不要autorun.inf和setup.exe这两个文件.我们这里的Easyboot已经有了一些其他东西(XP的安装版文件,PE的文件等等, ...

  6. python——操作符重载(重要)

    类可以重载python的操作符   旧认识:__X__的名字 是系统定义的名字:是python特殊方法专用标识.   操作符重载使我们的对象与内置的一样.__X__的名字的方法是特殊的挂钩(hook) ...

  7. h5+ 管理设备信息

    Device模块管理设备信息,用于获取手机设备的相关信息,如IMEI.IMSI.型号.厂商等.通过plus.device获取设备信息管理对象. 1.属性 1.1.imei: 设备的国际移动设备身份码, ...

  8. icvEvalCARTHaarClassifier

    /* *icvEvalCARTHaarClassifier *作用:通过计算haar特征值,来分配非叶子节点直到出现叶子节点,最后返回输出值val.  */ float icvEvalCARTHaar ...

  9. TCP/IP详解 卷一(第十三章 IGMP:Internet组管理协议)

    本章将介绍用于支持主机和路由器进行多播的Internet组管理协议(IGMP) 它让一个物理网络上的所有系统知道主机当前所在的多播组.多播路由器需要这些信息以便知道多播数据报应该向那些接口转发. 跟I ...

  10. Mysql的建表规范与注意事项

    一. 表设计规范 库名.表名.字段名必须使用小写字母,“_”分割. 库名.表名.字段名必须不超过12个字符. 库名.表名.字段名见名知意,建议使用名词而不是动词. 建议使用InnoDB存储引擎. 存储 ...