Подтвердить что ты не робот

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

В качестве примера игрушек я пытаюсь установить функцию 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()

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

введите описание изображения здесь

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

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

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

4b9b3361

Ответ 1

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

введите описание изображения здесь

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

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

Ответ 2

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).