本文共 3896 字,大约阅读时间需要 12 分钟。
原文链接为:
与此文相关的有重大参考价值的链接:
本代码在原链接代码的基础上进行了简化,改成了通用版本,只需设置必要参数即可。
本代码测试样例的data数据链接:链接:https://pan.baidu.com/s/1ArV去掉我3XqOTy3uyxZOIkiQzgA 提取码:bujk
%% 该代码为基于BP网络的语音识别通用程序,以下程序正文
% data矩阵的第一列是label列,每一行表示一个样本,每一列代表数据的属性
% labelNum为label列的类别数目
% sampleData为data去掉label列的数据矩阵
% outputLabel为data提取的label列
% sampleNum为总的数据样本数目
% trainNum为训练样本数目
% testNum为验证集数目
%% 清空环境变量 clc clear %% 训练数据预测数据提取及归一化 %载入语音信号 load data % data矩阵的第一列是label列,每一行表示一个样本,每一列代表数据的属性 [rowNum, colNum] = size(data); labelNum = 2; %labelNum为标签类别数目 % 从1到sampleNum间随机排序, sampleNum为样本数目 sampleNum = rowNum; k=rand(1,sampleNum); [m,n]=sort(k); % m是k按照顺序排列好的数组 % n相当于1到sampleNum的随机排列数组 % 输入输出数据 sampleData=data(:,2:colNum); outputLabel =data(:,1); %把输出从1维变成labelNum维 output=zeros(sampleNum,labelNum); for i=1:sampleNum tempLabel = outputLabel(i); tempValue = zeros(1, labelNum); tempValue(tempLabel) = 1; output(i,:) = tempValue; % 更改后与下面的switch块功能相同,但是当labelNum变化时,无须修改程序 % switch outputLabel(i) % case 1 % output(i,:)=[1 0]; % case 2 % output(i,:)=[0 1]; % end end %随机提取trainNum个样本为训练样本,testNum个样本为预测样本 trainNum = 900; % 训练样本根据实际数据的多少灵活设置 testNum = sampleNum - trainNum; input_train=sampleData(n(1:trainNum),:)'; output_train=output(n(1:trainNum),:)'; input_test=sampleData(n(trainNum+1:sampleNum),:)'; output_test=output(n(trainNum+1:sampleNum),:)'; %输入数据归一化 [inputn,inputps]=mapminmax(input_train); %% 网络结构初始化 innum=colNum-1; midnum=colNum; outnum=labelNum; %权值初始化 w1=rands(midnum,innum); b1=rands(midnum,1); w2=rands(midnum,outnum); b2=rands(outnum,1); w2_1=w2;w2_2=w2_1; w1_1=w1;w1_2=w1_1; b1_1=b1;b1_2=b1_1; b2_1=b2;b2_2=b2_1; %学习率 xite=0.1; alpha=0.01; loopNumber=10; I=zeros(1,midnum); Iout=zeros(1,midnum); FI=zeros(1,midnum); dw1=zeros(innum,midnum); db1=zeros(1,midnum); %% 网络训练 E=zeros(1,loopNumber); for ii=1:loopNumber E(ii)=0; for i=1:1:trainNum %% 网络预测输出 x=inputn(:,i); % 隐含层输出 for j=1:1:midnum I(j)=inputn(:,i)'*w1(j,:)'+b1(j); Iout(j)=1/(1+exp(-I(j))); %经典sigmoid函数 end % 输出层输出 yn=w2'*Iout'+b2; %% 权值阀值修正 %计算误差 e=output_train(:,i)-yn; E(ii)=E(ii)+sum(abs(e)); %计算权值变化率 dw2=e*Iout; db2=e'; for j=1:1:midnum S=1/(1+exp(-I(j))); %Sigmoid函数 1/(1+e^(-x)),不说你也肯定知道 FI(j)=S*(1-S); %Sigmoid函数的导数,求导以后刚好可用Sigmoid函数自身来表示。 end for k=1:1:innum for j=1:1:midnum tmp = 0; for t=1:1:outnum tmp = tmp +e(t)*w2(j,t); end dw1(k,j)=FI(j)*x(k)*tmp; db1(j)=FI(j)*tmp; %dw1(k,j)=FI(j)*x(k)*(e(1)*w2(j,1)+e(2)*w2(j,2)); %db1(j)=FI(j)*(e(1)*w2(j,1)+e(2)*w2(j,2)); end end w1=w1_1+xite*dw1'; b1=b1_1+xite*db1'; w2=w2_1+xite*dw2'; b2=b2_1+xite*db2'; w1_2=w1_1;w1_1=w1; w2_2=w2_1;w2_1=w2; b1_2=b1_1;b1_1=b1; b2_2=b2_1;b2_1=b2; end end %% 语音特征信号分类 inputn_test=mapminmax('apply',input_test,inputps); fore=zeros(labelNum,testNum); for ii=1:1 for i=1:testNum %1500 %隐含层输出 for j=1:1:midnum I(j)=inputn_test(:,i)'*w1(j,:)'+b1(j); Iout(j)=1/(1+exp(-I(j))); end fore(:,i)=w2'*Iout'+b2; end end %% 结果分析 %根据网络输出找出数据属于哪类 output_fore=zeros(1,testNum); for i=1:testNum output_fore(i)=find(fore(:,i)==max(fore(:,i))); end %BP网络预测误差 error=output_fore-outputLabel(n(trainNum+1:sampleNum))'; %画出预测语音种类和实际语音种类的分类图 figure(1) %plot(output_fore,'r')stairs(output_fore,'r')
hold on %plot(outputLabel(n(trainNum+1:sampleNum))','b') stairs(outputLabel(n(trainNum+1:sampleNum))','b') % n相当于1到simpleNum的随机排列数组 axis([0 testNum+1 0 labelNum+1]) legend('预测语音类别','实际语音类别') %画出误差图 figure(2) plot(error) title('BP网络分类误差','fontsize',12) xlabel('语音信号','fontsize',12) ylabel('分类误差','fontsize',12) %print -dtiff -r600 1-4 k=zeros(1,labelNum); %找出判断错误的分类属于哪一类 for i=1:testNum if error(i)~=0 [b,c]=max(output_test(:,i)); k(c)=k(c)+1; % switch c % % 根据label的不同,case的个数相应变化 % case 1 % k(1)=k(1)+1; % case 2 % k(2)=k(2)+1; % end end end %找出每类的个体和 kk=zeros(1,labelNum); for i=1:testNum [b,c]=max(output_test(:,i)); kk(c)=kk(c)+1; % switch c % % 根据label的不同,case的个数相应变化 % case 1 % kk(1)=kk(1)+1; % case 2 % kk(2)=kk(2)+1; % end end %正确率 rightridio=(kk-k)./kk; disp('正确率') disp(rightridio);
转载地址:http://bsjqi.baihongyu.com/