Почему эта реализация TensorFlow значительно менее успешна, чем NN Matlab?

29

В качестве примера игрушек я пытаюсь установить функцию f(x) = 1/x из 100 точек без шума. Реализация по умолчанию Matlab феноменально успешна со средней квадратичной разностью ~ 10 ^ -10 и идеально интерполируется.

Я реализую нейронную сеть с одним скрытым слоем из 10 сигмовидных нейронов. Я новичок в нейронных сетях, так что будьте осторожны с немым кодом.

import tensorflow as tf
import numpy as np

def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

#Can't make tensorflow consume ordinary lists unless they're parsed to ndarray
def toNd(lst):
    lgt = len(lst)
    x = np.zeros((1, lgt), dtype='float32')
    for i in range(0, lgt):
        x[0,i] = lst[i]
    return x

xBasic = np.linspace(0.2, 0.8, 101)
xTrain = toNd(xBasic)
yTrain = toNd(map(lambda x: 1/x, xBasic))

x = tf.placeholder("float", [1,None])
hiddenDim = 10

b = bias_variable([hiddenDim,1])
W = weight_variable([hiddenDim, 1])

b2 = bias_variable([1])
W2 = weight_variable([1, hiddenDim])

hidden = tf.nn.sigmoid(tf.matmul(W, x) + b)
y = tf.matmul(W2, hidden) + b2

# Minimize the squared errors.
loss = tf.reduce_mean(tf.square(y - yTrain))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)

# For initializing the variables.
init = tf.initialize_all_variables()

# Launch the graph
sess = tf.Session()
sess.run(init)

for step in xrange(0, 4001):
    train.run({x: xTrain}, sess)
    if step % 500 == 0:
        print loss.eval({x: xTrain}, sess)

Средняя квадратная разница заканчивается на ~ 2 * 10 ^ -3, что примерно на 7 порядков хуже, чем у Matlab. Визуализация с помощью

xTest = np.linspace(0.2, 0.8, 1001)
yTest = y.eval({x:toNd(xTest)}, sess)  
import matplotlib.pyplot as plt
plt.plot(xTest,yTest.transpose().tolist())
plt.plot(xTest,map(lambda x: 1/x, xTest))
plt.show()

мы видим, что посадка систематически несовершенна: Изображение 560 в то время как матрица выглядит идеально для невооруженного глаза с равномерными различиями, 10 ^ -5: Изображение 561 Я попытался реплицировать с помощью TensorFlow диаграмму сети Matlab:

Изображение 562

Кстати, диаграмма, по-видимому, подразумевает функцию активации tanh, а не сигмоида. Я не могу найти его где-нибудь в документации, чтобы быть уверенным. Однако, когда я пытаюсь использовать tanh neuron в TensorFlow, установка быстро терпит неудачу с nan для переменных. Я не знаю, почему.

Matlab использует алгоритм обучения Левенберга-Марквардта. Байесовская регуляризация еще более успешна со средними квадратами при 10 ^ -12 (мы, вероятно, находимся в области паров арифметики с плавающей точкой).

Почему реализация TensorFlow намного хуже, и что я могу сделать, чтобы сделать ее лучше?

  • 0
    Я еще не изучал тензорный поток, так что извините за это, но вы делаете некоторые странные вещи с numpy с помощью этой функции toNd . np.linspace уже возвращает ndarray, а не список, если вы хотите преобразовать список в ndarray, все, что вам нужно сделать, это np.array(my_list) , и если вам просто нужна дополнительная ось, вы можете сделать new_array = my_array[np.newaxis, :] . Это может быть просто остановка нуля ошибки, потому что это должно сделать это. В большинстве данных присутствует шум, и вы не обязательно хотите, чтобы на них была нулевая ошибка обучения. Судя по «redu_mean», это может быть перекрестная проверка.
  • 0
    @AdamAcosta toNd определенно является пробелом из-за отсутствия у меня опыта. Я пробовал np.array раньше, и проблема, похоже, заключается в том, что np.array([5,7]).shape имеет вид (2,) а не (2,1) . my_array[np.newaxis, :] кажется, исправляет это, спасибо! Я не использую Python, а скорее F # изо дня в день.
Показать ещё 2 комментария
Теги:
tensorflow
neural-network

2 ответа

24
Лучший ответ

Я пробовал тренироваться за 50000 итераций, которые он получил до ошибки 0.00012. Это займет около 180 секунд на Tesla K40.

Изображение 6407

Кажется, что для такого рода проблем спуск градиента первого порядка не подходит (каламбур), и вам нужны Levenberg-Marquardt или l-BFGS. Я не думаю, что кто-то их реализовал в TensorFlow.

Edit Используйте tf.train.AdamOptimizer(0.1) для этой проблемы. Он достигает 3.13729e-05 после 4000 итераций. Кроме того, GPU со стратегией по умолчанию также кажется плохой идеей для этой проблемы. Существует много небольших операций, и накладные расходы приводят к тому, что версия графического процессора работает на 3 раза медленнее, чем процессор на моей машине.

  • 0
    Спасибо за проверку. Ты имеешь в виду 5000 моих циклов, а значит, 20 миллионов тренировок? Можете ли вы подтвердить, что он не работает при смене скрытого слоя на tanh нейроны, и если да, знаете ли вы, почему это происходит?
  • 1
    Я только что изменил ваш xrange (4001) на xrange (5000). Для tanh, похоже, что тренировка расходится со скоростью обучения 0,5. В общем, для градиентного спуска вам нужно настроить скорость обучения для каждой проблемы, кажется, она работает, если я сделаю tf.train.GradientDescentOptimizer (0.1)
Показать ещё 6 комментариев
16

btw, здесь немного очищенная версия выше, которая очищает некоторые проблемы с формой и ненужное подпрыгивание между tf и np. Он достигает 3e-08 после 40k шагов или около 1,5e-5 после 4000:

import tensorflow as tf
import numpy as np

def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

xTrain = np.linspace(0.2, 0.8, 101).reshape([1, -1])
yTrain = (1/xTrain)

x = tf.placeholder(tf.float32, [1,None])
hiddenDim = 10

b = bias_variable([hiddenDim,1])
W = weight_variable([hiddenDim, 1])

b2 = bias_variable([1])
W2 = weight_variable([1, hiddenDim])

hidden = tf.nn.sigmoid(tf.matmul(W, x) + b)
y = tf.matmul(W2, hidden) + b2

# Minimize the squared errors.                                                                
loss = tf.reduce_mean(tf.square(y - yTrain))
step = tf.Variable(0, trainable=False)
rate = tf.train.exponential_decay(0.15, step, 1, 0.9999)
optimizer = tf.train.AdamOptimizer(rate)
train = optimizer.minimize(loss, global_step=step)
init = tf.initialize_all_variables()

# Launch the graph                                                                            
sess = tf.Session()
sess.run(init)

for step in xrange(0, 40001):
    train.run({x: xTrain}, sess)
    if step % 500 == 0:
        print loss.eval({x: xTrain}, sess)

Все, что было сказано, вероятно, не слишком удивительно, что LMA работает лучше, чем более общий оптимизатор DNN-стиля для установки 2D-кривой. Адам и остальные нацелены на очень большие проблемы размерности, а LMA начинает медленно лежать на очень больших сетях (см. 12-15).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню