การบันทึกคือ softmax และ softmax_cross_entropy_with_logits คืออะไร


352

ผมจะผ่านเอกสาร tensorflow API ที่นี่ ในเอกสาร tensorflow logitsที่พวกเขาใช้คำหลักที่เรียกว่า มันคืออะไร? ในวิธีการมากมายในเอกสาร API มันถูกเขียนเช่น

tf.nn.softmax(logits, name=None)

หากสิ่งที่เขียนเป็นlogitsเพียงTensorsทำไมการรักษาชื่อที่แตกต่างกันlogitsอย่างไร

อีกสิ่งหนึ่งคือมีสองวิธีที่ฉันไม่สามารถแยกความแตกต่างได้ พวกเขาเป็น

tf.nn.softmax(logits, name=None)
tf.nn.softmax_cross_entropy_with_logits(logits, labels, name=None)

ความแตกต่างระหว่างพวกเขาคืออะไร? เอกสารไม่ชัดเจนสำหรับฉัน ฉันรู้ว่าสิ่งที่tf.nn.softmaxทำ แต่ไม่ใช่อย่างอื่น ตัวอย่างจะเป็นประโยชน์จริง ๆ

คำตอบ:


427

Logits นั้นหมายถึงว่าฟังก์ชั่นทำงานกับเอาต์พุตที่ไม่ปรับสัดส่วนของเลเยอร์ก่อนหน้าและสเกลสัมพัทธ์เพื่อทำความเข้าใจหน่วยเป็นเส้นตรง โดยเฉพาะอย่างยิ่งหมายความว่าผลรวมของอินพุตอาจไม่เท่ากับ 1 ว่าค่าไม่ใช่ความน่าจะเป็น (คุณอาจมีอินพุต 5)

tf.nn.softmaxสร้างเพียงผลลัพธ์ของการใช้ฟังก์ชั่น softmaxกับเทนเซอร์อินพุท softmax "squishes" อินพุตดังนั้นsum(input) = 1มันเป็นวิธีการทำให้ปกติ รูปร่างของเอาต์พุตของ softmax นั้นเหมือนกับอินพุต: มันแค่ทำให้ค่าปกติ เอาต์พุตของ softmax สามารถตีความได้ว่าเป็นความน่าจะเป็น

a = tf.constant(np.array([[.1, .3, .5, .9]]))
print s.run(tf.nn.softmax(a))
[[ 0.16838508  0.205666    0.25120102  0.37474789]]

ในทางตรงกันข้ามtf.nn.softmax_cross_entropy_with_logitsคำนวณเอนโทรปีของผลลัพธ์หลังจากใช้ฟังก์ชั่น softmax (แต่มันรวมเข้าด้วยกันอย่างระมัดระวังทางคณิตศาสตร์มากขึ้น) มันคล้ายกับผลลัพธ์ของ:

sm = tf.nn.softmax(x)
ce = cross_entropy(sm)

เอนโทรปีของการไขว้เป็นตัวชี้วัดสรุป: มันรวมกับองค์ประกอบต่างๆ ผลลัพธ์ของเทนเซอร์tf.nn.softmax_cross_entropy_with_logitsรูปร่าง[2,5]เป็นรูปร่าง[2,1](มิติแรกถือเป็นแบทช์)

หากคุณต้องการเพิ่มประสิทธิภาพเพื่อลดการข้ามเอนโทรปีและคุณกำลัง softmaxing หลังจากเลเยอร์สุดท้ายของคุณคุณควรใช้tf.nn.softmax_cross_entropy_with_logitsแทนการทำด้วยตัวเองเพราะมันครอบคลุมกรณีมุมที่ไม่แน่นอนเชิงตัวเลขในทางที่ถูกต้องทางคณิตศาสตร์ มิฉะนั้นคุณจะต้องแฮ็คมันด้วยการเพิ่มเอปไซลอนเล็ก ๆ น้อย ๆ ที่นี่และที่นั่น

แก้ไข 2016-02-07: หากคุณมีเลเบลชั้นเดียวซึ่งวัตถุสามารถเป็นของคลาสเดียวได้ตอนนี้คุณอาจพิจารณาใช้tf.nn.sparse_softmax_cross_entropy_with_logitsเพื่อที่คุณจะได้ไม่ต้องแปลงเลเบลของคุณเป็นอาเรย์ที่มีความหนาแน่นสูง ฟังก์ชั่นนี้ถูกเพิ่มเข้ามาหลังจากปล่อย 0.6.0


1
เกี่ยวกับ softmax_cross_entropy_with_logits ฉันไม่รู้ว่าใช้อย่างถูกต้องหรือไม่ ผลลัพธ์ไม่เสถียรในรหัสของฉัน รหัสเดียวกันรันสองครั้งความแม่นยำทั้งหมดเปลี่ยนจาก 0.6 เป็น 0.8 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). แต่เมื่อฉันใช้วิธีอื่น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))ผลที่ได้คือมั่นคงและดีกว่า
Rida

15
คุณกำลังทำ Softmax เป็นสองเท่าในบรรทัดแรกของคุณ softmax_cross_entropy_with_logits คาดว่าจะมีการบันทึกที่ไม่ถูกปรับสัดส่วนไม่ใช่เอาต์พุตของ tf.nn.softmax คุณแค่ต้องการtf.nn.softmax_cross_entropy_with_logits(tf.add(tf.matmul(x, W, b))ในกรณีของคุณ
dga

7
@dga ฉันคิดว่าคุณมีการพิมพ์ผิดในรหัสของคุณให้bความต้องการที่จะอยู่นอกของวงเล็บtf.nn.softmax_cross_entropy_with_logits(tf.add(tf.matmul(x, W), b)
jrieke

1
"ขนาดสัมพัทธ์ที่จะเข้าใจหน่วยคืออะไร" ส่วนหนึ่งของประโยคแรกของคุณหมายความว่าอย่างไร
Charlie Parker

5
เพิ่มขึ้น แต่คำตอบของคุณไม่ถูกต้องเล็กน้อยเมื่อคุณพูดว่า "[t] รูปร่างของเอาต์พุตของ softmax เหมือนกับอินพุต - มันแค่ปรับค่าปกติ" Softmax ไม่เพียง "บีบ" ค่าเพื่อให้ผลรวมของพวกเขาเท่ากับ 1 นอกจากนี้ยังกระจายพวกเขาและนั่นอาจเป็นเหตุผลหลักว่าทำไมมันถึงใช้ ดูstackoverflow.com/questions/17187507/…โดยเฉพาะคำตอบของ Piotr Czapla
เปาโล Perrotta

282

เวอร์ชั่นสั้น:

สมมติว่าคุณมีเทนเซอร์สองตัวโดยที่y_hatมีคะแนนที่คำนวณได้สำหรับแต่ละคลาส (เช่นจาก y = W * x + b) และy_trueมีป้ายกำกับจริงที่เข้ารหัสร้อนแรงหนึ่งรายการ

y_hat  = ... # Predicted label, e.g. y = tf.matmul(X, W) + b
y_true = ... # True label, one-hot encoded

หากคุณตีความคะแนนในy_hatขณะที่ความน่าจะเป็นบันทึก unnormalized แล้วพวกเขาจะlogits

นอกจากนี้การสูญเสียข้ามเอนโทรปีทั้งหมดที่คำนวณในลักษณะนี้:

y_hat_softmax = tf.nn.softmax(y_hat)
total_loss = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), [1]))

เป็นหลักเทียบเท่ากับการสูญเสียข้ามเอนโทรปีทั้งหมดที่คำนวณด้วยฟังก์ชันsoftmax_cross_entropy_with_logits():

total_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))

รุ่นยาว:

y_hat = W*x + bในชั้นการส่งออกของเครือข่ายประสาทของคุณคุณอาจจะคำนวณอาร์เรย์ที่มีคะแนนระดับสำหรับแต่ละกรณีการฝึกอบรมของคุณเช่นจากการคำนวณหนึ่ง เพื่อเป็นตัวอย่างด้านล่างฉันได้สร้างy_hatอาร์เรย์แบบ 2 x 3 ที่แถวตรงกับอินสแตนซ์การฝึกอบรมและคอลัมน์สอดคล้องกับคลาส ดังนั้นที่นี่มี 2 กรณีการฝึกอบรมและ 3 ชั้นเรียน

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]])

โปรดทราบว่าค่าจะไม่ได้รับการทำให้เป็นมาตรฐาน (เช่นแถวไม่รวมกันไม่เกิน 1) เพื่อทำให้เป็นมาตรฐานพวกเราสามารถใช้ฟังก์ชั่น softmax ซึ่งตีความอินพุตเป็นความน่าจะเป็นบันทึกไม่ปกติ (aka บันทึก ) และเอาท์พุทความน่าจะเป็นเชิงเส้นปกติ

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]])

สิ่งสำคัญคือต้องเข้าใจสิ่งที่เอาต์พุต softmax กำลังพูดอย่างเต็มที่ ด้านล่างฉันได้แสดงตารางที่แสดงผลลัพธ์ที่ด้านบนอย่างชัดเจนยิ่งขึ้น จะเห็นได้ว่าตัวอย่างเช่นความน่าจะเป็นของการฝึกอบรมอินสแตนซ์ 1 คือ "Class 2" คือ 0.619 ความน่าจะเป็นของคลาสสำหรับแต่ละอินสแตนซ์การฝึกอบรมถูกทำให้เป็นมาตรฐานดังนั้นผลรวมของแต่ละแถวคือ 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

ดังนั้นตอนนี้เรามีคลาสน่าจะเป็นสำหรับแต่ละตัวอย่างการฝึกอบรมโดยเราสามารถใช้ argmax () ของแต่ละแถวเพื่อสร้างการจำแนกขั้นสุดท้าย จากด้านบนเราอาจสร้างอินสแตนซ์การฝึกอบรมที่ 1 เป็นของ "คลาส 2" และอินสแตนซ์การฝึกอบรม 2 เป็นของ "คลาส 1"

การจำแนกประเภทเหล่านี้ถูกต้องหรือไม่ เราต้องวัดกับฉลากจริงจากชุดฝึกอบรม คุณจะต้องใช้y_trueอาเรย์แบบเข้ารหัสหนึ่งครั้งที่แถวนั้นเป็นอินสแตนซ์การฝึกอบรมและคอลัมน์เป็นคลาสอีกครั้ง ด้านล่างฉันได้สร้างตัวอย่างy_trueหนึ่งแถวร้อนที่ป้ายกำกับที่แท้จริงสำหรับการฝึกอบรมอินสแตนซ์ 1 คือ "Class 2" และป้ายกำกับที่แท้จริงสำหรับอินสแตนซ์การฝึกอบรม 2 คือ "Class 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.]])

การกระจายความน่าจะเป็นy_hat_softmaxใกล้กับการกระจายความน่าจะเป็นy_trueหรือไม่ เราสามารถใช้การสูญเสียข้ามเอนโทรปีในการวัดข้อผิดพลาด

สูตรสำหรับการสูญเสียข้ามเอนโทรปี

เราสามารถคำนวณการสูญเสียข้ามเอนโทรปีบนพื้นฐานของแถวและดูผลลัพธ์ ด้านล่างเราจะเห็นได้ว่าอินสแตนซ์การฝึกอบรม 1 มีการสูญเสีย 0.479 ในขณะที่อินสแตนซ์การฝึกอบรม 2 มีการสูญเสียที่สูงกว่า 1.200 ผลลัพธ์นี้สมเหตุสมผลเนื่องจากในตัวอย่างของเราด้านบนy_hat_softmaxแสดงให้เห็นว่าความน่าจะเป็นที่สูงที่สุดของการฝึกอบรม 1 สำหรับ "คลาส 2" ซึ่งตรงกับอินสแตนซ์การฝึกอบรม 1 ในy_true; อย่างไรก็ตามการคาดการณ์สำหรับอินสแตนซ์การฝึกอบรม 2 แสดงความน่าจะเป็นสูงสุดสำหรับ "คลาส 1" ซึ่งไม่ตรงกับคลาส "คลาส 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])

สิ่งที่เราต้องการคือการสูญเสียทั้งหมดในทุกกรณีการฝึกอบรม ดังนั้นเราสามารถคำนวณ:

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

ใช้ softmax_cross_entropy_with_logits ()

เราสามารถคำนวณการสูญเสียเอนโทรปีโดยรวมได้โดยใช้tf.nn.softmax_cross_entropy_with_logits()ฟังก์ชั่นดังที่แสดงด้านล่าง

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

โปรดทราบว่าtotal_loss_1และtotal_loss_2ให้ผลลัพธ์ที่เทียบเท่าเป็นหลักโดยมีความแตกต่างเล็กน้อยในหลักสุดท้าย แต่คุณอาจรวมทั้งใช้วิธีการที่สองจะใช้เวลาหนึ่งบรรทัดน้อยของรหัสและสะสมข้อผิดพลาดน้อยลงเพราะตัวเลข softmax softmax_cross_entropy_with_logits()จะทำเพื่อคุณภายในของ


ฉันยืนยันทั้งหมดข้างต้น รหัสง่าย ๆ : M = tf.random.uniform([100, 10], minval=-1.0, maxval=1.0); labels = tf.one_hot(tf.random.uniform([100], minval=0, maxval=10 , dtype='int32'), 10); tf.nn.softmax_cross_entropy_with_logits(labels=labels, logits=M) - tf.reduce_sum(-tf.nn.log_softmax(M)*tf.one_hot(labels, 10), -1)ส่งคืนค่าใกล้เคียงศูนย์ทุกที่
Sami A. Haija

51

tf.nn.softmaxคำนวณการแพร่กระจายไปข้างหน้าผ่านเลเยอร์ softmax คุณใช้ในระหว่างการประเมินโมเดลเมื่อคุณคำนวณความน่าจะเป็นที่โมเดลส่งออก

tf.nn.softmax_cross_entropy_with_logitsคำนวณค่าใช้จ่ายสำหรับเลเยอร์ softmax มันถูกใช้เฉพาะในช่วงการฝึกอบรม

การบันทึกคือความน่าจะเป็นของการบันทึกที่ไม่ได้ทำให้เป็นปกติที่ส่งออกโมเดล


2
ฉันเข้าใจแล้ว ทำไมไม่เรียกใช้ฟังก์ชัน tf.nn.softmax_cross_entropy_sans_normalization
auro

8
@auro เพราะมันทำให้ค่า (ภายใน) เป็นปกติในระหว่างการคำนวณข้ามเอนโทรปี จุดประสงค์tf.nn.softmax_cross_entropy_with_logitsคือการประเมินว่าโมเดลแตกต่างจากฉลากทองมากน้อยเพียงใดเพื่อไม่ให้เอาต์พุตปกติ
erickrf

1
ในกรณีของการใช้ tf.nn.sparse_softmax_cross_entropy_with_logits () คำนวณค่าใช้จ่ายของเลเยอร์ softmax แบบเบาบางดังนั้นจึงควรใช้เฉพาะในระหว่างการฝึกอบรมสิ่งที่จะเป็นทางเลือกเมื่อเรียกใช้แบบจำลองกับข้อมูลใหม่เป็นไปได้หรือไม่ หนึ่ง.
SerialDev

2
@SerialDev ไม่สามารถรับความน่าจะเป็นtf.nn.sparse_softmax_cross_entropy_with_logitsได้ tf.nn.softmaxความน่าจะเป็นที่จะได้รับการใช้งาน
Nandeesh

4

คำตอบข้างต้นมีคำอธิบายที่เพียงพอสำหรับคำถามที่ถาม

นอกจากนั้น Tensorflow ยังเพิ่มประสิทธิภาพการทำงานของการใช้ฟังก์ชั่นการเปิดใช้งานแล้วคำนวณค่าใช้จ่ายโดยการเปิดใช้งานของตัวเองตามด้วยฟังก์ชั่นค่าใช้จ่าย ดังนั้นจึงเป็นการใช้งานที่ดี: tf.nn.softmax_cross_entropy()มากกว่าtf.nn.softmax(); tf.nn.cross_entropy()

คุณสามารถค้นหาความแตกต่างที่ชัดเจนระหว่างสิ่งเหล่านี้ในโมเดลที่ใช้ทรัพยากรมาก


1
คำตอบข้างต้นอย่างชัดเจนยังไม่ได้อ่านคำถาม .. พวกเขาทุกคนพูดในสิ่งเดียวกันซึ่งเป็นที่รู้จักกัน แต่ไม่ตอบคำถามตัวเอง
Euler_Salter

@abhish คุณหมายถึงtf.nn.softmaxตามด้วยtf.losses.softmax_cross_entropyหรือเปล่า
ankurrc

4

สิ่งที่จะไปsoftmaxคือ logit นี่คือสิ่งที่ J. Hinton ทำซ้ำในวิดีโอหลักสูตรตลอดเวลา


1

Tensorflow 2.0 คำตอบที่เข้ากันได้ : คำอธิบายdgaและstackoverflowuser2010มีรายละเอียดมากเกี่ยวกับการบันทึกและฟังก์ชั่นที่เกี่ยวข้อง

ฟังก์ชั่นเหล่านั้นทั้งหมดเมื่อใช้ในTensorflow 1.xจะทำงานได้ดี แต่ถ้าคุณโยกย้ายรหัสของคุณจาก1.x (1.14, 1.15, etc)ไปยังการ2.x (2.0, 2.1, etc..)ใช้ฟังก์ชั่นเหล่านั้นทำให้เกิดข้อผิดพลาด

ดังนั้นการระบุ 2.0 Compatible Calls สำหรับฟังก์ชั่นทั้งหมดที่เรากล่าวถึงข้างต้นถ้าเราย้ายจาก1.x to 2.xเพื่อผลประโยชน์ของชุมชน

ฟังก์ชั่นใน 1.x :

  1. tf.nn.softmax
  2. tf.nn.softmax_cross_entropy_with_logits
  3. tf.nn.sparse_softmax_cross_entropy_with_logits

ฟังก์ชั่นที่เกี่ยวข้องเมื่อโอนย้ายจาก 1.x เป็น 2.x :

  1. tf.compat.v2.nn.softmax
  2. tf.compat.v2.nn.softmax_cross_entropy_with_logits
  3. tf.compat.v2.nn.sparse_softmax_cross_entropy_with_logits

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการย้ายข้อมูลจาก 1.x ถึง 2.x โปรดดูคู่มือการย้ายข้อมูลนี้


0

อีกสิ่งหนึ่งที่ฉันต้องการเน้นอย่างแน่นอนเนื่องจาก logit เป็นเพียงเอาต์พุตดิบโดยทั่วไปคือเอาต์พุตของเลเยอร์สุดท้าย นี่อาจเป็นค่าลบเช่นกัน ถ้าเราใช้เป็นแบบประเมินเอนโทรปี "ตามที่ระบุไว้ด้านล่าง:

-tf.reduce_sum(y_true * tf.log(logits))

จากนั้นมันจะไม่ทำงาน ในฐานะที่เป็นบันทึกของ -ve ไม่ได้กำหนดไว้ ดังนั้นการใช้การเปิดใช้งาน softmax จะเอาชนะปัญหานี้ได้

นี่คือความเข้าใจของฉันโปรดแก้ไขฉันถ้าฉันผิด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.