Monday, January 8, 2018

How to convert a Keras model to a TensorFlow Estimator

Overview

TensorFlow has the the function of converting Keras model to TensorFlow Estimator. On this article, I checked how to use it.
About the TensorFlow Estimator. Please read the article below and official pages.


Anyway, Keras lets us write neural network model relatively easily. But sometimes we need a model following TensorFlow. On this kind of cases, we write the model by Keras at first and after that can convert it to TnsorFlow's one.



Convert-target


This time, I’ll convert the code shown in the article below.

Simple case of tf.keras

On this article, I rewrote the Keras code by tf.keras. From TensorFlow, we can use Keras by tf.keras. But I had never used this. So I checked and it was very simple and easy. On the article below, I made deep neural network for classification of iris data by Keras.


Roughly, the model is to classify the iris data. The model part is like below. As you can see, here, I'm using tf.keras.

from tensorflow.python import keras
from tensorflow.python.keras.models import Sequential
from tensorflow.python.keras.layers import Dense, Activation

# set model
model = Sequential()
model.add(Dense(8, input_dim=4))
model.add(Activation('relu'))
model.add(Dense(3, input_dim=8))
model.add(Activation('softmax'))
model.compile(optimizer='SGD', loss='categorical_crossentropy', metrics=['accuracy'])

Convert Keras model to TensorFlow Estimator


It needs just one line to convert Keras model to TensorFlow Estimator.

# convert keras to tensorflow estimator
estimator_model = keras.estimator.model_to_estimator(keras_model=model)

Bit confusing point for me was the setting of input data. I showed the code below. The Keras model was converted to TensorFlow Estimator. So about input, of course, it follows the way of that, meaning TensorFlow Estimator. Usually, for the input, we can use the function tf.estimator.inputs.numpy_input_fn(). But it takes dictionary as explaining variable’s input. When we use TensorFlow, we pass the data by placeholder, meaning this kind of behavior is intuitive and natural. On this case, about Keras model, I didn’t touch the input name. So I was bit confused about what I should set as the key of the dictionary for ‘x=’. The answer was simple. The model has the information of the input name and we can use that as it is like model.input_names[0].

# Define the training inputs
train_input_fn = tf.estimator.inputs.numpy_input_fn(
    x={model.input_names[0]: x_train.astype(np.float32)},
    y=y_train.astype(np.float32),
    num_epochs=None,
    shuffle=True)

estimator_model.train(input_fn=train_input_fn, steps=50)

Execute


The code below is to prepare iris data, make model by Keras, convert it to TensorFlow Estimator and train the model.

from sklearn import datasets
from sklearn.model_selection import train_test_split
import tensorflow as tf
from tensorflow.python import keras
from tensorflow.python.keras.models import Sequential
from tensorflow.python.keras.layers import Dense, Activation
from keras.utils import np_utils
import pandas as pd
import numpy as np

# prepare for data
iris = datasets.load_iris()

features = iris.data
targets = np_utils.to_categorical(iris.target)

# split data into train and test
x_train, x_test, y_train, y_test = train_test_split(features, targets, train_size=0.7)

# set model
model = Sequential()
model.add(Dense(8, input_dim=4))
model.add(Activation('relu'))
model.add(Dense(3, input_dim=8))
model.add(Activation('softmax'))
model.compile(optimizer='SGD', loss='categorical_crossentropy', metrics=['accuracy'])

# convert keras to tensorflow estimator
estimator_model = keras.estimator.model_to_estimator(keras_model=model)

# Define the training inputs
train_input_fn = tf.estimator.inputs.numpy_input_fn(
    x={model.input_names[0]: x_train.astype(np.float32)},
    y=y_train.astype(np.float32),
    num_epochs=None,
    shuffle=True)

estimator_model.train(input_fn=train_input_fn, steps=50)

By the same manner, we can evaluate the model.

# Define the test inputs
test_input_fn = tf.estimator.inputs.numpy_input_fn(
    x={model.input_names[0]: x_test.astype(np.float32)},
    y=y_test.astype(np.float32),
    num_epochs=1,
    shuffle=False)

# Evaluate by test data.
eva = estimator_model.evaluate(input_fn=test_input_fn)
print(eva)
{'loss': 0.82758605, 'accuracy': 0.77777779, 'global_step': 50}

If I don’t use tf.keras but keras?


Before, I used tf.keras. But frequently I use keras, not tf.keras. When I tried to use the convertor for keras model, I got the error.
The code is the following one. Only difference is the part of the importing of keras.
We may be able to use original keras as converting-target. But I didn’t check yet.

from sklearn import datasets
from sklearn.model_selection import train_test_split
import tensorflow as tf
from tensorflow.python import keras
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.utils import np_utils
import pandas as pd
import numpy as np

# prepare for data
iris = datasets.load_iris()

features = iris.data
targets = np_utils.to_categorical(iris.target)

# split data into train and test
x_train, x_test, y_train, y_test = train_test_split(features, targets, train_size=0.7)

# set model
model = Sequential()
model.add(Dense(8, input_dim=4))
model.add(Activation('relu'))
model.add(Dense(3, input_dim=8))
model.add(Activation('softmax'))
model.compile(optimizer='SGD', loss='categorical_crossentropy', metrics=['accuracy'])

# convert keras to tensorflow estimator
estimator_model = keras.estimator.model_to_estimator(keras_model=model)
ValueError: ('Expected `model` argument to be a `Model` instance, got ', <keras.models.Sequential object at 0x1144edda0>)