47.3_交叉熵误差

47.3 交叉熵误差

在线性回归中,我们使用均方误差作为损失函数,但在进行多分类时,需要使用专用的损失函数。最常用的是交叉熵误差(cross entropy error)。交叉熵误差的式子如下所示。

L=ktklogpk(47.2)L = - \sum_ {k} t _ {k} \log p _ {k} \tag {47.2}

式子中的 tkt_k 表示训练数据的第 kk 个维度的值。这个训练数据的元素值的记录规则为,类别正确的元素值是1,其他为0。这种表示方法叫作one-hot向量。式子中的 pkp_k 是使用了神经网络的softmax函数后的输出。

交叉熵误差的式子47.2有更简化的表达形式。例如有 t=(0,0,1)t = (0,0,1) , p=(p0,p1,p2)p = (p_0,p_1,p_2) ,把它们代入式子47.2,得到 L=logp2L = -\log p_2 。这意味着交叉熵误差也可以通过提取正确类别编号的概率 pp 来进行计算。因此,假设训练数据中正确类别的编号为 tt ,我们也可以通过下面的式子计算交叉熵误差。

L=logp[t](47.3)L = - \log \boldsymbol {p} [ t ] \tag {47.3}

式子中的 p[t]\pmb{p}[t] 表示只从向量 p\pmb{p} 中提取第 tt 个元素。这个切片操作是本步骤开头向 DeZero 中添加的功能。

此处介绍的交叉熵误差针对的是数据只有一个的情况。如果有 NN 个数据,我们应计算每个数据的交叉熵误差,将它们相加,然后除以 NN ,由此求出平均交叉熵误差。

下面实现交叉熵误差。我们将softmax函数和交叉熵误差合二为一,实现softmax CROSS_entropy-simple(x, t)函数。代码如下所示。

dezero/functions.py

def softmax CROSS_entropy-simple(x, t):
    x, t = as_variable(x), as_variable(t)
    N = x.shape[0]
    p = softmax(x) # 或者 softmaxsimple(x)
    p = clip(p, 1e-15, 1.0) # 为了防止log(0),将p设为大于1e-15的值
    log_p = log(p) # 这个log是DeZero函数
    tlog_p = log_p(np.arange(N), t.data]
    y = -1 * sum(tlog_p) / N
    return y

上面代码中的输入参数 xx 是使用神经网络的 softmax 函数之前的输出, tt 是训练数据。假设训练数据是正确类别的编号(标签,非 one-hot 向量)。

代码中 p=softmax(x)p = \text{softmax}(x)pp 元素是 0 和 1 之间的值。在下一步进行 log 计算时,向 log 函数输入 0 会导致错误发生(准确来说是警告)。为了防止这种

情况出现,在输入为0的情况下,我们用一个较小的值1e-15来代替它。这个替换是由clip函数完成的。clip函数的用法是clip(x, x_min, x_max)。调用该函数时,如果x的元素(Variable实例)小于x_min,其值会被替换为x_min;如果大于x_max,其值会被替换为x_max。这里就不介绍clip函数的实现了(代码在dezero/functions.py中)。

另外,上面的代码通过np range(N)创建了 [0,1,,N1][0, 1, \dots, N-1] 的ndarray实例。使用log_p[np.arange(N), t.data]可提取出对应于训练数据的模型输出log_p[0, t.data[0]]、log_p[1, t.data[1]]……这是一个一维数组。

上面的softmax CROSS_entropy-simple函数的实现比较简单。不过,dezero/functions.py中的softmax CROSS_entropy函数是更好的实现方式。为了帮助大家理解,本步骤采用了简单的实现方式。

下面对进行多分类的神经网络使用具体数据来计算交叉熵误差。

$\mathbf{x} = \mathbf{np}$  .array([0.2,-0.4],[0.3,0.5],[1.3,-3.2],[2.1,0.3]])  
t  $=$  np.array([2,0,1,0])  
y  $=$  model(x)  
loss  $=$  Fsoftmaxcross_entropy.simple(y,t)  
#或者F softmaxcross_entropy(y,t)  
print(loss)

运行结果

variable(1.4967442524053058)

上面的代码首先准备了输入数据 xx 、训练数据 tt ,训练数据中记录了正确类别的编号,然后用 y=model(x)y = \text{model}(x) 来变换数据,用 F. softmax CROSS_entropysimple(y, t) 来计算损失函数。现在我们已经做好实现多分类的准备了,下一步将实际进行操作。