Теано - простой пример обучения
Theano весьма полезен при обучении нейронных сетей, где нам приходится многократно рассчитывать стоимость и градиенты для достижения оптимума. Для больших наборов данных это требует больших вычислительных ресурсов. Theano делает это эффективно благодаря своей внутренней оптимизации вычислительного графа, которую мы видели ранее.
Постановка задачи
Теперь мы узнаем, как использовать библиотеку Theano для обучения сети. Мы рассмотрим простой случай, когда мы начнем с набора классов из четырех объектов. Мы вычисляем сумму этих характеристик после применения определенного веса (важности) к каждой функции.
Цель обучения - изменить веса, присвоенные каждой функции, так, чтобы сумма достигла целевого значения 100.
sum = f1 * w1 + f2 * w2 + f3 * w3 + f4 * w4
где f1, f2, ... - значения характеристик и w1, w2, ... - веса.
Позвольте мне проанализировать пример, чтобы лучше понять постановку проблемы. Мы примем начальное значение 1.0 для каждой функции и примем, что w1 равно0.1, w2 равно 0.25, w3 равно 0.15, и w4 равно 0.3. Определенной логики в присвоении значений весов нет, это просто наша интуиция. Таким образом, начальная сумма выглядит следующим образом -
sum = 1.0 * 0.1 + 1.0 * 0.25 + 1.0 * 0.15 + 1.0 * 0.3
Что в сумме 0.8. Теперь мы продолжим изменять присвоение весов, чтобы эта сумма приближалась к 100. Текущее результирующее значение0.8 далеко от нашего желаемого целевого значения 100. В терминах машинного обучения мы определяем costкак разница между целевым значением минус текущее выходное значение, обычно возводимая в квадрат, чтобы увеличить ошибку. Мы уменьшаем эту стоимость на каждой итерации, вычисляя градиенты и обновляя наш вектор весов.
Посмотрим, как вся эта логика реализована в Theano.
Объявление переменных
Сначала мы объявляем наш входной вектор x следующим образом:
x = tensor.fvector('x')
где x - одномерный массив значений с плавающей запятой.
Определим скаляр target переменная, как указано ниже -
target = tensor.fscalar('target')
Далее мы создаем тензор весов W с начальными значениями, как обсуждалось выше -
W = theano.shared(numpy.asarray([0.1, 0.25, 0.15, 0.3]), 'W')
Определение выражения Theano
Теперь мы вычисляем результат, используя следующее выражение -
y = (x * W).sum()
Обратите внимание, что в приведенном выше заявлении x и W- векторы, а не простые скалярные переменные. Теперь мы вычисляем ошибку (стоимость) с помощью следующего выражения -
cost = tensor.sqr(target - y)
Стоимость - это разница между целевым значением и текущим выходом в квадрате.
Чтобы вычислить градиент, который говорит нам, как далеко мы находимся от цели, мы используем встроенный grad метод следующим образом -
gradients = tensor.grad(cost, [W])
Теперь мы обновляем weights вектор, взяв скорость обучения 0.1 следующим образом -
W_updated = W - (0.1 * gradients[0])
Затем нам нужно обновить наш вектор весов, используя указанные выше значения. Мы делаем это в следующем заявлении -
updates = [(W, W_updated)]
Определение / вызов функции Theano
Наконец, мы определяем function в Theano, чтобы вычислить сумму.
f = function([x, target], y, updates=updates)
Чтобы вызвать указанную выше функцию определенное количество раз, мы создаем for цикл следующим образом -
for i in range(10):
output = f([1.0, 1.0, 1.0, 1.0], 100.0)
Как было сказано ранее, входными данными функции является вектор, содержащий начальные значения для четырех функций - мы присваиваем значение 1.0к каждой функции без какой-либо конкретной причины. Вы можете назначить разные значения по вашему выбору и проверить, сходится ли функция в конечном итоге. Мы будем печатать значения вектора весов и соответствующий вывод на каждой итерации. Это показано в приведенном ниже коде -
print ("iteration: ", i)
print ("Modified Weights: ", W.get_value())
print ("Output: ", output)
Полный список программ
Полный список программ воспроизводится здесь для вашего быстрого ознакомления -
from theano import *
import numpy
x = tensor.fvector('x')
target = tensor.fscalar('target')
W = theano.shared(numpy.asarray([0.1, 0.25, 0.15, 0.3]), 'W')
print ("Weights: ", W.get_value())
y = (x * W).sum()
cost = tensor.sqr(target - y)
gradients = tensor.grad(cost, [W])
W_updated = W - (0.1 * gradients[0])
updates = [(W, W_updated)]
f = function([x, target], y, updates=updates)
for i in range(10):
output = f([1.0, 1.0, 1.0, 1.0], 100.0)
print ("iteration: ", i)
print ("Modified Weights: ", W.get_value())
print ("Output: ", output)
Когда вы запустите программу, вы увидите следующий вывод -
Weights: [0.1 0.25 0.15 0.3 ]
iteration: 0
Modified Weights: [19.94 20.09 19.99 20.14]
Output: 0.8
iteration: 1
Modified Weights: [23.908 24.058 23.958 24.108]
Output: 80.16000000000001
iteration: 2
Modified Weights: [24.7016 24.8516 24.7516 24.9016]
Output: 96.03200000000001
iteration: 3
Modified Weights: [24.86032 25.01032 24.91032 25.06032]
Output: 99.2064
iteration: 4
Modified Weights: [24.892064 25.042064 24.942064 25.092064]
Output: 99.84128
iteration: 5
Modified Weights: [24.8984128 25.0484128 24.9484128 25.0984128]
Output: 99.968256
iteration: 6
Modified Weights: [24.89968256 25.04968256 24.94968256 25.09968256]
Output: 99.9936512
iteration: 7
Modified Weights: [24.89993651 25.04993651 24.94993651 25.09993651]
Output: 99.99873024
iteration: 8
Modified Weights: [24.8999873 25.0499873 24.9499873 25.0999873]
Output: 99.99974604799999
iteration: 9
Modified Weights: [24.89999746 25.04999746 24.94999746 25.09999746]
Output: 99.99994920960002
Обратите внимание, что после четырех итераций на выходе будет 99.96 и после пяти итераций это 99.99, что близко к желаемой цели 100.0.
В зависимости от желаемой точности можно с уверенностью сделать вывод, что сеть обучается за 4–5 итераций. После завершения обучения найдите вектор весов, который после 5 итераций принимает следующие значения:
iteration: 5
Modified Weights: [24.8984128 25.0484128 24.9484128 25.0984128]
Теперь вы можете использовать эти значения в своей сети для развертывания модели.