tf.nn.softmax_cross_entropy_with_logits_v2(labels, logits)
は主に3つの操作を実行することに気づきました。
それらを正規化するためにロジット(y_hat)にsoftmaxを適用します:y_hat_softmax = softmax(y_hat)
。
クロスエントロピー損失を計算します:y_cross = y_true * tf.log(y_hat_softmax)
インスタンスの異なるクラスの合計:-tf.reduce_sum(y_cross, reduction_indices=[1])
here から借りたコードは、これを完全に示しています。
y_true = tf.convert_to_tensor(np.array([[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]]))
y_hat = tf.convert_to_tensor(np.array([[0.5, 1.5, 0.1],[2.2, 1.3, 1.7]]))
# first step
y_hat_softmax = tf.nn.softmax(y_hat)
# second step
y_cross = y_true * tf.log(y_hat_softmax)
# third step
result = - tf.reduce_sum(y_cross, 1)
# use tf.nn.softmax_cross_entropy_with_logits_v2
result_tf = tf.nn.softmax_cross_entropy_with_logits_v2(labels = y_true, logits = y_hat)
with tf.Session() as sess:
sess.run(result)
sess.run(result_tf)
print('y_hat_softmax:\n{0}\n'.format(y_hat_softmax.eval()))
print('y_true: \n{0}\n'.format(y_true.eval()))
print('y_cross: \n{0}\n'.format(y_cross.eval()))
print('result: \n{0}\n'.format(result.eval()))
print('result_tf: \n{0}'.format(result_tf.eval()))
出力:
y_hat_softmax:
[[0.227863 0.61939586 0.15274114]
[0.49674623 0.20196195 0.30129182]]
y_true:
[[0. 1. 0.]
[0. 0. 1.]]
y_cross:
[[-0. -0.4790107 -0. ]
[-0. -0. -1.19967598]]
result:
[0.4790107 1.19967598]
result_tf:
[0.4790107 1.19967598]
ただし、1つのホットラベルには0または1のいずれかが含まれるため、このようなバイナリの場合のクロスエントロピーは here および here に示すように次のように定式化されます。
この数式のコードを次のセルに記述します。その結果は上記とは異なります。私の質問はどちらが良いですか、それとも正しいですか? tensorflowには、この式に従ってクロスエントロピーを計算する機能もありますか?
y_true = np.array([[0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
y_hat_softmax_from_tf = np.array([[0.227863, 0.61939586, 0.15274114],
[0.49674623, 0.20196195, 0.30129182]])
comb = np.dstack((y_true, y_hat_softmax_from_tf))
#print(comb)
print('y_hat_softmax_from_tf: \n{0}\n'.format(y_hat_softmax_from_tf))
print('y_true: \n{0}\n'.format(y_true))
def cross_entropy_fn(sample):
output = []
for label in sample:
if label[0]:
y_cross_1 = label[0] * np.log(label[1])
else:
y_cross_1 = (1 - label[0]) * np.log(1 - label[1])
output.append(y_cross_1)
return output
y_cross_1 = np.array([cross_entropy_fn(sample) for sample in comb])
print('y_cross_1: \n{0}\n'.format(y_cross_1))
result_1 = - np.sum(y_cross_1, 1)
print('result_1: \n{0}'.format(result_1))
出力
y_hat_softmax_from_tf:
[[0.227863 0.61939586 0.15274114]
[0.49674623 0.20196195 0.30129182]]
y_true:
[[0. 1. 0.]
[0. 0. 1.]]
y_cross_1:
[[-0.25859328 -0.4790107 -0.16574901]
[-0.68666072 -0.225599 -1.19967598]]
result_1:
[0.90335299 2.11193571]
数式は正しいですが、バイナリ分類でのみ機能します。 tensorflowのデモコードは3つのクラスを分類します。リンゴとオレンジを比較するようなものです。 答えの1つ あなたはそれについて言及していることも参照します。
この定式化は、2つのクラスを予測する1つの出力を持つネットワークによく使用されます(通常、1の場合は正のクラスメンバーシップ、0の出力の場合は負)。その場合、iの値は1つしかありません-iの合計を失う可能性があります。
これらの2つの数式(バイナリクロスエントロピーvs多項式クロスエントロピー)の違いと、それぞれが適用できる場合については、 この質問 で詳しく説明しています。
2番目の質問に対する答えは「はい」です。このような関数 tf.nn.sigmoid_cross_entropy_with_logits
。上記の質問を参照してください。