基于ReLU和Softmax的简单深度神经网络matlab代码设计 - 20170427

更新时间:2024-04-15 00:10:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

基于ReLU和Softmax的简单深度神经网络matlab代码设计

本文以matlab为工具介绍下如何实现神经元激活函数为ReLU的深度神经网络。ReLU函数的数学公式很简单ReLU(x)=max(x,0),但其对DNN的贡献是巨大的。若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) ifrt(k)<=0

TrainLabel(k)=1; else

TrainLabel(k)=2; end end

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

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

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

1. Main_function

clear all clc

close all

loadMyData.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;%网络最后一层神经元数数目,再考虑一个偏置。

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 ->stackTheta,netconfig保存一些结构参数

[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;

%%每次训练的小批量样本数

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代码如下,都是

2

Andrew Ng的教程里面的提供的。

2. Main_module_without_minFunc1

clear all clc

close all

loadMyData.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 ->stackTheta,netconfig保存一些结构参数

[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;

3

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;

% %%每次训练的小批量样本数

% 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. 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);%传进来的样本数

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

4

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

4. relu

function re = relu(x) re = max(x,0)-1; end

5. drelu

functiondre= drelu(x) dre=zeros(size(x)); dre(x>0)=1;

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

6. 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

7. 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);

6

curPos = curPos+blen; % Set previous layer size

prevLayerSize = netconfig.layersizes{d}; end end

8. stack2params

function [params, netconfig] = stack2params(stack) params = []; for d = 1:numel(stack) params = [params ; stack{d}.w(:) ; stack{d}.b(:) ]; end ifnargout> 1 ifnumel(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

loadMyData.mat

loadweights_matrix.mat

inputsize=size(TrainData ,1);%获取数据的维度 datanum=size(TrainData ,2);%获取数据的数量 % netsize=[inputsize,50,50,50];

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

netsize=[inputsize,4,3]; classnum=2;%类别数目

7

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

functionv_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

8

本文来源:https://www.bwwdw.com/article/e3lp.html

Top