Рубрики
Без рубрики

Учебник по нейронной сети TensorFlow

Автор оригинала: Mihajlo Pavloski.

Учебник по нейронной сети TensorFlow

TensorFlow-это библиотека с открытым исходным кодом для приложений машинного обучения. Это система второго поколения Google Brain, после замены близкого источника Неверия, и используется Google как для исследовательских, так и для производственных приложений. Приложения TensorFlow могут быть написаны на нескольких языках: Python, Go, Java и C. Эта статья посвящена его версии Python и рассматривает установку библиотеки, базовые низкоуровневые компоненты и построение нейронной сети с нуля для выполнения обучения на реальном наборе данных.

Продолжительность обучения нейронных сетей глубокого обучения часто является узким местом в более сложных сценариях. Поскольку нейронные сети, а также другие алгоритмы ML в основном работают с матричными умножениями, их гораздо быстрее запускать на графических процессорах (GPU), а не на стандартных центральных процессорах (CPU).

TensorFlow поддерживает как процессоры, так и графические процессоры, и Google даже выпустила собственное специализированное оборудование для вычислений в облаке , называемое Tensor Processing Unit (TPU) , которое обеспечивает лучшую производительность среди различных процессоров.

Установка

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

В принципе, существует как минимум 5 различных вариантов установки с использованием: virtualenv, pip, Docker, Anaconda и установка из исходного кода.

  • Установка с помощью virtualenv и Docker позволяет нам установить TensorFlow в отдельной среде, изолированной от других ваших библиотек Python.
  • Anaconda-это дистрибутив Python, содержащий большой набор библиотек для научных вычислений, включая TensorFlow.
  • pip рассматривается как “родной” установщик для пакетов Python без использования каких-либо отдельных сред.
  • Наконец, установка из исходного кода проходит через Git и является лучшим способом выбора конкретной версии программного обеспечения, причем текущая стабильная версия TensorFlow-r1.4 (на момент написания этой статьи).

Самый распространенный и простой способ установки-через virtualenv и pip, поэтому они будут объяснены в этом посте.

Если вы какое-то время использовали Python, вы, вероятно, знаете pip. Вот как вы можете получить его на машине Ubuntu:

# Install pip
sudo apt-get install python-pip python-dev   # Python 2.7
sudo apt-get install python3-pip python3-dev # Python 3.x

Следующие строки объясняют установку TensorFlow на компьютере Ubuntu и Mac OSX:

# CPU support
pip install tensorflow      # Python 2.7
pip3 install tensorflow     # Python 3.x

# GPU support
pip install tensorflow-gpu  # Python 2.7
pip3 install tensorflow-gpu # Python 3.x

Вышеприведенные команды также будут работать на компьютере с Windows, но только для версий Python 3.5.x и 3.6.x.

Установка TensorFlow в отдельной среде может быть выполнена через virtualenv или conda (которая является частью Anaconda). Процесс в целом следует тем же линиям, что и выше, только на этот раз вам сначала нужно создать и активировать новую среду с помощью:

virtualenv --system-site-packages ~/tensorflow
source ~/tensorflow/bin/activate

Это позволит сохранить все необходимые пакеты отдельно от тех, которые вы установили глобально в своей системе.

Основные компоненты API

Существуют различные API-интерфейсы, доступные для программирования TensorFlow. Самый низкий уровень известен как Core и работает с основными компонентами: тензорами, графами и сеансами.

API более высокого уровня, такие как tf.estimator , созданы для упрощения рабочего процесса и автоматизации таких процессов, как управление наборами данных, обучение, оценка и т. Д. В любом случае, знание основных функций библиотеки жизненно важно для создания современных обучающих приложений.

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

Тензоры

Тензоры – это базовая структура данных в TensorFlow, которая хранит данные в любом количестве измерений, подобно многомерным массивам в NumPy. Существует три основных типа тензоров: константы, переменные и заполнители.

  • Константы являются неизменяемым типом тензоров. Их можно рассматривать как узлы без входных данных, выводящие единственное значение, которое они хранят внутри.
  • Переменные – это изменяемый тип тензоров, значение которых может изменяться во время выполнения графика. В приложениях ML переменные обычно хранят параметры, которые необходимо оптимизировать (например, веса между узлами в нейронной сети). Переменные должны быть инициализированы перед запуском графика явным вызовом специальной операции.
  • Заполнители – это тензоры, хранящие данные из внешних источников. Они представляют собой “обещание”, что значение будет предоставлено при запуске графика. В приложениях ML заполнители обычно используются для ввода данных в модель обучения.

Следующие несколько строк дают пример трех типов тензоров:

import tensorflow as tf

tf.reset_default_graph()

# Define a placeholder
a = tf.placeholder("float", name='pholdA')
print("a:", a)

# Define a variable 
b = tf.Variable(2.0, name='varB')
print("b:", b)

# Define a constant
c = tf.constant([1., 2., 3., 4.], name='consC')
print("c:", c)
a: Tensor("pholdA:0", dtype=float32)
b: 
c: Tensor("consC:0", shape=(4,), dtype=float32)

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

Графики

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

d = a * b + c
d
 dtype=float32>

Полученный результат снова является тензором с именем “add”, и наша модель теперь выглядит так, как показано на рисунке ниже. Вы можете исследовать свой график, а также другие параметры, используя встроенную функцию TensorFlow TensorBoard .

График тензорного потока

Рис. 1: График тензорного потока, состоящий из умножения и сложения.

Еще одним полезным инструментом для изучения вашего графика является следующий, который выводит все операции в нем.

# call the default graph
graph = tf.get_default_graph()

# print operations in the graph
for op in graph.get_operations():
    print(op.name)
pholdA
varB/initial_value
varB
varB/Assign
varB/read
consC
mul
add

Сессий

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

# Initialize variables
init = tf.global_variables_initializer()

# Run a session and calculate d
sess = tf.Session()
sess.run(init)
print(sess.run(d, feed_dict={a: [[0.5], [2], [3]]}))
sess.close()
[[  2.   3.   4.   5.]
 [  5.   6.   7.   8.]
 [  7.   8.   9.  10.]]

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

В следующем разделе мы будем использовать Core API для построения нейронной сети для машинного обучения на реальных данных.

Нейросетевая модель

В этой части мы строим нейронную сеть обратной связи с нуля, используя основные компоненты TensorFlow. Мы сравниваем три архитектуры нейронной сети, которые будут различаться по количеству узлов в одном скрытом слое.

Набор данных Iris

Мы используем простой Iris dataset , который состоит из 150 примеров растений, каждое из которых имеет свои 4 измерения (используемые в качестве входных признаков) и свой тип (выходное значение, которое должно быть предсказано). Растение может принадлежать к одному из трех возможных типов (setosa, virginica и versicolor). Давайте сначала загрузим данные с сайта Tensorflow – они разбиты на обучающие и тестовые подмножества по 120 и 30 примеров в каждом.

# Import the needed libraries
import numpy as np
import pandas as pd
import tensorflow as tf
import urllib.request as request
import matplotlib.pyplot as plt

# Download dataset
IRIS_TRAIN_URL = "http://download.tensorflow.org/data/iris_training.csv"
IRIS_TEST_URL = "http://download.tensorflow.org/data/iris_test.csv"

names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'species']
train = pd.read_csv(IRIS_TRAIN_URL, names=names, skiprows=1)
test = pd.read_csv(IRIS_TEST_URL, names=names, skiprows=1)

# Train and test input data
Xtrain = train.drop("species", axis=1)
Xtest = test.drop("species", axis=1)

# Encode target values into binary ('one-hot' style) representation
ytrain = pd.get_dummies(train.species)
ytest = pd.get_dummies(test.species)

Модель и обучение

Форма входного и выходного слоев нашей нейронной сети будет соответствовать форме данных, то есть входной слой будет содержать четыре нейрона, представляющих четыре входных объекта, в то время как выходной слой будет содержать три нейрона из-за трех битов, используемых для кодирования вида растения в стиле one-hot . Например, вид “setosa” может быть закодирован вектором [1, 0, 0], “virginica” – вектором [0, 1, 0] и т. Д.

Мы выбираем три значения числа нейронов в скрытом слое: 5, 10 и 20, в результате чего размеры сети составляют (4-5-3), (4-10-3) и (4-20-3). Это означает, что наша первая сеть, например, будет иметь 4 входных нейрона, 5 “скрытых” нейронов и 3 выходных нейрона.

Нейронная сеть

Рисунок 2: Наша трехслойная нейронная сеть обратной связи.

Приведенный ниже код определяет функцию, в которой мы создаем модель, определяем функцию потерь, которую необходимо минимизировать, и запускаем сеанс с 2000 итерациями, чтобы узнать оптимальные веса W_1 и W_2 . Как упоминалось ранее, входные и выходные матрицы подаются в тензоры tf.placeholder , а веса представляются в виде переменных, поскольку их значения изменяются на каждой итерации. Функция потерь определяется как среднеквадратичная ошибка между нашим прогнозом y_est и фактическим типом вида y , а функция активации, которую мы используем, – это сигмоид . Функция create_train_model возвращает изученные веса и выводит конечное значение функции потерь.

# Create and train a tensorflow model of a neural network
def create_train_model(hidden_nodes, num_iters):
    
    # Reset the graph
    tf.reset_default_graph()

    # Placeholders for input and output data
    X = tf.placeholder(shape=(120, 4), dtype=tf.float64, name='X')
    y = tf.placeholder(shape=(120, 3), dtype=tf.float64, name='y')

    # Variables for two group of weights between the three layers of the network
    W1 = tf.Variable(np.random.rand(4, hidden_nodes), dtype=tf.float64)
    W2 = tf.Variable(np.random.rand(hidden_nodes, 3), dtype=tf.float64)

    # Create the neural net graph
    A1 = tf.sigmoid(tf.matmul(X, W1))
    y_est = tf.sigmoid(tf.matmul(A1, W2))

    # Define a loss function
    deltas = tf.square(y_est - y)
    loss = tf.reduce_sum(deltas)

    # Define a train operation to minimize the loss
    optimizer = tf.train.GradientDescentOptimizer(0.005)
    train = optimizer.minimize(loss)

    # Initialize variables and run session
    init = tf.global_variables_initializer()
    sess = tf.Session()
    sess.run(init)

    # Go through num_iters iterations
    for i in range(num_iters):
        sess.run(train, feed_dict={X: Xtrain, y: ytrain})
        loss_plot[hidden_nodes].append(sess.run(loss, feed_dict={X: Xtrain.as_matrix(), y: ytrain.as_matrix()}))
        weights1 = sess.run(W1)
        weights2 = sess.run(W2)
        
    print("loss (hidden nodes: %d, iterations: %d): %.2f" % (hidden_nodes, num_iters, loss_plot[hidden_nodes][-1]))
    sess.close()
    return weights1, weights2

Хорошо, давайте создадим три сетевые архитектуры и построим функцию потерь по итерациям.

# Run the training for 3 different network architectures: (4-5-3) (4-10-3) (4-20-3)

# Plot the loss function over iterations
num_hidden_nodes = [5, 10, 20]
loss_plot = {5: [], 10: [], 20: []}
weights1 = {5: None, 10: None, 20: None}
weights2 = {5: None, 10: None, 20: None}
num_iters = 2000

plt.figure(figsize=(12,8))
for hidden_nodes in num_hidden_nodes:
    weights1[hidden_nodes], weights2[hidden_nodes] = create_train_model(hidden_nodes, num_iters)
    plt.plot(range(num_iters), loss_plot[hidden_nodes], label="nn: 4-%d-3" % hidden_nodes)
    
plt.xlabel('Iteration', fontsize=12)
plt.ylabel('Loss', fontsize=12)
plt.legend(fontsize=12)
loss (hidden nodes: 5, iterations: 2000): 31.82
loss (hidden nodes: 10, iterations: 2000): 5.90
loss (hidden nodes: 20, iterations: 2000): 5.61


Функция потерь во время тренировки

Рис. 3: Функция потерь за 2000 итераций для различных сетевых архитектур.

Мы видим, что сети с 20 скрытыми нейронами требуется больше времени, чтобы достичь минимума, что связано с ее более высокой сложностью. Сеть с 5 скрытыми нейронами застревает в локальном минимуме и не дает хороших результатов.

Во всяком случае, для такого простого набора данных, как Iris, даже небольшая сеть с 5 скрытыми нейронами должна быть в состоянии изучить хорошую модель. В нашем случае это было просто случайное событие, что модель застряла в локальном минимуме, и это не произойдет очень часто, если мы будем запускать код снова и снова.

Оценка модели

Наконец, давайте оценим наши модели. Мы используем изученные веса W_1 и W_2 и вперед распространяем примеры тестового набора. Метрика точности определяется как процент правильно предсказанных примеров.

# Evaluate models on the test set
X = tf.placeholder(shape=(30, 4), dtype=tf.float64, name='X')
y = tf.placeholder(shape=(30, 3), dtype=tf.float64, name='y')

for hidden_nodes in num_hidden_nodes:

    # Forward propagation
    W1 = tf.Variable(weights1[hidden_nodes])
    W2 = tf.Variable(weights2[hidden_nodes])
    A1 = tf.sigmoid(tf.matmul(X, W1))
    y_est = tf.sigmoid(tf.matmul(A1, W2))

    # Calculate the predicted outputs
    init = tf.global_variables_initializer()
    with tf.Session() as sess:
        sess.run(init)
        y_est_np = sess.run(y_est, feed_dict={X: Xtest, y: ytest})

    # Calculate the prediction accuracy
    correct = [estimate.argmax(axis=0) == target.argmax(axis=0) 
               for estimate, target in zip(y_est_np, ytest.as_matrix())]
    accuracy = 100 * sum(correct) / len(correct)
    print('Network architecture 4-%d-3, accuracy: %.2f%%' % (hidden_nodes, accuracy))
Network architecture 4-5-3, accuracy: 90.00%
Network architecture 4-10-3, accuracy: 96.67%
Network architecture 4-20-3, accuracy: 96.67%

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

Вы можете взглянуть на еще более простой пример использования высокоуровневого API Tensorflow здесь .

Ресурсы

Этот учебник охватывал лишь малую часть того, что может сделать TensorFlow. Вот несколько замечательных ресурсов, чтобы узнать больше о TensorFlow и глубоком обучении в целом:

Выводы

В этом посте мы представили библиотеку TensorFlow для машинного обучения, предоставили краткие руководства по установке, представили основные компоненты низкоуровневого Core API TensorFlow: Тензоры, графики и сеансы и, наконец, построили нейросетевую модель для классификации реальных данных набора данных Iris.

В общем, может потребоваться некоторое время, чтобы понять философию кодирования TensorFlow, поскольку это символическая библиотека, но как только вы познакомитесь с основными компонентами, это довольно удобно для создания приложений машинного обучения. В этом посте мы использовали низкоуровневый Core API для того, чтобы представить основные компоненты и иметь полный контроль над моделью, но обычно гораздо проще использовать API более высокого уровня, такой как tf.estimator , или даже внешнюю библиотеку, такую как Keras .