2016-11-03 11 views
8

Google niedawno ogłosiła Clould ML, https://cloud.google.com/ml/ i jest bardzo przydatna. Jednak jednym ograniczeniem jest to, że wejście/wyjście z programu Tensorflow powinno obsługiwać gs: //.Wprowadzanie/zamykanie pliku opakowania Google Storage dla Cloud ML?

Jeśli używamy wszystkich tensorflow APIS do odczytu/zapisu plików, powinno być OK, ponieważ te API obsługują gs://.

Jednakże, jeśli używamy natywnego pliku IO API, takich jak open, to nie działa, ponieważ nie rozumieją gs://

na przykład:

with open(vocab_file, 'wb') as f: 
     cPickle.dump(self.words, f) 

Ten kod nie będzie działać w Google Cloud ML.

Jednak modyfikowanie wszystkich macierzystych interfejsów API IO do interfejsów API tensorflow lub API Google Python jest naprawdę uciążliwe. Czy istnieje prosty sposób na zrobienie tego? Wszelkie opakowania do obsługi systemów pamięci masowej Google, gs:// na macierzystym pliku IO?

Zgodnie z sugestią tutaj Pickled scipy sparse matrix as input data?, być może możemy użyć file_io.read_file_to_string('gs://...'), ale nadal wymaga to znacznej modyfikacji kodu.

Odpowiedz

4

Jednym z rozwiązań jest skopiowanie wszystkich danych na dysk lokalny podczas uruchamiania programu. Można to zrobić za pomocą gsutil wewnątrz skryptu Python, który pobiera biegać, coś takiego:

vocab_file = 'vocab.pickled' 
subprocess.check_call(['gsutil', '-m' , 'cp', '-r', 
         os.path.join('gs://path/to/', vocab_file), '/tmp']) 

with open(os.path.join('/tmp', vocab_file), 'wb') as f: 
    cPickle.dump(self.words, f) 

A jeśli masz wyjścia, można zapisać je na dysku lokalnym i gsutil rsync im. (Należy jednak pamiętać, aby obsługiwać ponowne uruchamianie poprawnie, ponieważ można umieścić na innej maszynie).

Innym rozwiązaniem jest małpa plastra open (Uwaga: niesprawdzone):

import __builtin__ 

# NB: not all modes are compatible; should handle more carefully. 
# Probably should be reported on 
# https://github.com/tensorflow/tensorflow/issues/4357 
def new_open(name, mode='r', buffering=-1): 
    return file_io.FileIO(name, mode) 

__builtin__.open = new_open 

prostu należy zrobić zanim moduł faktycznie próbuje odczytać z GCS.

1

apache_beam ma moduł gcsio, który może być użyty do zwrócenia standardowego obiektu plików Python do odczytu/zapisu obiektów GCS. Możesz użyć tego obiektu z dowolną metodą, która działa z obiektami plików Pythona. Na przykład

def open_local_or_gcs(path, mode): 
    """Opens the given path.""" 
    if path.startswith('gs://'): 
    try: 
     return gcsio.GcsIO().open(path, mode) 
    except Exception as e: # pylint: disable=broad-except 
     # Currently we retry exactly once, to work around flaky gcs calls. 
     logging.error('Retrying after exception reading gcs file: %s', e) 
     time.sleep(10) 
     return gcsio.GcsIO().open(path, mode) 
    else: 
    return open(path, mode) 

with open_local_or_gcs(vocab_file, 'wb') as f: 
    cPickle.dump(self.words, f) 
+0

Dzięki! To wygląda bardzo dobrze. Myślę, że Tensorflow file_io również może być rozwiązaniem. 'z file_io.FileIO (ścieżka_pliku, tryb =" w ") jako f'. Czy myślisz, że to też jest w porządku? Jeszcze nie w pełni testowałem. –

+2

Zinterpretowałem twoje pytanie jako chcące uniknąć zastąpienia wszystkich wywołań funkcji open() wyspecjalizowanymi funkcjami. Jeśli tak nie jest, to znaczy, że chcesz zastąpić wywołania funkcji open(), wtedy gcsio.open_local_or_gcs i file_io.FileIO są dość podobne, wpływają tylko na zależności, które wprowadzasz - file_io jest już częścią TF. Ale FileIO wykorzystuje niektóre niestandardowe tryby, co może wpłynąć na twoją decyzję. – rhaertel80

3

Czy to tak:

from tensorflow.python.lib.io import file_io 

with file_io.FileIO('gs://.....', mode='w+') as f: 
    cPickle.dump(self.words, f) 

Albo można przeczytać Marynata złożyć w ten sposób:

file_stream = file_io.FileIO(train_file, mode='r') 
x_train, y_train, x_test, y_test = pickle.load(file_stream)