Что такое Tensorflow? Примеры применения. Установка

Те, кто активно занимаются машинным обучением и, особенно, нейронными сетями, наверняка слышали, а возможно, и применяли инструмент Tensorflow в своей практической деятельности. Это относительно новая разработка компании Google 2015-го года, которая приобрела огромную популярность:

https://www.tensorflow.org/

Так что же такое Tensorflow и что он делает? Если ответить кратко на этот вопрос, то он позволяет проводить вычисления посредством графа. Да, в математике существуют графы специального вида – графы вычислений, с помощью которых можно эффективно делать расчеты для заданных математических выражений. Чтобы было понятнее, о чем речь, представьте, что у нас есть функция вида:

и мы хотим посчитать ее значения при разных x, y. Один из способов сделать это как раз через граф вычислений:

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

Общая идея вычислительного графа – представить целевую функцию набором элементарных математических операций (сложение, вычитание, умножение, деление) и стандартного набора функций (sin, cos, exp, log, sqrt и т.д.). Существует теорема, доказывающая, что любую непрерывную функцию можно представить с заданной точностью набором таких математических действий, то есть, с помощью вычислительного графа.

Но какое все это имеет отношение к нейронным сетям? Самое прямое. Любую нейронную сеть можно представить в виде вычислительного графа. Предположим, мы создаем простую полносвязную трехслойную НС:

На входе каждого нейрона скрытого слоя будет формироваться сумма:

где ; ; . Затем, эта сумма пропускается через функции активации этих нейронов:

И то же самое выполняется для выходного нейрона:

,

где ; . И выходное значение:

Как вы уже догадались, все эти вычисления можно представить в виде следующего графа:

Вычисление производных с помощью графа

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

и рассмотрим идею расчета производных, которая положена в основу Tensorflow. Сразу отмечу, что мы будем искать численные значения производных, а не их аналитический вид. То есть, Tensorflow выполняет численное дифференцирование функций, используя для этого метод обратного вычисления производных (reverse mode differentiation):

https://en.wikipedia.org/wiki/Automatic_differentiation

Это значит, что вначале нам нужно значениям x, y присвоить некоторые значения, для которых и будут вычислять частные производные. Пусть, x = 2, y = -4. Пропускаем эти значения по графу и запоминаем результаты вычислений в каждом узле.

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

 

где

 

Фактически, это правило вычисления производной сложной функции, известное еще со школьной скамьи. Чтобы было понятнее, применяя его, получим следующие значения частных производных в аналитическом виде:

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

Так как функциональные узлы вычислительного графа составлены из элементарных функций, то Tensorflow «знает» аналитический вид их производных. И, в частности, «понимает», что . Само значение a = -2 у нас было вычислено при прямом проходе по графу с x = 2, y = -4. Значит,

Далее, по цепному правилу нам нужно вычислить частную производную

Она просто равна 1, поэтому . Аналогично сразу вычисляем и производную .

Следующим шагом нам нужно вычислить производную:

И, затем, на основе частных производных  вычислить их при x = 2, y = -4:

Складываем полученные величины и получаем частные производные функции по x и y:

Вот так, с помощью вычислительного графа, мы нашли значения производных функции  в точке x = 2, y = -4. Аналогичным образом находит значения производных и Tensorflow.

Примеры использования Tensorflow

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

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
 
import tensorflow as tf
 
x = tf.Variable([[2.0]])
y = tf.Variable([[-4.0]])
 
with tf.GradientTape() as tape:
  f = (x + y) ** 2 + 2 * x * y
 
df = tape.gradient(f, [x, y])
 
print(df[0], df[1], sep="\n")

Вначале мы импортируем пакет Tensorflow, затем, создаем две переменные x и y со значениями 2 и -4. С помощью функции GradientTape() сохраняем все промежуточные значения графа для последующего расчета производных. Данные сохраняются в объекте tape (лента). После этого, мы вызываем метод gradient() объекта tape и указываем функцию, а также аргументы, по которым будет производиться вычисление производных. В конце выводим вычисленные значения в консоль:

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

Как видите, имеем те же самые значения -12 и 0 для производных функции по x и y.

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

Реализация градиентного спуска

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

x = tf.Variable(-1.0)
y = lambda: x ** 2 - x
 
N = 100
opt = tf.optimizers.SGD(learning_rate=0.1)
for n in range(N):
  opt.minimize(y, [x])
 
print(x.numpy())

После N=100 итерации SGD получаем значение 0,49999 – очень близкое к оптимальному значению 0,5.

Как видите, Tensorflow можно использовать не только для НС, но и в других, самых разных задачах, где требуется вычислять производные, проводить по ним оптимизацию и находить соответствующие решения. Это универсальный инструмент, использующий графы вычислений, который мы можем применять по своему усмотрению в самых разных задачах.

Установка Tensorflow

В заключение этого занятия пару слов про установку Tensorflow версии 2 и выше. Первый важный момент. На момент записи этого видео Tensorflow 2.x работал с Python версий 3.7.x. Поэтому, если у вас одна из последних версий интерпретатора языка, то следует установить пониже – 3.7.x и переключиться на нее при работе с Tensorflow. После этого, сам пакет можно установить простой командой:

pip install tensorflow

По умолчанию этот пакет пытается использовать GPU для распараллеливания вычислений. Чтобы Tensorflow мог подключаться к графическому процессору, необходимо на компьютер установить дополнительное программное обеспечение:

CUDA Toolkit

доступное по адресу:

https://developer.nvidia.com/cuda-gpus

Но делать это не обязательно. Если GPU не используется, то Tensorflow все вычисления проводит на CPU – центральном процессоре компьютера. И чтобы он не выдавал при этом лишних предупреждений, в начале программ я записываю следующие две строчки:

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

Для проверки корректности установки можно прописать еще две таких строчки:

import tensorflow as tf
print(tf.__version__)

У меня на момент записи видео отображается версия 2.4.1. Более подробную информацию по установке Tensorflow можно посмотреть на официальном сайте:

https://www.tensorflow.org/install

Надеюсь, из этого занятия вам стало понятнее, что из себя в целом представляет пакет Tensorflow. На последующих занятиях мы с вами подробнее рассмотрим некоторые аспекты его работы, особенно те, которые применяются для построения и обучения НС.

Видео по теме