-
一般情況下我們使用一個batch的數據計算出一個平均的loss,再使用這個loss反向傳播求得模型參數的梯度並更新,例如:
loss = tf.reduce_mean(y - y_pred) # 文中y和y_pred的shape均為:[b, 1],其中b是batch_size.
這種情況比較好理解,loss只是一個值,其反向傳播時對於每個參數也值計算出一個梯度值。
-
而如果我們沒有使用
tf.reduce_mean()
等類似求平均的操作,即:loss = y - y_pred
求出的loss其shape是[b, 1]。即batch中的每一個樣本都有一個對應的loss值。這個時候如果我們繼續調用:
grads = tape.gradient(loss, model.trainable_variables) optimizer.apply_gradients(zip(grads, model.trainable_variables))
也不會報錯,不禁讓人疑惑這個
tape.gradient()
是怎么處理loss不是標量值的情況的。 -
先說結論:當loss不是單值時
tape.gradient(loss, variables)
會首先針對loss中每一個單值對variables求梯度得到多套梯度。再對每套梯度對應元素求和合並為一套梯度返回。 -
驗證:
-
其他補充
tf.keras.losses.BinaryCrossentopy
等大寫字母開頭的損失類在我們傳入y, y_pred
時會自動對所有樣本的loss求平均,其返回一個標量的loss。tf.keras.losses.binary_crossentropy()
等小寫字母開頭的函數式接口在我們傳入y, y_pred
時不會對所有樣本的loss求平均,其返回一個張量形式的losses,維度為[batch, 1]。