本文最后更新于 1475 天前,其中的信息可能已经有所发展或是发生改变。
为了回顾忘的差不多的matlab,使用底层代码实现一些界面功能。随便可视化下一元和多元高斯分布。(加深机器学习中 吴恩达 – 15.7的多元高斯分布 的印象 )
为什么不用GUIDE实现界面?虽然GUIDE做界面简单、好用,但即便界面多么简单、其生成的程序都会有两个文件,一个界面文件fig一个逻辑文件m,界面与逻辑分离在这些简单的小程序里面优势并不大,所以我还是倾向使用底层代码,它可以只使用一个m文件完成界面与逻辑。
1. 可视化一元高斯分布:
中文wiki:一元高斯分布
MATLAB 底层代码可视化一元高斯分布:
function [] = UnivarGaussianDistribution()
% Plot Univariate Gaussian distribution
% Parameter
[x_min, x_max] = deal(-2, 10);
[sigma_min, sigma_max] = deal(-2, 10);
[mu_min, mu_max] = deal(-2, 10);
% Create data
x = linspace(x_min, x_max, 1000);
global sigma mu
% Default sigma, mu is average of maximum and minimum.
sigma = (sigma_min + sigma_max) / 2;
mu = (mu_min + mu_max) / 2;
% Now create the other GUI
% position: [x, y, width, height]
S.fh = figure('units','pixels',...
'position',[500 300 600 500],...
'menubar','none',...
'name','GaussianDistributionVisulization-Univariate ',...
'numbertitle','off',...
'resize','off');
% axes
ha = axes('Parent', S.fh, ...
'Units', 'pixels', ...
'Position', [50 120 500 320]);
% plot data
line = plot(x, gaussianfunc(x, mu, sigma), 'r', 'linewidth', 1);
xlim([x_min, x_max]); ylim([-0.5, 2.5]);
title('$y = f(x|\mu, \sigma) = \frac{1}{\sigma \sqrt{2\pi}}e^\frac{-(x - \mu)^2}{2 \sigma^2}$',...
'Interpreter','latex', 'FontSize', 18)
% slider_1
S.tx(1) = uicontrol('style','text',...
'unit','pixel',...
'position',[150 10 40 20],...
'string','mu',...
'fontsize',10);
S.sl(1) = uicontrol('style','slide',...
'unit','pixel',...
'position',[200 10 200 20],...
'min', mu_min, 'value', mu,'max', mu_max);
S.ed(1) = uicontrol('style','edit',...
'unit','pixel',...
'position',[410 10 40 20],...
'fontsize',10,...
'string',num2str(mu)); % Displays the value.
% slider_2
S.tx(2) = uicontrol('style','text',...
'unit','pixel',...
'position',[150 50 40 20],...
'string','sigma',...
'fontsize',10);
S.sl(2) = uicontrol('style','slide',...
'unit','pixel',...
'position',[200 50 200 20],...
'min', sigma_min, 'value', sigma, 'max', sigma_max);
S.ed(2) = uicontrol('style','edit',...
'unit','pixel',...
'position',[410 50 40 20],...
'fontsize',10,...
'string',num2str(sigma)); % Displays the value.
set([S.sl(:);S.ed(:)],'call',{@h_call, S, line, x});
% shared Callback.
end
function gaus_y = gaussianfunc(x, mu, sigma)
gaus_y = 1/(sqrt(2*pi) * sigma) * exp(-(x - mu).^2 / (2 * sigma.^2));
end
function [] = h_call(varargin)
% Callback for the slider.
[h, ~, S, line, x] = deal(varargin{:}); % Get the calling handle and structure.
global sigma mu
switch h % Who called?
case S.sl(1)
mu = get(S.sl(1),'val');
set(S.ed(1),'string', mu) % Set edit to current slider.
case S.sl(2)
sigma = get(S.sl(2),'val');
set(S.ed(2),'string', sigma) % Set edit to current slider.
case S.ed(1)
E = str2double(get(S.ed(1),'string')); % Numerical edit string.
SL1 = get(S.sl(1),{'min','value','max'}); % Get the slider's info.
if E >= SL1{1} && E <= SL1{3}
mu = E;
set(S.sl(1),'value',E) % E falls within range of slider.
else
set(S.ed(1),'string',SL1{2}) % User tried to set slider out of range.
end
case S.ed(2)
E = str2double(get(S.ed(2),'string')); % Numerical edit string.
SL2 = get(S.sl(2),{'min','value','max'}); % Get the slider's info.
if E >= SL2{1} && E <= SL2{3}
sigma = E;
set(S.sl(2),'value',E) % E falls within range of slider.
else
set(S.ed(2),'string',SL2{2}) % User tried to set slider out of range.
end
end
gaus_y = gaussianfunc(x, mu, sigma);
set(line, 'ydata', gaus_y);
end
运行样图:
滑动 slider 减小 sigma
增大 mu
2. 可视化多元高斯分布
中文wiki:多元高斯分布
function [] = MultiGaussianDistribution()
% Plot Multivariate Gaussian distribution
close
% Create data
[xy_min, xy_max] = deal(-2, 10);
var_range = 5; % mu, Sigma range +/-5
global Sigma mu line tog_value z_shaped
mu = [1, 3];
Sigma = [1, 0; 0, 4];
% Sigma must be a square, symmetric, positive definite matrix.
tog_value = 1;
[mu_min, mu_max] = deal(mu - var_range, mu + var_range);
[Sigma_min, Sigma_max] = deal(Sigma - var_range, Sigma + var_range);
[x, y] = meshgrid(linspace(xy_min, xy_max, 100),linspace(xy_min, xy_max, 100));
X = [x(:) y(:)];
z = mvnpdf(X, mu, Sigma);
z_shaped = reshape(z, 100, 100);
% Now create the other GUI
% position: [x, y, width, height]
fg = figure('units','pixels',...
'position',[500 200 665 500],...
'name','GaussianDistributionVisulization-Multivariate ',...
'numbertitle','off',...
'resize','off');
% axes
S.ax = axes('Parent', fg, ...
'Units', 'pixels', ...
'Position', [100 120 500 320]);
% plot data
line = surf(x, y, z_shaped,...
'edgecolor', 'interp');
xlim([xy_min, xy_max]); ylim([xy_min, xy_max]);
latex_text = ['$${f_x(x_1,\ldots ,x_k)={\frac {1}{\sqrt {(2\pi)^k|{',...
'\Sigma}|}}} \exp \left(-{\frac {1}{2}}({{X} }-{{\mu }})^{{T}',...
' }{{\Sigma }}^{-1}({{X} }-{{\mu }})\right)}$$'];
title(latex_text,...
'Interpreter', 'latex', 'FontSize', 12);
xlim([xy_min, xy_max]);ylim([xy_min, xy_max]);zlim([-0.02, 0.09]);
xlabel('x'); ylabel('y');
%% check box for surf or contourf
S.togbtn = uicontrol('style', 'togglebutton',...
'unit', 'pixel',...
'position', [20, 450, 50, 30],...
'string', 'surf',...
'val', tog_value,...
'fontsize', 10,...
'TooltipString', 'Switch figure style between 3-D surface and contour.');
%% slider 1-2: mu(1), mu(2)
position_mu = {[5 50 75 20], [80 50 140 20]; [5 10 75 20], [80 10 140 20]};
for ii = 1:2
S.tx(ii) = uicontrol('style', 'text',...
'unit', 'pixel',...
'position', position_mu{ii, 1},...
'string', sprintf('mu(%d): %d', ii, mu(ii)),...
'fontsize', 10);
S.sl(ii) = uicontrol('style', 'slide',...
'unit', 'pixel',...
'position', position_mu{ii, 2},...
'min', mu_min(ii), 'value', mu(ii),'max', mu_max(ii));
end
%% slider 3-6: Sigma(1, 1)-Sigma(2, 2)
position_Sigma = {
[225 40 75 40], [300 50 140 20];
[225 0 75 40], [300 10 140 20];
[445 40 75 40], [520 50 140 20];
[445 0 75 40], [520 10 140 20];
};
for ii = 1:4
[row, column] = ind2sub(size(Sigma), ii);
S.tx(ii + 2) = uicontrol('style', 'text',...
'unit', 'pixel',...
'position', position_Sigma{ii, 1},...
'string', sprintf('Sigma(%d, %d): %d', row, column, Sigma(ii)),...
'fontsize', 10);
S.sl(ii + 2) = uicontrol('style', 'slide',...
'unit', 'pixel',...
'position', position_Sigma{ii, 2},...
'min', Sigma_min(ii), 'value', Sigma(ii),'max', Sigma_max(ii));
end
set([S.togbtn; S.sl(:)],'call',{@h_call, S, X, x, y}); % shared Callback.
end
function [] = h_call(varargin)
% Callback for the slider.
[h, ~, S, X, x, y] = deal(varargin{:}); % Get the calling handle and structure.
global Sigma mu line tog_value z_shaped
switch h % Who called?
case S.togbtn
tog_value = get(S.togbtn, 'value'); % Get toggle button's state
if tog_value
line = surf(x, y, reshape(z_shaped, 100, 100),...
'edgecolor', 'interp');
set(S.togbtn, 'string', 'surf');
else
line = contour(x, y, reshape(z_shaped, 100, 100),...
'ShowText', 'on', 'LineWidth', 1);
set(S.togbtn, 'string', 'contour');
end
case S.sl(1)
mu(1) = get(S.sl(1),'val'); % Get slider's value.
set(S.tx(1), 'string',['mu(1): ', num2str(mu(1))]); % update text box.
case S.sl(2)
mu(2) = get(S.sl(2),'val'); % Get slider's value.
set(S.tx(2), 'string',['mu(2): ', num2str(mu(2))]); % update text box.
case S.sl(3)
Sigma(1) = get(S.sl(3),'val'); % Get slider's value.
set(S.tx(3), 'string',['Sigma(1,1): ', num2str(Sigma(1))]); % update text box.
case S.sl(4)
Sigma(2) = get(S.sl(4),'val');
set(S.tx(4), 'string',['Sigma(2,1): ', num2str(Sigma(2))]); % update text box.
Sigma(3) = Sigma(2); % make sure Sigma is symmetric matrix.
set(S.sl(5), 'value', Sigma(2)); % Adjust the slider to match the value.
set(S.tx(5), 'string',['Sigma(1,2): ', num2str(Sigma(2))]);
case S.sl(5)
Sigma(3) = get(S.sl(5),'val');
set(S.tx(5), 'string',['Sigma(1,2): ', num2str(Sigma(3))]); % update text box.
Sigma(2) = Sigma(3); % Make sure Sigma is symmetric matrix.
set(S.sl(4), 'value', Sigma(3)); % Adjust the slider to match the value.
set(S.tx(4), 'string',['Sigma(2,1): ', num2str(Sigma(3))]); % update text box.
case S.sl(6)
Sigma(4) = get(S.sl(6),'val');
set(S.tx(6), 'string',['Sigma(2,2): ', num2str(Sigma(4))]);
end
try
z_shaped = reshape(mvnpdf(X, mu, Sigma), 100, 100); % if Sigma not square, symmetric, positive definite matrix.
if tog_value
%{
I want to improve script performance. Casue I think update
axes's zdata faster than plot a new axes.
%}
% line = surf(x, y, z_shaped,...
% 'edgecolor', 'interp');
% % line = surf(x, y, z_shaped,...
% % 'edgecolor', 'interp');
% set(S.togbtn, 'string', 'surf');
set(line, 'zdata', z_shaped)
else
h_contour = allchild(S.ax);
set(h_contour, 'zdata', z_shaped)
%{
I want to improve script performance. Casue I think update
axes's zdata faster than plot a new axes.
%}
% line = contour(x, y, z_shaped,... % I want to improve script performance.
% 'ShowText', 'on', 'LineWidth', 1);
% set(S.togbtn, 'string', 'contour');
end
catch ME
if (strcmp(ME.identifier, 'stats:mvnpdf:BadMatrixSigma'))
disp('Incorrect Sigma: ');disp(Sigma);
warndlg('Sigma must be a square, symmetric, positive definite matrix.')
else
errordlg(ME.message)
end
end
end
图例:
点击左上角按钮切换成等势线-contour