Wie im folgenden offiziellen Dokument gezeigt, wird bei der Durchführung der Vorhersage mit Charge eine verteilte Verarbeitung auf der Seite der ML-Engine durchgeführt, und die Reihenfolge der Eingabe und Ausgabe stimmt nicht überein. Sie müssen also einen sogenannten ** Instanzschlüssel ** verwenden, um die Ein- und Ausgänge eindeutig zu machen.
Mit anderen Worten, es ist notwendig, den Instanzschlüssel explizit als Eingabe zu schreiben, aber bei der Verarbeitung der Vorhersage muss er so implementiert werden, dass er zusammen mit dem vorhergesagten Wert ausgegeben wird, ohne etwas zu tun. Ich habe nicht sorgfältig geschrieben, wie man es in das offizielle Dokument umsetzt, und ich hatte nicht viel japanische Literatur, deshalb werde ich es in Qiita veröffentlichen, einschließlich eines Memorandums.
AI Platform verwendet verteilte Verarbeitung, um Stapelvorhersagejobs auszuführen. Das heißt, die Daten werden auf einen beliebigen Cluster virtueller Maschinen verteilt und in einer unvorhersehbaren Reihenfolge verarbeitet. Sie müssen einen Instanzschlüssel definiert haben, damit Sie die zurückgegebenen Vorhersagen mit der Eingabeinstanz abgleichen können. Der Instanzschlüssel ist ein Wert, den jede Instanz hat und der für eine Reihe von Dateninstanzen eindeutig ist. Der einfachste Schlüssel ist die Indexnummer.
https://cloud.google.com/ml-engine/docs/prediction-overview?hl=ja#instance_keys
Ich habe zwei Implementierungsmethoden ausprobiert.
Dieses Mal gehen wir davon aus, dass die Bewertung aus userId und movieId unter Verwendung des MovieLens-Datasets (Bewertung.csv) vorhergesagt wird. Verwenden Sie für den Indexschlüssel die Indexnummer der Daten, wie im offiziellen Dokument beschrieben.
userId | movieId | rating | key |
---|---|---|---|
1 | 1 | 1.5 | 1 |
1 | 2 | 2.5 | 2 |
2 | 1 | 3.5 | 3 |
2 | 2 | 4.5 | 4 |
Erstens [forward_features function] Schauen Sie sich die Beschreibung an (https://github.com/tensorflow/tensorflow/blob/r1.8/tensorflow/contrib/estimator/python/estimator/extenders.py#L143). Ich schreibe über Batch Prediction. (Wie eingangs erwähnt, gibt es auch eine Erklärung, dass die Ausgabereihenfolge nicht garantiert ist, sodass eine erneute Verbindung mit der Eingabetaste erforderlich ist.)
def forward_features(estimator, keys=None):
"""Forward features to predictions dictionary.
In some cases, user wants to see some of the features in estimators prediction
output. As an example, consider a batch prediction service: The service simply
runs inference on the users graph and returns the results. Keys are essential
because there is no order guarantee on the outputs so they need to be rejoined
to the inputs via keys or transclusion of the inputs in the outputs.
Das Modell, das ich dieses Mal geschrieben habe, ist ein einfaches Modell wie folgt. Wie Sie der Abbildung entnehmen können, ist der Instanzschlüssel der Eingabeebene des Modells mit keinem Knoten verbunden. Bei der Implementierung von forward_features wird jedoch der Instanzschlüssel in die Ausgabe des Schätzers aufgenommen, sodass ich denke, dass er dort verbunden wird. (Wahrscheinlich hier) Bei der Implementierung des Modells ist es nicht besonders schwierig, nur den Schlüssel explizit zu schreiben.
MAX_MOVIES=100000
MAX_USERS=100000
DIM_EMBEDDING=10
def get_model():
key = tf.keras.layers.Input(shape=(), name='key', dtype='int32')
w_inputs = tf.keras.layers.Input(shape=(1,), dtype='int32', name='movieId')
w = tf.keras.layers.Embedding(MAX_MOVIES, DIM_EMBEDDING, name='movie')(w_inputs)
u_inputs = tf.keras.layers.Input(shape=(1,), dtype='int32', name='userId')
u = tf.keras.layers.Embedding(MAX_USERS, DIM_EMBEDDING, name='user')(u_inputs)
o = tf.keras.layers.Multiply()([w, u])
o = tf.keras.layers.Dropout(rate=0.5)(o)
o = tf.keras.layers.Flatten()(o)
o = tf.keras.layers.Dense(10, activation='relu')(o)
o = tf.keras.layers.Dense(1, name='predictions')(o)
model = tf.keras.Model(inputs=[w_inputs, u_inputs, key], outputs=o)
model.summary()
return model
Die Funktion "forward_features" wird in der Hauptfunktion ("train_and_evaluate") verwendet, die das Modell kompiliert / einen Schätzer aus dem Modell erstellt.
def train_and_evaluate(outdir, train_step):
tf.logging.set_verbosity(v=tf.logging.INFO)
model = get_model()
model.compile(optimizer='adam', loss="mae", metrics=["mae"])
estimator = tf.keras.estimator.model_to_estimator(keras_model = model,
model_dir = outdir,
config = tf.estimator.RunConfig(save_checkpoints_secs=100))
train_spec = tf.estimator.TrainSpec(input_fn=lambda: read_dataset(filename='train.csv',
mode=tf.estimator.ModeKeys.TRAIN),
max_steps=train_step)
exporter = tf.estimator.LatestExporter(name='exporter',
serving_input_receiver_fn=serving_input_fn)
#Forward Estimator hier_Eingehüllt in Funktionen
estimator = tf.contrib.estimator.forward_features(estimator, 'key')
eval_spec = tf.estimator.EvalSpec(input_fn=lambda: read_dataset(filename='test.csv',
mode=tf.estimator.ModeKeys.EVAL),
exporters=exporter,
steps=None,
throttle_secs=15)
tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)
Der vorhergesagte Wert ist seltsam, weil ich im Training nicht viele Daten eingegeben habe. Sie können sehen, dass der Instanzschlüssel so zurückgegeben wird, wie er mit dem vorhergesagten Wert ist.
Es gibt eine Beschreibung in dieser Ausgabe, aber im Tensorflow 2-System ist der Contrib.estimator, zu dem forward_features gehört, in der Ausgabe veraltet Möglicherweise müssen Sie Ihre eigene Funktion feature_forward wie beschrieben definieren.
Wie in der folgenden Abbildung gezeigt, ist der Wert, der von der letzten Dichte ausgegeben wird, der vorhergesagte Wert, aber der Instanzschlüssel ist unverändert und wird als endgültige Ausgabe verwendet. Da der Instanzschlüssel als Skalarwert eingeht, wird er auch umgeformt, um ihn zu formen. Auf diese Weise ist es möglich, den Instanzschlüssel ohne Verarbeitung auszugeben.
MAX_MOVIES=100000
MAX_USERS=100000
DIM_EMBEDDING=10
def get_model():
key_raw = tf.keras.layers.Input(shape=(), name='key', dtype='int32')
key = tf.keras.layers.Reshape((1,), input_shape=(), dtype='int32')(key_raw)
w_inputs = tf.keras.layers.Input(shape=(1,), dtype='int32', name='movieId')
w = tf.keras.layers.Embedding(MAX_MOVIES, DIM_EMBEDDING, name='movie')(w_inputs)
u_inputs = tf.keras.layers.Input(shape=(1,), dtype='int32', name='userId')
u = tf.keras.layers.Embedding(MAX_USERS, DIM_EMBEDDING, name='user')(u_inputs)
o = tf.keras.layers.Multiply()([w, u])
o = tf.keras.layers.Dropout(rate=0.5)(o)
o = tf.keras.layers.Flatten()(o)
o = tf.keras.layers.Dense(10, activation='relu')(o)
o = tf.keras.layers.Dense(1, name='predictions')(o)
#Hier konzentrieren wir uns auf die Vorhersage und den Instanzschlüssel
#Da der Instanzschlüssel vom Typ int ist, lasse ich ihn zwangsweise schweben, um dem Typ zu entsprechen
pred = tf.keras.layers.Concatenate()([o, tf.cast(key, tf.float32)])
model = tf.keras.Model(inputs=[w_inputs, u_inputs, key_raw], outputs=pred)
model.summary()
return model
Bei dieser Methode müssen Sie jedoch eine benutzerdefinierte Verlustfunktion schreiben, da der Instanzschlüssel bei der Berechnung des Verlusts berücksichtigt wird. Ich denke nicht, dass es so schwierig ist, weil Sie nur den Wert der Vorhersage in der Funktion wie unten gezeigt erhalten müssen.
def my_rmse(y_true, y_pred):
return tf.keras.backend.sqrt(tf.keras.backend.mean(
tf.keras.backend.square(y_pred[1][0] - y_true))) # y_pred[1][0]Um nur Vorhersage mit zu bekommen
In Bezug auf andere Implementierungen wurden keine weiteren Änderungen vorgenommen. Wenn Sie die Vorhersage wie unten gezeigt versuchen, wird sie wie folgt ausgegeben.
Ich habe diesmal zwei Methoden ausprobiert, aber der Unterschied besteht darin, dass es fast keinen Unterschied im Verarbeitungsinhalt gibt, je nachdem, ob Sie die auf der Tensorflow-Seite vorbereitete Funktion (forward_features) verwenden oder die Diagrammstruktur selbst schreiben. Ich werde. (Ersteres wird natürlich empfohlen) Ich hatte nicht viel japanische Literatur über Batch Prediction auf ML Engine, also hoffe ich, dass es denen hilft, die Probleme mit der gleichen Sache haben.
Recommended Posts