Alteryx Promote Knowledge Base

Definitive answers from Promote experts.

Deploying a Keras/TensorFlow Model to Promote

SydneyF
Alteryx Alumni (Retired)
Created

Keras is an open-sourceneural network API library, written in Python (but also available for R) and designed to run on top of TensorFlow, CNTK, or Theano. Keras is designed to be user-friendly,modular, and extensible, allowing for the rapid prototyping of neural network models. It is a great entry point to deep learning for beginners.

There are two types of Keras models; Sequential and Functional. A Sequential model is a linear stack of layers, meaning that the layers of your neural network connect only to the layers immediately before and after a given layer. A limitation of the sequential model is that it does not allow for models that share layers of have multiple inputs or outputs. The Functional API allows you to create models with greater flexibility as it allows you to define models where the layers connect to more thanjust the immediatesurrounding layers, and create more complex models, such as multi-output modelsor models with shared layers.

In this example, we will create a Sequential Model for the MNIST database, which comes as a part of the Keras library.

If you are not familiar with it, the MNIST (Modified National Institute of Standards and Technology) database is pretty much the Iris flower data set of the deep learning world. It is a database of 70,000 handwritten digit images (typically split into 60,000 training images and 10,000 validation examples), labeled with the digit they represent. These images have been normalized to fit a 28X28 pixel bounding box, and are represented with greyscale values.

MnistExamples.png

This dataset is popular in part because it allows for pattern recognition without complex pre-processing and formatting.The MNIST database that comes with the Keras library is structured as a 3-d array of value, image width, and image height. For our multi-layer perceptron model, this data structure needs to be modified to a simple vector of pixels. Because these images are 28x28 pixels, a vector representationwill have a length of 784 input values. Each pixel in an image has a grey scale value ranging from 0 to 255.

# Import packages

import
numpy as np
from keras.datasets import mnist #load in data set
from keras.models import Sequential
from keras.layers import Dense
from keras.utils import np_utils
import matplotlib.pyplot as plt

import os
from keras.models import model_from_json

# set a random seed
np.random.seed(64)

# Import dataset
from keras.datasets import mnist

# Create 4-square plot
plt.subplot(221)
plt.imshow(x_train[42], cmap=plt.get_cmap('gray'))
plt.subplot(222)
plt.imshow(x_train[64], cmap=plt.get_cmap('gray'))
plt.subplot(223)
plt.imshow(x_train[920], cmap=plt.get_cmap('gray'))
plt.subplot(224)
plt.imshow(x_train[10], cmap=plt.get_cmap('gray'))

# plot the plot
plt.show()

handwrittenDigets.png

Converting the images to 784 lengthvectors can easily be accomplished with the reshape function on NumPy array. We also need to hot-encode the output classifications (the label for the image), to_categorical() function from thekeras.utils package.

# Transform pixel data from 3D array to vector (len = 28*28 = 784)
pixels = x_train.shape[1] * x_train.shape[2]
x_train = x_train.reshape(x_train.shape[0], pixels).astype('float32')
x_test = x_test.reshape(x_test.shape[0], pixels).astype('float32')

# Rescale input values from 0-255 to 0-1
x_train = x_train/255
x_test = x_test/255

# Hot encode output classes
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
classes = y_test.shape[1]

Now that our data has been converted to an appropriate format, we can start building out our example Keras model.

# Define model
model = Sequential()

# Input Layer
model.add(Dense(pixels, input_dim=pixels, kernel_initializer='normal', activation="relu"))

# Output Layer
model.add(Dense(classes, kernel_initializer='normal', activation="softmax"))

# Compile Model
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

# Build Model
model.fit(x_train, y_train, epochs=5, batch_size=100)

Once the model is trained and built, we need to save it so it can be deployed to Promote.For Keras models, a model's architecture and weights are saved separately. Model weights are saved toanHDF5 format, which is a grid format.The model architecture can be saved using two different formats; JSON andYAML.

Please note that if you haven't already you may need to install the h5py python package for the model weights saved file.

The code to save Keras models in each format is as follows:

# Serialize model to JSON model_json = model.to_json()  with open("model.json", "w") as json_file:     json_file.write(model_json)
# Serialize model to YAML model_yaml = model.to_yaml()  with open("model.yaml", "w") as yaml_file:     yaml_file.write(model_yaml) 
# Serialize weights to HDF5 model.save_weights("model.h5")

Please see the article Save and Load Your Keras Deep Learning Models from Machine Learning Mastery for additional detail.

You can save the model as JSON or YAML, the format doesn't matter much. You will just need to adjust your Promote deployment code to match the model format. For this example, we will be using the JSON model for the model architecture. The output of this step should include two files: the model architecture in the flavor of your choice, and a HDF5 file containing the model weights.

Now that we have saved our Keras model, we can create a script to deploy the model to Promote.

To include our models in the Promote deployment, we should save them in a folder called objects in the same directory as our deployment Python script. We also need a requirements.txt file that lists our model dependencies. For this model, our file includes:

promote keras tensorflow
numpy

It is important to include Tensorflow in this list, even though we never directly import itbecause our Keras model is running on top of Tensorflow. If we do not include the Tensorflow package in our model's container, the model will fail because it will not have the "underlying engine" needed to run.

The folder structure with our deployment script looks like this:

Keras-model/ ├── deploytoPromote.py ├── requirements.txt └── objects     └── model.json
└── model.h5

Within our deploytoPromote script, first, we need to import the required packages and load in our model:

import promote
import numpy as np
from keras.models import model_from_json
from keras.datasets import mnist
import os

# Load JSON and create model json_file = open(os.path.abspath('./objects/model.json'), 'r') loaded_model_json = json_file.read() json_file.close() # Load weights loaded_model.load_weights(os.path.abspath('./objects/model.h5')) loaded_model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy'])

Then, write a function that creates the prediction:

def KerasModel(data):     r = loaded_model.predict(np.array([data]))     x = np.argsort(-r)     return {'response': str(x[0][0])} 

And then the actual deployment stuff, including a test:

USERNAME = 'USERNAME' API_KEY = 'YOURAPIKEYHERE' PROMOTE_URL = "http://promote.internal.alteryx.com/"  p = promote.Promote(USERNAME, API_KEY, PROMOTE_URL)  # Load data for testing
(x_train, y_train), (x_test, y_test) = mnist.load_data() x_test = x_test.reshape(x_test.shape[0], 784).astype('float32') x_test = x_test/255
# Select an individual test record, formatted as a list TESTDATA = x_test[42].tolist() # Deploy to Promote p.deploy("KerasModel", KerasModel, TESTDATA)

Running the script we just wrote will deploy the Keras (on top of Tensorflow) model to Promote. Notice in the Promote model logs, that TensorFlow is being used for the Keras model backend, and the MNIST data is being downloaded to the container (because we import it to use as a test data set).

2018-11-26_9-34-30.png

Once our model has built successfully and is up and running, can test our Promote model with some Python code lifted from Promote under the Samples tab in the model:

2018-11-26_9-48-20.png

In our test code, we need to bring in a test image, convert it to the format the model expects (784-length vector, normalized values 0-1) and then send these values as a list to be compatible with the Promote API call. We have already formatted our prediction function to convert the list to an np array.

2018-11-26_11-28-35.png

This model is ready to be integrated with an application used to detect hand-written digits! This model has been set up to expect a list input, where each value in the list corresponds to a pixel value in a 28X28 image. The list format is JSON safe, which is what allows the input values to be sent through the Promote API. The conversion from image to list could easily occur within your application.

This is a simplified example, but hopefully gives you the building blocks to deploy your own Keras model to Promote!