TensorFlow в глубоком обучении

Основы TensorFlow. Переменные, функции, оптимизация выражений

Здравствуйте и вновь добро пожаловать на занятия по теме «Обработка данных: практическое глубокое обучение в Theano и TensorFlow».

В этой лекции мы рассмотрим библиотеку TensorFlow и разберёмся в её основах, как до этого разбирались с основами Theano. Мы познакомимся с основными переменными, функциями и выражениями и узнаем, как оптимизировать простейшие функции. При этом мы множество раз будем сравнивать их с аналогами из файла theano1.py, так что просмотрите его, если вы этого ещё не делали.

Итак, импортируем наши обычные библиотеки.

import numpy as np

import tensorflow as tf

Тут возникает маленькая проблемка, поскольку библиотека Numpy оказалась не последней версии. Когда я использовал pip, последняя версия была 1.8RC, а когда пользовался EasyUnstall, последней версией была 1.11. Поэтому, вероятно, вам следует воспользоваться EasyInstall, если у вас текущая версия Numpy не является последней.

Итак, установим новую версию и импортируем библиотеки ещё раз.

В библиотеке TensorFlow заполнители (placeholders) похожи на переменные Theano. Давайте создадим матрицу. Первое, что мы при этом должны указать, – это тип. Мы также можем указать её размерность, хотя это необязательно, и имя, хотя это также необязательно.

A = tf.placeholder(tf.float32, shape=(5, 5), name=’A’)

Мы также можем создать вектор, не указывая при этом размерность и имя:

v = tf.placeholder(tf.float32)

И мы можем произвести матричное умножение, аналогичное тому, которое мы делали в Theano, и, как мне кажется, функция matmul несколько удобнее, чем функция dot.

w = tf.matmul(A, v)

Так же, как и в Theano, нам необходимо указать значения переменных – пока что мы их ещё не указывали. В TensorFlow текущая работа идёт в так называемой сессии. Поэтому откроем сессию и запустим матричное умножение. Сессия использует параметр feed_dict, с помощью которой мы объясняем ей, что есть А и что есть v, при этом чтобы указать значения, можно использовать Numpy. Выведем сразу результат на экран, чтобы увидеть, что получилось.

with tf.Session() as session:

 output = session.run(w, feed_dict={A: np.random.randn(5, 5), v: np.random.randn(5, 1)})

 print(output, type(output))

В результате мы получаем массив Numpy.

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

Теперь возьмём переменную, значение которой будем обновлять с помощью градиентного спуска, и первым делом я покажу вам один пример. Мы можем создать переменную TensorFlow, используя функцию random_normal или с помощью массива Numpy, а также можем сделать нашу переменную скаляром.

shape = (2, 2)

x = tf.Variable(tf.random_normal(shape))

t = tf.Variable(0)

В TensorFlow переменные надо инициировать. Для этого можно использовать функцию initialize_all_variables. Она возвращает всё то, что будет вызвано далее в сессии.

init = tf.initialize_all_variables()

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

Мы также можем вывести на экран значения переменных TensorFlow, используя функцию eval, но только после её запуска.

with tf.Session() as session:

    session.run(init)

    print x.eval()

    print t.eval()

Теперь давайте попробуем найти минимум простенькой функции затрат, как мы делали это в Theano. Создадим переменную, присвоив ей значение 20, как это было в случае с Theano, и создадим такую же функцию затрат.

u = tf.Variable(20.0)

cost = u*u + u + 1

Между Theano и TensorFlow есть одно различие, заключающееся в том, что в TensorFlow мы не пишем сами обновление для переменной. Вместо этого мы выбираем оптимизатор, которых в TensorFlow есть целый ряд и который реализует желаемый вами алгоритм. Возьмём, к примеру, GradientDescentOptimizer, который реализует обычный градиентный спуск. 0,3 – это значение коэффициента обучения. Если вы хотите узнать больше о возможных параметрах, обратитесь к документации. После этого мы указываем выражение, значение которого хотим минимизировать.

train_op = tf.train.GradientDescentOptimizer(0.3).minimize(cost)

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

init = tf.initialize_all_variables()

with tf.Session() as session:

  session.run(init)

   for i in xrange(12):

   session.run(train_op)

print “i = %d, cost = %.3f, u = %.3f” % (i, cost.eval(), u.eval())

И в результате получаем ожидаемый результат.

Построение нейронной сети в TensorFlow

А теперь применим изученные прежде основы TensorFlow для построения нейронной сети. Если вы желаете лишь просмотреть код, а не писать его самостоятельно, перейдите по адресу и в папке ann_class2 найдите файл tensorflow2.py.

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

import numpy as np

import tensorflow as tf

import matplotlib.pyplot as plt

from util import get_normalized_data, y2indicator

Функцию error_rate мы также используем старую, из примера с библиотекой Theano.

def error_rate(p, t):

return np.mean(p != t)

Далее, как обычно, загружаем наши данные. Все параметры и гиперпараметры, вновь-таки, берём те же, что и в предыдущем примере с Theano, но в данном случае мы введём в нашу нейронную сеть ещё один скрытый слой с 100 узлов.

def main():

    X, Y = get_normalized_data()

    max_iter = 30

    print_period = 10

    lr = 0.00004

    reg = 0.01

    Xtrain = X[:-1000,]

    Ytrain = Y[:-1000]

    Xtest  = X[-1000:,]

    Ytest  = Y[-1000:]

    Ytrain_ind = y2indicator(Ytrain)

    Ytest_ind = y2indicator(Ytest)

    N, D = Xtrain.shape

    batch_sz = 500

    n_batches = N / batch_sz

    M1 = 300

    M2 = 100

    K = 10

    W1_init = np.random.randn(D, M1) / 28

    b1_init = np.zeros(M1)

    W2_init = np.random.randn(M1, M2) / np.sqrt(M1)

    b2_init = np.zeros(M2)

    W3_init = np.random.randn(M2, K) / np.sqrt(M2)

    b3_init = np.zeros(K)

Теперь, как и в случае с Theano, создадим переменные и выражения TensorFlow.

    X = tf.placeholder(tf.float32, shape=(None, D), name=’X’)

    T = tf.placeholder(tf.float32, shape=(None, K), name=’T’)

    W1 = tf.Variable(W1_init.astype(np.float32))

    b1 = tf.Variable(b1_init.astype(np.float32))

    W2 = tf.Variable(W2_init.astype(np.float32))

    b2 = tf.Variable(b2_init.astype(np.float32))

    W3 = tf.Variable(W3_init.astype(np.float32))

    b3 = tf.Variable(b3_init.astype(np.float32))

Теперь используем функции TensorFlow для определения модели. В качестве функции активации первого и второго скрытых слоёв используем функцию relu. Третью переменную назовём Yish, поскольку это не «настоящее» Y, а лишь матричное умножение Z2 и W3 плюс b3 без использования функции софтмакс, так как функция софтмакс по ряду причин включена в расчёт функции затрат.

Z1 = tf.nn.relu( tf.matmul(X, W1) + b1 )

Z2 = tf.nn.relu( tf.matmul(Z1, W2) + b2 )

Yish = tf.matmul(Z2, W3) + b3

Саму же функцию затрат мы можем записать с использованием несколько необычной функции softmax_cross_entropy_with logits и переменной Yish, а также целевой переменной.

  cost = tf.reduce_sum(tf.nn.softmax_cross_entropy_with_logits(Yish, T))

Теперь нам нужно написать выражения для функций train и predict – для расчёта коэффициента ошибок. В данном примере мы используем RMSPropOptimizer, тем более что RMSPropOptimizer включает в себя импульс.

train_op = tf.train.RMSPropOptimizer(lr, decay=0.99, momentum=0.9).minimize(cost)

predict_op = tf.argmax(Yish, 1)

Далее вам всё, вероятно, будет знакомо – мы инициируем наши переменные, открываем сессию и пишем обычный уже цикл. Заметьте, в Theano мы вызываем функцию, тогда как в TensorFlow мы вызываем сессию для запуска функции, а данные передаём через параметр feed_dict.

LL = []

init = tf.initialize_all_variables()

with tf.Session() as session:

session.run(init)

for i in xrange(max_iter):

for j in xrange(n_batches):

Xbatch = Xtrain[j*batch_sz:(j*batch_sz + batch_sz),]

Ybatch = Ytrain_ind[j*batch_sz:(j*batch_sz + batch_sz),]

session.run(train_op, feed_dict={X: Xbatch, T: Ybatch})

if j % print_period == 0:

test_cost = session.run(cost, feed_dict={X: Xtest, T: Ytest_ind})

prediction = session.run(predict_op, feed_dict={X: Xtest})

 err = error_rate(prediction, Ytest)

print(“Cost / err at iteration i=%d, j=%d: %.3f / %.3f” % (i, j, test_cost, err))

LL.append(test_cost)

Ну, и после всего этого выводим на экран наши данные.

plt.plot(LL)

plt.show()

if __name__ == ‘__main__’:

main()

Запустим нашу программу.

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

Андрей Никитенко
Андрей Никитенко
Задать вопрос эксперту
Понравилась статья? Поделить с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

Share via
Copy link