Versi pendek:
Misalkan Anda memiliki dua tensor, di mana y_hat
berisi skor yang dihitung untuk setiap kelas (misalnya, dari y = W * x + b) dan y_true
berisi label benar yang disandikan satu-panas.
y_hat = ... # Predicted label, e.g. y = tf.matmul(X, W) + b
y_true = ... # True label, one-hot encoded
Jika Anda menginterpretasikan skor dalam y_hat
sebagai probabilitas log yang tidak dinormalkan , maka itu adalah log .
Selain itu, total kerugian lintas-entropi yang dihitung dengan cara ini:
y_hat_softmax = tf.nn.softmax(y_hat)
total_loss = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), [1]))
pada dasarnya setara dengan total kehilangan lintas-entropi yang dihitung dengan fungsi softmax_cross_entropy_with_logits()
:
total_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))
Versi panjang:
Di lapisan output dari jaringan saraf Anda, Anda mungkin akan menghitung array yang berisi skor kelas untuk setiap instance pelatihan Anda, seperti dari perhitungan y_hat = W*x + b
. Sebagai contoh, di bawah ini saya telah membuat ay_hat
array 2 x 3, di mana baris terkait dengan instance pelatihan dan kolom sesuai dengan kelas. Jadi di sini ada 2 contoh pelatihan dan 3 kelas.
import tensorflow as tf
import numpy as np
sess = tf.Session()
# Create example y_hat.
y_hat = tf.convert_to_tensor(np.array([[0.5, 1.5, 0.1],[2.2, 1.3, 1.7]]))
sess.run(y_hat)
# array([[ 0.5, 1.5, 0.1],
# [ 2.2, 1.3, 1.7]])
Perhatikan bahwa nilai tidak dinormalisasi (yaitu baris tidak menambahkan hingga 1). Untuk menormalkannya, kita dapat menerapkan fungsi softmax, yang menginterpretasikan input sebagai probabilitas log yang tidak dinormalisasi (alias log dinormalisasi ) dan output probabilitas linear yang dinormalisasi.
y_hat_softmax = tf.nn.softmax(y_hat)
sess.run(y_hat_softmax)
# array([[ 0.227863 , 0.61939586, 0.15274114],
# [ 0.49674623, 0.20196195, 0.30129182]])
Sangat penting untuk memahami sepenuhnya apa yang dikatakan output softmax. Di bawah ini saya telah menunjukkan tabel yang lebih jelas mewakili output di atas. Dapat dilihat bahwa, misalnya, probabilitas pelatihan contoh 1 menjadi "Kelas 2" adalah 0,619. Probabilitas kelas untuk setiap instance pelatihan dinormalisasi, sehingga jumlah setiap baris adalah 1.0.
Pr(Class 1) Pr(Class 2) Pr(Class 3)
,--------------------------------------
Training instance 1 | 0.227863 | 0.61939586 | 0.15274114
Training instance 2 | 0.49674623 | 0.20196195 | 0.30129182
Jadi sekarang kita memiliki probabilitas kelas untuk setiap instance pelatihan, di mana kita dapat mengambil argmax () dari setiap baris untuk menghasilkan klasifikasi akhir. Dari atas, kami dapat membuat instance pelatihan 1 milik "Kelas 2" dan instance pelatihan 2 milik "Kelas 1".
Apakah klasifikasi ini benar? Kita perlu mengukur terhadap label yang sebenarnya dari set pelatihan. Anda akan membutuhkan y_true
array yang dikodekan satu-panas , di mana lagi baris adalah contoh pelatihan dan kolom adalah kelas. Di bawah ini saya telah membuat contoh y_true
array satu-panas di mana label sebenarnya untuk instance pelatihan 1 adalah "Kelas 2" dan label sebenarnya untuk instance pelatihan 2 adalah "Kelas 3".
y_true = tf.convert_to_tensor(np.array([[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]]))
sess.run(y_true)
# array([[ 0., 1., 0.],
# [ 0., 0., 1.]])
Apakah distribusi probabilitas y_hat_softmax
dekat dengan distribusi probabilitas y_true
? Kita bisa menggunakan kehilangan lintas-entropi untuk mengukur kesalahan.
Kita dapat menghitung kehilangan lintas-entropi berdasarkan baris-bijaksana dan melihat hasilnya. Di bawah ini kita dapat melihat bahwa instance pelatihan 1 memiliki kerugian sebesar 0,479, sedangkan instance pelatihan 2 memiliki kehilangan yang lebih tinggi sebesar 1,200. Hasil ini masuk akal karena dalam contoh kami di atas, y_hat_softmax
menunjukkan bahwa contoh pelatihan 1 probabilitas tertinggi adalah untuk "Kelas 2", yang cocok dengan contoh pelatihan 1 di y_true
; Namun, prediksi untuk instance pelatihan 2 menunjukkan probabilitas tertinggi untuk "Kelas 1", yang tidak cocok dengan kelas sebenarnya "Kelas 3".
loss_per_instance_1 = -tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1])
sess.run(loss_per_instance_1)
# array([ 0.4790107 , 1.19967598])
Apa yang benar-benar kita inginkan adalah kerugian total dari semua contoh pelatihan. Jadi kita dapat menghitung:
total_loss_1 = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1]))
sess.run(total_loss_1)
# 0.83934333897877944
Menggunakan softmax_cross_entropy_with_logits ()
Sebagai gantinya, kami dapat menghitung total kehilangan entropi silang menggunakan tf.nn.softmax_cross_entropy_with_logits()
fungsi, seperti yang ditunjukkan di bawah ini.
loss_per_instance_2 = tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true)
sess.run(loss_per_instance_2)
# array([ 0.4790107 , 1.19967598])
total_loss_2 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))
sess.run(total_loss_2)
# 0.83934333897877922
Perhatikan itu total_loss_1
dan total_loss_2
hasilkan pada dasarnya hasil yang setara dengan beberapa perbedaan kecil dalam digit terakhir. Namun, Anda mungkin juga menggunakan pendekatan kedua: dibutuhkan satu baris kode kurang dan mengakumulasi lebih sedikit kesalahan numerik karena softmax dilakukan untuk Anda di dalamnya softmax_cross_entropy_with_logits()
.
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(tf.nn.softmax(tf.add(tf.matmul(x,W),b)),y) cost=tf.reduce_mean(cross_entropy)
. Tetapi ketika saya menggunakan cara lain,pred=tf.nn.softmax(tf.add(tf.matmul(x,W),b)) cost =tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1))
hasilnya stabil dan lebih baik.