x
*
y
по
x
равна
y
,
а частная производная
x * y
по
y
равна
x
.
Приложение Б. Краткое руководство по тензорам и операциям над ними
573
Рис. Б.5.
График функции atan(x)
Генерируемые
tf.grad()
и
tf.grads()
функции возвращают только производные,
а не возвращаемое значение исходной функции. Например, что, если для
h(x, y)
нам
нужно узнать не только производные, но и значение
h
? Для этой цели можно вос
пользоваться функцией
tf.valueAndGrads()
:
const vdh = tf.valueAndGrads(h);
const out = vdh([tf.tensor1d([1, 2]), tf.tensor1d([-1, -2])]);
Результат ее (
out
) — объект с двумя полями:
value
, которое содержит значение
h
при заданных входных значениях, и
grads
в том же формате, что и возвращаемое
значение сгенерированной
tf.grads()
функции, а именно в виде массива тензоров
частных производных:
out.value.print();
out.grads[0].print();
out.grads[1].print();
Tensor
[-1, -4]
Tensor
[-1, -2]
Tensor
[1, 2]
Все обсуждавшиеся здесь API служат для вычисления производных функций
по их явным аргументам. Однако в одном из распространенных сценариев глубо
кого обучения участвуют функции, использующие в своих вычислениях весовые
коэффициенты. Эти весовые коэффициенты представлены объектами
tf.Variable
и
не
передаются явным образом в функции в виде аргументов. И нам нередко при
ходится вычислять частные производные подобных функций по весам во время об
учения. Этот технологический процесс реализуется функцией
tf.variableGrads()
,
отслеживающей, к каким обучаемым переменным обращается дифференцируемая
574
Приложения
функция, и автоматически вычисляющей производные по ним. Рассмотрим следу
ющий пример:
Поле
value
возвращаемого
tf.variableGrads()
результата представляет собой
значение, возвращаемое
f
при заданных значениях
a
,
b
и
x
. Поле
grads
представляет
собой JavaScriptобъект, содержащий производные по двум переменным (
a
и
b
) под
соответствующими ключевыми именами. Например, производная
f(a,
b)
по
a
равна
x ^ 2
, а производная
f(a, b)
по
b
равна
x
:
grads.a.print();
grads.b.print();
в результате чего получаем правильные значения:
Tensor
[1, 4]
Tensor
[1, 2]
Упражнения
1. Создайте с помощью
tf.tensorBuffer()
единичный четырехмерный тензор, удов
летворяющий следующим свойствам: форма
[5,
5,
5,
5]
, нули на всех позициях, за
исключением элементов, индексы которых представляют собой четыре одинаковых
числа (например,
[2,
2,
2,
2]
), значения которых должны быть равны 1.
2. Создайте трехмерный тензор формы
[2,
4,
5]
с помощью функции
tf.ran-
domUniform()
с интервалом по умолчанию
[0,
1)
. Напишите, используя
tf.sum()
,
строку кода для выполнения сверткисуммирования по второму и третьему из
мерениям. Посмотрите на результат. Его форма должна быть
[2]
. Как вы думаете,
какими примерно должны быть значения элементов? Соответствует ли результат
вашим ожиданиям?
(Подсказка: каково математическое ожидание числа, равномерно распределен
ного по интервалу
[0,
1)
? Каково математическое ожидание суммы двух таких
значений, если они статистически независимы друг от друга?)
3. Создайте матрицу 4
×
4 с помощью
tf.randomUniform()
(двумерный тензор
формы
[4,
4]
). Извлеките из нее с помощью
tf.slice()
подматрицу 2
×
2, рас
положенную в центре.
Приложение Б. Краткое руководство по тензорам и операциям над ними
575
4. Создайте с помощью
tf.ones()
,
tf.mul()
и
tf.concat()
следующий трехмерный
тензор: форма
[5,
4,
3]
; значения элементов первого среза по первой оси (тензор
формы
[1,
4,
3]
) должны быть все равны 1; значения элементов второго среза по
второй оси должны быть все равны 2 и т. д.
Бонусные баллы: тензор содержит много элементов, так что проверить пра
вильность просто по выведенному функцией
print()
в консоль непросто. По
думайте, как бы вы написали модульный тест для проверки его правильности?
(Подсказка: воспользуйтесь методами
data()
,
dataSync()
или
arraySync()
).
5. Напишите JavaScriptфункцию, выполняющую следующие операции над двумя
двумерными входными тензорами (матрицами) одинаковой формы. Вопервых,
сложите эти две матрицы. Вовторых, разделите полученную матрицу на 2 по
элементно. Втретьих, транспонируйте получившуюся в итоге матрицу. Функция
должна возвращать результат транспонирования.
А. Какими функциями TensorFlow.js вы воспользуетесь для написания этой
функции?
Б. Сможете ли вы реализовать эту функцию дважды: один раз с помощью функ
ционального API, а второй раз — с помощью цепочечного API? Какая реали
зация выглядит аккуратнее и более удобочитаема?
В. Что включает в себя транслирование?
Г. Как предотвратить возможные утечки памяти в этой функции?
Д. Попробуйте написать модульный тест (с помощью библиотеки Jasmine из
https://jasmine.github.io/
) для контроля отсутствия утечек памяти.
Франсуа Шолле, Эрик Нильсон, Стэн Байлесчи, Шэнкуинг Цэй
Do'stlaringiz bilan baham: |