Search code examples
pythontensorflowflaskkerasartificial-intelligence

error Loading keras (tensorflow) model from .h5 file in flask


When I run the file I get these errors:

python app.py
2023-09-03 22:09:58.412966: I tensorflow/core/platform/cpu_feature_guard.cc:182] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.
To enable the following instructions: SSE SSE2 SSE3 SSE4.1 SSE4.2 AVX, in other operations, rebuild TensorFlow with the appropriate compiler flags.
Traceback (most recent call last):
  File "C:\Users\Osama\python enviroment\app.py", line 95, in <module>
    model = load_local_model()
            ^^^^^^^^^^^^^^^^^^
  File "C:\Users\Osama\python enviroment\app.py", line 29, in load_local_model
    model = load_model(model_path)
            ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Osama\AppData\Local\Programs\Python\Python311\Lib\site-packages\keras\src\saving\saving_api.py", line 238, in load_model
    return legacy_sm_saving_lib.load_model(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Osama\AppData\Local\Programs\Python\Python311\Lib\site-packages\keras\src\utils\traceback_utils.py", line 70, in error_handler
    raise e.with_traceback(filtered_tb) from None
  File "C:\Users\Osama\AppData\Local\Programs\Python\Python311\Lib\site-packages\keras\src\utils\generic_utils.py", line 102, in func_load
    code = marshal.loads(raw_code)
           ^^^^^^^^^^^^^^^^^^^^^^^
ValueError: bad marshal data (unknown type code)

here is the full code:

import os
import uuid
import requests
from PIL import Image
import tensorflow as tf
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.image import load_img, img_to_array
from flask import Flask, request, jsonify
from werkzeug.utils import secure_filename
from dotenv import load_dotenv
import json

load_dotenv()

app = Flask(__name__)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
model = None

ALLOWED_EXT = {'jpg', 'jpeg', 'png', 'jfif'}
classes = ['Meningioma', 'Glioma', 'Pituitary']


def allowed_file(filename: str) -> bool:
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXT


def load_local_model() -> tf.keras.Model:
    model_path = os.path.join(BASE_DIR, 'model.h5')
    model = load_model(model_path)
    return model


def predict(filename: str, model) -> tuple[list[str], list[float]]:
    img = load_img(filename, target_size=(256, 256))
    img = img_to_array(img)
    img = img.reshape(1, 256, 256, 3)

    img = img.astype('float32')
    img = img / 255.0
    result = model.predict(img)

    dict_result = {}
    for i in range(len(classes)):
        dict_result[result[0][i]] = classes[i]

    res = result[0]
    res.sort()
    res = res[::-1]
    prob = res[:3]

    prob_result = []
    class_result = []
    for i in range(len(prob)):
        prob_result.append(round(prob[i] * 100, 3))
        class_result.append(dict_result[prob[i]])

    return class_result, prob_result


@app.route('/predict', methods=['POST'])
def predict_image():
    if 'file' not in request.files:
        return jsonify({'error': 'No file found in the request'})

    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': 'No file selected'})

    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        unique_filename = str(uuid.uuid4())
        img_path = os.path.join(
            BASE_DIR, 'static/images', unique_filename + '.jpg')
        file.save(img_path)

        class_result, prob_result = predict(img_path, model)

        predictions = {
            "class1": class_result[0],
            "class2": class_result[1],
            "class3": class_result[1],
            "prob1": prob_result[0],
            "prob2": prob_result[1],
            "prob3": prob_result[2],
        }

        return jsonify(predictions)
        return jsonify({'message': 'serve is working'})
    else:
        return jsonify({'error': 'Invalid file format'})


if __name__ == "__main__":
    # Load model locally
    model = load_local_model()
    print("Model loaded.")

    app.run(host='0.0.0.0', port=int(os.getenv('PORT', 5000)), debug=False)

And here is the GitHub repo if you wanna take a look at the file structure.

I really don't have experience working with Python since I'm a web front-end developer so maybe something is wrong with the code but I've tried everything: ChatGpt, Bing and of course, spent hours on Stackoverflow.

And thanks for your time ❤️


Solution

  • The problem was caused by using incompatible versions in my Flask app. Here's how I resolved it:

    1. TensorFlow Version Mismatch:

      • The model was trained using TensorFlow v2.12.0, but I had TensorFlow v2.13.0 installed in my Flask app.
      • To fix this, I downgraded my TensorFlow version to match the one used during training. You can do this by running the following command:
        pip install tensorflow==2.12.0
        
    2. Python Version Mismatch:

      • The model was built using Python v3.10.9, while I was using Python v3.11.3 in my Flask app.
      • To ensure compatibility, I switched to the correct Python version by creating a virtual environment and installing Python v3.10.9. Here are the steps:
        • Install virtualenv if you don't have it already:
          pip install virtualenv
          
        • Create a virtual environment:
          virtualenv myenv
          
        • Activate the virtual environment:
          • For Windows:
            myenv\Scripts\activate
            
          • For Linux/macOS:
            source myenv/bin/activate
            
        • Install Python v3.10.9 in the virtual environment:
          pip install python==3.10.9
          

    After applying these changes, the TensorFlow version and Python version in my Flask app were compatible with the model. This resolved the issue for me, and I hope it helps you too.

    Please note that it's important to ensure version compatibility between your model, TensorFlow, and Python to avoid such issues in the future.