2015-10-21 96 views
2

我有以下情形:高效的方式

  • 我的數據集>> GPU內存
  • 我minibatches < GPU內存......使得根據大小我最多可容納在記憶中10次同時仍然訓練沒問題。

我的數據集的大小意味着我不會再訪問數據點,所以我認爲沒有意義讓他們共享?或者在那裏?我在想,也許最多有10個size = mini-batch的共享初始化變量是有益的,這樣我就可以一次交換10個,而不是每次只交換一個。另外,是否可以並行預加載小批量?

回答

5

如果您沒有重新訪問數據點,那麼使用共享變量可能沒有任何價值。

下面的代碼可以修改並用於評估將數據導入特定計算的不同方法。

「輸入」方法是當您不需要重新訪問數據時可能最好的方法。只有您可以將整個數據集放入GPU內存中,「shared_all」方法可能會勝過其他所有內容。 「shared_batched」允許您評估是否按層次分批處理數據可能有所幫助。

在「shared_batched」方法中,數據集被分成許多宏批次,每個宏批次被分成許多微批次。一個共享變量用於保存單個宏批處理。該代碼評估當前宏批次中的所有微批次。一旦一個完整的宏批處理已經被處理,下一個宏批被加載到共享變量中,並且代碼再次在其中的微批中迭代。

一般而言,可能預計少量大容量內存傳輸的運行速度會比大容量較小傳輸量(每個傳輸的總傳輸量相同)快。但是這需要在可以確定的情況下進行測試(例如使用下面的代碼);因人而異。

使用「借用」參數也可能會對性能產生重大影響,但在使用之前請注意the implications

import math 
import timeit 
import numpy 
import theano 
import theano.tensor as tt 


def test_input(data, batch_size): 
    assert data.shape[0] % batch_size == 0 
    batch_count = data.shape[0]/batch_size 
    x = tt.tensor4() 
    f = theano.function([x], outputs=x.sum()) 
    total = 0. 
    start = timeit.default_timer() 
    for batch_index in xrange(batch_count): 
     total += f(data[batch_index * batch_size: (batch_index + 1) * batch_size]) 
    print 'IN\tNA\t%s\t%s\t%s\t%s' % (batch_size, batch_size, timeit.default_timer() - start, total) 


def test_shared_all(data, batch_size): 
    batch_count = data.shape[0]/batch_size 
    for borrow in (True, False): 
     start = timeit.default_timer() 
     all = theano.shared(data, borrow=borrow) 
     load_time = timeit.default_timer() - start 
     x = tt.tensor4() 
     i = tt.lscalar() 
     f = theano.function([i], outputs=x.sum(), givens={x: all[i * batch_size:(i + 1) * batch_size]}) 
     total = 0. 
     start = timeit.default_timer() 
     for batch_index in xrange(batch_count): 
      total += f(batch_index) 
     print 'SA\t%s\t%s\t%s\t%s\t%s' % (
      borrow, batch_size, batch_size, load_time + timeit.default_timer() - start, total) 


def test_shared_batched(data, macro_batch_size, micro_batch_size): 
    assert data.shape[0] % macro_batch_size == 0 
    assert macro_batch_size % micro_batch_size == 0 
    macro_batch_count = data.shape[0]/macro_batch_size 
    micro_batch_count = macro_batch_size/micro_batch_size 
    macro_batch = theano.shared(numpy.empty((macro_batch_size,) + data.shape[1:], dtype=theano.config.floatX), 
           borrow=True) 
    x = tt.tensor4() 
    i = tt.lscalar() 
    f = theano.function([i], outputs=x.sum(), givens={x: macro_batch[i * micro_batch_size:(i + 1) * micro_batch_size]}) 
    for borrow in (True, False): 
     total = 0. 
     start = timeit.default_timer() 
     for macro_batch_index in xrange(macro_batch_count): 
      macro_batch.set_value(
       data[macro_batch_index * macro_batch_size: (macro_batch_index + 1) * macro_batch_size], borrow=borrow) 
      for micro_batch_index in xrange(micro_batch_count): 
       total += f(micro_batch_index) 
     print 'SB\t%s\t%s\t%s\t%s\t%s' % (
      borrow, macro_batch_size, micro_batch_size, timeit.default_timer() - start, total) 


def main(): 
    numpy.random.seed(1) 

    shape = (20000, 3, 32, 32) 

    print 'Creating random data with shape', shape 
    data = numpy.random.standard_normal(size=shape).astype(theano.config.floatX) 

    print 'Running tests' 
    for macro_batch_size in (shape[0]/pow(10, i) for i in xrange(int(math.log(shape[0], 10)))): 
     test_shared_all(data, macro_batch_size) 
     test_input(data, macro_batch_size) 
     for micro_batch_size in (macro_batch_size/pow(10, i) for i in 
           xrange(int(math.log(macro_batch_size, 10)) + 1)): 
      test_shared_batched(data, macro_batch_size, micro_batch_size) 


main() 
+0

非常感謝你:) – Sumido