[英]Debugging tensorflow fit not making sense
因此,我使用自行實現的代碼和 Tensorflow 結果得到了不同的結果。 我想測試每個值,看看我的錯誤在哪里(損失、梯度、優化器等)。
因此,我做了一個測試代碼,就像這個 repo中受時尚 mnist 示例啟發的代碼一樣。 為簡單起見,我將在問題末尾復制粘貼它。
邏輯:
基本上,我在 1 個批次上做 1 個 epoch。 然后保存:
因為我使用默認的 SGD TensorFlow 算法,所以保存的梯度應該等於(initial_weights - final_weights)/0.01
。 這個想法是從這里得到的。
但是,這不會發生,更重要的是,如果我除以 0.0001 而不是 0.01 (奇怪的是 0.01^2),結果會更接近。
我的邏輯有錯誤嗎? 測試代碼? 我找不到它了。
PS:我嘗試在 Linux 上使用 tf 版本 2.2.0 和 2.4.1。
import tensorflow as tf
import numpy as np
from pdb import set_trace
def get_dataset():
fashion_mnist = tf.keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
return (train_images, train_labels), (test_images, test_labels)
def get_model(init1='glorot_uniform', init2='glorot_uniform'):
tf.random.set_seed(1)
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(128, activation='relu', kernel_initializer=init1),
tf.keras.layers.Dense(10, kernel_initializer=init2)
])
model.compile(optimizer='sgd',
loss=tf.keras.losses.CategoricalCrossentropy(from_logits=False),
metrics=['accuracy'])
return model
def train(model, x_fit, y_fit):
np.save("initial_weights.npy", np.array(model.get_weights()))
with tf.GradientTape() as g:
y_pred = model(x_fit)
loss = tf.keras.losses.categorical_crossentropy(y_pred=y_pred, y_true=y_fit)
np.save("loss.npy", np.array(loss))
gradients = g.gradient(loss, model.trainable_weights)
np.save("gradients.npy", np.array(gradients))
model.fit(x_fit, y_fit, epochs=1, batch_size=100)
np.save("final_weights.npy", np.array(model.get_weights()))
if __name__ == "__main__":
(train_images, train_labels), (test_images, test_labels) = get_dataset()
model = get_model()
y_fit = np.zeros((100, 10))
for i, val in enumerate(train_labels[:100]):
y_fit[i][val] = 1.
train(model, train_images[:100], y_fit)
results = {
"loss": np.load("loss.npy", allow_pickle=True),
"init_weights": np.load("initial_weights.npy", allow_pickle=True),
"gradients": np.load("gradients.npy", allow_pickle=True),
"final_weights": np.load("final_weights.npy", allow_pickle=True)
}
for i_w, f_w, gr in zip(results["init_weights"], results["final_weights"], results["gradients"]):
gr = gr.numpy()
print(np.allclose(gr, (i_w - f_w) / 0.01))
# set_trace()
看起來對fit
的調用是對批量大小的梯度進行平均。 我不知道這是否是設計的錯誤。
當你手動計算梯度時,你可以調用model.optimizer.apply_gradients
來更新你的權重,你應該得到正確的結果。
def train(model, x_fit, y_fit):
np.save("initial_weights.npy", np.array(model.get_weights()))
with tf.GradientTape() as g:
y_pred = model(x_fit)
loss = tf.keras.losses.categorical_crossentropy(y_pred=y_pred, y_true=y_fit)
np.save("loss.npy", np.array(loss))
gradients = g.gradient(loss, model.trainable_weights)
np.save("gradients.npy", np.array(gradients))
model.optimizer.apply_gradients(zip(gradients, model.trainable_weights))
np.save("final_weights.npy", np.array(model.get_weights()))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.