вектор
с четырех
мерным
тензором
! Четырехмерный вектор — это одномерный тензор с одной осью
координат, содержащий ровно четыре значения, в то время как у четырехмерного
тензора — четыре оси координат (причем число измерений по каждой оси коор
динат может быть любым). Размерность может означать либо число элементов
по конкретной оси координат (как в нашем четырехмерном векторе), либо число
осей координат в тензоре (например, четырехмерный тензор). Иногда это может
приводить к путанице. Формально правильнее и менее двусмысленно будет гово
рить о тензорах ранга 4, но двусмысленное название «четырехмерный тензор», тем
не менее встречается очень часто. В большинстве случаев это не вызывает проблем,
поскольку из контекста обычно понятно, что имеется в виду.
Как и в случае скалярных тензоров, для обращения к значениям элементов одно
мерного тензора можно использовать методы
data()
и
dataSync()
, например:
> await myVector.data()
Float32Array(4) [-1.2000000476837158, 0, 19, 78]
Или можно использовать синхронную версию
data()
— вышеупомянутый метод
dataSync()
, — но учтите, что
dataSync()
может блокировать поток выполнения UI
и его следует по возможности избегать:
> myVector.dataSync()
Float32Array(4) [-1.2000000476837158, 0, 19, 78]
Приложение Б. Краткое руководство по тензорам и операциям над ними
553
Для доступа к значению конкретного элемента одномерного тензора можно про
сто обратиться к нему по индексу TypedArray, возвращаемому методами
data()
или
dataSync()
, например:
> [await myVector.data()][2]
19
Б.1.3. tensor2d (тензоры ранга 2)
Двумерный тензор содержит две оси координат. В некоторых случаях двумерные
тензоры называют
матрицами
, а его две оси координат интерпретируют как индексы
строк и столбцов матрицы соответственно. Матрицу можно наглядно изобразить
в виде прямоугольной сетки элементов (см. третий блок на рис. Б.1). В TensorFlow.js
> const myMatrix = tf.tensor2d([[1, 2, 3], [40, 50, 60]]);
> myMatrix.shape;
[2, 3]
> myMatrix.rank;
2
Записи на первой оси координат называются
строками
(rows), а на второй —
столбцами
(columns). В предыдущем примере первая строка выглядит как
[1,
2,
3]
,
а первый столбец —
[1,
40]
. Важно отдавать себе отчет, что методы
data()
и
dataSync()
возвращают данные в виде «плоских» массивов
в построчном порядке
(rowmajor). Другими словами, сначала в
Float32Array
будут находиться элементы
первой строки, за которыми будут следовать элементы второй строки и т. д.
1
:
> await myMatrix.data();
Float32Array(6) [1, 2, 3, 40, 50, 60]
Ранее мы упоминали, что методы
data()
и
dataSync()
с последующим индексом
можно использовать для доступа к значению любого элемента одномерного тензора.
Индексация при работе с двумерными тензорами усложняется, поскольку объект
TypedArray, возвращаемый методами
data()
или
dataSync()
, схлопывает элементы
двумерного тензора. Например, для обращения к элементу TypedArray, соответ
ствующему элементу во второй строке и втором столбце двумерного тензора, не
обходимо выполнить следующие арифметические операции:
> (await myMatrix.data())[1 * 3 + 1];
50
К счастью, TensorFlow.js предоставляет дополнительные методы для извле
чения значений из тензоров в обычные структуры данных JavaScript:
array()
и
arraySync()
. В отличие от
data()
и
dataSync()
эти методы возвращают вложенные
JavaScriptмассивы, сохраняющие ранг и формы исходных тензоров. Например:
> JSON.stringify(await myMatrix.array())
"[[1,2,3],[40,50,60]]"
1
В отличие от упорядочения данных по столбцам, встречающегося в некоторых фреймвор
ках численной обработки, например MATLAB и R.
554
Приложения
Для обращения к элементу во второй строке и втором столбце достаточно про
извести двойную индексацию вложенного массива:
> (await myMatrix.array())[1][1]
50
Благодаря этому не требуются арифметические операции с индексами, что осо
бенно удобно для многомерных тензоров.
arraySync()
— синхронная версия
array()
.
Как и
dataSync()
,
arraySync()
может блокировать поток выполнения UI и потому
использовать ее следует осмотрительно.
В вызове
tf.tensor2d()
мы передали в качестве аргумента вложенный JavaScript
массив. Этот аргумент состоит из строк массивов, вложенных в другой массив.
На основе этой вложенной структуры
tf.tensor2d()
выясняет форму двумерного
тензора — количество строк и столбцов в нем соответственно. Можно также создать
такой же двумерный тензор с помощью
tf.tensor2d()
, передав элементы в виде пло
ского (невложенного) JavaScriptмассива и указав дополнительно второй аргумент,
определяющий форму двумерного тензора:
> const myMatrix = tf.tensor2d([1, 2, 3, 40, 50, 60], [2, 3]);
> myMatrix.shape;
[2, 3]
> myMatrix.rank;
2
При таком подходе произведение всех чисел аргумента
shape
должно равняться
числу элементов в массиве чисел, иначе во время вызова
tf.tensor2d()
будет воз
вращена ошибка. Тензоры более высоких рангов также можно создавать двумя
аналогичными способами: либо с помощью одного вложенного массива, либо
с помощью плоского массива, сопровождаемого аргументом
shape
. В различных
примерах в книге используются оба подхода.
Б.1.4. Тензоры ранга 3 и более высоких рангов
Если упаковать несколько двумерных тензоров в новый массив, получится трех
мерный тензор, который можно представить себе в виде куба элементов (четвертый
блок на рис. Б.1). Тензоры ранга 3 создаются в TensorFlow.js аналогично предыду
щим рангам:
> const myRank3Tensor = tf.tensor3d([[[1, 2, 3],
[4, 5, 6]],
[[10, 20, 30],
[40, 50, 60]]]);
> myRank3Tensor.shape;
[2, 2, 3]
> myRank3Tensor.rank;
3
Приложение Б. Краткое руководство по тензорам и операциям над ними
555
Другой способ сделать то же самое — передать плоский (невложенный) массив
значений вместе с его формой, указанной явным образом:
> const anotherRank3Tensor = tf.tensor3d(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
[2, 2, 3]);
Функцию
tf.tensor3d
в этом примере можно заменить более общей функцией
tf.tensor()
. С ее помощью можно создавать тензоры вплоть до ранга 6. В следу
ющем примере создаются тензор ранга 3 и тензор ранга 6:
> anotherRank3Tensor = tf.tensor(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
[2, 2, 3]);
> anotherRank3Tensor.shape;
[2, 2, 3]
> anotherRank3Tensor.rank;
3
> tinyRank6Tensor = tf.tensor([13], [1, 1, 1, 1, 1, 1]);
> tinyRank6Tensor.shape;
[1, 1, 1, 1, 1, 1]
> tinyRank6Tensor.rank;
6
Б.1.5. Понятие батчей данных
На практике первая ось координат (ось 0, поскольку индексы начинаются с 0) во
всех тензорах, которые только могут встретиться вам в глубоком обучении, прак
тически всегда будет
осью батчей
(batch axis, иногда ее называют
осью примеров
данных
(samples axis) или
измерением батчей
(batch dimension)). Поэтому ранг
подаваемого на вход модели тензора будет на единицу превышать ранг отдельных
входных признаков. Это справедливо для всех моделей TensorFlow.js в этой книге.
Размер этого первого измерения равен числу примеров данных в батче, называе
мому
размером батча
(batch size). Например, в примере классификации ирисов из
главы 3 (см. листинг 3.9) входной признак каждого из примеров состоит из четырех
чисел в виде вектора длиной 4 (одномерный тензор формы
[4]
). Поэтому входной
сигнал модели классификации ирисов — двумерный, формы
[null,
4]
, в которой
первый
null
указывает, что размер пакета будет выяснен во время работы модели
(рис. Б.2). Это соглашение о батчах применимо также к выходному сигналу модели.
Например, выходной сигнал модели классификации ирисов представляет собой
унитарное представление трех возможных типов ирисов для каждого отдельного
входного признака — одномерный тензор формы
[3]
. Однако фактически выходной
сигнал модели здесь — двумерный тензор формы
[null,
3]
, в которой первое из
мерение со значением
null
соответствует размеру пакета, которое будет определено
позднее.
Do'stlaringiz bilan baham: |