0

Ich muss verstehen, wie Sie Modelle in Google Cloud ML bereitstellen. Meine erste Aufgabe besteht darin, einen sehr einfachen Textklassifizierer für den Dienst bereitzustellen. Ich mache es in den folgenden Schritten (vielleicht weniger Schritte verkürzt werden könnte, wenn dem so ist, fühlen sich frei, mich wissen zu lassen):Bereitstellen des Keras-Modells in Google Cloud ML für die Bereitstellung von Prognosen

  1. das Modell definieren mit Keras und den Export in YAML
  2. Legen Sie bis YAML und Export als Tensorflow SavedModel
  3. hochladen Modell zu Google Cloud Storage
  4. Deploy Modell aus dem Speicher zu Google Cloud ML
  5. Stellen Sie die Upload-Modellversion als Standard auf den Modellen Website.
  6. Run-Modell mit einem Abtastwerteingang

ich schließlich Schritt 1-5 Arbeit gemacht habe, aber jetzt bekomme ich diesen seltsamen Fehler unten zu sehen, wenn das Modell läuft. Kann jemand helfen? Details zu den Schritten finden Sie unten. Hoffentlich kann es auch anderen helfen, die auf einem der vorherigen Schritte stecken geblieben sind. Mein Modell funktioniert lokal gut.

Ich habe gesehen Deploying Keras Models via Google Cloud ML und Export a basic Tensorflow model to Google Cloud ML, aber sie scheinen auf andere Schritte des Prozesses stecken.

Fehler

Prediction failed: Exception during model execution: AbortionError(code=StatusCode.INVALID_ARGUMENT, details="In[0] is not a matrix 
     [[Node: MatMul = MatMul[T=DT_FLOAT, _output_shapes=[[-1,64]], transpose_a=false, transpose_b=false, _device="/job:localhost/replica:0/task:0/cpu:0"](Mean, softmax_W/read)]]") 

Schritt 1

# import necessary classes from Keras.. 
model_input = Input(shape=(maxlen,), dtype='int32') 
embed = Embedding(input_dim=nb_tokens, 
        output_dim=256, 
        mask_zero=False, 
        input_length=maxlen, 
        name='embedding') 
x = embed(model_input) 
x = GlobalAveragePooling1D()(x) 
outputs = [Dense(nb_classes, activation='softmax', name='softmax')(x)] 
model = Model(input=[model_input], output=outputs, name="fasttext") 
# export to YAML.. 

Schritt 2

from __future__ import print_function 

import sys 
import os 

import tensorflow as tf 
from tensorflow.contrib.session_bundle import exporter 
import keras 
from keras import backend as K 
from keras.models import model_from_config, model_from_yaml 
from optparse import OptionParser 

EXPORT_VERSION = 1 # for us to keep track of different model versions (integer) 

def export_model(model_def, model_weights, export_path): 

    with tf.Session() as sess: 
     init_op = tf.global_variables_initializer() 
     sess.run(init_op) 

     K.set_learning_phase(0) # all new operations will be in test mode from now on 

     yaml_file = open(model_def, 'r') 
     yaml_string = yaml_file.read() 
     yaml_file.close() 

     model = model_from_yaml(yaml_string) 

     # force initialization 
     model.compile(loss='categorical_crossentropy', 
         optimizer='adam') 
     Wsave = model.get_weights() 
     model.set_weights(Wsave) 

     # weights are not loaded as I'm just testing, not really deploying 
     # model.load_weights(model_weights) 

     print(model.input) 
     print(model.output) 

     pred_node_names = output_node_names = 'Softmax:0' 
     num_output = 1 

     export_path_base = export_path 
     export_path = os.path.join(
      tf.compat.as_bytes(export_path_base), 
      tf.compat.as_bytes('initial')) 
     builder = tf.saved_model.builder.SavedModelBuilder(export_path) 

     # Build the signature_def_map. 
     x = model.input 
     y = model.output 

     values, indices = tf.nn.top_k(y, 5) 
     table = tf.contrib.lookup.index_to_string_table_from_tensor(tf.constant([str(i) for i in xrange(5)])) 
     prediction_classes = table.lookup(tf.to_int64(indices)) 

     classification_inputs = tf.saved_model.utils.build_tensor_info(model.input) 
     classification_outputs_classes = tf.saved_model.utils.build_tensor_info(prediction_classes) 
     classification_outputs_scores = tf.saved_model.utils.build_tensor_info(values) 
     classification_signature = (
     tf.saved_model.signature_def_utils.build_signature_def(inputs={tf.saved_model.signature_constants.CLASSIFY_INPUTS: classification_inputs}, 
      outputs={tf.saved_model.signature_constants.CLASSIFY_OUTPUT_CLASSES: classification_outputs_classes, tf.saved_model.signature_constants.CLASSIFY_OUTPUT_SCORES: classification_outputs_scores}, 
      method_name=tf.saved_model.signature_constants.CLASSIFY_METHOD_NAME)) 

     tensor_info_x = tf.saved_model.utils.build_tensor_info(x) 
     tensor_info_y = tf.saved_model.utils.build_tensor_info(y) 

     prediction_signature = (tf.saved_model.signature_def_utils.build_signature_def(
      inputs={'images': tensor_info_x}, 
      outputs={'scores': tensor_info_y}, 
      method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME)) 

     legacy_init_op = tf.group(tf.tables_initializer(), name='legacy_init_op') 
     builder.add_meta_graph_and_variables(
      sess, [tf.saved_model.tag_constants.SERVING], 
      signature_def_map={'predict_images': prediction_signature, 
       tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: classification_signature,}, 
      legacy_init_op=legacy_init_op) 

     builder.save() 
     print('Done exporting!') 

     raise SystemExit 

if __name__ == '__main__': 
    usage = "usage: %prog [options] arg" 
    parser = OptionParser(usage) 
    (options, args) = parser.parse_args() 

    if len(args) < 3: 
     raise ValueError("Too few arguments!") 

    model_def = args[0] 
    model_weights = args[1] 
    export_path = args[2] 
    export_model(model_def, model_weights, export_path) 

Schritt 3

gsutil cp -r fasttext_cloud/ gs://quiet-notch-xyz.appspot.com

Schritt 4

from __future__ import print_function 

from oauth2client.client import GoogleCredentials 
from googleapiclient import discovery 
from googleapiclient import errors 
import time 

projectID = 'projects/{}'.format('quiet-notch-xyz') 
modelName = 'fasttext' 
modelID = '{}/models/{}'.format(projectID, modelName) 
versionName = 'Initial' 
versionDescription = 'Initial release.' 
trainedModelLocation = 'gs://quiet-notch-xyz.appspot.com/fasttext/' 

credentials = GoogleCredentials.get_application_default() 
ml = discovery.build('ml', 'v1', credentials=credentials) 

# Create a dictionary with the fields from the request body. 
requestDict = {'name': modelName, 'description': 'Online predictions.'} 

# Create a request to call projects.models.create. 
request = ml.projects().models().create(parent=projectID, body=requestDict) 

# Make the call. 
try: 
    response = request.execute() 
except errors.HttpError as err: 
    # Something went wrong, print out some information. 
    print('There was an error creating the model.' + 
     ' Check the details:') 
    print(err._get_reason()) 

    # Clear the response for next time. 
    response = None 
    raise 


time.sleep(10) 

requestDict = {'name': versionName, 
       'description': versionDescription, 
       'deploymentUri': trainedModelLocation} 

# Create a request to call projects.models.versions.create 
request = ml.projects().models().versions().create(parent=modelID, 
       body=requestDict) 

# Make the call. 
try: 
    print("Creating model setup..", end=' ') 
    response = request.execute() 

    # Get the operation name. 
    operationID = response['name'] 
    print('Done.') 

except errors.HttpError as err: 
    # Something went wrong, print out some information. 
    print('There was an error creating the version.' + 
      ' Check the details:') 
    print(err._get_reason()) 
    raise 

done = False 
request = ml.projects().operations().get(name=operationID) 
print("Adding model from storage..", end=' ') 

while (not done): 
    response = None 

    # Wait for 10000 milliseconds. 
    time.sleep(10) 

    # Make the next call. 
    try: 
     response = request.execute() 

     # Check for finish. 
     done = True # response.get('done', False) 

    except errors.HttpError as err: 
     # Something went wrong, print out some information. 
     print('There was an error getting the operation.' + 
       'Check the details:') 
     print(err._get_reason()) 
     done = True 
     raise 

print("Done.") 

Schritt 5

Verwenden Website.

Schritt 6

def predict_json(instances, project='quiet-notch-xyz', model='fasttext', version=None): 
    """Send json data to a deployed model for prediction. 

    Args: 
     project (str): project where the Cloud ML Engine Model is deployed. 
     model (str): model name. 
     instances ([Mapping[str: Any]]): Keys should be the names of Tensors 
      your deployed model expects as inputs. Values should be datatypes 
      convertible to Tensors, or (potentially nested) lists of datatypes 
      convertible to tensors. 
     version: str, version of the model to target. 
    Returns: 
     Mapping[str: any]: dictionary of prediction results defined by the 
      model. 
    """ 
    # Create the ML Engine service object. 
    # To authenticate set the environment variable 
    # GOOGLE_APPLICATION_CREDENTIALS=<path_to_service_account_file> 
    service = googleapiclient.discovery.build('ml', 'v1') 
    name = 'projects/{}/models/{}'.format(project, model) 

    if version is not None: 
     name += '/versions/{}'.format(version) 

    response = service.projects().predict(
     name=name, 
     body={'instances': instances} 
    ).execute() 

    if 'error' in response: 
     raise RuntimeError(response['error']) 

    return response['predictions'] 

Dann Funktion mit Testeingang auszuführen: predict_json({'inputs':[[18, 87, 13, 589, 0]]})

+0

Möglicherweise gibt es mehr als ein Problem, aber lassen Sie uns hier beginnen: CloudML Engine unterstützt derzeit nur die Verwendung einer einzigen Signatur (die Standardsignatur). Mit Blick auf Ihren Code glaube ich, dass prediction_signature eher zum Erfolg führt, aber Sie haben dies nicht zur Standardunterschrift gemacht. Kannst du das versuchen? Da die Bereitstellung in der Cloud einige Zeit dauern kann, empfehle ich Folgendes, um lokal zu testen: 'gcloud ml-engine local vorherzusagen' – rhaertel80

+0

Okay, das scheint vernünftig. Ich muss zugeben, dass ich die Funktion 'builder.add_meta_graph_and_variables()' nicht verstanden habe. Wie kann ich die Standardunterschrift ändern? – pir

+1

Das wird unordentlich, also werde ich es als eine Antwort hinzufügen, die ich fortlaufend aktualisieren werde, bis wir das Problem (s) gelöst haben. Übrigens, ich habe den gespeicherten Modellprozess mit einer 'simple_save'-Funktion vereinfacht, die in' contrib' auftaucht und in TF 1.4 verfügbar sein sollte: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/ saved_model/python/saved_model/utils.py # L28 – rhaertel80

Antwort

1

nun die Verwendung von Keras auf CloudML Motor eine Probe demonstriert, einschließlich der Vorhersage. Sie können die Probe finden Sie hier:

https://github.com/GoogleCloudPlatform/cloudml-samples/tree/master/census/keras

Ich würde vorschlagen, um Ihren Code zu diesem Code zu vergleichen.

Einige weitere Vorschläge, die noch relevant sein: unterstützt

CloudML Motor zur Zeit nur eine einzige Signatur (die Standardsignatur) verwendet wird. Mit Blick auf Ihren Code glaube ich, dass prediction_signature eher zum Erfolg führt, aber Sie haben dies nicht zur Standardunterschrift gemacht. Ich schlage vor, die folgenden:

builder.add_meta_graph_and_variables(
      sess, [tf.saved_model.tag_constants.SERVING], 
      signature_def_map={tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: prediction_signature,}, 
      legacy_init_op=legacy_init_op) 

Wenn Sie den Dienst bereitstellen, dann würden Sie Vorhersage, wie so aufrufen:

predict_json({'images':[[18, 87, 13, 589, 0]]}) 

Wenn Sie lokal testen gcloud ml-engine local predict --json-instances die Eingangsdaten unter Verwendung ist etwas anders (Streichhölzer die des Chargenvorhersageservice). Jede Newline getrennte Zeile sieht wie folgt aus (eine Datei mit zwei Zeilen angezeigt):

{'images':[[18, 87, 13, 589, 0]]} 
{'images':[[21, 85, 13, 100, 1]]} 

ich eigentlich gar nicht genug wissen über die Form von model.x die Daten, um sicherzustellen, ist für Ihr Modell korrekt gesendet werden.

Zur Erläuterung kann es aufschlussreich sein, den Unterschied zwischen den Methoden Classification und Prediction in SavedModel zu betrachten. Ein Unterschied besteht darin, dass bei Verwendung von tensorflow_serving, das auf gRPC basiert und stark typisiert ist, Classification eine stark typisierte Signatur bereitstellt, die die meisten Klassifizierer verwenden können. Dann können Sie denselben Client für jeden Klassifikator wiederverwenden.

Das ist nicht sehr nützlich bei der Verwendung von JSON, da JSON nicht stark typisiert ist.

Ein weiterer Unterschied ist, dass, wenn tensorflow_serving Verwendung Prediction säulenbasierte Eingaben (eine Karte von Merkmalsnamen zu jedem Wert für diese Funktion in der gesamten Charge) übernimmt, während Classification akzeptiert Reihe basierte Eingaben (jeweils Eingabeinstanz/Beispiel ist eine Reihe).

CloudML abstrahiert das ein bisschen und erfordert immer zeilenbasierte Eingaben (eine Liste von Instanzen). Wir unterstützen zwar offiziell nur Prediction, aber Classification sollte auch funktionieren.

+0

Vielen Dank! Ich versuche das gerade jetzt. Können Sie etwas erklären, was der Unterschied zwischen der Vorhersagesignatur und der Klassifizierungssignatur ist? Ich habe es von einem Tensorflow Tutorial auf MNIST bekommen, wenn ich mich richtig erinnere. – pir

+1

hinzugefügt eine Erklärung. – rhaertel80

+0

Große Erklärung, danke. Ich habe gerade versucht, das Modell in der Cloud auszuführen (kann nicht lokal ausgeführt werden), nachdem ich es standardmäßig mit dieser neuen Signatur exportiert habe. Ich bekomme den gleichen Fehler. Irgendwelche Ideen? – pir

Verwandte Themen