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

自制三层神经网络预测MNIST结果随机,求问题排查指引

三层MNIST神经网络训练后预测结果随机性异常

自行搭建三层神经网络用于MNIST数据集预测,代码无报错,但对同一图像预测时,每次运行结果差异极大,接近随机状态。以下是代码及三次运行结果:

核心函数代码

import pandas as pd
import numpy as np
from PIL import Image
import os
np.set_printoptions(formatter={'float_kind':'{:f}'.format})

def init_setup():
    #three layers perception
    w1=np.random.randn(10,784)-0.8
    b1=np.random.rand(10,1)-0.8
    #second layer
    w2=np.random.randn(10,10)-0.8
    b2=np.random.randn(10,1)-0.8
    #third layer
    w3=np.random.randn(10,10)-0.8
    b3=np.random.randn(10,1)-0.8
    return w1,b1,w2,b2,w3,b3

def activate(A):
    # use ReLU function as the activation function
    Z=np.maximum(0,A)
    return Z

def softmax(Z):
    return np.exp(Z)/np.sum(np.exp(Z))

def forward_propagation(A,w1,b1,w2,b2,w3,b3):
    # input A :(784,1)-> A1: (10,1) ->A2: (10,1) -> prob: (10,1)
    z1=w1@A+b1
    A1=activate(z1)
    z2=w2@A1+b2
    A2=activate(z2)
    z3=w3@A2+b3
    prob=softmax(z3)
    return z1,A1,z2,A2,z3,prob

def one_hot(Y:np.ndarray)->np.ndarray:
    one_hot=np.zeros((10, 1)).astype(int)
    one_hot[Y]=1
    return one_hot

def back_propagation(A,z1,A1:np.ndarray,z2,A2:np.ndarray,z3,prob,w1,w2:np.ndarray,w3,Y:np.ndarray,lr:float):
    m=1/Y.size
    dz3=prob-Y 
    # print('loss ', np.sum(dz3))
    dw3=m*dz3@A2.T
    db3=  dz3
    dz2=ReLU_deriv(z2)*w3.T@dz3
    dw2 =  dz2@A1.T
    db2 =  dz2
    dz1=ReLU_deriv(z1)*w2.T@dz2
    dw1 = dz1@A.T
    db1 =  dz1
    return db1,dw1,dw2,db2,dw3,db3

def ReLU_deriv(Z):
    Z[Z>0]=1
    Z[Z<=0]=0
    return Z 

def step(lr,w1,b1,w2,b2,w3,b3,dw1,db1,dw2,db2,dw3,db3):
    w1 = w1 - lr * dw1
    b1 = b1 - lr * db1    
    w2 = w2 - lr * dw2  
    b2 = b2 - lr * db2
    w3 = w3 - lr * dw3 
    b3 = b3 - lr * db3       
    return w1,b1,w2,b2,w3,b3

训练与测试代码

def learn():
    lr=0.00002
    w1,b1,w2,b2,w3,b3=init_setup()
    # read the data from a csv file
    df=pd.read_csv('data.csv')
    # Shuffle the data
    df = df.sample(frac=1).reset_index(drop=True)
    for epoch in range(0,5):
        lr=lr/10
        for _,row in df.iterrows():
            A=row.values[1:]
            A=A.reshape(784,1)
            Y=int(row.values[0])
            Y=one_hot(Y)
            z1,A1,z2,A2,z3,prob=forward_propagation(A,w1,b1,w2,b2,w3,b3)
            db1,dw1,dw2,db2,dw3,db3=back_propagation(A,z1,A1,z2,A2,z3,prob,w1,w2,w3,Y,lr)
            w1,b1,w2,b2,w3,b3=step(lr,w1,b1,w2,b2,w3,b3,dw1,db1,dw2,db2,dw3,db3)
    return  w1,b1,w2,b2,w3,b3

optimize_params=learn()
w1,b1,w2,b2,w3,b3=optimize_params
img=Image.open(r'C:\Users\Desktop\MNIST - JPG - training\2\16.jpg')
A=np.asarray(img)
A=A.reshape(-1,1)
z1,A1,z2,A2,z3,prob=forward_propagation(A,w1,b1,w2,b2,w3,b3)
print(prob)
print(np.argmax(prob))

三次运行结果

>>>[[0.020815] >>>[[0.025916] >>>[[0.161880]
    [0.019490]     [0.031197]     [0.104364]
    [0.113170]     [0.006868]     [0.093192]
    [0.051033]     [0.426709]     [0.041726]
    [0.107867]     [0.043123]     [0.062953]
    [0.009533]     [0.001528]     [0.324685]
    [0.148977]     [0.080894]     [0.102557]
    [0.333544]     [0.273520]     [0.043415]
    [0.147408]     [0.049245]     [0.009269]
    [0.048163]]    [0.060999]]    [0.055960]]
>>>7           >>>3           >>>5

问题排查与修复方案

  • 学习率衰减逻辑错误:初始学习率0.00002已经过小,且每轮epoch都将学习率除以10,5轮后学习率变为2e-10,权重几乎无法更新,网络参数接近初始随机值。修复:去掉每轮除以10的逻辑,将初始学习率调整为0.01或0.001,后续可根据收敛情况调整衰减策略。
  • 权重初始化不合理:np.random.randn(...) - 0.8会让初始权重偏向负数,经过ReLU激活后大量神经元输出为0,导致梯度消失。修复:使用He初始化(适配ReLU):
    w1 = np.random.randn(10,784) * np.sqrt(2/784)
    b1 = np.zeros((10,1))  # 偏置初始化为0更稳定
    
  • 反向传播梯度计算错误:
    • m=1/Y.size错误,单样本训练时批量大小为1,m应等于1,当前设置会将梯度缩小10倍,更新幅度不足。
    • ReLU导数直接修改输入数组Z,会污染原数据,修复为:
      def ReLU_deriv(Z):
          return np.where(Z > 0, 1, 0)
      
  • 输入数据未归一化:MNIST像素值范围是0-255,未归一化会导致权重更新数值不稳定。修复:将输入A除以255,归一化到0-1范围:
    A = row.values[1:] / 255.0
    
  • softmax数值稳定性问题:直接计算np.exp(Z)易出现数值溢出,修复为:
    def softmax(Z):
        exp_Z = np.exp(Z - np.max(Z))  # 减去最大值避免溢出
        return exp_Z / np.sum(exp_Z)
    
  • 未固定随机种子:每次运行初始权重和数据shuffle都是随机的,加上网络未有效学习,导致结果差异大。修复:在代码开头设置随机种子:
    np.random.seed(42)
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 03:36:20