@TOC界面设计
本文主要介绍如何实现一个神经网络或深度学习应用的matlab-GUI实例,该程序具有界面,并且能实现BP网络、竞争网络、LVQ网络三种网络算法。
设计一个可以实现分类,预测,聚类功能的神经网络系统,设计的系统包括三种网络算法:BP网络算法,竞争网络算法,LVQ网络算法。其中BP网络与LVQ网络可以实现分类、预测功能;竞争网络可以实现聚类功能。
设计的界面中包括网络类型的选择,网络结构的设置,网络参数的设置,网络训练结果和测试结果的可视化。对于分类的问题,可以对期望值和实际值的差异进行可视化, 聚类的问题可以对最后的结果进行可视化,方便用户观察网络的拟合效果,从而进一步调节参数来训练网络。
设计的界面,由两部分组成,一部分主要是显示网络类型的选择、网络结构的设置,网络参数的设定,另一部分主要实现结果的可视化。除主界面外,还包含有两个子界面,一个用于提示该系统的使用方法,另一个用于展现竞争网络的聚类结果。
GUI界面设计:
界面包括一个下拉式菜单,可以选择三种网络,网络结构分别由三个静态文本框和可编辑文本组成;网络参数也是使用三个可编辑文本来输入参数。数据导入模块如图。
程序部分:
参数设计和网络结构设置部分
%% 网络结构设置(可编辑文本)
% 输入层的神经元个数
function edit_structure1_Callback(hObject, eventdata, handles)
% 使用set函数将文本中的内容清除
set(hObject, 'String');
% 将数据存储在一个对象中,方便调用
global inputlayer_num
uicontrol(hObject);
inputlayer_num = str2num(get(hObject, 'string'));
if isnan(inputlayer_num)
errordlg("yon need input a number", "Error input", "modal")
end
% --- Executes during object creation, after setting all properties.
function edit_structure1_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
% 输出层神经元个数
function edit_structure3_Callback(hObject, eventdata, handles)
% 使用set函数将文本中的内容清除
set(hObject, 'String');
uicontrol(hObject);
global outputlayer_num;
outputlayer_num = str2num(get(hObject, 'string'));
if isnan(outputlayer_num)
errordlg("yon need input a number", "Error input", "modal")
end
% --- Executes during object creation, after setting all properties.
function edit_structure3_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
% 隐藏层神经元个数
function edit_structure2_Callback(hObject, eventdata, handles)
% 使用set函数将文本中的内容清除
set(hObject, 'String');
uicontrol(hObject);
global hiddenlayer_num
% 获取隐层神经元个数
hiddenlayer_num = str2num(get(hObject, 'string'));
if isnan(hiddenlayer_num)
errordlg("yon need input a number", "Error input", "modal")
end
% --- Executes during object creation, after setting all properties.
function edit_structure2_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
%% 网络参数设置(可编辑文本)
% 迭代次数设置
function edit_params1_Callback(hObject, eventdata, handles)
% 使用set函数将文本中的内容清除
set(hObject, 'String');
uicontrol(hObject);
global params_epochs;
% 设置迭代次数
params_epochs = str2num(get(hObject, 'string'));
if isnan(params_epochs)
errordlg("yon need input a number", "Error input", "modal")
end
% --- Executes during object creation, after setting all properties.
function edit_params1_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
% 学习率设置
function edit_params2_Callback(hObject, eventdata, handles)
% 使用set函数将文本中的内容清除
set(hObject, 'String');
uicontrol(hObject);
% 设置学习率
global params_lr;
params_lr= str2num(get(hObject, 'string'));
if isnan(params_lr)
errordlg("yon need input a number", "Error input", "modal")
end
% --- Executes during object creation, after setting all properties.
function edit_params2_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
% 目标误差设置
function edit_params3_Callback(hObject, eventdata, handles)
% 使用set函数将文本中的内容清除
set(hObject, 'String');
uicontrol(hObject);
% 设置目标误差
global params_goal;
params_goal= str2num(get(hObject, 'string'));
if isnan(params_goal)
errordlg("yon need input a number", "Error input", "modal")
end
% --- Executes during object creation, after setting all properties.
function edit_params3_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
数据导入部分:
%% 数据导入工作区(按钮)
function pushbutton_importdata1_Callback(hObject, eventdata, handles)
% 导入数据
[filename, pathname] = uigetfile( ...
{'*.m;*.fig;*.mat;*.mdl', 'All MATLAB Files (*.m, *.fig, *.mat, *.mdl)'; ...
'*.*', 'All Files (*.*)'}, ...
'Pick a file');
if (filename==0 & pathname==0)
msgbox('您没有选择文件,请重新选择!','打开文件出错','error');
else
Numdata = load(strcat([pathname,filename])); %加载数据,保存为一个结构体
dataname=fieldnames(Numdata); %获取结构体的所有变量名,保存为一个矩阵
length = size(dataname,1); %获取矩阵的长度
for i=1:length
strname = dataname(i,1);
assignin('base',char(strname), getfield(Numdata,char(strname)));% 要将变量名转换为字符串,getfield获取结构体中指定变量的值,然后用assignin将变量加载到工作空间
end
msgbox('打开及读取数据完毕!','确认','warn');
end
%% 数据导入:输入及输出
% 输入
function edit_input_data_Callback(hObject, eventdata, handles)
% 清空文本
set(hObject, 'String');
uicontrol(hObject);
% 获取文本中的输入名
input_name = get(hObject, 'string');
% 从工作区导入输入数据
global input;
input = evalin('base', input_name);
% --- Executes during object creation, after setting all properties.
function edit_input_data_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
% 输出
function edit_output_data_Callback(hObject, eventdata, handles)
% 清空文本
set(hObject, 'String');
uicontrol(hObject);
% 获取文本的输出名
output_name = get(hObject, 'string');
% 从工作区导入输出数据
global output;
output = evalin('base', output_name);
% --- Executes during object creation, after setting all properties.
function edit_output_data_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
网络训练部分
%% 网络训练按钮(按钮)
% --- Executes on button press in pushbutton_network_sim.
function pushbutton_network_sim_Callback(hObject, eventdata, handles)
% 调用参数:输入层神经元,隐藏层神经元,输出层神经元,迭代次数,学习率,误差目标
% 输入数据,输出数据
global inputlayer_num;global hiddenlayer_num;global outputlayer_num;
global params_epochs;global params_lr;global params_goal;
global input;global output;
% 网络选择
global types
types
if types == 'BP网络 '
global output_train; global output_test;
global output_test_pred; global output_train_pred; % 将实际输出设为全局变量
[m, n] = size(input);
% 打乱数据集
k = rand(1, m);
[a, b] = sort(k);
% 随机选择训练样本,测试样本
% 训练集占比80%
train_percent = ceil(0.8 * m);
input = input';
output = output';
size(input)
size(output)
input_train = input(:, b(1 : train_percent)); % 训练输入
output_train = output(:, b(1 : train_percent)); % 期望输出
input_test = input(:, b(train_percent + 1 : m)); % 测试输入
output_test = output(:, b(train_percent + 1 : m)); % 测试期望输出
% 训练数据归一化
[inputn, inputps] = mapminmax(input_train);
[outputn, outputps] = mapminmax(output_train);
% 构建BP网络
net = newff(inputn, outputn, hiddenlayer_num);
net.trainParam.epochs = params_epochs; % 迭代次数
net.trainParam.lr = params_lr; % 学习率
net.trainParam.goal = params_goal; % 误差目标
% 网络训练
net = train(net, inputn, outputn);
an_train = sim(net, inputn);
output_train_pred = mapminmax('reverse', an_train, outputps); % 训练的实际输出
% 网络测试
inputn_test = mapminmax('apply', input_test, inputps); % 归一化
an = sim(net, inputn_test); % 测试
output_test_pred = mapminmax('reverse', an, outputps); % 反归一化,测试的实际输出
end
% 竞争网络
if types == '竞争网络 '
% 将训练结果和预测结果设为全局变量
global sim_train_pred; global sim_test_pred;
% 导入数据
input = input;
[m, n] = size(input);
% 分割训练样本与测试集
train_percent= m * 0.8;
input_train = input(1 : train_percent, :); % 训练集
input_train = input_train';
input_test = input(train_percent + 1 : m, :); % 测试集
input_test = input_test';
% 构建网络
Q = minmax(input_train);
net = newc(Q, hiddenlayer_num, params_lr);
net = init(net);
net.trainParam.epochs = params_epochs;
% 训练网络
net = train(net, input_train);
% 带回原数据测试网络
sim_train = sim(net, input_train);
sim_train_pred = vec2ind(sim_train);
% 测试网络
sim_test = sim(net, input_test);
sim_test_pred = vec2ind(sim_test);
end
% LVQ网络设置
if types == 'LVQ网络'
% 将期望输出与实际输出设为全局变量
global output_train; global output_test;
global y_pred_train_ind; global y_pred_test_ind;
% 数据集划分,随机选择80%样本作为训练集
input = input';
output = output';
size(input)
[m, n] = size(input);
sample = randperm(n); % 打乱样本集
max(sample)
trian_percent = ceil( n * 0.8); % 选择80%样本作为训练集
input_train = input(:, sample(1 : trian_percent));
output_train = output(:, sample(1 : trian_percent));
output_train_vec = ind2vec(output_train); % 将类别转化为向量形式
% 测试集
input_test = input(:, sample(trian_percent + 1 : end));
output_test = output(:, sample(trian_percent + 1 : end));
output_test_vec = ind2vec(output_test); % 将类别转化为向量形式
% 创建网络
net = lvqnet(hiddenlayer_num, params_lr);
net.trainParam.epochs = params_epochs;
net.trainParam.lr = params_lr;
net.trainParam.goal = params_goal;
% 训练网络
net = train(net, input_train, output_train_vec);
% 测试训练样本
y_pred_train = sim(net, input_train);
y_pred_train_ind = vec2ind(y_pred_train);
% 仿真测试
y_pred_test = sim(net, input_test);
y_pred_test_ind = vec2ind(y_pred_test);
end
坐标轴绘制部分(竞争网络是调用一个如下图的子界面来显示分类结果,如下图所示),调用子界面的代码为:
if types == '竞争网络 '
% 打开竞争网络显示界面
h = gcf;
COMPETE_Window;
end
%% 执行绘制图形命令
% --- Executes on button press in pushbutton_plot_error.
function pushbutton_plot_error_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton_plot_error (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% 获取变量
global types
if types == 'BP网络 '
% 调用第一个坐标轴绘制测试误差
axes(handles.axes_train_error);
% 调用数据
global output_train; global output_train_pred;
% 如果样本数过多, 随机抽取50%的样本绘图
[m, n] = size(output_train);
n = n;
sample = ceil(0.5 * n);
if n > 100
train_sample = output_train(:, 1 : 5 : sample);
train_pred_sample = output_train_pred(:, 1 : 5 : sample);
else
train_sample = output_train;
train_pred_sample = output_train_pred;
end
% 绘图
plot(train_sample, ':og');
hold on
plot(train_pred_sample, '- *');
xlabel('样本'); ylabel('输出');
legend('期望输出', '实际输出');
% 调用第二个坐标轴绘制测试误差
axes(handles.axes_test_error);
% 调用数据
global output_test; global output_test_pred;
% 随机抽取50%的样本绘图
[m, n] = size(output_test);
n = n;
if n > 100
sample = ceil(0.5 * n);
test_sample = output_test(:, 1 : 5 : sample);
test_pred_sample = output_test_pred(:, 1 : 5 : sample);
else
test_sample = output_test;
test_pred_sample = output_test_pred;
end
% 绘图
plot(test_sample, ':og');
hold on
plot(test_pred_sample, '- *');
xlabel('样本'); ylabel('输出');
legend('期望输出', '实际输出');
end
if types == '竞争网络 '
% 打开竞争网络显示界面
h = gcf;
COMPETE_Window;
end
if types == 'LVQ网络'
% 绘图
% 调用第一个坐标轴绘制测试误差
axes(handles.axes_train_error);
% 调用数据
global output_train; global y_pred_train_ind;
% 如果样本数过多, 随机抽取50%的样本绘图
[m, n] = size(output_train);
n = n;
sample = ceil(0.5 * n);
if n > 100
train_sample = output_train(:, 1 : 5 : sample);
train_pred_sample = y_pred_train_ind(:, 1 : 5 : sample);
else
train_sample = output_train;
train_pred_sample = y_pred_train_ind;
end
% 绘图
plot(train_sample, ':og');
hold on
plot(train_pred_sample, '- *');
xlabel('样本'); ylabel('输出');
legend('期望输出', '实际输出');
% 调用第二个坐标轴绘制测试误差
axes(handles.axes_test_error);
% 调用数据
global output_test; global y_pred_test_ind;
% 随机抽取50%的样本绘图
[m, n] = size(output_test);
n = n;
if n > 100
sample = ceil(0.5 * n);
test_sample = output_test(:, 1 : 5 : sample);
test_pred_sample = y_pred_test_ind(:, 1 : 5 : sample);
else
test_sample = output_test;
test_pred_sample = y_pred_test_ind;
end
% 绘图
plot(test_sample, ':og');
hold on
plot(test_pred_sample, '- *');
xlabel('样本'); ylabel('输出');
legend('期望输出', '实际输出');
end
在每次绘图完成后都需要清空坐标轴的图像,代码如下:
%% 清空图像
% --- Executes on button press in pushbutton_clear_axes.
function pushbutton_clear_axes_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton_clear_axes (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% 清空训练误差图
axes(handles.axes_train_error);
cla reset;
box on;
set(handles.axes_train_error, 'xtick', []);
set(handles.axes_train_error, 'ytick', []);
% 清空测试误差图
axes(handles.axes_test_error);
cla reset;
box on;
set(handles.axes_test_error, 'xtick', []);
set(handles.axes_test_error, 'ytick', []);
结果展示: