ChatGPT解决这个技术问题 Extra ChatGPT

神经网络总是预测同一个类别

我正在尝试实现一个神经网络,将图像分类为两个离散类别之一。然而,问题是,它目前总是预测任何输入为 0,我不确定为什么。

这是我的特征提取方法:

def extract(file):
    # Resize and subtract mean pixel
    img = cv2.resize(cv2.imread(file), (224, 224)).astype(np.float32)
    img[:, :, 0] -= 103.939
    img[:, :, 1] -= 116.779
    img[:, :, 2] -= 123.68
    # Normalize features
    img = (img.flatten() - np.mean(img)) / np.std(img)

    return np.array([img])

这是我的梯度下降例程:

def fit(x, y, t1, t2):
    """Training routine"""
    ils = x.shape[1] if len(x.shape) > 1 else 1
    labels = len(set(y))

    if t1 is None or t2 is None:
        t1 = randweights(ils, 10)
        t2 = randweights(10, labels)

    params = np.concatenate([t1.reshape(-1), t2.reshape(-1)])
    res = grad(params, ils, 10, labels, x, y)
    params -= 0.1 * res

    return unpack(params, ils, 10, labels)

这是我的前向和后向(梯度)传播:

def forward(x, theta1, theta2):
    """Forward propagation"""

    m = x.shape[0]

    # Forward prop
    a1 = np.vstack((np.ones([1, m]), x.T))
    z2 = np.dot(theta1, a1)

    a2 = np.vstack((np.ones([1, m]), sigmoid(z2)))
    a3 = sigmoid(np.dot(theta2, a2))

    return (a1, a2, a3, z2, m)

def grad(params, ils, hls, labels, x, Y, lmbda=0.01):
    """Compute gradient for hypothesis Theta"""

    theta1, theta2 = unpack(params, ils, hls, labels)

    a1, a2, a3, z2, m = forward(x, theta1, theta2)
    d3 = a3 - Y.T
    print('Current error: {}'.format(np.mean(np.abs(d3))))

    d2 = np.dot(theta2.T, d3) * (np.vstack([np.ones([1, m]), sigmoid_prime(z2)]))
    d3 = d3.T
    d2 = d2[1:, :].T

    t1_grad = np.dot(d2.T, a1.T)
    t2_grad = np.dot(d3.T, a2.T)

    theta1[0] = np.zeros([1, theta1.shape[1]])
    theta2[0] = np.zeros([1, theta2.shape[1]])

    t1_grad = t1_grad + (lmbda / m) * theta1
    t2_grad = t2_grad + (lmbda / m) * theta2

    return np.concatenate([t1_grad.reshape(-1), t2_grad.reshape(-1)])

这是我的预测功能:

def predict(theta1, theta2, x):
    """Predict output using learned weights"""
    m = x.shape[0]

    h1 = sigmoid(np.hstack((np.ones([m, 1]), x)).dot(theta1.T))
    h2 = sigmoid(np.hstack((np.ones([m, 1]), h1)).dot(theta2.T))

    return h2.argmax(axis=1)

我可以看到错误率随着每次迭代而逐渐降低,通常收敛于 1.26e-05 左右。

到目前为止我已经尝试过:

PCA 不同的数据集(来自 sklearn 的虹膜和来自 Coursera ML 课程的手写数字,两者的准确率都达到了 95% 左右)。但是,这两个都是批量处理的,所以我可以假设我的一般实现是正确的,但是我提取特征的方式或训练分类器的方式都有问题。尝试了 sklearn 的 SGDClassifier,它的性能并没有好多少,给了我大约 50% 的准确率。那么,这些功能有问题吗?

编辑: h2 的平均输出如下所示:

[0.5004899   0.45264441]
[0.50048522  0.47439413]
[0.50049019  0.46557124]
[0.50049261  0.45297816]

因此,所有验证示例的 sigmoid 输出都非常相似。

一个想法,你是在随机化你的训练集吗?如果第一批中有一堆 0 类,它可能很早就开始关注它们。
数据是有序的,即:10000 个 0,然后 10000 个 1。
刚刚意识到你说的是“批处理”。我想我对“小批量”感到困惑,这是一个常见问题。我需要再考虑一下。
仅供参考:我尝试随机化输入数据,结果仍然相同。
尝试从您的最终 predict 调用中返回原始 h2 值。它们也都一样吗?

M
Martin Thoma

我的网络确实总是预测同一类。问题是什么?

我有过几次。虽然我目前懒得看你的代码,但我想我可以给出一些一般性的提示,这也可能对其他有相同症状但可能存在不同潜在问题的人有所帮助。

调试神经网络

拟合一项数据集

对于网络应该能够预测的每个类别,请尝试以下操作:

创建一个只有一个 i 类数据点的数据集。使网络适合此数据集。网络是否学会预测“第 i 类”?

如果这不起作用,则有四个可能的错误来源:

错误的训练算法:尝试一个较小的模型,打印很多在两者之间计算的值,看看它们是否符合您的期望。除以 0:在分母上加一个小数 0 的对数 / 负数:就像除以 0 数据:您的数据可能类型错误。例如,您的数据可能需要为 float32 类型,但实际上是整数。模型:也有可能您刚刚创建了一个无法预测您想要什么的模型。当您尝试更简单的模型时,应该会发现这一点。初始化/优化:根据模型,您的初始化和优化算法可能会发挥至关重要的作用。对于使用标准随机梯度下降的初学者,我会说随机初始化权重非常重要(每个权重都有不同的值)。 - 另见:这个问题/答案

学习曲线

有关详细信息,请参阅 sklearn

https://i.stack.imgur.com/mhAUB.png

这个想法是从一个很小的训练数据集(可能只有一个项目)开始。那么模型应该能够完美地拟合数据。如果这可行,您将制作一个稍大的数据集。你的训练误差应该会在某个时候略微上升。这揭示了您的模型对数据建模的能力。

数据分析

检查其他类出现的频率。如果一个类别支配其他类别(例如,一个类别占数据的 99.9%),这是一个问题。寻找“异常值检测”技术。

更多的

学习率:如果您的网络没有改善并且仅比随机机会稍微好一点,请尝试降低学习率。对于计算机视觉,通常使用 0.001 的学习率/工作。如果您使用 Adam 作为优化器,这也是相关的。

预处理:确保对训练和测试使用相同的预处理。您可能会看到混淆矩阵的差异(请参阅此问题)

常见错误

这是受 reddit 启发的:

你忘了应用预处理

垂死的 ReLU

学习率太小/太大

最后一层的激活函数错误:你的目标不是总和吗? -> 不要使用 softmax 目标的单个元素是负数 -> 不要使用 Softmax、ReLU、Sigmoid。 tanh 可能是一个选择

你的目标不是总和吗? -> 不要使用 softmax

目标的单个元素是否定的 -> 不要使用 Softmax、ReLU、Sigmoid。 tanh 可能是一个选择

网络太深:你没有训练。首先尝试一个更简单的神经网络。

非常不平衡的数据:您可能需要研究不平衡学习


目标的单个元素是否定的 -> 不要使用 Softmax、ReLU、Sigmoid。 tanh 可能是一种选择。在这种情况下,您能否建议正确的激活功能?
您看到我建议 tanh 了吗?你还有什么期待? (您总是可以设计自己的;有时线性也是一个不错的选择)
我误读了。我认为 tanh 在不使用的函数列表中。也许应该是 Tanh,因为它是句子中的第一个词
“您的目标不是总和?-> 不要使用 softmax”和“您的目标的单个元素是负数”-您所说的“目标”到底是什么意思?
谢谢老师,我遇到了学习率问题。你救了我。作为一般调试或模型构建步骤,对于阅读本文的任何人,我总是建议从一些琐碎的事情开始,并构建您的模型一次只更改一个东西,同时关注您的指标。由于变量太多,查明问题总是会变得更加棘手。
Y
Yurii Dolhikh

经过一个半星期的研究,我想我明白了问题所在。代码本身没有任何问题。阻止我的实现成功分类的唯一两个问题是花费的学习时间和正确选择学习率/正则化参数。

我现在已经运行了一些学习程序,它已经将准确率提高到 75%,尽管仍有很大的改进空间。


你能告诉我你之前运行了多少,注意到它之后又运行了多少?我自己也遇到了一些问题,但即使再过一段时间它似乎并没有自行纠正,最终仍然只能一遍又一遍地预测同一个班级..
这里也有同样的问题
我遇到了同样的问题。尝试在调度程序中使用学习率,并对其进行更多时期的训练,并在 500 个时期后以 100% 的准确率设法过度拟合我的数据
对于任何遇到相同问题的人,您需要花更多时间调整 LR——这就是答案。
通常是导致这个问题的学习率太高还是太低?
T
Tommaso Di Noto

我也发生了同样的事情。我有一个不平衡的数据集(0 类和 1 类之间的样本分布分别约为 66%-33%),并且在第一次迭代后,网络总是为所有样本输出 0.0

我的问题只是学习率太高。将其切换为 1e-05 解决了该问题。

更一般地说,我建议在参数更新之前打印:

你的净输出(一批)

对应标签(同批次)

损失值(在同一批次上)可以逐个样本或汇总。

然后在参数更新后检查相同的三项。您应该在下一批中看到净输出的逐渐变化。当我的学习率太高时,已经在第二次迭代中,对于批次中的所有样本,净输出将射向所有 1.0 或所有 0.0


U
Urmay Shah

我也发生了同样的事情。我的在 deeplearning4j JAVA 库中用于图像分类。它不断为每次测试提供最后一个训练文件夹的最终输出。我能够通过降低学习率来解决它。

可以使用的方法:

降低学习率。 (第一个我的是 0.01 - 降低到 1e-4 并且它起作用了)增加批量大小(有时随机梯度下降不起作用,那么你可以尝试提供更多的批量大小(32,64,128,256,..)洗牌训练数据


就我而言,我用你的解决方案解决了。我将学习率从 0.001 切换到 0.0001。谢谢。
谢谢你的建议。批量大小是我模型中的问题。
L
Lucky Ning

我遇到了模型总是预测相同标签的问题。它困扰了我一个星期。最后,我通过将 RELU 替换为其他激活函数来解决它。RELU 会导致“Dying ReLU”问题。

在我解决问题之前。我试过:

检查正负采样率,从 1:25 到 1:3。但它不起作用改变批量大小和学习率和其他损失。但它不起作用

最后我发现将学习率从 0.005 降低到 0.0002 已经有效。


A
Atik Faysal

我也发生了同样的事情。该模型仅预测 7 类 CNN 的一类。我试图改变激活函数、批量大小但没有任何效果。然后改变学习率也对我有用。

opt = keras.optimizers.Adam(learning_rate=1e-06)

正如你所看到的,我不得不选择一个非常低的学习率。我的训练样本数为 5250,验证样本数为 1575。


L
LiNKeR

以防其他人遇到这个问题。我的采用 deeplearning4j Lenet(CNN) 架构,它不断为每次测试提供最后一个训练文件夹的最终输出。我能够通过 increasing my batchsizeshuffling the training data 解决它,因此每批至少包含来自多个文件夹的样本。我的数据类的批次大小为 1,实际上是 dangerous

编辑:尽管我最近观察到的另一件事是每个班级的训练样本集有限,尽管 dataset 很大。 eg 训练一个 neural-network 来识别 human faces,但对于 1 person 最多只能说 2 个不同的面孔,这意味着当数据集由 10,000 persons 组成,因此总共有 20,000 facesdataset。对于 10,000 persons,更好的 dataset 将是 1000 个不同的 faces,因此 dataset 总共为 10,000,000 faces .如果您希望避免将数据过度拟合到一个类,这是相对必要的,这样您的 network 就可以轻松概括并产生更好的预测。


Y
Yinon_90

我也有同样的问题,我通过使用 ResNet50 的迁移学习进行二进制分类,我能够通过替换来解决它:

Dense(output_dim=2048, activation= 'relu')

Dense(output_dim=128, activation= 'relu')

并且还通过删除 Keras 增强并重新训练 RestNet50 的最后一层


g
glitch

在尝试了许多解决方案之后,我发现问题出在预测阶段,而不是训练或模型架构。我用于预测的方法在所有情况下都显示为零,即使我的验证准确度相对较高,因为这条线:

predicted_class_indices=np.argmax(scores,axis=1)

如果您正在处理二进制分类,请尝试:

predict = model.predict(
    validation_generator, steps=None, callbacks=None, max_queue_size=10, workers=1,
    use_multiprocessing=False, verbose=0
)

K
K.Steven

TOPUP 答案真的对我有用。我的情况是,当我使用大型数据集(超过 400 万个样本)训练 bert4reco 模型时,acc 和 log_loss 在整个时期始终保持在 0.5 和 0.8 之间(花费 8 小时,我每 100 步打印一次结果)。然后我使用了一个非常小的数据集和一个更小的模型,终于成功了!模型开始学习一些东西,acc 和 log_loss 开始增加并在 300 个 epoch 后达到收敛!

最后,TOPUP 答案是这类问题的一个很好的清单。有时,如果您在训练开始时看不到任何变化,那么您的模型可能需要很长时间才能真正学到一些东西。最好用户 mini dataset 来断言,然后你可以等待它学习或使用一些有效的设备,如 GPU 或 TPU


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅