функциональным
(functional), поскольку в его
основе — вызов функций из пространства имен
tf.*
. Второй API мы будем называть
Приложение Б. Краткое руководство по тензорам и операциям над ними
563
цепочечным
(chaining), поскольку операции в нем идут одна за другой, как бы цепоч
кой (как вы видели в предыдущем примере). Большинство операций в TensorFlow.js
доступны как в функциональной версии, в пространстве имен
tf.*
, так и в цепочеч
ной, в виде методов объектов тензоров. Вы можете выбирать любую из этих версий,
в зависимости от своих потребностей. В книге мы используем оба API в различных
местах, отдавая предпочтение цепочечному API для последовательных операций.
Поэлементные и сверточные операции
Общее свойство всех упомянутых примеров унарных операций (
tf.neg()
,
tf.reci-
procal()
и
tf.relu()
) — независимое выполнение операций над отдельными эле
ментами входных тензоров. В результате форма возвращаемого этими операциями
тензора совпадает с формой входного тензора. Впрочем, многие унарные операции
в TensorFlow.js приводят к уменьшению формы тензора, по сравнению с исходным.
Что означает «уменьшение» в контексте форм тензоров? В некоторых случаях —
меньший ранг. Например, унарная операция, получающая на входе трехмерный
тензор (тензор ранга 3), может возвращать скаляр (тензор ранга 0). В других случаях
оно может значить, что размер определенного измерения меньше, чем исходного.
Например, унарная операция, получив на входе тензор формы
[3,
20]
, может вер
нуть тензор формы
[3,
1]
. Вне зависимости от вида сжатия формы, такие операции
называются
сверточными
(reduction operations).
Одна из чаще всего используемых операций свертки —
tf.mean()
. В цепочечном
API она доступна в качестве метода
mean()
класса
Tensor
. При вызове без каких
либо дополнительных аргументов, она вычисляет арифметическое среднее всех
элементов входного тензора, вне зависимости от его формы, и возвращает скаляр.
В цепочечном API она используется примерно так:
> const x = tf.tensor2d([[0, 10], [20, 30]]);
> x.mean().print();
Tensor
15
Иногда необходимо вычислить среднее значение по отдельным строкам двумер
ного тензора (матрицы), а не по тензору в целом. Для этого можно передать в метод
mean()
дополнительный аргумент:
> x.mean(-1).print();
Tensor
[5, 25]
Аргумент
-1
означает, что метод
mean()
должен вычислять арифметические
средние значения по последнему измерению тензора
1
. Это измерение называется
в подобном случае
свертываемым измерением
(reduction dimension), поскольку оно
сворачивается в выходном тензоре, который оказывается тензором ранга 1. Указать
сверточное измерение можно также с помощью его индекса:
> x.mean(1).print();
1
Что соответствует принятому в языке Python соглашению об индексах.
564
Приложения
Обратите внимание, что метод
mean()
позволяет указывать и несколько свер
точных измерений. Например, если нужно вычислить для трехмерного входного
тензора формы
[10,
6,
3]
арифметическое среднее по последним двум измерениям
и получить в результате тензор формы
[10]
, можно вызвать метод
mean()
в виде
x.mean([-2,
-1])
или
x.mean([1, 2])
. Мы оставим это читателю в качестве упраж
нения в конце этого приложения.
В числе других часто используемых унарных операций свертки:
z
z
метод
tf.sum()
— практически идентичен
tf.mean()
, но вычисляет сумму, а не
среднее значение, элементов;
z
z
метод
tf.norm()
, вычисляющий норму элементов. Существует множество видов
норм. Например, норма L1 представляет собой сумму модулей элементов. Нор
ма L2 вычисляется путем извлечения квадратного корня из суммы квадратов
элементов, другими словами, представляет собой длину вектора в евклидовом
пространстве. С помощью метода
tf.norm()
можно вычислять дисперсию или
среднеквадратичное отклонение списка чисел;
z
z
методы
tf.min()
и
tf.max()
, вычисляющие минимальное и максимальное значе
ния элементов соответственно;
z
z
метод
tf.argMax()
, возвращающий индекс максимального элемента по оси сверт
ки. Эту операцию часто применяют для преобразования вероятностей классов
в индекс наилучшего класса (например, см. задачу классификации ирисов в раз
деле 3.3.2). Аналогичную функциональность поиска минимального значения
предоставляет метод
tf.argMin()
.
Мы уже упоминали, что поэлементные операции сохраняют форму входного
тензора. Но обратное утверждение не соответствует действительности. Некоторые
сохраняющие форму входного тензора операции — вовсе не поэлементные. Напри
мер, операция
tf.transpose()
производит транспонирование матрицы, при котором
элемент с индексами
[i,
j]
во входном двумерном тензоре переводится в элемент
с индексами
[j,
i]
в выходном двумерном тензоре. Входная и выходная формы при
использовании метода
tf.transpose()
идентичны, если входной тензор представляет
собой квадратную матрицу, но это вовсе не поэлементная операция, так как значение
элемента
[i,
j]
выходного тензора зависит не только от значения элемента
[i,
j]
входного тензора, а от значений на других позициях.
Б.2.2. Бинарные операции
В отличие от унарных операций для бинарной операции необходимо два аргумента.
Вероятно, чаще всего используемая бинарная операция
tf.add()
. Она же, вероятно,
и самая простая, так как просто складывает два тензора. Например:
> const x = tf.tensor2d([[0, 2], [4, 6]]);
> const y = tf.tensor2d([[10, 20], [30, 46]]);
> tf.add(x, y).print();
Tensor
[[10, 22],
[34, 52]]
Приложение Б. Краткое руководство по тензорам и операциям над ними
565
Некоторые аналогичные бинарные операции:
z
z
метод
tf.sub()
для вычитания одного тензора из другого;
z
z
метод
tf.mul()
для умножения двух тензоров;
z
z
метод
tf.matMul()
для вычисления матричного произведения двух тензоров;
z
z
методы
tf.logicalAnd()
,
tf.logicalOr()
и
tf.logicaXor()
для выполнения соот
ветственно логических операций И, ИЛИ и исключающее ИЛИ над тензорами
булева типа.
Некоторые бинарные операции поддерживают
Do'stlaringiz bilan baham: |