利用Matlab构建深度前馈神经网络以及各类优化算法的应用(SGD、mSGD、AdaGrad、RMSProp、Adam)

  • 本文介绍如何利用Matlab从头搭建深度前馈神经网络,实现手写字体mnist数据集的识别,以及展示各类优化算法的训练效果,包括SGD、mSGD、AdaGrad、RMSProp、Adam,最终网络的识别率能达到98%。读者可自行调整网络结构和参数。
  • 本文的Matlab代码和mnist数据集下载地址为:
    链接: https://pan.baidu.com/s/1Me0T2xZwpn3xnN7b7XPrbg 密码: t23u
  • 如果对神经网络的公式推导不熟悉,可以看看这个神经网络的基本理论公式推导
    首先,神经网络的激活函数选择Sigmoid和Relu两种。神经网络的隐藏层选择Relu激活函数,输出层选择Sigmoid激活函数。
function [y] = sigmoid(x)
%sigmoid sigmoid激活函数
%   此处显示详细说明
y = 1./(1 + exp(-x));
end
function [y] = relu(x)
%relu 激活函数
%   此处显示详细说明
p = (x > 0);
y = x.*p;
end

创建深度网络的结构

function [dnn,parameter] = creatnn(K)
%UNTITLED6 此处显示有关此函数的摘要
% parameter 是结构体,包括参数:
%                       learning_rate: 学习率
%                       momentum: 动量系数,一般为0.5,0.9,0.99
%                       attenuation_rate: 衰减系数
%                       delta:稳定数值
%                       step: 步长 一般为 0.001
%                       method: 方法{'SGD','mSGD','nSGD','AdaGrad','RMSProp','nRMSProp','Adam'}
L = size(K.a,2);
for i = 1:L-1
    dnn{i}.W = unifrnd(-sqrt(6/(K.a(i)+K.a(i+1))),sqrt(6/(K.a(i)+K.a(i+1))),K.a(i+1),K.a(i));
    % dnn{i}.W = normrnd(0,0.1,K.a(i+1),K.a(i));
    dnn{i}.function = K.f{i};
    dnn{i}.b = 0.01*ones(K.a(i+1),1);
end
    parameter.learning_rate = 0.01;
    parameter.momentum = 0.9;
    parameter.attenuation_rate = 0.9;
    parameter.delta = 1e-6;
    parameter.step = 0.001;
    parameter.method = "SGD";
    parameter.beta1 = 0.9;
    parameter.beta2 = 0.999;
end

构建前向传播函数

function [y, Y] = forwordprop(dnn,x)
%UNTITLED3 此处显示有关此函数的摘要
%   此处显示详细说明
L = size(dnn,2);
m = size(x,2);
Y{1} = x;
for i = 1:L
    z = dnn{i}.W*x + repmat(dnn{i}.b,1,m);
    if dnn{i}.function == "relu"
        y = relu(z);
    end
    if dnn{i}.function == "sigmoid"
        y = sigmoid(z);
    end
    Y{i+1} = y;
    x = y;
end
end

构建反向误差传播函数

function [dnn] = backprop(x,label,dnn,parameter)
%UNTITLED2 此处显示有关此函数的摘要
%   parameter 是结构体,包括参数:
%                       learning_rate: 学习率
%                       momentum: 动量系数,一般为0.5,0.9,0.99
%                       attenuation_rate: 衰减系数
%                       delta:稳定数值
%                       step: 步长 一般为 0.001
%                       method: 方法{'SGD','mSGD','nSGD','AdaGrad','RMSProp','nRMSProp','Adam'}
%
L = size(dnn,2)+1;
m = size(x,2);
[y, Y] = forwordprop(dnn,x);
g = -label./y + (1 - label)./(1 - y);
method = {"SGD","mSGD","nSGD","AdaGrad","RMSProp","nRMSProp","Adam"};

persistent global_step;
if isempty(global_step)
   global_step = 0;
end
global_step = global_step + 1;
% fprintf("global_step %d\n",global_step)
global E;
E(global_step) = sum(sum(-label.*log(y)-(1 - label).*log(1 - y)))/m;
persistent V;
if isempty(V)
    for i = 1:L-1
        V{i}.vw = dnn{i}.W*0;
        V{i}.vb = dnn{i}.b*0;
    end
end

if parameter.method == method{1,1}
    for i = L : -1 : 2
        if dnn{i-1}.function == "relu"
            g = g.*(Y{i} > 0);
        end
        if dnn{i-1}.function == "sigmoid"
            g = g.*Y{i}.*(1 - Y{i});
        end
            dw = g*Y{i - 1}.'/m;
            db = sum(g,2)/m;
            g = dnn{i-1}.W'*g;
            dnn{i-1}.W = dnn{i-1}.W - parameter.learning_rate*dw;
            dnn{i-1}.b = dnn{i-1}.b - parameter.learning_rate*db;
    end                                                                                                                                                                                                                                                                                        
end

if parameter.method == method{1,2}
    for i = L : -1 : 2
        if dnn{i-1}.function == "relu"
            g = g.*(Y{i} > 0);
        end
        if dnn{i-1}.function == "sigmoid"
            g = g.*Y{i}.*(1 - Y{i});
        end
            dw = g*Y{i - 1}.'/m;
            db = sum(g,2)/m;
            g = dnn{i-1}.W'*g;
            V{i-1}.vw = parameter.momentum*V{i-1}.vw - parameter.learning_rate*dw; 
            V{i-1}.vb = parameter.momentum*V{i-1}.vb - parameter.learning_rate*db;
            dnn{i-1}.W = dnn{i-1}.W + V{i-1}.vw;
            dnn{i-1}.b = dnn{i-1}.b + V{i-1}.vb;
    end
end

if parameter.method == method{1,3} % 未实现    
    for i = L : -1 : 2
        if dnn{i-1}.function == "relu"
            g = g.*(Y{i} > 0);
        end
        if dnn{i-1}.function == "sigmoid"
            g = g.*Y{i}.*(1 - Y{i});
        end
            dw = g*Y{i - 1}.'/m;
            db = sum(g,2)/m;
            g = dnn{i-1}.W'*g;
            V{i-1}.vw = parameter.momentum*V{i-1}.vw - parameter.learning_rate*dw; 
            V{i-1}.vb = parameter.momentum*V{i-1}.vb - parameter.learning_rate*db;
            dnn{i-1}.W = dnn{i-1}.W + V{i-1}.vw;
            dnn{i-1}.b = dnn{i-1}.b + V{i-1}.vb;
    end
end

if parameter.method == method{1,4}     
    for i = L : -1 : 2
        if dnn{i-1}.function == "relu"
            g = g.*(Y{i} > 0);
        end
        if dnn{i-1}.function == "sigmoid"
            g = g.*Y{i}.*(1 - Y{i});
        end
            dw = g*Y{i - 1}.'/m;
            db = sum(g,2)/m;
            g = dnn{i-1}.W'*g;
            V{i-1}.vw = V{i-1}.vw + dw.*dw; 
            V{i-1}.vb = V{i-1}.vb + db.*db;
            dnn{i-1}.W = dnn{i-1}.W - parameter.learning_rate./(parameter.delta + sqrt(V{i-1}.vw)).*dw;
            dnn{i-1}.b = dnn{i-1}.b - parameter.learning_rate./(parameter.delta + sqrt(V{i-1}.vb)).*db;
    end
end

if parameter.method == method{1,5}     
    for i = L : -1 : 2
        if dnn{i-1}.function == "relu"
            g = g.*(Y{i} > 0);
        end
        if dnn{i-1}.function == "sigmoid"
            g = g.*Y{i}.*(1 - Y{i});
        end
            dw = g*Y{i - 1}.'/m;
            db = sum(g,2)/m;
            g = dnn{i-1}.W'*g;
            V{i-1}.vw = parameter.attenuation_rate*V{i-1}.vw + (1 - parameter.attenuation_rate)*dw.*dw; 
            V{i-1}.vb = parameter.attenuation_rate*V{i-1}.vb + (1 - parameter.attenuation_rate)*db.*db;
            dnn{i-1}.W = dnn{i-1}.W - parameter.learning_rate./sqrt(parameter.delta + V{i-1}.vw).*dw;
            dnn{i-1}.b = dnn{i-1}.b - parameter.learning_rate./sqrt(parameter.delta + V{i-1}.vb).*db;
    end
end

persistent s;
if parameter.method == method{1,7}  
    if isempty(s)
        for i = 1:L-1
            s{i}.vw = dnn{i}.W*0;
            s{i}.vb = dnn{i}.b*0;
        end
    end
    for i = L : -1 : 2
        if dnn{i-1}.function == "relu"
            g = g.*(Y{i} > 0);
        end
        if dnn{i-1}.function == "sigmoid"
            g = g.*Y{i}.*(1 - Y{i});
        end
            dw = g*Y{i - 1}.'/m;
            db = sum(g,2)/m;
            g = dnn{i-1}.W'*g;
            s{i-1}.vw = parameter.beta2*s{i-1}.vw + (1 - parameter.beta1)*dw; 
            s{i-1}.vb = parameter.beta2*s{i-1}.vb + (1 - parameter.beta1)*db;
            V{i-1}.vw = parameter.beta2*V{i-1}.vw + (1 - parameter.beta2)*dw.*dw; 
            V{i-1}.vb = parameter.beta2*V{i-1}.vb + (1 - parameter.beta2)*db.*db;
            
            dnn{i-1}.W = dnn{i-1}.W - parameter.learning_rate*(s{i-1}.vw/(1-parameter.beta1.^global_step))./(parameter.delta + sqrt(V{i-1}.vw./(1 - parameter.beta2.^global_step)));
            dnn{i-1}.b = dnn{i-1}.b - parameter.learning_rate*(s{i-1}.vb/(1-parameter.beta1.^global_step))./(parameter.delta + sqrt(V{i-1}.vb./(1 - parameter.beta2.^global_step)));
    end
end
end
  • 注意,如果训练过程中出现正确率很低,而且保持不变,应该考虑数值不稳定的问题,也就是出现了无穷小NaN,考虑在函数开始的g中添加数值稳定项。

好了,到这里,网络需要的函数都搭建完成了。下面开始构建一个双隐层的前馈神经网络,实现mnist数据集的识别。

clear all
load('mnist_uint8.mat');
test_x = (double(test_x)/255)';
train_x = (double(train_x)/255)';
test_y = double(test_y.');
train_y = double(train_y.');
K.f = {"relu","relu","relu","sigmoid"};
K.a = [784,400,300,500,10];
[net,P] = creatnn(K);
P.method = "RMSProp";
P.learning_rate = 0.001;
m = size(train_x,2);
batch_size = 100;
MAX_P = 2000;
global E;
for i = 1:MAX_P
    q = randi(m,1,batch_size);
    train = train_x(:,q);
    label = train_y(:,q);
    net = backprop(train,label,net,P);
    if mod(i,50) == 0
        [output,~] = forwordprop(net,train);
        [~,index0] = max(output);
        [~,index1] = max(label);
        rate = sum(index0 == index1)/batch_size;
        fprintf("第%d训练包的正确率:%f\n",i,rate)
        [output,~] = forwordprop(net,test_x);
        [~,index0] = max(output);
        [~,index1] = max(test_y);
        rate = sum(index0 == index1)/size(test_x,2);
        fprintf("测试集的正确率:%f\n",rate)
    end
end

测试结果:
识别率和训练误差
训练误差:
这里写图片描述
好了,大家可以自行搭建网络了,如果遇到什么问题可以下面留言哦!

  • 22
    点赞
  • 142
    收藏
    觉得还不错? 一键收藏
  • 66
    评论
Deep Learning Toolbox™提供了一个框架,用于设计和实现具有算法,预训练模型和应用程序的深度神经。您可以使用卷积神经(ConvNets,CNN)和长期短期记忆(LSTM)网对图像,时间序列和文本数据进行分类和回归。应用程序和图表可帮助您可视化激活,编辑网体系结构以及监控培训进度。 对于小型训练集,您可以使用预训练的深层网模型(包括SqueezeNet,Inception-v3,ResNet-101,GoogLeNet和VGG-19)以及从TensorFlow™-Keras和Caffe导入的模型执行传输学习。 了解深度学习工具箱的基础知识 深度学习图像 从头开始训练卷积神经或使用预训练网快速学习新任务 使用时间序列,序列和文本进行深度学习 为时间序列分类,回归和预测任务创建和训练网 深度学习调整和可视化 绘制培训进度,评估准确性,进行预测,调整培训选项以及可视化网学习的功能 并行和云中的深度学习 通过本地或云中的多个GPU扩展深度学习,并以交互方式或批量作业培训多个网 深度学习应用 通过计算机视觉,图像处理,自动驾驶,信号和音频扩展深度学习工作流程 深度学习导入,导出和自定义 导入和导出网,定义自定义深度学习图层以及自定义数据存储 深度学习代码生成 生成MATLAB代码或CUDA ®和C ++代码和部署深学习网 函数逼近和聚类 使用浅层神经执行回归,分类和聚类 时间序列和控制系统 基于浅网的模型非线性动态系统; 使用顺序数据进行预测。
以下是MATLAB实现基于BP神经灰狼优化算法的多输入寻优的完整代码: ``` function [xopt,fopt]=GWO_BP(Function_name,ub,lb,dim,SearchAgents_no,Max_iter) % 输入: % Function_name: 测试函数名 % ub: 自变量上界 % lb: 自变量下界 % dim: 自变量维度 % SearchAgents_no: 狼群数量 % Max_iter: 最大迭代次数 % 输出: % xopt: 最优解 % fopt: 最优值 % BP神经初始化 net=feedforwardnet([10 5 1]); % 三层前馈神经网络 net.trainFcn='trainlm'; % Levenberg-Marquardt算法 net.trainParam.showWindow=0; % 不显示窗口 net.trainParam.showCommandLine=0; % 不显示命令行 net.trainParam.epochs=100; % 训练次数 net=init(net); % 灰狼优化初始化 Alpha_pos=zeros(1,dim); % Alpha狼位置 Alpha_score=inf; % Alpha狼得分 Beta_pos=zeros(1,dim); % Beta狼位置 Beta_score=inf; % Beta狼得分 Delta_pos=zeros(1,dim); % Delta狼位置 Delta_score=inf; % Delta狼得分 Positions=initialization(SearchAgents_no,dim,ub,lb); % 狼群位置 Convergence_curve=zeros(1,Max_iter); % 收敛曲线 % 灰狼优化主循环 for iter=1:Max_iter for i=1:size(Positions,1) % 计算适应度 fitness=calculate_fitness(Positions(i,:),net,Function_name); % 更新Alpha、Beta、Delta狼 if fitness<Alpha_score Alpha_score=fitness; Alpha_pos=Positions(i,:); end if fitness>Alpha_score && fitness<Beta_score Beta_score=fitness; Beta_pos=Positions(i,:); end if fitness>Alpha_score && fitness>Beta_score && fitness<Delta_score Delta_score=fitness; Delta_pos=Positions(i,:); end end % 更新参数a和A a=2-iter*((2)/Max_iter); A=2*a*rand()-a; % 更新狼群位置 for i=1:size(Positions,1) D_alpha=abs(A*Alpha_pos-Positions(i,:)); D_beta=abs(A*Beta_pos-Positions(i,:)); D_delta=abs(A*Delta_pos-Positions(i,:)); X1=Alpha_pos-A*D_alpha; X2=Beta_pos-A*D_beta; X3=Delta_pos-A*D_delta; Positions(i,:)=mean([X1;X2;X3]); end % 更新神经参数 for i=1:size(Positions,1) net=configure(net,Positions(i,:)',zeros(dim,1)'); net=train(net,Positions(i,:)',fitness); end % 更新收敛曲线 Convergence_curve(iter)=Alpha_score; end % 输出结果 xopt=Alpha_pos; fopt=Alpha_score; % 绘制收敛曲线 figure; plot(Convergence_curve); xlabel('迭代次数'); ylabel('最优值'); title('收敛曲线'); end % 狼群初始化函数 function Positions=initialization(SearchAgents_no,dim,ub,lb) Positions=rand(SearchAgents_no,dim).*(ub-lb)+lb; end % 计算适应度函数 function fitness=calculate_fitness(Position,net,Function_name) if strcmp(Function_name,'BP') % 神经预测 % ... % 计算误差 % ... % 适应度为误差的相反数 fitness=-error; else % 其他测试函数 % ... end end ``` 在上述代码中,我们使用了feedforwardnet函数初始化了一个三层前馈神经网络,并使用trainlm算法训练网。在calculate_fitness函数中,我们对输入的位置进行神经预测,并计算误差,最终将误差的相反数作为适应度。在主循环中,我们按照灰狼优化算法的步骤逐步更新了狼群位置和参数,同时利用每个位置对神经进行训练。最终输出最优解和最优值,并绘制了收敛曲线。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 66
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值