Сохраните дату! Google I / O возвращается 18-20 мая Зарегистрируйтесь сейчас
Эта страница переведена с помощью Cloud Translation API.
Switch to English

Введение в тензоры

Посмотреть на TensorFlow.org Запускаем в Google Colab Посмотреть исходный код на GitHub Скачать блокнот
import tensorflow as tf
import numpy as np

Тензоры - это многомерные массивы с однородным типом (называемым dtype ). Вы можете увидеть все поддерживаемые dtypes вtf.dtypes.DType .

Если вы знакомы с NumPy , тензоры (вроде) похожи на np.arrays .

Все тензоры неизменяемы, как числа и строки Python: вы никогда не можете обновить содержимое тензора, а только создать новый.

Основы

Создадим несколько основных тензоров.

Вот тензор «скаляра» или «ранга 0». Скаляр содержит одно значение и не содержит «осей».

# This will be an int32 tensor by default; see "dtypes" below.
rank_0_tensor = tf.constant(4)
print(rank_0_tensor)
tf.Tensor(4, shape=(), dtype=int32)

Тензор «вектора» или «ранга-1» подобен списку значений. Вектор имеет одну ось:

# Let's make this a float tensor.
rank_1_tensor = tf.constant([2.0, 3.0, 4.0])
print(rank_1_tensor)
tf.Tensor([2. 3. 4.], shape=(3,), dtype=float32)

Тензор «матрицы» или «ранга-2» имеет две оси:

# If you want to be specific, you can set the dtype (see below) at creation time
rank_2_tensor = tf.constant([[1, 2],
                             [3, 4],
                             [5, 6]], dtype=tf.float16)
print(rank_2_tensor)
tf.Tensor(
[[1. 2.]
 [3. 4.]
 [5. 6.]], shape=(3, 2), dtype=float16)
Скаляр, форма: [] Вектор, фигура: [3] Матрица, форма: [3, 2]
Скаляр, число 4Строка из 3 частей, каждая из которых содержит номер.Сетка 3x2, каждая ячейка которой содержит число.

У тензоров может быть больше осей; вот тензор с тремя осями:

# There can be an arbitrary number of
# axes (sometimes called "dimensions")
rank_3_tensor = tf.constant([
  [[0, 1, 2, 3, 4],
   [5, 6, 7, 8, 9]],
  [[10, 11, 12, 13, 14],
   [15, 16, 17, 18, 19]],
  [[20, 21, 22, 23, 24],
   [25, 26, 27, 28, 29]],])

print(rank_3_tensor)
tf.Tensor(
[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]]

 [[10 11 12 13 14]
  [15 16 17 18 19]]

 [[20 21 22 23 24]
  [25 26 27 28 29]]], shape=(3, 2, 5), dtype=int32)

Есть много способов визуализировать тензор с более чем двумя осями.

Трехосевой тензор, форма: [3, 2, 5]

Вы можете преобразовать тензор в массив NumPy либо с помощью np.array либо с tensor.numpy метода tensor.numpy :

np.array(rank_2_tensor)
array([[1., 2.],
       [3., 4.],
       [5., 6.]], dtype=float16)
rank_2_tensor.numpy()
array([[1., 2.],
       [3., 4.],
       [5., 6.]], dtype=float16)

Тензоры часто содержат числа с плавающей запятой и целые числа, но имеют много других типов, в том числе:

  • комплексные числа
  • струны

Базовый класс tf.Tensor требует, чтобы тензоры были «прямоугольными», то есть вдоль каждой оси все элементы tf.Tensor одинаковый размер. Однако существуют специальные типы тензоров, которые могут обрабатывать различные формы:

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

a = tf.constant([[1, 2],
                 [3, 4]])
b = tf.constant([[1, 1],
                 [1, 1]]) # Could have also said `tf.ones([2,2])`

print(tf.add(a, b), "\n")
print(tf.multiply(a, b), "\n")
print(tf.matmul(a, b), "\n")
tf.Tensor(
[[2 3]
 [4 5]], shape=(2, 2), dtype=int32) 

tf.Tensor(
[[1 2]
 [3 4]], shape=(2, 2), dtype=int32) 

tf.Tensor(
[[3 3]
 [7 7]], shape=(2, 2), dtype=int32)
print(a + b, "\n") # element-wise addition
print(a * b, "\n") # element-wise multiplication
print(a @ b, "\n") # matrix multiplication
tf.Tensor(
[[2 3]
 [4 5]], shape=(2, 2), dtype=int32) 

tf.Tensor(
[[1 2]
 [3 4]], shape=(2, 2), dtype=int32) 

tf.Tensor(
[[3 3]
 [7 7]], shape=(2, 2), dtype=int32)

Тензоры используются во всех видах операций (ops).

c = tf.constant([[4.0, 5.0], [10.0, 1.0]])

# Find the largest value
print(tf.reduce_max(c))
# Find the index of the largest value
print(tf.argmax(c))
# Compute the softmax
print(tf.nn.softmax(c))
tf.Tensor(10.0, shape=(), dtype=float32)
tf.Tensor([1 0], shape=(2,), dtype=int64)
tf.Tensor(
[[2.6894143e-01 7.3105854e-01]
 [9.9987662e-01 1.2339458e-04]], shape=(2, 2), dtype=float32)

О формах

У тензоров есть формы. Немного словарного запаса:

  • Форма : длина (количество элементов) каждой из осей тензора.
  • Ранг : Количество тензорных осей. Скаляр имеет ранг 0, вектор - ранг 1, матрица - ранг 2.
  • Ось или измерение : конкретное измерение тензора.
  • Размер : общее количество элементов в тензоре, векторе формы продукта.

tf.TensorShape объектов tf.TensorShape и tf.TensorShape есть удобные свойства для доступа к ним:

rank_4_tensor = tf.zeros([3, 2, 4, 5])
Тензор ранга 4, форма: [3, 2, 4, 5]
Тензорная форма похожа на вектор.4-осевой тензор
print("Type of every element:", rank_4_tensor.dtype)
print("Number of axes:", rank_4_tensor.ndim)
print("Shape of tensor:", rank_4_tensor.shape)
print("Elements along axis 0 of tensor:", rank_4_tensor.shape[0])
print("Elements along the last axis of tensor:", rank_4_tensor.shape[-1])
print("Total number of elements (3*2*4*5): ", tf.size(rank_4_tensor).numpy())
Type of every element: <dtype: 'float32'>
Number of axes: 4
Shape of tensor: (3, 2, 4, 5)
Elements along axis 0 of tensor: 3
Elements along the last axis of tensor: 5
Total number of elements (3*2*4*5):  120

Хотя оси часто называют их индексами, вы всегда должны отслеживать значение каждой из них. Часто оси располагаются в порядке от глобального к локальному: сначала ось партии, затем пространственные размеры и особенности для каждого местоположения в последнюю очередь. Таким образом, векторы признаков представляют собой непрерывные области памяти.

Типичный порядок осей
Следите за каждой осью. 4-осевой тензор может быть: Пакет, Ширина, Высота, Характеристики.

Индексирование

Одноосное индексирование

TensorFlow следует стандартным правилам индексации Python, аналогичным индексированию списка или строки в Python , и основным правилам индексации NumPy.

  • индексы начинаются с 0
  • отрицательные индексы считаются в обратном порядке с конца
  • двоеточия, : , используются для срезов: start:stop:step
rank_1_tensor = tf.constant([0, 1, 1, 2, 3, 5, 8, 13, 21, 34])
print(rank_1_tensor.numpy())
[ 0  1  1  2  3  5  8 13 21 34]

Индексирование со скаляром удаляет ось:

print("First:", rank_1_tensor[0].numpy())
print("Second:", rank_1_tensor[1].numpy())
print("Last:", rank_1_tensor[-1].numpy())
First: 0
Second: 1
Last: 34

Индексирование с помощью : slice сохраняет ось:

print("Everything:", rank_1_tensor[:].numpy())
print("Before 4:", rank_1_tensor[:4].numpy())
print("From 4 to the end:", rank_1_tensor[4:].numpy())
print("From 2, before 7:", rank_1_tensor[2:7].numpy())
print("Every other item:", rank_1_tensor[::2].numpy())
print("Reversed:", rank_1_tensor[::-1].numpy())
Everything: [ 0  1  1  2  3  5  8 13 21 34]
Before 4: [0 1 1 2]
From 4 to the end: [ 3  5  8 13 21 34]
From 2, before 7: [1 2 3 5 8]
Every other item: [ 0  1  3  8 21]
Reversed: [34 21 13  8  5  3  2  1  1  0]

Многоосевая индексация

Тензоры более высокого ранга индексируются путем передачи нескольких индексов.

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

print(rank_2_tensor.numpy())
[[1. 2.]
 [3. 4.]
 [5. 6.]]

Передавая целое число для каждого индекса, результатом будет скаляр.

# Pull out a single value from a 2-rank tensor
print(rank_2_tensor[1, 1].numpy())
4.0

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

# Get row and column tensors
print("Second row:", rank_2_tensor[1, :].numpy())
print("Second column:", rank_2_tensor[:, 1].numpy())
print("Last row:", rank_2_tensor[-1, :].numpy())
print("First item in last column:", rank_2_tensor[0, -1].numpy())
print("Skip the first row:")
print(rank_2_tensor[1:, :].numpy(), "\n")
Second row: [3. 4.]
Second column: [2. 4. 6.]
Last row: [5. 6.]
First item in last column: 2.0
Skip the first row:
[[3. 4.]
 [5. 6.]]

Вот пример с 3-осевым тензором:

print(rank_3_tensor[:, :, 4])
tf.Tensor(
[[ 4  9]
 [14 19]
 [24 29]], shape=(3, 2), dtype=int32)
Выбор последней функции во всех местах в каждом примере в партии
Тензор 3x2x5 со всеми значениями в индексе 4 последней выбранной оси.Выбранные значения упакованы в 2-осевой тензор.

Прочтите руководство по нарезке тензоров, чтобы узнать, как применить индексирование для управления отдельными элементами в ваших тензорах.

Манипулирование формами

Изменение формы тензора очень полезно.

# Shape returns a `TensorShape` object that shows the size along each axis
x = tf.constant([[1], [2], [3]])
print(x.shape)
(3, 1)
# You can convert this object into a Python list, too
print(x.shape.as_list())
[3, 1]

Вы можете преобразовать тензор в новую форму. Операция tf.reshape выполняется быстро и дешево, поскольку базовые данные не нужно дублировать.

# You can reshape a tensor to a new shape.
# Note that you're passing in a list
reshaped = tf.reshape(x, [1, 3])
print(x.shape)
print(reshaped.shape)
(3, 1)
(1, 3)

Данные сохраняют свой макет в памяти, и создается новый тензор с запрошенной формой, указывающий на те же данные. TensorFlow использует «строковое» упорядочение памяти в стиле C, где приращение крайнего правого индекса соответствует одному шагу в памяти.

print(rank_3_tensor)
tf.Tensor(
[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]]

 [[10 11 12 13 14]
  [15 16 17 18 19]]

 [[20 21 22 23 24]
  [25 26 27 28 29]]], shape=(3, 2, 5), dtype=int32)

Если вы сгладите тензор, вы увидите, в каком порядке он размещен в памяти.

# A `-1` passed in the `shape` argument says "Whatever fits".
print(tf.reshape(rank_3_tensor, [-1]))
tf.Tensor(
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 24 25 26 27 28 29], shape=(30,), dtype=int32)

Обычно единственным разумным использованием tf.reshape является объединение или разделение смежных осей (или добавление / удаление 1 с).

Для этого тензора 3x2x5 изменение формы до (3x2) x5 или 3x (2x5) является разумным решением, поскольку срезы не смешиваются:

print(tf.reshape(rank_3_tensor, [3*2, 5]), "\n")
print(tf.reshape(rank_3_tensor, [3, -1]))
tf.Tensor(
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]
 [20 21 22 23 24]
 [25 26 27 28 29]], shape=(6, 5), dtype=int32) 

tf.Tensor(
[[ 0  1  2  3  4  5  6  7  8  9]
 [10 11 12 13 14 15 16 17 18 19]
 [20 21 22 23 24 25 26 27 28 29]], shape=(3, 10), dtype=int32)
Несколько хороших изменений.
Тензор 3x2x5Те же данные преобразованы в (3x2) x5Те же данные преобразованы в 3x (2x5)

Изменение формы будет "работать" для любой новой формы с тем же общим числом элементов, но не принесет ничего полезного, если вы не соблюдаете порядок осей.

Поменять местами оси в tf.reshape не получится; для этого вам понадобится tf.transpose .

# Bad examples: don't do this

# You can't reorder axes with reshape.
print(tf.reshape(rank_3_tensor, [2, 3, 5]), "\n") 

# This is a mess
print(tf.reshape(rank_3_tensor, [5, 6]), "\n")

# This doesn't work at all
try:
  tf.reshape(rank_3_tensor, [7, -1])
except Exception as e:
  print(f"{type(e).__name__}: {e}")
tf.Tensor(
[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]
  [10 11 12 13 14]]

 [[15 16 17 18 19]
  [20 21 22 23 24]
  [25 26 27 28 29]]], shape=(2, 3, 5), dtype=int32) 

tf.Tensor(
[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]
 [12 13 14 15 16 17]
 [18 19 20 21 22 23]
 [24 25 26 27 28 29]], shape=(5, 6), dtype=int32) 

InvalidArgumentError: Input to reshape is a tensor with 30 values, but the requested shape requires a multiple of 7 [Op:Reshape]
Некоторые плохие изменения.
Вы не можете изменить порядок осей, используйте для этого tf.transposeВсе, что объединяет фрагменты данных вместе, вероятно, неправильно.Новая форма должна точно соответствовать.

Вы можете встретить не полностью заданные формы. Либо фигура содержит None (длина оси неизвестна), либо вся фигура равна None (ранг тензора неизвестен).

За исключением tf.RaggedTensor , такие формы будут встречаться только в контексте символьных API-интерфейсов построения графиков TensorFlow:

Подробнее о DTypes

Чтобы проверить tf.Tensor данныхTensor.dtype свойствоTensor.dtype .

При создании tf.Tensor из объекта Python вы можете дополнительно указать тип данных.

Если вы этого не сделаете, TensorFlow выберет тип данных, который может представлять ваши данные. TensorFlow преобразует целые числа Python в tf.int32 и числа с плавающей запятой Python в tf.float32 . В противном случае TensorFlow использует те же правила, что и NumPy при преобразовании в массивы.

Вы можете преобразовывать от типа к типу.

the_f64_tensor = tf.constant([2.2, 3.3, 4.4], dtype=tf.float64)
the_f16_tensor = tf.cast(the_f64_tensor, dtype=tf.float16)
# Now, cast to an uint8 and lose the decimal precision
the_u8_tensor = tf.cast(the_f16_tensor, dtype=tf.uint8)
print(the_u8_tensor)
tf.Tensor([2 3 4], shape=(3,), dtype=uint8)

Вещание

Трансляция - это концепция, заимствованная из эквивалентной функции в NumPy . Короче говоря, при определенных условиях меньшие тензоры автоматически «растягиваются», чтобы соответствовать большим тензорам при выполнении над ними комбинированных операций.

Самый простой и распространенный случай - это попытка умножить или добавить тензор к скаляру. В этом случае скаляр транслируется, чтобы иметь ту же форму, что и другой аргумент.

x = tf.constant([1, 2, 3])

y = tf.constant(2)
z = tf.constant([2, 2, 2])
# All of these are the same computation
print(tf.multiply(x, 2))
print(x * y)
print(x * z)
tf.Tensor([2 4 6], shape=(3,), dtype=int32)
tf.Tensor([2 4 6], shape=(3,), dtype=int32)
tf.Tensor([2 4 6], shape=(3,), dtype=int32)

Точно так же оси с длиной 1 могут быть растянуты, чтобы соответствовать другим аргументам. Оба аргумента могут быть растянуты в одном и том же вычислении.

В этом случае матрица 3x1 поэлементно умножается на матрицу 1x4 для получения матрицы 3x4. Обратите внимание, что первая единица необязательна: y имеет форму [4] .

# These are the same computations
x = tf.reshape(x,[3,1])
y = tf.range(1, 5)
print(x, "\n")
print(y, "\n")
print(tf.multiply(x, y))
tf.Tensor(
[[1]
 [2]
 [3]], shape=(3, 1), dtype=int32) 

tf.Tensor([1 2 3 4], shape=(4,), dtype=int32) 

tf.Tensor(
[[ 1  2  3  4]
 [ 2  4  6  8]
 [ 3  6  9 12]], shape=(3, 4), dtype=int32)
Транслируемое добавление: [3, 1] умноженное на [1, 4] дает [3,4]
Добавление матрицы 3x1 к матрице 4x1 приводит к матрице 3x4

Вот такая же операция без трансляции:

x_stretch = tf.constant([[1, 1, 1, 1],
                         [2, 2, 2, 2],
                         [3, 3, 3, 3]])

y_stretch = tf.constant([[1, 2, 3, 4],
                         [1, 2, 3, 4],
                         [1, 2, 3, 4]])

print(x_stretch * y_stretch)  # Again, operator overloading
tf.Tensor(
[[ 1  2  3  4]
 [ 2  4  6  8]
 [ 3  6  9 12]], shape=(3, 4), dtype=int32)

В большинстве случаев широковещательная передача эффективна как по времени, так и по пространству, поскольку операция широковещания никогда не материализует расширенные тензоры в памяти.

Вы видите, как выглядит трансляция, используяtf.broadcast_to .

print(tf.broadcast_to(tf.constant([1, 2, 3]), [3, 3]))
tf.Tensor(
[[1 2 3]
 [1 2 3]
 [1 2 3]], shape=(3, 3), dtype=int32)

В отличие от математической операции, например, broadcast_to не делает ничего особенного для экономии памяти. Здесь вы материализуете тензор.

Это может быть еще более сложным. В этом разделе книги Джейка Вандерпласа « Справочник по науке о данных» показано больше трюков с трансляцией (опять же в NumPy).

tf.convert_to_tensor

Большинство операций, например tf.matmul и tf.reshape принимают аргументы класса tf.Tensor . Однако вы заметите, что в приведенном выше случае принимаются объекты Python в форме тензоров.

Большинство, но не все, операционные convert_to_tensor вызывают convert_to_tensor для нетензорных аргументов. Существует реестр преобразований, и большинство классов объектов, таких как ndarray NumPy, TensorShape , списки Python и tf.Variable будут преобразованы автоматически.

См. tf.register_tensor_conversion_function для более подробной информации, и если у вас есть собственный тип, вы хотите автоматически преобразовать его в тензор.

Рваные тензоры

Тензор с переменным числом элементов вдоль некоторой оси называется «рваным». Используйте tf.ragged.RaggedTensor для tf.ragged.RaggedTensor данных.

Например, это нельзя представить как обычный тензор:

tf.RaggedTensor , shape: [4, None]
Двухосный рваный тензор, каждая строка может иметь разную длину.
ragged_list = [
    [0, 1, 2, 3],
    [4, 5],
    [6, 7, 8],
    [9]]
try:
  tensor = tf.constant(ragged_list)
except Exception as e:
  print(f"{type(e).__name__}: {e}")
ValueError: Can't convert non-rectangular Python sequence to Tensor.

Вместо этого создайтеtf.RaggedTensor используя tf.ragged.constant :

ragged_tensor = tf.ragged.constant(ragged_list)
print(ragged_tensor)
<tf.RaggedTensor [[0, 1, 2, 3], [4, 5], [6, 7, 8], [9]]>

Формаtf.RaggedTensor будет содержать несколько осей с неизвестной длиной:

print(ragged_tensor.shape)
(4, None)

Струнные тензоры

tf.string - это dtype , то есть вы можете представлять данные в виде строк (байтовых массивов переменной длины) в тензорах.

Строки являются атомарными и не могут быть проиндексированы так, как строки Python. Длина строки не является одной из осей тензора. См. tf.strings для функций для управления ими.

Вот тензор скалярной струны:

# Tensors can be strings, too here is a scalar string.
scalar_string_tensor = tf.constant("Gray wolf")
print(scalar_string_tensor)
tf.Tensor(b'Gray wolf', shape=(), dtype=string)

И вектор строк:

Вектор строк, форма: [3,]
Длина струны не является одной из осей тензора.
# If you have three string tensors of different lengths, this is OK.
tensor_of_strings = tf.constant(["Gray wolf",
                                 "Quick brown fox",
                                 "Lazy dog"])
# Note that the shape is (3,). The string length is not included.
print(tensor_of_strings)
tf.Tensor([b'Gray wolf' b'Quick brown fox' b'Lazy dog'], shape=(3,), dtype=string)

В приведенной выше распечатке префикс b указывает, что tf.string dtype - это не строка в Юникоде, а строка байтов. См. Учебное пособие по Unicode для получения дополнительной информации о работе с текстом Unicode в TensorFlow.

Если вы передаете символы юникода, они кодируются в кодировке utf-8.

tf.constant("🥳👍")
<tf.Tensor: shape=(), dtype=string, numpy=b'\xf0\x9f\xa5\xb3\xf0\x9f\x91\x8d'>

Некоторые базовые функции со строками можно найти в tf.strings , включая tf.strings.split .

# You can use split to split a string into a set of tensors
print(tf.strings.split(scalar_string_tensor, sep=" "))
tf.Tensor([b'Gray' b'wolf'], shape=(2,), dtype=string)
# ...but it turns into a `RaggedTensor` if you split up a tensor of strings,
# as each string might be split into a different number of parts.
print(tf.strings.split(tensor_of_strings))
<tf.RaggedTensor [[b'Gray', b'wolf'], [b'Quick', b'brown', b'fox'], [b'Lazy', b'dog']]>
Три струны разделены, форма: [3, None]
Разделение нескольких строк возвращает tf.RaggedTensor

И tf.string.to_number :

text = tf.constant("1 10 100")
print(tf.strings.to_number(tf.strings.split(text, " ")))
tf.Tensor([  1.  10. 100.], shape=(3,), dtype=float32)

Хотя вы не можете использовать tf.cast для преобразования тензора строки в числа, вы можете преобразовать его в байты, а затем в числа.

byte_strings = tf.strings.bytes_split(tf.constant("Duck"))
byte_ints = tf.io.decode_raw(tf.constant("Duck"), tf.uint8)
print("Byte strings:", byte_strings)
print("Bytes:", byte_ints)
Byte strings: tf.Tensor([b'D' b'u' b'c' b'k'], shape=(4,), dtype=string)
Bytes: tf.Tensor([ 68 117  99 107], shape=(4,), dtype=uint8)
# Or split it up as unicode and then decode it
unicode_bytes = tf.constant("アヒル 🦆")
unicode_char_bytes = tf.strings.unicode_split(unicode_bytes, "UTF-8")
unicode_values = tf.strings.unicode_decode(unicode_bytes, "UTF-8")

print("\nUnicode bytes:", unicode_bytes)
print("\nUnicode chars:", unicode_char_bytes)
print("\nUnicode values:", unicode_values)
Unicode bytes: tf.Tensor(b'\xe3\x82\xa2\xe3\x83\x92\xe3\x83\xab \xf0\x9f\xa6\x86', shape=(), dtype=string)

Unicode chars: tf.Tensor([b'\xe3\x82\xa2' b'\xe3\x83\x92' b'\xe3\x83\xab' b' ' b'\xf0\x9f\xa6\x86'], shape=(5,), dtype=string)

Unicode values: tf.Tensor([ 12450  12498  12523     32 129414], shape=(5,), dtype=int32)

tf.string dtype используется для всех необработанных байтовых данных в TensorFlow. Модуль tf.io содержит функции для преобразования данных в байты и обратно, включая декодирование изображений и синтаксический анализ csv.

Редкие тензоры

Иногда ваши данные разрежены, например, очень широкое пространство для встраивания. tf.sparse.SparseTensor поддерживает tf.sparse.SparseTensor и связанные с ним операции для эффективного хранения разреженных данных.

tf.SparseTensor , shape: [3, 4]
Сетка 3x4 со значениями только в двух ячейках.
# Sparse tensors store values by index in a memory-efficient manner
sparse_tensor = tf.sparse.SparseTensor(indices=[[0, 0], [1, 2]],
                                       values=[1, 2],
                                       dense_shape=[3, 4])
print(sparse_tensor, "\n")

# You can convert sparse tensors to dense
print(tf.sparse.to_dense(sparse_tensor))
SparseTensor(indices=tf.Tensor(
[[0 0]
 [1 2]], shape=(2, 2), dtype=int64), values=tf.Tensor([1 2], shape=(2,), dtype=int32), dense_shape=tf.Tensor([3 4], shape=(2,), dtype=int64)) 

tf.Tensor(
[[1 0 0 0]
 [0 0 2 0]
 [0 0 0 0]], shape=(3, 4), dtype=int32)