You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

神经网络代价函数收敛值过低,手写数字识别准确率仅12%求助

手写数字识别神经网络训练异常排查求助

我参考经典书籍实现手写数字识别神经网络,具体配置如下:

  • 数据集:60000张28×28灰度训练图,10000张测试图
  • 网络结构:784输入神经元 → 两层各16神经元的隐藏层 → 10输出神经元
  • 参数初始化:权重与偏置初始化为-0.5至0.5的随机值
  • 代价函数:C = 0.5*(a-y).^2

训练约75个epoch后,代价函数从1.35降至0.46便不再下降,但模型识别准确率仅12%,接近随机猜测水平。多次检查数学逻辑未发现问题,怀疑代码存在未察觉的bug,以下是训练主循环的核心Matlab代码:

a_0 = training_images;
epoch = 0;
while epoch < 5 || C(epoch - 1) - C(epoch) > 0.001    
epoch = epoch + 1;

%Propagate forwards
z_1 = weights_1*a_0 + biases_1;
a_1 = sigmoid(z_1);
z_2 = weights_2*a_1 + biases_2;
a_2 = sigmoid(z_2);
z_3 = weights_3*a_2 + biases_3;
a_3 = sigmoid(z_3);

%Evaluate cost function
C(epoch) = 0.5*mean(sum((a_3-y).^2, 1));

%Propagate backwards
sigmoid_d1 = a_1 .* (1-a_1); %Sigmoid derivative
sigmoid_d2 = a_2 .* (1-a_2);
sigmoid_d3 = a_3 .* (1-a_3);
delta_3 = (a_3-y).*sigmoid_d3;
delta_2 = weights_3.'*delta_3 .* sigmoid_d2;
delta_1 = weights_2.'*delta_2 .* sigmoid_d1;

%Calculate gradient
for image_index = 1:num_images
    dC_dw3(:, :, image_index) = delta_3(:, image_index) * a_2(:, image_index).';
    dC_dw2(:, :, image_index) = delta_2(:, image_index) * a_1(:, image_index).';
    dC_dw1(:, :, image_index) = delta_1(:, image_index) * a_0(:, image_index).';
end

%Calculate adjustment
training_rate = 0.1;
adjust_biases_1 = -training_rate * mean(delta_1, 2);
adjust_biases_2 = -training_rate * mean(delta_2, 2);
adjust_biases_3 = -training_rate * mean(delta_3, 2);
adjust_weights_1 = -training_rate * mean(dC_dw1, 3);
adjust_weights_2 = -training_rate * mean(dC_dw2, 3);
adjust_weights_3 = -training_rate * mean(dC_dw3, 3);
biases_1 = biases_1 + adjust_biases_1;
biases_2 = biases_2 + adjust_biases_2;
biases_3 = biases_3 + adjust_biases_3;
weights_1 = weights_1 + adjust_weights_1;
weights_2 = weights_2 + adjust_weights_2;
weights_3 = weights_3 + adjust_weights_3;

核心问题排查方向

1. 数据维度与矩阵乘法不匹配

  • 检查training_images的维度:若a_0是样本数×784的矩阵,weights_1*a_0会维度不匹配(weights_1应为16×784,需a_0转置为784×样本数才能相乘)。维度错误会导致激活值计算完全偏离,后续梯度全错,直接导致网络无法学习。
  • 验证标签y的维度:输出a_3是10×样本数的矩阵,y必须是同维度的one-hot编码矩阵。若y维度不符,a_3-y的计算错误会让代价函数和梯度完全失效。

2. 权重初始化导致神经元饱和

  • 直接用-0.5到0.5的均匀初始化,对sigmoid激活函数来说,易导致神经元输出接近0或1,此时sigmoid导数接近0,梯度消失,网络无法更新。建议改用Xavier初始化:weights = randn(n_out, n_in) / sqrt(n_in),避免激活值饱和。

3. 训练循环终止条件的索引错误

  • 循环条件while epoch < 5 || C(epoch - 1) - C(epoch) > 0.001在epoch=0时,C(epoch-1)为C(-1),会触发索引越界错误,导致循环逻辑异常,可能提前终止或错误迭代。应调整为:
    epoch = 0;
    % 先计算初始代价
    C(1) = ...; % 提前计算初始状态的代价
    while epoch < 5 || (epoch >=5 && C(epoch) - C(epoch+1) > 0.001)
        epoch = epoch + 1;
        % 训练逻辑
    end
    

4. 梯度计算的效率与正确性问题

  • 用循环逐个计算样本梯度的逻辑虽正确,但易出现索引错误,且效率低下。可直接用矩阵运算替代循环:
    dC_dw3 = delta_3 * a_2'; % delta_3是10×N,a_2是16×N,相乘得到10×16的梯度矩阵
    dC_dw2 = delta_2 * a_1';
    dC_dw1 = delta_1 * a_0';
    % 直接取平均
    adjust_weights_1 = -training_rate * mean(dC_dw1, 2);
    
  • 检查偏置更新的维度:mean(delta_1, 2)得到16×1向量,需确保biases_1也是16×1维度,否则维度不匹配会导致更新错误。

5. 代价函数与激活函数不匹配

  • 平方代价函数搭配sigmoid输出层时,若输出接近0或1,梯度会极小,导致网络更新缓慢。分类任务更适合用交叉熵代价函数,可避免梯度消失问题,大幅提升训练效率。

修复建议

  1. 优先验证并修正输入数据与标签的维度,确保矩阵乘法维度完全匹配
  2. 替换权重初始化方式为Xavier初始化
  3. 修复训练循环的终止条件,避免索引越界
  4. 改用交叉熵代价函数替代平方代价函数
  5. 用矩阵运算替代梯度计算的循环,减少出错概率

内容的提问来源于stack exchange,提问作者Levi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:27:39