在做seq2seq的時候,經常需要使用sequence_loss這是損失函數。
現在分析一下sequence_loss這個函數到底在做什么
# coding: utf-8
import numpy as np
import tensorflow as tf
from tensorflow.contrib.seq2seq import sequence_loss
logits_np = np.array([
[[1.0, 2.0], [1.0, 2.0]],
[[1.0, 2.0], [1.0, 2.0]]
])
targets_np = np.array([
[0,1],
[1,1]
], dtype=np.int32)
logits = tf.convert_to_tensor(logits_np)
targets = tf.convert_to_tensor(targets_np)
cost = sequence_loss(logits=logits,
targets=targets,
weights=tf.ones_like(targets, dtype=tf.float64))
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
r = sess.run(cost)
print(r)
# sequence_loss的結果是0.563261687518082
求loss值
\[logits=\left[\begin{matrix} [1.0, 2.0] & [1.0, 2.0] \cr [1.0, 2.0] & [1.0, 2.0]\end{matrix}\right] \]
\[target=\left[\begin{matrix} 0.0 & 1.0 \cr 1.0 & 1.0 \end{matrix}\right] \]
\[cost=sequence\_loss( logits=logits,targets=targets,weights=tf.ones_like(targets, dtype=tf.float64)) \]
sequence_loss的求值過程
1.softmax求值
2.交叉熵選擇
3.求平均值
1.softmax
將得分或者概率fi,統一轉化到0到1之間,就是計算權重占比(歸一化處理)
但是在計算權重的時候,分數都通過自然數e映射轉換,目的是,讓大的分數更大,讓小的分數更小,增加區分度
\[f_i(z)=-log( \frac{ e^{f_i} }{ \sum{e^{f_j} }} ) \]
其輸入值是一個向量,向量中元素為任意實數的得分值
輸出一個向量,其中每個元素值在0到1之間,且所有元素之和為1(計算每個得分在總分中的占比。這里通過指數映射了一下 )
\[f_i(z)=-log( \frac{ e^{f_i} }{ \sum{e^{f_j} }} ) \]
logits = [
[[1.0, 2.0], [1.0, 2.0]],
[[1.0, 2.0], [1.0, 2.0]]
]
\[softmax=\left[\begin{matrix} [ \frac{ e^{1.0} }{ e^{1.0}+e^{2.0}} , \frac{ e^{2.0} }{ e^{1.0}+e^{2.0}}] & [\frac{ e^{1.0} }{ e^{1.0}+e^{2.0}},\frac{ e^{2.0} }{ e^{1.0}+e^{2.0}}] \cr [\frac{ e^{1.0} }{ e^{1.0}+e^{2.0}},\frac{ e^{2.0} }{ e^{1.0}+e^{2.0}}] & [\frac{ e^{1.0} }{ e^{1.0}+e^{2.0}},\frac{ e^{2.0} }{ e^{1.0}+e^{2.0}}]\end{matrix}\right] \]
2求交叉熵
targets = [
[0,1],
[1,1]
]
根據targets, 確定選取哪個值。
\[crross\_softmax=\left[\begin{matrix} -log(\frac{ e^{1.0} }{ e^{1.0}+e^{2.0}}) & -log(\frac{ e^{2.0} }{ e^{1.0}+e^{2.0}}) \cr -log(\frac{ e^{2.0} }{ e^{1.0}+e^{2.0}}) & -log(\frac{ e^{2.0} }{ e^{1.0}+e^{2.0}}\end{matrix}) \right] \]
再求平均值
loss1=(-log(2.718/(2.718+7.387))+(-log(7.387/(2.718+7.387))))/2
loss2=(-log(7.387/(2.718+7.387))+(-log(7.387/(2.718+7.387))))/2
loss=(loss1+loss2)/2
loss=0.563