【问题标题】:Why MXNet is reporting the incorrect validation accuracy?为什么 MXNet 报告错误的验证准确性?
【发布时间】:2018-01-27 08:01:13
【问题描述】:

我是 MXNet 的新手,想解决一个使用 1 层网络解决数字分类问题的简单示例。我的程序如下:

import math
import numpy as np
import mxnet as mx
import matplotlib.pyplot as plt
import logging
logging.getLogger().setLevel(logging.DEBUG)
#============================================================
with np.load("notMNIST.npz") as data:

    images, labels = data["images"], data["labels"]

# Reshape the images from 28x28 into 784 1D-array and flaten the labels. 
images = images.reshape(784, 18720) labels = labels.reshape(18720)

# Apply one-hot encoding. 
Images = images.T.astype(np.float32) 
Labels = np.zeros((18720, 10)).astype(np.float32) 
Labels[np.arange(18720), labels] = 1

# Segment the data into training, evaluation and testing. 
X_train = Images[0 : 15000] 
y_train = Labels[0 : 15000]

X_eval = Images[15000 : 16000] 
y_eval = Labels[ 1200 :  2200] # IMPORTANT!!!

X_test = Images[16000 : 18720] 
y_test = Labels[16000 : 18720]

train_iter = mx.io.NDArrayIter(X_train, y_train, 100, shuffle=False)
_eval_iter = mx.io.NDArrayIter(X_eval , y_eval , 100, shuffle=False)
#============================================================
# Variables
X = mx.sym.Variable(name='data')

# Neural Network Layers
fully_connected_layer = mx.sym.FullyConnected(data=X, name='fc1', num_hidden=10)

# Outputs
lro = mx.sym.SoftmaxOutput(data=fully_connected_layer, name="softmax")
#============================================================

model = mx.mod.Module(symbol=lro)

model.fit(train_data=train_iter, eval_data=_eval_iter, 
          optimizer='sgd', optimizer_params={
              'learning_rate' : 1e-5, 
              'momentum' : 0.1}, 
          eval_metric="acc",
          num_epoch=500)

在运行带有评估标签1500016000 的程序后,最后一步是报告97% 的验证准确度,我个人认为这对于一层网络来说太高了。因此,我特意将评估标签更改为12002200 并看到程序仍然在83~86% 左右报告准确度(起初我认为这可能只是一个巧合并尝试了几个不同的评估标签但仍然得到类似的结果)。

我在程序中犯了哪些错误?

【问题讨论】:

    标签: mxnet


    【解决方案1】:

    TLDR;

    如果您停止执行 one-hot 编码,则可以解决此问题。

    而不是传递标签[0:15000],标签[15000:16000]和标签[16000:18720]传递标签[0:15000]、标签[15000:16000]和标签[16000:18720]。

    这会将正确评估标签上的准确度降低到平庸的 0.796000,而在“随机”评估标签上降低到 0.095000。

    详细解答

    由于 mxnet.metric.Accuracy 的计算具有误导性,您获得了如此高的准确度。在内部,根据提供的参数“preds”和“labels”的形状,准确度指标可以在 2 种“模式”下工作:

    1. 如果“preds”和“labels”的形状不匹配,Accuracy 会将“preds”的每一行解释为样本属于每个类别的概率。该类被定义为数组中的项目索引。

    例如,如果您有 preds=[[0.1, 0.9], [0.8, 0.2]] 那么这意味着:

    • 第一个例子属于类别 0 的概率为 0.1,属于类别 1 的概率为 0.9
    • 第二个例子以 0.8 的概率属于 0 类,以 0.2 的概率属于 1 类

    在这种模式下工作,“标签”应该是一个真实类的数组。在我们的例子中,假设模型是绝对正确的,“labels”数组应该是 [1, 0]。

    2) 如果“preds”和“labels”的形状确实匹配,则 Accuracy 将数组视为预测类和真实类。因此,每个项目都被视为一个样本的一类。然后计算是通过比较具有相同索引的“preds”“labels”中的项目来完成的。

    当您将 one-hot 编码应用于标签时,将使用第二种计算模式,因为模型的预测形状与 one-hot 编码的形状相匹配。 Accuracy 将数组中的每个项目解释为一个独立的样本,并将它们相互比较。

    在内部,Accuracy converts float array to int,对于小于 1 的浮点数总是产生 0。这种行为基本上将所有预测转换为 0,除非有一个概率为 1.0 的类的极少数情况。所以在大多数情况下,我们得到 preds = [0, 0, ..., 0]。

    One-hot 编码数组包含除 1 之外的所有项目等于 0。这意味着我们将有类似 [0, 1, 0, ..., 0] 的内容。

    Accuracy 比较这两个数组时,发现除了一个位置之外,它们大部分是相等的,返回错误的高精度。

    这是一个简单的复制示例:

    import mxnet as mx
    predicts = mx.nd.array([[1.29206967e-09,   3.40120096e-05,   2.23299547e-12,   3.98692492e-07,
        1.21151755e-10,   2.59370694e-08,   1.95488334e-02,   1.13474562e-05,
        9.80405331e-01,   3.51648767e-12]])
    labels = mx.nd.array([[0, 0, 0, 0, 0, 0, 0, 0, 1, 0]])
    acc = mx.metric.Accuracy()
    acc.update(preds=predicts, labels=labels)
    print(acc.get())
    

    这会给我们

    ('accuracy', 0.90000000000000002)
    

    因为 one-hot 编码正好包含 1 个非零元素。

    【讨论】:

      猜你喜欢
      • 2018-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-07
      • 1970-01-01
      相关资源
      最近更新 更多