基于ReLU和Softmax的简单深度神经网络matlab代码
设计
领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计
本文以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)
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
loadMyData.mat
inputsize=size(TrainData ,1);%获取数据的维度
datanum=size(TrainData ,2);%获取数据的数量
1
% 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 ->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代码如下,都是Andrew Ng的教程里面的提供的。
2.Main_function with minFunc of UFLDL
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;
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.Main_function2 with minFunc of UFLDL
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 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
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);
%想理解这里,还有后面的梯度是如何计算出的,建议看那本关于矩阵的工具
书
关于书的成语关于读书的排比句社区图书漂流公约怎么写关于读书的小报汉书pdf
《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
functiondre= 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
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;%类别数目
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