采用ReLU作为激活函数的简单深度神经网络matlab代码设计

本文介绍下如何实现神经元激活函数为ReLU深度神经网络。ReLU函数的数学公式很简单ReLU(x)=max(x,0)。若DNN用于数据分类,则可以简单的认为其主要由两个部分组成:多隐层网络+分类器。分类器采用softmax

第一步:准备数据

1)将你需要分类的样本数据以每列的形式保存于矩阵中;->TrainData 
2)将每个样本的类别标记按数据顺序存为一行向量,类别为1,2,3,…,n->TrainLabel

将数据保存入MyData.mat数据文件中。

采用以下程序实现数据的生成。 

x=1:10

y=1:8:80

rt=x.*x-50*x+40*y-y.^2;

TrainData=[x;y];

for k=1:10

    v_rt_k=rt(k)

    if rt(k)<=0

        TrainLabel(k)=1;

    else

        TrainLabel(k)=2;

    end

end

save('MyData.mat','TrainData','TrainLabel')

 

:网络配置、参数初始化和转换

将第一步中准备好的数据载入内存中,并采用以下程序运行数据。

1. Main_function without minFunc

clear all

clc

close all

load MyData.mat

inputsize=size(TrainData ,1);%获取数据的维度

datanum=size(TrainData ,2);%获取数据的数量

% netsize=[inputsize,50,50,50];

%可以简单地用一个向量来定义网络的深度,以及每层神经元数目。这表示一个三隐藏层的DNN,神经元数都为50

netsize=[inputsize,4,3];

classnum=2;%类别数目

 

lastsize=netsize(end)+1;%网络最后一层神经元数数目,再考虑一个偏置。

 

stack = initializeNet(netsize);%初始化网络参数,以结构体的形式保存。

 

v_stack=stack

v_stack_1=stack{1}

v_stack_1_w=stack{1}.w

v_stack_1_b=stack{1}.b

v_stack_2=stack{2}

v_stack_2_w=stack{2}.w

v_stack_2_b=stack{2}.b

 

%在训练时,往往需要将参数转成一列向量,提供给损失函数。stack ->stackThetanetconfig保存一些结构参数

[stackTheta, netconfig] = stack2params(stack);

v_stackTheta=stackTheta

v_netconfig=netconfig

v_netconfig_layersizes=netconfig.layersizes

 

v_lastsize=lastsize

SoftmaxTheta = 0.0005 * randn(lastsize * classnum, 1);

v_SoftmaxTheta=SoftmaxTheta

 

Theta=[ SoftmaxTheta ; stackTheta ];%最终网络需要的参数

% the following part is for the traing epoch.

batchsize=10;

% batchsize=5;

%%每次训练的小批量样本数</span>  

batchnum=floor(size(TrainData,2)/batchsize);  

DataNum=size(TrainData,2);  

alpha=1e-2;

%这是学习率,一般随着网络的悬念都需要不断的减小  

lambda = 1e-4; % Weight decay parameter

for epoch=1:16000

    v_epoch=epoch

    idx=randperm(DataNum);

    for t=1:batchnum

        subdata=TrainData(:,idx((t-1)*batchsize+1:(t)*batchsize));

        sublabel=TrainLabel(idx((t-1)*batchsize+1:(t)*batchsize));

        [cost,grad]=ReLUDNNCost(Theta,classnum,lastsize,netconfig,lambda,subdata,sublabel);

        Theta=Theta-alpha*grad;

        v_grad=grad

    end      

end

% Note: Theta传递进入损失函数内部时,还需要从Theta抽出stackTheta,再转成stack代码如下,都是Andrew Ng的教程里面的提供的。 

 

2. Main_function with minFunc of UFLDL

clear all

clc

close all

load MyData.mat

inputsize=size(TrainData ,1);%获取数据的维度

datanum=size(TrainData ,2);%获取数据的数量

% netsize=[inputsize,50,50,50];

%可以简单地用一个向量来定义网络的深度,以及每层神经元数目。这表示一个三隐藏层的DNN,神经元数都为50

netsize=[inputsize,4,3];

classnum=2;%类别数目

 

lastsize=netsize(end)+1;%网络最后一层神经元数数目,再考虑一个偏置。

% v_lastsize=lastsize

 

stack = initializeNet(netsize);%初始化网络参数,以结构体的形式保存。

 

v_stack=stack

v_stack_1=stack{1}

v_stack_1_w=stack{1}.w

v_stack_1_b=stack{1}.b

v_stack_2=stack{2}

v_stack_2_w=stack{2}.w

v_stack_2_b=stack{2}.b

 

%在训练时,往往需要将参数转成一列向量,提供给损失函数。stack ->stackThetanetconfig保存一些结构参数

[stackTheta, netconfig] = stack2params(stack);

v_stackTheta=stackTheta

v_netconfig=netconfig

v_netconfig_layersizes=netconfig.layersizes

 

v_lastsize=lastsize

SoftmaxTheta = 0.0005 * randn(lastsize * classnum, 1);

v_SoftmaxTheta=SoftmaxTheta

 

Theta=[ SoftmaxTheta ; stackTheta ];%最终网络需要的参数

 

% the following part is for the minFunc in the UFLDL tutorial

options.Method = 'lbfgs';

options.maxIter = 20000;

options.MaxFunEvals=1000000;

options.display = 'on';

lambda = 1e-4;

[OptTheta, cost] = minFunc( @(p)ReLUDNNCost(p,classnum,lastsize,netconfig,lambda, TrainData,TrainLabel),Theta, options);

 

v_TrainLabel=TrainLabel

save('weights_matrix_minFunc.mat','OptTheta')

 

% % the following part is for the SGD traing epoch.

% batchsize=10;

% % batchsize=5;

% %%每次训练的小批量样本数</span>  

% batchnum=floor(size(TrainData,2)/batchsize);  

% DataNum=size(TrainData,2);  

% alpha=1e-2;

% %这是学习率,一般随着网络的悬念都需要不断的减小  

% lambda = 1e-4; % Weight decay parameter

% for epoch=1:16000

%     v_epoch=epoch

%     idx=randperm(DataNum);

%     for t=1:batchnum

%         subdata=TrainData(:,idx((t-1)*batchsize+1:(t)*batchsize));

%         sublabel=TrainLabel(idx((t-1)*batchsize+1:(t)*batchsize));

%         [cost,grad]=ReLUDNNCost(Theta,classnum,lastsize,netconfig,lambda,subdata,sublabel);

%         Theta=Theta-alpha*grad;

%         v_grad=grad

%     end      

% end

% save('weights_matrix_minFunc.mat','Theta')

 

3. Main_function2 with minFunc of UFLDL

clear all

clc

close all

load MyData.mat

inputsize=size(TrainData ,1);%获取数据的维度

datanum=size(TrainData ,2);%获取数据的数量

% netsize=[inputsize,50,50,50];

%可以简单地用一个向量来定义网络的深度,以及每层神经元数目。这表示一个三隐藏层的DNN,神经元数都为50

netsize=[inputsize,4,3];

classnum=2;%类别数目

 

lastsize=netsize(end)+1;%网络最后一层神经元数数目,再考虑一个偏置。

% v_lastsize=lastsize

 

stack = initializeNet(netsize);%初始化网络参数,以结构体的形式保存。

 

v_stack=stack

v_stack_1=stack{1}

v_stack_1_w=stack{1}.w

v_stack_1_b=stack{1}.b

v_stack_2=stack{2}

v_stack_2_w=stack{2}.w

v_stack_2_b=stack{2}.b

 

%在训练时,往往需要将参数转成一列向量,提供给损失函数。stack ->stackThetanetconfig保存一些结构参数

[stackTheta, netconfig] = stack2params(stack);

v_stackTheta=stackTheta

v_netconfig=netconfig

v_netconfig_layersizes=netconfig.layersizes

 

v_lastsize=lastsize

SoftmaxTheta = 0.0005 * randn(lastsize * classnum, 1);

v_SoftmaxTheta=SoftmaxTheta

 

Theta=[ SoftmaxTheta ; stackTheta ];%最终网络需要的参数

% the following part is for the traing epoch.

batchsize=10;

% batchsize=5;

%%每次训练的小批量样本数</span>  

batchnum=floor(size(TrainData,2)/batchsize);  

DataNum=size(TrainData,2);  

alpha=1e-2;

%这是学习率,一般随着网络的悬念都需要不断的减小  

lambda = 1e-4; % Weight decay parameter

for epoch=1:16000

    v_epoch=epoch

    idx=randperm(DataNum);

    for t=1:batchnum

        subdata=TrainData(:,idx((t-1)*batchsize+1:(t)*batchsize));

        sublabel=TrainLabel(idx((t-1)*batchsize+1:(t)*batchsize));

        [cost,grad]=ReLUDNNCost(Theta,classnum,lastsize,netconfig,lambda,subdata,sublabel);

        Theta=Theta-alpha*grad;

        v_grad=grad

    end      

    v_trainLabels=sublabel

end

save('weights_matrix2.mat','Theta')

4. ReLUDNNCost

function [cost,grad] = ReLUDNNCost(theta,numClasses,lasthiddenSize, netconfig,lambda, trainData,trainLabels)

%参数获取的一些操作

softmaxTheta = reshape(theta(1:lasthiddenSize*numClasses), numClasses, lasthiddenSize);

stack = params2stack(theta(lasthiddenSize*numClasses+1:end), netconfig);

%theta向量中抽取网络权值参数并转化

stackgrad = cell(size(stack));

 

PARA=cell(numel(stack),1);%这里保存在应用BP算法求梯度时需要的数据

datanum=size(trainData,2);%传进来的样本数

 

%开始前馈,网络虽然多层,但只是重复而已

data=trainData;

for d = 1:numel(stack)

PARA{d}.a=data;

z2=(stack{d}.w*data)+stack{d}.b*ones(1,datanum);

a2=relu(z2);%RelU函数

data=a2;

PARA{d}.daz=drelu(z2);%RelU函数的导函数

end

a2=[a2;ones(1,datanum)];

%开始求解损失

% v_trainLabels=trainLabels

% v_datanum=datanum

groundTruth = full(sparse(trainLabels, 1:datanum, 1));

% %这是Andrew NG教程原版的语句,但其在应用小批量样本训练时会出错,下一行是另一种实现方式

 

% v_trainLabels=trainLabels

% v_numClasses=numClasses

% v_element1=repmat(trainLabels,numClasses,1)

% v_element2=(1:1:numClasses)'

% groundTruth=bsxfun(@eq,repmat(trainLabels,numClasses,1),(1:1:numClasses)');

% v_groundTruth=groundTruth

% pause

M = softmaxTheta*a2;

h = exp(M);

h = bsxfun(@rdivide, h, sum(h));

% v_size_groundTruth=size(groundTruth)

% v_log_h=size(log(h))

cost = -1/datanum*sum(sum(groundTruth.*log(h)))+lambda/2*sum(sum(softmaxTheta.^2));

%softmax 损失函数,没啥好说的

softmaxThetaGrad = -1/datanum*((groundTruth-h)*a2')+lambda*softmaxTheta;

%softmax 目标函数对softmaxTheta 的导数,

 

predelta=-softmaxTheta'*(groundTruth-h);

%想理解这里,还有后面的梯度是如何计算出的,建议看那本关于矩阵的工具书《The Matrix Cookbook

predelta=predelta(1:end-1,:);

for d = numel(stack):-1:1

delta=predelta.*PARA{d}.daz;

stackgrad{d}.w=delta*PARA{d}.a'/datanum;%.*PARA{d}.idx

stackgrad{d}.b=sum(delta,2)/datanum;

predelta=stack{d}.w'*delta;

end

grad = [softmaxThetaGrad(:) ; stack2params(stackgrad)];

end

 

5. relu

function re = relu(x)

re = max(x,0)-1;

end

 

6. drelu

function dre= drelu(x)

dre=zeros(size(x));

dre(x>0)=1;

dre(x==0)=0.5;%这句可以不要

end

 

7. initializeNet

function stack = initializeNet(netsize)

layersize=length(netsize(:));

stack = cell(layersize-1,1);

for l=1:layersize-1

    hiddenSize=netsize(l+1);

    visibleSize=netsize(l);

    r =sqrt(6) / sqrt(hiddenSize+visibleSize+1);

    stack{l}.w= rand(hiddenSize, visibleSize) * 2 * r - r; stack{l}.b= zeros(hiddenSize, 1);

end

end

 

8. params2stack

function stack = params2stack(params, netconfig)

depth = numel(netconfig.layersizes);

stack = cell(depth,1);

prevLayerSize = netconfig.inputsize; % the size of the previous layer

curPos = double(1); % mark current position in parameter vector

for d = 1:depth

% Create layer d

stack{d} = struct;

% Extract weights

wlen = double(netconfig.layersizes{d} * prevLayerSize);

stack{d}.w = reshape(params(curPos:curPos+wlen-1), netconfig.layersizes{d}, prevLayerSize);

curPos = curPos+wlen;

% Extract bias

blen = double(netconfig.layersizes{d});

stack{d}.b = reshape(params(curPos:curPos+blen-1), netconfig.layersizes{d}, 1);

curPos = curPos+blen;

% Set previous layer size

prevLayerSize = netconfig.layersizes{d};

end

end

 

9. stack2params

function [params, netconfig] = stack2params(stack)

params = [];

for d = 1:numel(stack)

    params = [params ; stack{d}.w(:) ;

        stack{d}.b(:) ];

end

if nargout > 1

    if numel(stack) == 0

        netconfig.inputsize = 0;

        netconfig.layersizes = {};

    else

        netconfig.inputsize = size(stack{1}.w, 2);

        netconfig.layersizes = {};

        for d = 1:numel(stack)

            netconfig.layersizes = [netconfig.layersizes ; size(stack{d}.w,1)];

        end

    end

end

end

 

采用已训练的深度网络对输入数据进行测试

1. Main_test_function

clear all

clc

close all

load MyData.mat

load weights_matrix.mat

inputsize=size(TrainData ,1);%获取数据的维度

datanum=size(TrainData ,2);%获取数据的数量

% netsize=[inputsize,50,50,50];

%可以简单地用一个向量来定义网络的深度,以及每层神经元数目。这表示一个三隐藏层的DNN,神经元数都为50

netsize=[inputsize,4,3];

classnum=2;%类别数目

 

netconfig2.inputsize=netsize(1)

netconfig2.layersizes{1}=netsize(2)

netconfig2.layersizes{2}=netsize(3)

netconfig2.layersizes=netconfig2.layersizes'

 

lastsize=netsize(end)+1;%网络最后一层神经元数数目,再考虑一个偏置。

 

v_result = forward_computation(Theta,classnum,lastsize,netconfig2,TrainData)

v_TrainLabel=TrainLabel

 

2. forward_computation

function v_result = forward_computation(theta,numClasses,lasthiddenSize, netconfig,trainData,trainLabels)

%参数获取的一些操作

softmaxTheta = reshape(theta(1:lasthiddenSize*numClasses), numClasses, lasthiddenSize);

stack = params2stack(theta(lasthiddenSize*numClasses+1:end), netconfig);

%theta向量中抽取网络权值参数并转化

stackgrad = cell(size(stack));

 

PARA=cell(numel(stack),1);%这里保存在应用BP算法求梯度时需要的数据

datanum=size(trainData,2);%传进来的样本数

 

%开始前馈,网络虽然多层,但只是重复而已

data=trainData;

for d = 1:numel(stack)

PARA{d}.a=data;

z2=(stack{d}.w*data)+stack{d}.b*ones(1,datanum);

a2=relu(z2);%RelU函数

data=a2;

PARA{d}.daz=drelu(z2);%RelU函数的导函数

end

a2=[a2;ones(1,datanum)];

 

M = softmaxTheta*a2;

h = exp(M);

h = bsxfun(@rdivide, h, sum(h));

v_result=h

end

  • 9
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值