Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load Keras model with AWS Lambda

I am trying to deploy a NN model that I trained locally on my machine using Keras. I use my model (locally) as:

from keras.models import load_model
model = load_model("/path/to/model/model.h5")
prediction = model.predict(x)

Now, I need to use the same model on my lambda function. I uploaded the model in an s3 bucket. I then tried to access the file as:

model = load_model("https://s3-eu-west-1.amazonaws.com/my-bucket/models/model.h5")

But it tells me that the file does not exist. I guess it's a privilege problem. I also tried as (similar to how I read JSON files from s3):

client_s3 = boto3.client("s3")
result = client_s3.get_object(Bucket="my-bucket", Key='models/model.h5')
model = load_model(result["Body"].read())

But I obtain this error:

"stackTrace": [
[
  "/var/task/lambda_function.py",
  322,
  "lambda_handler",
  "model = load_model(result[\"Body\"].read())"
],
[
  "/var/task/keras/models.py",
  227,
  "load_model",
  "with h5py.File(filepath, mode='r') as f:"
],
[
  "/var/task/h5py/_hl/files.py",
  269,
  "__init__",
  "fid = make_fid(name, mode, userblock_size, fapl, swmr=swmr)"
],
[
  "/var/task/h5py/_hl/files.py",
  99,
  "make_fid",
  "fid = h5f.open(name, flags, fapl=fapl)"
],
[
  "h5py/_objects.pyx",
  54,
  "h5py._objects.with_phil.wrapper",
  null
],
[
  "h5py/_objects.pyx",
  55,
  "h5py._objects.with_phil.wrapper",
  null
],
[
  "h5py/h5f.pyx",
  78,
  "h5py.h5f.open",
  null
],
[
  "h5py/defs.pyx",
  621,
  "h5py.defs.H5Fopen",
  null
],
[
  "h5py/_errors.pyx",
  123,
  "h5py._errors.set_exception",
  null
]
],
"errorType": "UnicodeDecodeError",
"errorMessage": "'utf8' codec can't decode byte 0x89 in position 29: invalid start byte"
}

I suspect the result["Body"].read() function cannot be used with h5py object. What is the best way to load a h5py model from s3?

SOLUTION: The solution is to download the file into the /tmp/ folder:

result = client_s3.download_file("my-bucket",'model.h5', "/tmp/model.h5")
model = load_model("/tmp/day/model.h5")
like image 495
Titus Pullo Avatar asked Dec 16 '17 16:12

Titus Pullo


2 Answers

The problem

boto3.client("s3")..get_object(...)["Body"].read() returns a bytestring, but keras.models.load_model expects a filepath (source).

The solution

Store the file somewhere. tempfile might come in handy.

like image 62
Martin Thoma Avatar answered Oct 09 '22 02:10

Martin Thoma


Following links posted by @Raji, I discovered keras has recently implemented functionality to load model files and/or weights files from google cloud storage.

First set up a new project on google cloud, and create a new bucket on google cloud storage, and upload your model file there. Or in my case, upload the weights file there (example address "gs://my-bucket/my_weights.hdf5"). Generate new service account credentials and download the corresponding json file into your repo and note the absolute filepath (like "/path/to/repo/my_credentials.json").

Set environment variables:

# .env
GOOGLE_APPLICATION_CREDENTIALS="/path/to/repo/my_credentials.json" 
MODEL_WEIGHTS_FILEPATH="gs://my-bucket/my_weights.hdf5"

FYI: I got errors like "All attempts to get a Google authentication bearer token failed" until I set the "GOOGLE_APPLICATION_CREDENTIALS" env var to satisfy the implicit checks for credentials.

Load weights from google cloud storage:


import os
from dotenv import load_dotenv

load_dotenv()

MODEL_WEIGHTS_FILEPATH = os.getenv("MODEL_WEIGHTS_FILEPATH")

print(MODEL_WEIGHTS_FILEPATH)

# an optional check
import tensorflow as tf
tf.io.gfile.exists(MODEL_WEIGHTS_FILEPATH)

model = unweighted_model() # your keras model
weighted_model = model.load_weights(MODEL_WEIGHTS_FILEPATH)
weighted_model.predict("zyx") # predict or do whatever with your model
like image 1
s2t2 Avatar answered Oct 09 '22 00:10

s2t2