5

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") 
2
  • Is the model.h5 file in the bucket is publicly accessible? If not use the AWS SDK for S3 to download the file and save it into /tmp folder and load to the model. Commented Dec 16, 2017 at 17:48
  • It's not public, I solved by downloading it. I updated the question with the solution Commented Dec 18, 2017 at 14:09

4 Answers 4

4

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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 

Comments

0

This worked for me https://github.com/keras-team/keras/issues/9343#issuecomment-440903847

s3 = boto3.resource('s3') obj = s3.Object(bucket_name, model_file_name) #.h5 file body = obj.get()['Body'].read() file_access_property_list = h5py.h5p.create(h5py.h5p.FILE_ACCESS) file_access_property_list.set_fapl_core(backing_store=False) file_access_property_list.set_file_image(body) file_id_args = { 'fapl': file_access_property_list, 'flags': h5py.h5f.ACC_RDONLY, 'name': b'this should never matter', } h5_file_args = { 'backing_store': False, 'driver': 'core', 'mode': 'r', } with contextlib.closing(h5py.h5f.open(**file_id_args)) as file_id: with h5py.File(file_id, **h5_file_args) as h5_file: loaded_model = load_model(h5_file) #from keras.models 

Now, loaded_model can be used to make predictions

Comments

0

This worked for me:

s3_client = boto3.client('s3') s3_client.download_file('bucket_name','file_name','model') #downloading the model to temporary file named "model" with h5py.File('model','r') as f: model = load_model(f) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.