字符识别
此示例说明如何训练神经网络以执行简单的字符识别。
定义问题
脚本 prprob
定义了一个包含 26 列的矩阵 X
,每列对应一个字母。每列有 35 个值,值可能是 1,也可能是 0。每列(包含 35 个值)定义一个字母的 5×7 位图。
矩阵 T
是一个 26×26 的单位矩阵,它将 26 个输入向量映射到 26 个类。
[X,T] = prprob;
以下命令将第一个字母 A 绘制为一个位图。
plotchar(X(:,1))
创建第一个神经网络
为求解此问题,我们将使用针对模式识别建立的具有 25 个隐藏神经元的前馈神经网络。
由于神经网络以随机初始权重进行初始化,因此每次运行该示例进行训练后的结果都略有不同。为了避免这种随机性,请设置随机种子以便每次都重现相同的结果。这对于您自己的应用情形不是必需的。
setdemorandstream(pi); net1 = feedforwardnet(25); view(net1)
训练第一个神经网络
函数 train
将数据划分为训练集、验证集和测试集。训练集用于更新网络,验证集用于在网络过拟合训练数据之前停止网络,从而保持良好的泛化。测试集用作完全独立的测量手段,用于衡量网络针对新样本的预期表现。
当网络针对训练集或验证集不再可能有改善时,训练停止。
net1.divideFcn = '';
net1 = train(net1,X,T,nnMATLAB);
Computing Resources: MATLAB on GLNXA64
训练第二个神经网络
我们希望网络不仅可以识别形状标准的字母,还可以识别含噪的字母。因此,我们将尝试针对含噪数据训练第二个网络,并将其泛化能力与第一个网络进行比较。
以下命令为每个字母 Xn
创建 30 个含噪副本。值由 min
和 max
限制在 0 和 1 之间。还定义了相应的目标 Tn
。
numNoise = 30; Xn = min(max(repmat(X,1,numNoise)+randn(35,26*numNoise)*0.2,0),1); Tn = repmat(T,1,numNoise);
以下是 A 的含噪版本。
figure plotchar(Xn(:,1))
以下命令将创建并训练第二个网络。
net2 = feedforwardnet(25); net2 = train(net2,Xn,Tn,nnMATLAB);
Computing Resources: MATLAB on GLNXA64
测试两个神经网络
noiseLevels = 0:.05:1; numLevels = length(noiseLevels); percError1 = zeros(1,numLevels); percError2 = zeros(1,numLevels); for i = 1:numLevels Xtest = min(max(repmat(X,1,numNoise)+randn(35,26*numNoise)*noiseLevels(i),0),1); Y1 = net1(Xtest); percError1(i) = sum(sum(abs(Tn-compet(Y1))))/(26*numNoise*2); Y2 = net2(Xtest); percError2(i) = sum(sum(abs(Tn-compet(Y2))))/(26*numNoise*2); end figure plot(noiseLevels,percError1*100,'--',noiseLevels,percError2*100); title('Percentage of Recognition Errors'); xlabel('Noise Level'); ylabel('Errors'); legend('Network 1','Network 2','Location','NorthWest')
由于存在噪声,在无噪声情况下训练的网络 1 的错误数多于在有噪声情况下训练的网络 2。