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

MNIST手写数字分类神经网络准确率卡11.35%,求故障排查

MNIST手写数字分类网络准确率卡在11.35%的问题排查

问题描述

我用Python从零构建基于MNIST数据集的手写数字分类神经网络,准确率一直卡在11.35%,无法定位错误。参考了一份能达到60%准确率的代码,但我的代码几乎一致却无法复现效果。

我的代码实现

神经网络核心代码

"""1. 输入层784个神经元
   2. 隐藏层1共128个神经元
   3. 隐藏层2共64个神经元
   4. 输出层10个神经元"""
def softmax(input):
    y = np.exp(input - input.max())
    activated = y/ np.sum(y, axis=0)
    return activated
 
def softmax_grad(x):
    exps = np.exp(x-x.max())
    return exps / np.sum(exps,axis = 0) * (1 - exps /np.sum(exps,axis = 0))

def sigmoid(input):
    activated = 1/(1 + np.exp(-input))
    return activated

def sigmoid_grad(input):
    grad = input*(1-input)
    return grad


class DenseNN:
    def __init__(self,d0,d1,d2,d3):
        self.params = {'w1': nn.Xavier.initialize(d0, d1),
                       'w2': nn.Xavier.initialize(d1, d2),
                       'w3': nn.Xavier.initialize(d2, d3)}
        
    def forward(self,a0):
        params = self.params
        params['a0'] = a0
        params['z1'] = np.dot(params['w1'],params['a0'])
        params['a1'] = sigmoid(params['z1'])
        
        params['z2'] = np.dot(params['w2'],params['a1'])
        params['a2'] = sigmoid(params['z2'])
        
        params['z3'] = np.dot(params['w3'],params['a2'])
        params['a3'] = softmax(params['z3'])
        
        return params['a3']
        
    def backprop(self,y_true,y_pred):
        params = self.params
        w_change = {}
        error = softmax_grad(params['z3'])*((y_pred - y_true)/y_true.shape[0])
        w_change['w3'] = np.outer(error,params['a2'])
        
        error = np.dot(params['w3'].T,error)*sigmoid_grad(params['a2'])
        w_change['w2'] = np.outer(error,params['a1'])
        
        error = np.dot(params['w2'].T,error)*sigmoid_grad(params['a1'])
        w_change['w1'] = np.outer(error,params['a0'])
        return w_change
        
    def update_weights(self,learning_rate,w_change):
        self.params['w1'] -= learning_rate*w_change['w1']
        self.params['w2'] -= learning_rate*w_change['w2']
        self.params['w3'] -= learning_rate*w_change['w3']

    def train(self,epochs,lr):
        for epoch in range(epochs):
            for i in range(60000):
                a0 = np.array([x_train[i]]).T
                o = np.array([y_train[i]]).T
                y_pred = self.forward(a0)
                w_change = self.backprop(o,y_pred)
                self.update_weights(lr,w_change)
                # print(self.compute_accuracy()*100)
                # print(calc_mse(a3, o))
            print((self.compute_accuracy())*100)
    
    def compute_accuracy(self):
        '''
            对输入做前向传播,检查输出最大值的索引是否与标签y的索引一致,
            统计所有预测结果的正确率平均值
        '''
        predictions = []

        for i in range(10000):
            idx = i
            a0 = x_test[idx]
            a0 = np.array([a0]).T
            #print("acc a1",np.shape(a1))
            o = y_test[idx]
            o = np.array([o]).T
            #print("acc o",np.shape(o))
            output = self.forward(a0)
            pred = np.argmax(output)
            predictions.append(pred == np.argmax(o))
        return np.mean(predictions)

数据加载代码

# 加载CSV格式数据集
train_data = pd.read_csv('../Datasets/MNIST/mnist_train.csv')
test_data = pd.read_csv('../Datasets/MNIST/mnist_test.csv')

# 训练数据处理
x_train = train_data.drop('label',axis=1).to_numpy()
y_train = pd.get_dummies(train_data['label']).values

# 测试数据处理
x_test = test_data.drop('label',axis=1).to_numpy()
y_test = pd.get_dummies(test_data['label']).values

# 归一化处理
fac = 0.99 / 255
x_train = np.asfarray(x_train) * fac + 0.01
x_test = np.asfarray(x_test) * fac + 0.01

# 打印维度信息
print(np.shape(x_train)) #(60000,784)
print(np.shape(y_train)) #(60000,10)
print(np.shape(x_test)) #(10000,784)
print(np.shape(y_test)) #(10000,10)
print((x_train))

问题解决

感谢Bartosz Mikulski的提示,问题出在Xavier权重初始化的实现上。修改权重初始化代码后,准确率得到明显提升;再添加偏置参数后,效果进一步优化。

修改后的权重初始化代码

self.params = {
    'w1':np.random.randn(d1, d0) * np.sqrt(1. / d1),
    'w2':np.random.randn(d2, d1) * np.sqrt(1. / d2),
    'w3':np.random.randn(d3, d2) * np.sqrt(1. / d3),
    'b1':np.random.randn(d1, 1)  * np.sqrt(1. / d1),
    'b2':np.random.randn(d2, 1)  * np.sqrt(1. / d2),
    'b3':np.random.randn(d3, 1)  * np.sqrt(1. / d3),
}

优化后的效果

  • 修改权重初始化后,准确率脱离11.35%的瓶颈,开始显著提升
  • 添加偏置参数后,准确率进一步提高到理想水平

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 16:25:21