Математические операции и функции над тензорами

На этом занятии рассмотрим основные функции для создания тензоровс заданными значениями, а также базовые математические операции, которые можно выполнять в пакете Tensorflow.

Функции автозаполнения

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

Название

Описание

eye(N, M=None, …)

Возвращает массив размером NxMс единичными диагональными элементами (остальные элементы равны нулю).

identity(input, …)

Возвращаеткопию тензора input.

ones(shape, …)

Возвращает массив заданного размера и типа, состоящего из всех единиц.

ones_like(shape, …)

Возвращает массив заданного размера и типа, состоящего из всех единиц.

zeros(shape, …)

Возвращает массив заданного размера и типа, состоящего из всех нулей.

zeros_like()

Возвращает массив заданного размера и типа, состоящего из всех нулей.

fill(shape, value, …)

Возвращает массив заданного размера и типа со значениями value.

range()

Генератор числовых последовательностей с заданным диапазоном и шагом.

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

a = tf.zeros((3,3))
print(a)

Функция ones() работает аналогичным образом, только вместо нулей записывает единицы:

b = tf.ones((5,3))
print(b)

Похожие функции zeros_like() и ones_like() создают тензоры с нулевыми и единичными значениями, но размерности берут из переданного им другого тензора. Например:

c = tf.ones_like(a)

создаст матрицу из единиц размером 3x3, так как тензор aимеет такие размеры.

Следующая функция eye() создает матрицу с единицами по главной диагонали и нулевыми значениями вне ее:

d = tf.eye(3)
print(d)

После выполнения в консоли увидим:

tf.Tensor(
[[1. 0. 0.]
 [0. 1. 0.]
[0. 0. 1.]], shape=(3, 3), dtype=float32)

Если же указать два аргумента:

d = tf.eye(3, 2)

то получим аналогичную матрицу, но с размерами 3x2.

Для создания копий тензоров с сохранением их значений можно воспользоваться специальной функцией identity(), например, так:

e = tf.identity(c)

Будет создана копия тензора c.

Следующий метод fill() позволяет создавать тензоры с заданным числовым значением:

f = tf.fill((2, 3), -1)

Получим тензор 2x3 со значениями -1.

Наконец, функция range() знакомая вам по классическому Python, позволяет в Tensorflow генерировать последовательности чисел в заданных границах и с заданным шагом, например, так:

g = tf.range(1, 11, 0.2)

Обратите внимание, что можно использовать вещественные числа в качестве значений этой функции (в отличие от аналогичной функции языка Python, где допустимы только целые числа).

Генерация случайных чисел

В Tensorflow имеется модуль random, отвечающий за генерацию тензоров со случайными значениями.

Название

Описание

random.normal()

Возвращаеттензор с нормально распределенными случайными величинами с заданным МО и СКО.

tf.random.truncated_normal()

Также возвращает тензор нормальных СВ, но в диапазоне ±2σ относительно МО.

random.uniform()

Возвращаеттензор с равномерно распределенными СВ в указанном интервале.

random.shuffle()

Перемешивает элементы тензора.

random.set_seed()

Устанавливает «зерно» датчика случайных чисел.

Все эти функции выполняются вполне очевидным способом:

a = tf.random.normal((2, 4), 0, 0.1)  # тензор 2x4 с нормальными СВ
b = tf.random.uniform((2, 2), -1, 1)  # тензор 2x2 с равномерными СВ в диапазоне [-1; 1]
c = tf.random.shuffle(range(10))  # перемешивание последовательности чисел
tf.random.set_seed(1)  # установка зерна датчика случайных чисел
d = tf.random.truncated_normal((1, 5), -1, 0.1)  # тензор 1x5 с ограниченными нормальными СВ

Математические операции в Tensorflow

Рассмотрим основные математические операции в пакете Tensorflow. Предположим, имеются два одномерных тензора (векторы):

a = tf.constant([1, 2, 3])
b = tf.constant([9, 8, 7])
print(a, b, sep="\n", end="\n\n")

С ними можно выполнять следующие распространенные операции:

z1 = tf.add(a, b)       # сложение
z2 = a + b              # сложение
z1 = tf.subtract(a, b)  # вычитание
z2 = a - b              # вычитание
z1 = tf.divide(a, b)    # деление (поэлементное)
z2 = a / b              # деление (поэлементное)
z1 = tf.multiply(a, b)  # умножение (поэлементное)
z2 = a * b              # умножение (поэлементное)
z1 = a ** 2             # возведение в степень (поэлементное)
 
z1 = tf.tensordot(a, b, axes=0) # векторное внешнее умножение
z2 = tf.tensordot(a, b, axes=1) # векторное внутреннее умножение
 
a2 = tf.constant(tf.range(1, 10), shape=(3, 3))
b2 = tf.constant(tf.range(5, 14), shape=(3, 3))
 
z1 = tf.matmul(a2, b2)  # матричное умножение
z2 = a2 @ b2            # матричное умножение
print(z1, z2, sep="\n\n")

Здесь все достаточно очевидно, поэтому нет смысла подробно расписывать. Опять же, для более детального понимания, можно обратиться к курсу NumPy,где все это разбирается подробнее.

Основные математические функции

Пакет Tensorflow поддерживает множество стандартных математических функций. Я покажу лишь базовые из них, а остальные, в принципе, очевидные и применяются похожим образом.

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

m = tf.tensordot(a, b, axes=0)  # матрица 3x3

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

z = tf.reduce_sum(m)        # вычисление суммы элементов (по всем осям)

Если же нам нужно вычислить сумму только по столбцам, то для этого следует указать ось axis=0:

z = tf.reduce_sum(m, axis=0)    # вычисление суммы элементов (при axis=0 суммируются строки)

Вас может удивить, что axis=0 – это суммирование по столбцам, а не по строкам. В действительности, этот параметр указывает по какой оси перебирать данные в тензоре и поэлементно суммировать между собой. В данном случае выбираются строки и суммируются, получается эффект суммирования по столбцам.

При необходимости можно указать несколько осей, например, так:

z = tf.reduce_sum(m, axis=[0, 1])    # вычисление суммы элементов (по axis=0 и 1)

это будет эквивалентно суммированию всех элементов в матрице m.

Аналогично работают следующие математические функции:

z = tf.reduce_mean(m)	     # среднее арифметическое
z = tf.reduce_max(m, axis=0)      # максимальное по столбцам
z = tf.reduce_min(m, axis=1)      # минимальное по строкам
z = tf.reduce_prod(m)             # произведение значений элементов матрицы

Есть и другие математические функции, например, вычисление квадратного корня и возведение в квадрат:

z = tf.sqrt(tf.cast(a, dtype=tf.float32))   # работает только с вещественными типами
z = tf.square(a)        # возведение в квадрат

Также существуют все тригонометрические функции:

z = tf.sin(tf.range(-3.14, 3.14, 1))    # синус от значений тензора
z = tf.cos(tf.range(-3.14, 3.14, 1))    # косинус от значений тензора

Кроме того, имеются все распространенные специальные функции, используемые в нейронных сетях:

z = tf.keras.activations.relu(a)
z = tf.keras.activations.sigmoid(tf.cast(a, dtype=tf.float32))
z = tf.keras.activations.linear(a)

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

Видео по теме