Эффективный TensorFlow Глава 11. Отладка моделей в TensorFlow

TensorFlow

Эта статья переведена с:«Отладка моделей TensorFlow», Если есть какое-либо нарушение, пожалуйста, свяжитесь, чтобы удалить его, только для академических обменов, пожалуйста, не используйте его в коммерческих целях. Если есть какие-либо ошибки, пожалуйста, свяжитесь, чтобы указать.

Символическая природа TensorFlow делает отладку кода TensorFlow относительно сложной по сравнению с обычным кодом Python. Здесь я представляю некоторые инструменты, которые поставляются с TensorFlow, чтобы упростить отладку.

Вероятно, самая распространенная ошибка при использовании TensorFlow — передача тензора неправильной формы. Многие операции TensorFlow могут работать с тензорами разных рангов и форм. Это удобно при использовании API, но может вызвать дополнительную головную боль, когда что-то пойдет не так.

Например, рассмотрим следующееtf.matmulоперация умножения двух матриц:

a = tf.random_uniform([2, 3])
b = tf.random_uniform([3, 4])
c = tf.matmul(a, b)  # c is a tensor of shape [2, 4]

Но следующая функция также может реализовать матричное умножение:

a = tf.random_uniform([10, 2, 3])
b = tf.random_uniform([10, 3, 4])
tf.matmul(a, b)  # c is a tensor of shape [10, 2, 4]

Вот что мы былишироковещательная частьПример операции добавления, поддерживающей широковещательную рассылку:

a = tf.constant([[1.], [2.]])
b = tf.constant([1., 2.])
c = a + b  # c is a tensor of shape [2, 2]

использоватьtf.assert *Операция проверяет ваш тензор

Одним из способов снижения вероятности нежелательного поведения является использованиеtf.assert *Операция проверяет ранг или форму промежуточного тензора.

a = tf.constant([[1.], [2.]])
b = tf.constant([1., 2.])
check_a = tf.assert_rank(a, 1)  # This will raise an InvalidArgumentError exception
check_b = tf.assert_rank(b, 1)
with tf.control_dependencies([check_a, check_b]):
    c = a + b  # c is a tensor of shape [2, 2]

Помните, что узлы утверждения являются частью графа в TensorFlow, как и любая другая операция, и если они не оцениваются, они будут выполнены.Session.run()период устранен. Поэтому не забудьте создать явные зависимости для операций утверждения, чтобы заставить TensorFlow выполнять их.

Вы также можете использовать утверждения для проверки значений тензоров во время выполнения:

check_pos = tf.assert_positive(a)

об операциях утвержденийДетали, см. официальную документацию.

использоватьtf.Printвывести значения тензора

Еще одна встроенная функция, полезная для отладки:tf.Print, который записывает данный тензор в стандартный стек ошибок:

input_copy = tf.Print(input, tensors_to_print_list)

обращать внимание,tf.PrintФункция выводит копию своего первого аргумента в качестве возвращаемого значения. пустьtf.PrintСпособ принудительного запуска состоит в том, чтобы передать его вывод другому действию для выполнения. Например, если бы мы хотели вывести значения тензоров a и b перед их добавлением, мы могли бы сделать:

a = ...
b = ...
a = tf.Print(a, [a, b])
c = a + b

В качестве альтернативы мы можем определить зависимости управления вручную.

использоватьtf.compute_gradient_errorПроверьте значение изменения градиента

Не все операции в TensorFlow имеют изменения градиента, и легко непреднамеренно построить графики, которые TensorFlow не может вычислить изменения градиента.

Давайте посмотрим пример:

import tensorflow as tf

def non_differentiable_softmax_entropy(logits):
    probs = tf.nn.softmax(logits)
    return tf.nn.softmax_cross_entropy_with_logits(labels=probs, logits=logits)

w = tf.get_variable("w", shape=[5])
y = -non_differentiable_softmax_entropy(w)

opt = tf.train.AdamOptimizer()
train_op = opt.minimize(y)

sess = tf.Session()
sess.run(tf.global_variables_initializer())
for i in range(10000):
    sess.run(train_op)

print(sess.run(tf.nn.softmax(w)))

мы используемtf.nn.softmax_cross_entropy_with_logitsОпределяет энтропию в категориальном распределении. Затем мы используем оптимизатор Адама, чтобы найти веса с максимальной энтропией. Если вы прошли курс теории информации, то знаете, что равномерное распределение содержит максимальную энтропию. Таким образом, вы ожидаете, что его результат будет[0.2, 0.2, 0.2, 0.2, 0.2]. Но если вы выполните этот код, вы получите неожиданный результат:

[ 0.34081486  0.24287023  0.23465775  0.08935683  0.09230034]

Оказывается, чтоtf.nn.softmax_cross_entropy_with_logitsНеопределенные изменения градиента меток! Но если мы не знаем об этом явлении, как мы можем узнать о нем?

К счастью, TensorFlow поставляется с числовым дифференциатором, который можно использовать для поиска символических ошибок градиента. Давайте посмотрим, как мы можем его использовать:

with tf.Session():
    diff = tf.test.compute_gradient_error(w, [5], y, [])
    print(diff)

Если вы запустите его, вы увидите, что разница между значением и знаком довольно велика (я пробовал около 0,06 - 0,1).

Теперь давайте изменим нашу функцию и выполним ее снова:

import tensorflow as tf
import numpy as np

def softmax_entropy(logits, dim=-1):
    plogp = tf.nn.softmax(logits, dim) * tf.nn.log_softmax(logits, dim)
    return -tf.reduce_sum(plogp, dim)

w = tf.get_variable("w", shape=[5])
y = -softmax_entropy(w)

print(w.get_shape())
print(y.get_shape())

with tf.Session() as sess:
    diff = tf.test.compute_gradient_error(w, [5], y, [])
    print(diff)

Разница должна быть около 0,0001, этот результат выглядит намного лучше.

Теперь, если вы снова запустите оптимизатор с правильной версией, вы увидите, что окончательные веса таковы:

[ 0.2  0.2  0.2  0.2  0.2]

Это ответ, который мы хотим.

TensorFlow summariesиtfdbg(TensorFlow Debugger)два других инструмента для отладки, см. официальную документацию для получения дополнительной информации.