Numpy 神经网络无法学习(停留在 10% 的准确度)- Python

问题描述 投票:0回答:1

所以我尝试使用 numpy 构建一个基本的 ANN。问题是我的预测准确率一直在 10% 左右,但我不明白为什么会这样。这是所有代码。

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt

data = pd.read_csv('train.csv')

data = np.array(data)
m, n = data.shape
np.random.shuffle(data)

data_train = data.T
X_train = data_train[1:n]
Y_train = data_train[0]

def init_params():
    W1 = np.random.randn(10, 784)
    b1 = np.random.rand(10, 1)
    W2 = np.random.randn(10, 10)
    b2 = np.random.randn(10, 1)
    return W1, b1, W2, b2

def ReLU(Z):
    return np.maximum(0, Z)

def softmax(Z):
        e = np.exp(Z - Z.max(axis=0, keepdims=True))
        return e/e.sum(axis=0, keepdims=True)

def forward_prop(W1, b1, W2, b2, X):
    Z1 = W1.dot(X) + b1
    A1 = ReLU(Z1)
    Z2 = W2.dot(A1) + b2
    A2 = softmax(Z2)
    return Z1, A1, Z2, A2

def one_hot(Y):
    one_hot_Y = np.zeros((Y.size, Y.max() + 1))
    one_hot_Y[np.arange(Y.size), Y] = 1
    one_hot_Y = one_hot_Y.T
    return one_hot_Y

def deriv_ReLU(Z):
    return (Z > 0).astype(int)


def back_prop(Z1, A1, Z2, A2, W2, X, Y):
    m = Y.size
    one_hot_Y = one_hot(Y)
    dZ2 = A2 - one_hot_Y
    dW2 = 1 / m * dZ2.dot(A1.T)
    db2 = 1 / m * np.sum(dZ2, 1).reshape(-1, 1)
    dZ1 = W2.T.dot(dZ2) * deriv_ReLU(Z1)
    dW1 = 1 / m * dZ1.dot(X.T)
    db1 = 1 / m * np.sum(dZ1, 1).reshape(-1, 1)
    return dW1, db1, dW2, db2

def update_params(W1, b1, W2, b2, dW1, db1, dW2, db2, alpha):
    W1 = W1 - alpha * dW1
    db1 = b1 - alpha * db1
    W2 = W2 - alpha * dW2
    db2 = b2 - alpha * db2
    return W1, b1, W2, b2

def get_predictions(A2):
    return np.argmax(A2, 0)

def get_accuracy(predictions, Y):
    print(predictions, Y)
    return np.sum(predictions == Y) / Y.size

def gradient_descent(X, Y, iterations, alpha):
    W1, b1, W2, b2 = init_params()
    for i in range(iterations):
        Z1, A1, Z2, A2 = forward_prop(W1, b1, W2, b2, X)
        dW1, db1, dW2, db2 = back_prop(Z1, A1, Z2, A2, W2, X, Y)
        W1, b1, W2, b2 = update_params(W1, b1, W2, b2, dW1, db1, dW2, db2, alpha)
        if (i % 50):
            print(f'Iteration: {i}')
            print(f'Accuracy: {get_accuracy(get_predictions(A2), Y)}')
    return W1, b1, W2, b2

W1, b1, W2, b2 = gradient_descent(X_train, Y_train, 100, 0.1)

我认为这可能是我使用的数据的问题,但在尝试新数据后,情况并非如此。很明显,在反向传播的某个地方(我猜)我搞砸了一些东西并切换了一些变量。使用的数据是手写数字的 MNIST 数据集,有 10 个类别。 我做了更多的挖掘,我注意到实际上该模型似乎一直在输出单个数字作为预测。我不明白为什么。

python numpy deep-learning neural-network
1个回答
0
投票

好吧,我在 chatGPT 的帮助下成功解决了自己的问题:

我在那里有一些拼写错误,特别是在 update_params() 函数中,我更新了导数而不是更新实际层。

偏差更新问题: update_params 函数在更新偏差时存在潜在问题:

db1 = b1 - alpha * db1

这行应该是:

b1 = b1 - alpha * db1

同样,检查 db2 以确保:

b2 = b2 - alpha * db2

由于错误的变量被更新,偏差在训练过程中保持不变,从而阻碍了有效的学习。

真正改变游戏的是接下来的两点:

权重初始化: 确保您的权重初始化不会产生太大或太小的值。标准方法是按 sqrt(1/n) 缩放权重,其中:

n 是给定层的输入数量。

W1 = np.random.randn(10, 784) * np.sqrt(1 / 784)
W2 = np.random.randn(10, 10) * np.sqrt(1 / 10)

这可以防止梯度消失/爆炸的问题。

这改变了游戏规则:

数据标准化: 确保您的输入数据 X(本例中为像素)已标准化。通常,像素值的范围是 0 到 255,因此您应该将输入数据除以 255,以使值保持在 0 到 1 之间。

X_train = X_train / 255.0

这种标准化通常有助于稳定学习。

现在就完成了。我能够在 100 次迭代内获得 90% 的准确率。我现在将测试不同的激活函数并找到最合适的。谢谢你聊天GPT。

© www.soinside.com 2019 - 2024. All rights reserved.