Alteryx Promote Knowledge Base

Definitive answers from Promote experts.
Don't forget to submit your entry for the Excellence Awards by October 30! | Need more information about the program? Check out the blog here

Deploying a Keras/TensorFlow Model to Promote


Keras is an open-source neural 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 than just the immediate surrounding layers, and create more complex models, such as multi-output models or 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. 





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 representation will have a length of 784 input values. Each pixel in an image has a grey scale value ranging from 0 to 255.


# Import packages

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

# Import dataset
from keras.datasets import mnist

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

# plot the plot





Converting the images to 784 length vectors 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 the keras.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, 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 to an HDF5 format, which is a grid format. The model architecture can be saved using two different formats; JSON and YAML.


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:
# Serialize model to YAML
model_yaml = model.to_yaml()

with open("model.yaml", "w") as yaml_file:
# Serialize weights to HDF5


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:




It is important to include Tensorflow in this list, even though we never directly import it because 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:


├── 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.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:



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). 




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:





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.





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!