众所周知,encoder的输出是[N,T,vocab_size],vocab_size表示词表中每个单词的置信度。
在计算loss时我们的目标y和单词置信度的矩阵y帽又是如何进行交叉熵计算的呢?
下面我会使用一个例子来演示这个过程;
首先交叉熵的公式为:
loss = -sum(weight * y * log(y_hat))
其中:
- weight是一个可选的序列权重向量,可用于缓解过短/过长句子的影响
- y是真实目标序列,是一个one-hot向量
- y_hat是模型输出的概率分布矩阵
- y * log(y_hat)是对真实目标在概率矩阵中对应位置的对数概率取负值
假设我们有:
- 词表大小为5
- 目标序列 y = [[0, 1, 0, 0, 0], [0, 0, 0, 1, 0]]
- 模型输出概率矩阵 y_hat = [
[0.1, 0.6, 0.1, 0.1, 0.1],
[0.2, 0.1, 0.2, 0.4, 0.1]
]- 暂时不考虑权重系数weights
首先,我们根据公式对每个时间步进行计算:
时间步1:
- y = [0, 1, 0, 0, 0]
- y * log(y_hat) = [0, -0.51, 0, 0, 0]
y * log(y_hat)的计算过程为:
-
先计算log(y_hat)
log(y_hat) = [log(0.1), log(0.6), log(0.1), log(0.1), log(0.1)]
= [-2.30, -0.51, -2.30, -2.30, -2.30] -
再与y进行元素乘积
y * log(y_hat) = [0, 1, 0, 0, 0] * [-2.30, -0.51, -2.30, -2.30, -2.30]
= [0 * -2.30, 1 * -0.51, 0 * -2.30, 0 * -2.30, 0 * -2.30]
= [0, -0.51, 0, 0, 0]
时间步2:
- y = [0, 0, 0, 1, 0]
- y * log(y_hat) = [0, 0, 0, -0.92, 0] (过程同理)
然后,我们对所有时间步的结果求和:
loss = -sum(y * log(y_hat))
= -([0, -0.51, 0, 0, 0] + [0, 0, 0, -0.92, 0])
= -(-0.51 - 0.92)
= 1.43
可以看到,我们先用y(one-hot向量)与log(y_hat)做元素乘积,得到每个单词对应的负对数概率。
然后对所有时间步的负对数概率求和,得到整个序列的交叉熵损失值1.43。
这就是公式 loss = -sum(weight * y * log(y_hat)) 在序列到序列模型中的具体应用。
通过最小化这个交叉熵损失值,模型可以学习输出越来越接近真实目标序列的概率分布。