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

Почему Tensorflow 100x медленнее, чем connetjs в этом простом примере NN?

Я работаю с convnetjs в течение 1 года, и теперь я хочу перейти к более мощным и быстрым библиотекам. Я думал, что Tensorflow будет на порядок быстрее, чем JS-библиотека, поэтому я написал простую нейронную сеть для обеих библиотек и сделал несколько тестов. Это нейронная сеть 3-5-5-1, обученная одному примеру для определенного количества эпох с слоями SGD и RELU.

Код тензора:

import tensorflow as tf
import numpy
import time

NUM_CORES = 1  # Choose how many cores to use.
sess = tf.Session(config=tf.ConfigProto(inter_op_parallelism_threads=NUM_CORES, intra_op_parallelism_threads=NUM_CORES))

# Parameters
learning_rate = 0.001
training_epochs = 1000
batch_size = 1

# Network Parameters
n_input = 3 # Data input
n_hidden_1 = 5 # 1st layer num features
n_hidden_2 = 5 # 2nd layer num features
n_output = 1 # Data output

# tf Graph input
x = tf.placeholder("float", [None, n_input], "a")
y = tf.placeholder("float", [None, n_output], "b")

# Create model
def multilayer_perceptron(_X, _weights, _biases):
    layer_1 = tf.nn.relu(tf.add(tf.matmul(_X, _weights['h1']), _biases['b1'])) #Hidden layer with RELU activation
    layer_2 = tf.nn.relu(tf.add(tf.matmul(layer_1, _weights['h2']), _biases['b2'])) #Hidden layer with RELU activation
    return tf.matmul(layer_2, _weights['out']) + _biases['out']

# Store layers weight & bias
weights = {
    'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
    'h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
    'out': tf.Variable(tf.random_normal([n_hidden_2, n_output]))
}
biases = {
    'b1': tf.Variable(tf.random_normal([n_hidden_1])),
    'b2': tf.Variable(tf.random_normal([n_hidden_2])),
    'out': tf.Variable(tf.random_normal([n_output]))
}

# Construct model
pred = multilayer_perceptron(x, weights, biases)

# Define loss and optimizer
cost = tf.reduce_sum(tf.nn.l2_loss(pred-y)) / batch_size # L2 loss
optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(cost) # Adam Optimizer

# Initializing the variables
init = tf.initialize_all_variables()

# Launch the graph
sess.run(init)

# Training Data
train_X = numpy.asarray([[0.1,0.2,0.3]])
train_Y = numpy.asarray([[0.5]])

# Training cycle
start = time.clock()
for epoch in range(training_epochs):
    # Fit training using batch data
    sess.run(optimizer, feed_dict={x: train_X, y: train_Y})
end = time.clock()

print end - start #2.5 seconds -> 400 epochs per second 
print "Optimization Finished!"

Код JS:

<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Regression example convnetjs</title>
    <script src="http://cs.stanford.edu/people/karpathy/convnetjs/build/convnet.js"></script>
    <script src="http://cs.stanford.edu/people/karpathy/convnetjs/build/util.js"></script>
    <script>
        var layer_defs, net, trainer;
        function start() {
            layer_defs = [];
            layer_defs.push({ type: 'input', out_sx: 1, out_sy: 1, out_depth: 3 });
            layer_defs.push({ type: 'fc', num_neurons: 5, activation: 'relu' });
            layer_defs.push({ type: 'fc', num_neurons: 5, activation: 'relu' });
            layer_defs.push({ type: 'regression', num_neurons: 1 });
            net = new convnetjs.Net();
            net.makeLayers(layer_defs);
            trainer = new convnetjs.SGDTrainer(net, { learning_rate: 0.001, method: 'sgd', batch_size: 1, l2_decay: 0.001, l1_decay: 0.001 });

        var start = performance.now();
            for(var i = 0; i < 100000; i++) {
                var x = new convnetjs.Vol([0.1, 0.2, 0.3]);
                trainer.train(x, [0.5]);
            }
        var end = performance.now();
        console.log(end-start); //3 seconds -> 33333 epochs per second
        var predicted_values = net.forward(x);
            console.log(predicted_values.w[0]);
        }

    </script>
</head>
<body>
    <button onclick="start()">Start</button>
</body>
</html>

Результаты состоят в том, что convnetjs тренируется в течение 100 000 эпох за 3 секунды, тогда как Tensorflow тренируется на 1000 эпох за 2,5 секунды. Ожидается ли это?

4b9b3361

Ответ 1

Могло быть много причин:

  • Ввод данных настолько мал, что большую часть времени тратится на простое преобразование между python и ядром С++, а JS - всего лишь один язык.

  • В Tensorflow используется только одно ядро, в то время как JS может использовать более одного

  • библиотека JS способна создать высоко оптимизированную версию программы JIT.

Реальные преимущества Tensorflow придут, когда распределенная версия будет общедоступной. Тогда возможность запуска больших сетей на многих узлах будет более важна, чем скорость одного node.

Ответ 2

Как и сейчас (версия 0.6), не имеет значения, используете ли вы процессор или графический процессор для тензорного потока, тензорный поток будет медленным и на GPU.

Вот соответствующие тесты

Тензорный поток может быть медленнее, чем факел, connetjs и т.д. на CPU из-за:

  • Вы можете использовать неоптимизированный график вычислений.
  • TF не настолько зрелый, как факел, convnetjs и т.д. Он просто не так оптимизирован. Я надеюсь, что еще.
  • Согласно слухам, Google не заботится об оптимизации для одной машины. Готовьте, что

    3a) мы живем в возрасте кластера

    3b) вы можете купить 57-ядерный процессор за 195 $ (однако я не тестировал, работает ли TF с этим оборудованием

    3c) Здесь что говорит Google об их квантовом компьютере. В 100 миллионов раз быстрее, чем обычная система.

TensorFlow работает медленнее, чем кофе, факел и т.д. на GPU из-за:

  • TF (как для 0.6) не поддерживает полностью cuda 7.5.
  • TF (как для 0.6) не поддерживает cudnn v3 и cudnn v4.

    и это делает TF 0.6 на несколько порядков медленнее, чем его конкуренты, на "машинных компьютерах/любителях".

    Однако существует проблема для решения проблемы cuda 7.5 и cudnn v3. Тем не менее, он закрыт как дублированный еще один вопрос, который намного менее конкретный (IMHO). Последний вопрос, который все еще открыт, не обязывает поддерживать cuda 7.5 и cudnn v3/v4 (да, я пессимист).

Итак, мы можем только

  • Надеемся и дождитесь, пока Google решит эти проблемы (добавьте поддержку cuda 7.5 и cudnn v3/v4 и поддержите TF в курсе всех событий)
  • Заплатить. Поскольку TF является открытым исходным кодом. Или подождать кого-нибудь, чтобы внести свой вклад:)

У меня была та же путаница, что и автор этого вопроса. Надеюсь, мой ответ помог.

Ответ 3

Да, для крошечных моделей это ожидается.

Тензорный поток не оптимизирован для крошечных нейронных сетей с отдельными партиями, потому что ускорение этого режима - пустая трата времени. Эти модели не дорогие, поэтому нет смысла. Если бы вы сделали размер мини-камеры крупнее (возможно, 64 случая), а модель несколько больше (сотни скрытых единиц), я бы ожидал, что тензор будет намного быстрее по сравнению с другой библиотекой.

Представьте себе, что нейронная сеть наивно используется в python с использованием numpy. Для этой модели также была бы медленной реализация наивного numpy.

Ответ 4

Проблема может быть связана с функцией потери. Почему бы не попробовать это вместо?

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(pred, y))