25

Ho lavorato con convnetjs per 1 anno e ora voglio passare a librerie più potenti e veloci. Pensavo che Tensorflow sarebbe stato più veloce di una libreria JS, quindi ho scritto una semplice rete neurale per entrambe le librerie e fatto alcuni test. È una rete neurale 3-5-5-1, addestrata su un singolo esempio per un certo numero di epoche con strati SGD e RELU.Perché Tensorflow 100x è più lento di convnetjs in questo semplice esempio NN?

codice tensorflow:

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!" 

codice 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> 

I risultati sono che convnetjs treni per 100'000 epoche in 3 secondi, mentre tensorflow treni per 1000 epoche in 2,5 secondi. È previsto?

risposta

15

Ci potrebbero essere molte ragioni:

  • ingresso I dati è così piccola che la maggior parte del tempo viene speso solo conversione tra pitone e il nucleo C++, mentre il JS è solo un linguaggio.

  • Si utilizza solo core in tensorflow mentre il JS potrebbe potenzialmente sfruttare più

  • biblioteca JS è in grado di creare una versione JIT altamente ottimizzato del programma.

I veri vantaggi di Tensorflow arriveranno quando la versione distribuita sarà pubblica. Quindi la capacità di eseguire grandi reti su molti nodi sarà più importante della velocità di un singolo nodo.

+1

Penso anche che per ottenere il massimo da Tensorflow è necessario utilizzare molti nodi e possibilmente GPU; sfortunatamente, eseguo la maggior parte del mio codice su una singola CPU. Comunque, devo sottolineare che 1) convnetjs gira su un singolo core, non ha alcuna ottimizzazione per funzionare in parallelo (almeno da solo) 2) Ho provato ad usare 4 core in Tensorflow su una macchina quad-core, ma è più lento rispetto all'utilizzo di 1 core (ma ciò era previsto). – okh

+0

queste risposte sono bang on a mio parere. la tua rete è super minuscola e un core è sufficiente per eseguirlo più velocemente che mai. aggiungi l'overhead di TF e perderai. fai 10 strati con 100 unità ciascuno e poi vedrai dove splende. (usa gpu!) – user1269942

12

Per ora (versione 0.6), non importa se si utilizza CPU o GPU per tensorflow, anche tensorflow sarà lento su GPU.

Here are corresponding benchmarks

tensorflow può essere più lenta della torcia, convnetjs, ecc su CPU dovuto a:

  1. È possibile utilizzare il grafico non ottimizzato calcolo.
  2. TF non è così maturo come torcia, convnetjs, ecc. Semplicemente non è così ottimizzato. Spero ancora.
  3. Secondo voci a google non interessa l'ottimizzazione per una singola macchina. Bare in mente, che

    3a) viviamo nell'era gruppo

    3b) si can buy 57-core processor for 195$ (comunque non ho ancora testato se TF funziona con questo hardware

    3c) Ecco what google says about their quantum computer. 100 milioni di volte più veloce di un sistema convenzionale.

tensorflow è più lento di caffe, torcia, ecc su GPU causa di:

  1. TF (come per 0,6) non si completamente supporto CUDA 7.5.
  2. TF (come per 0.6) non supporta cudnn v3 e cudnn v4.

    e questo rende TF 0.6 più ordini più lento rispetto ai suoi concorrenti su "desktop di apprendimento automatico/amatori".

    Tuttavia, vi è an issue per indirizzo cuda 7.5 e cudnn v3. Tuttavia, è chiuso come duplicato con another issue, which is much less concrete (IMHO). Quest'ultimo problema, che è ancora aperto, non obbliga a supportare cuda 7.5 e cudnn v3/v4 (sì, sono un pessimista).

Quindi, possiamo solo sia

  1. Speranza e attendere che Google per risolvere questi problemi (aggiungere cuda 7.5 e cudnn v3/v4 sostegno e tenere TF fino ad oggi tutta la strada)
  2. Contribuire. Come TF è opensource. O aspettare qualcuno a contribuire :)

Ho avuto la stessa confusione di un autore di questa domanda. Spero che la mia risposta abbia aiutato.

+2

per favore nota che questa risposta è severamente superata, dato che ora siamo a 0.110 tensorflow e distribuito è stato rilasciato il coefficiente di tensione – Julius

+1

! per ora (versione master branch in ott, 6, 2016) tensorflow supporta già nvidia cuda 8 e cudnn v8! Ora il flusso di tensorflow potrebbe essere ancora più veloce! –

5

Sì, per i modelli piccoli questo è previsto.

Tensorflow non è ottimizzato per minuscole reti neurali con lotti di articoli singoli perché rendere il regime più veloce è una perdita di tempo. Quei modelli non sono costosi quindi non ha senso. Se avessi ingrandito la dimensione del minibatch (64 casi forse) e il modello fosse un po 'più grande (centinaia di unità nascoste), mi aspetterei che il carico di tensorflow sia molto più veloce rispetto all'altra libreria.

Immaginate di implementare la rete neurale in modo ingenuo in python usando numpy. Un'implementazione ingenua di numpy sarebbe anche lenta per questo modello.

0

Il problema potrebbe riguardare la funzione di perdita. Perché non provare questo invece?

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