这几天做UFLDL练习,反复用到其中一个函数display_network,刚开始没有在意,只是调用。后来觉得有必要搞懂,遂细读了代码,理清了内部逻辑,翻译了原注释,又加上自己理解的注释。想上传到资源上去,总找不到上传界面,就发表在博客上。希望对感兴趣者有帮助。
这个程序总体上就是把矩阵数据逐列当成图像显示。显示形式是个格子框,每幅图像一格。
function [h, array] = displayAsGrids(A, colNum, ...
opt_normalize, opt_graycolor,opt_colmajor)
% 把矩阵A中的列显示在一个格子框中,框中格子布局可通过参数指定
% 原始函数由UFLDL网站第一单元练习提供,因多次用到,遂读懂并按自己需要改造
% 简单说明:把A中所有列都变成一个方阵(行数是完全平方数)当成一幅图像显示
% 显示形式是一个格子框,每幅图像占一个格子,格子框纵横数量有两种确定方式:
% 1,指定横向格子数(输入变量colNum),则纵向格子数自动确定
% 2,未指定横行格子数,则横向格子数自动取A列数开方调整,会出现空白
% 出现空白的原因:列数不是完全平方数(例如200),且要按规定调整
% 参数说明
% colNum: 显示格子有多少列?默认值为A列数的平方根
% opt_normalize: 要不要归一化数据,以便全部数据有统一的对比度,默认为真
% opt_graycolor: 是不是用灰度作为热图,默认是
% opt_colmajor: 图像逐列放入格子框时行向优先还是列向优先?默认为假
% 调用举例
% displayAsGrids(A,20); % 如 A大小为[64 200],则格子框为10x20
% displayAsGrids(A); % 自动按行、列数确定格子框规格,A同上,则为12x17
warning off all
% 检查变量opt_normalize是否定义,或者是否为空,未定义或为空则取默认值:真
if ~exist('opt_normalize', 'var') || isempty(opt_normalize), opt_normalize= true; end
% 检查变量opt_graycolor是否定义,或者是否为空,未定义或为空则取默认值:真
if ~exist('opt_graycolor', 'var') || isempty(opt_graycolor), opt_graycolor= true; end
% 检查变量opt_colmajor是否定义,或者是否为空,未定义或为空则取默认值:假
if ~exist('opt_colmajor', 'var') || isempty(opt_colmajor), opt_colmajor = false; end
% 重新调节元素值,全局调整去平均值
A = A - mean(A(:));
% 颜色表:用灰度显示。gray命令将颜色表置成灰度
if opt_graycolor, colormap(gray); end
% 计算格子框横向数目(列数,gridColNum)与纵向数目(行数,gridRowNum)
[L M] = size(A);
if ~exist('colNum', 'var') % 未定义横向格子数,则自动推算
if floor(sqrt(M))^2 ~= M % 列数不是个完全平方数,舍入
gridColNum = ceil(sqrt(M));
% 调整横向格子数:矩阵列数与横向格子数不能整除时,增加其值直到越界
while mod(M, gridColNum)~=0 && gridColNum<1.2*sqrt(M), gridColNum=gridColNum+1; end
gridRowNum = ceil(M/gridColNum);
else
gridColNum = sqrt(M); % 列数是完全平方数,格子框是方框
gridRowNum = gridColNum;
end
else
gridColNum = colNum; % 定义了横向格子数,纵向格子数自然确定
gridRowNum = ceil(M/gridColNum);
end
% 格子框当成一幅图像显示比一幅一幅显示要快得多,这里把各幅图像放进去
% array 是格子框,格子间左右上下间隔一行/一列,初值置为-1
sz = sqrt(L);
buf = 1;
array = -ones(buf+gridRowNum*(sz+buf),buf+gridColNum*(sz+buf));
% opt_graycolor为假,初值调整为 -0.1
if ~opt_graycolor, array = 0.1.* array; end
% 根据opt_colmajor,用两种方式形成array实际数据(行列顺序调不调整)
if ~opt_colmajor % opt_colmajor为假,要取行序
k = 1; % k是A矩阵列数的指针
for i = 1:gridRowNum % 逐格子放置图像,行向优先
for j = 1:gridColNum % 一行内从左到右
if k > M, continue; end
clim = max(abs(A(:,k))); % 取列内(一幅图像内)最大值
if opt_normalize % 要归一化,列内规整
array(buf+(i-1)*(sz+buf)+(1:sz),buf+(j-1)*(sz+buf)+(1:sz)) = reshape(A(:,k),sz,sz)/clim;
else % 不用归一化,矩阵范围内规整
array(buf+(i-1)*(sz+buf)+(1:sz),buf+(j-1)*(sz+buf)+(1:sz)) = reshape(A(:,k),sz,sz)/max(abs(A(:)));
end
k = k + 1;
end
end
else % opt_colmajor为真,要取列序
k = 1;
for j = 1:gridColNum % 逐格子放置图像,列向优先
for i = 1:gridRowNum % 一列内从上到下
if k>M, continue; end
clim = max(abs(A(:,k)));
if opt_normalize
array(buf+(i-1)*(sz+buf)+(1:sz),buf+(j-1)*(sz+buf)+(1:sz)) = reshape(A(:,k),sz,sz)/clim;
else
array(buf+(i-1)*(sz+buf)+(1:sz),buf+(j-1)*(sz+buf)+(1:sz)) = reshape(A(:,k),sz,sz);
end
k = k + 1;
end
end
end
% 数据准备好了,开始绘图
if opt_graycolor, h = imagesc(array,'EraseMode','none',[-1 1]);
else h = imagesc(array,'EraseMode','none',[-1 1]);
end
axis image off
drawnow;
warning on all