UFLDL深度学习笔记 (七)拓扑稀疏编码与矩阵化
UFLDL深度学习笔记 (七)拓扑稀疏编码与矩阵化
主要思路
前面几篇所讲的都是围绕神经网络展开的,一个标志就是激活函数非线性;在前人的研究中,也存在线性激活函数的稀疏编码,该方法试图直接学习数据的特征集,利用与此特征集相应的基向量,将学习得到的特征集从特征空间转换到样本数据空间,这样可以用特征集重构样本数据。
数据集、特征集、基向量分别表示为\(x、A、s\).构造如下目标代价函数,对估计误差的代价采用二阶范数,对稀疏性因子的惩罚代价采用一阶范数。原文中没有对误差项在数据集上做平均,真实情况下都会除以数据集个数\(m\).
\]
接下来,原文中解释说为了增强稀疏性约束,避免取\(A\)的缩放值也能获得相同的代价,稀疏性惩罚需要考虑特征集的数值,进一步改进代价函数为
\]
代价函数仍然存在L1范数的0点不可微问题,通过近似平滑解决,定义常量值平滑参数\(\epsilon\), 将代价函数变成
\]
由于本代价函数非凸,而固定任意一个变量之后,代价函数是凸函数,所以可以通过交替固定\(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}\) 。得到拓扑稀疏编码的代价函数为
\]
进一步用分组矩阵G来表示邻域分组规则,\(G_{r,c}=1\)表示第r组包含第c个特征,目标函数重写为
\]
矩阵化推导
以上符号都是非常抽象意义上的变量,矩阵化实现时就需要考虑清楚每行每列的操作是不是按照预设的每一项运算规则实现的,原文中没有这部分内容,我也花费了一番功夫推导。
按照前文所说的交替求\(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.
\]
单向合并成矩阵表示为
\]
同时我们发现此表达式为一阶方程,可以得到代价函数取极小值时的\(A\)。可得s固定时使代价函数最小的\(A\)为
即$$min J(A,s) \Leftrightarrow A = \frac {xs^T} {ssT+m \gamma I}; $$ .
固定\(A\)求解\(s\)的梯度
展开代价函数并对\(s\)求解,
\]
其中\(G=[g_{l,f}]_{F \times F}\) ,\(g_{l,f}=1\)表示第\(l\)组包含第f个特征。 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深度学习笔记 (七)拓扑稀疏编码与矩阵化的更多相关文章
- UFLDL深度学习笔记 (二)SoftMax 回归(矩阵化推导)
UFLDL深度学习笔记 (二)Softmax 回归 本文为学习"UFLDL Softmax回归"的笔记与代码实现,文中略过了对代价函数求偏导的过程,本篇笔记主要补充求偏导步骤的详细 ...
- UFLDL深度学习笔记 (一)反向传播与稀疏自编码
UFLDL深度学习笔记 (一)基本知识与稀疏自编码 前言 近来正在系统研究一下深度学习,作为新入门者,为了更好地理解.交流,准备把学习过程总结记录下来.最开始的规划是先学习理论推导:然后学习一两种开源 ...
- UFLDL深度学习笔记 (五)自编码线性解码器
UFLDL深度学习笔记 (五)自编码线性解码器 1. 基本问题 在第一篇 UFLDL深度学习笔记 (一)基本知识与稀疏自编码中讨论了激活函数为\(sigmoid\)函数的系数自编码网络,本文要讨论&q ...
- UFLDL深度学习笔记 (六)卷积神经网络
UFLDL深度学习笔记 (六)卷积神经网络 1. 主要思路 "UFLDL 卷积神经网络"主要讲解了对大尺寸图像应用前面所讨论神经网络学习的方法,其中的变化有两条,第一,对大尺寸图像 ...
- UFLDL深度学习笔记 (四)用于分类的深度网络
UFLDL深度学习笔记 (四)用于分类的深度网络 1. 主要思路 本文要讨论的"UFLDL 建立分类用深度网络"基本原理基于前2节的softmax回归和 无监督特征学习,区别在于使 ...
- UFLDL深度学习笔记 (三)无监督特征学习
UFLDL深度学习笔记 (三)无监督特征学习 1. 主题思路 "UFLDL 无监督特征学习"本节全称为自我学习与无监督特征学习,和前一节softmax回归很类似,所以本篇笔记会比较 ...
- (转)Qt Model/View 学习笔记 (七)——Delegate类
Qt Model/View 学习笔记 (七) Delegate 类 概念 与MVC模式不同,model/view结构没有用于与用户交互的完全独立的组件.一般来讲, view负责把数据展示 给用户,也 ...
- Google TensorFlow深度学习笔记
Google Deep Learning Notes Google 深度学习笔记 由于谷歌机器学习教程更新太慢,所以一边学习Deep Learning教程,经常总结是个好习惯,笔记目录奉上. Gith ...
- Learning ROS for Robotics Programming Second Edition学习笔记(七) indigo PCL xtion pro live
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS forRobotics Pro ...
随机推荐
- HNOI2016 游记
题外 忽然想起去年的HNOI2015总结里好像引了一句诗: 此情可待成追忆,只是当时已惘然. Day0 唔,感觉不知道想些什么,只是觉得其实还没有做好准备,想学的东西学的仓促,想复习的东西,也只能看一 ...
- threadlocal彻底理解
如果你定义了一个单实例的java bean,它有若干属性,但是有一个属性不是线程安全的,比如说HashMap.并且碰巧你并不需要在不同的线程中共享这个属性,也就是说这个属性不存在跨线程的意义.那么你不 ...
- go语言的一些特性
go语言中如何判断一个方法是私有的还是公有的?说出来你可能不信,通过首字母的大小写. 不管是一个变量还是一个函数,如果它的首字母是大写的,那么它就是包外可见的,也就是说可以 从这个包的外面访问这个资源 ...
- [Angular] @ViewChild read custom directive and exportAs
For example we have a component: <Card ></Card> And a driective: <Card highlighted> ...
- Font Awesome入门教程
Font Awesome 图标 Font Awesome 是一套绝佳的图标字体库和CSS框架. Font Awesome 字体为您提供可缩放矢量图标,它可以被定制大小.颜色.阴影以及任何可以用CSS的 ...
- htmlspecialchars_decode
htmlspecialchars_decode htmlspecialchars_decode - 将特殊的 HTML 实体转换回普通字符 htmlspecialchars - 将特殊字符转换为 ...
- mysql 修复
/home/wkubuntu/mysql/data/iZ25sgya7raZbak.pid pid 文件notfond 错误解决 一.截图 snipingtool skip-locking 修改成 ...
- vue vue-router beforeRouteEnter
beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 因为当守卫执行前,组件实 ...
- Catch That Cow(广度优先搜索_bfs)
Catch That Cow Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 48036 Accepted: 150 ...
- sql server 执行大.sql文件
打开cmd执行:osql -S 127.0.0.1 -U sa -P sa -i d:\test.sql 执行后会提示输入密码.