Ошибка типа “прерывистая” при запуске CNN внутри контейнера Docker

Вопрос или проблема

Я работал над простым API компьютерного зрения с несколькими конечными точками для извлечения полезной информации из изображений ebay. API размещается в контейнере Docker, который ищет h5 файлы, загружает их, если они отсутствуют, запускает все и начинает сервер каждый раз, когда контейнер создается. Одна из конечных точек – это обученный классификатор VGG-16, который разделяет изображения на группы для дальнейшего анализа и проверки человеком. Эта конечная точка демонстрирует странное поведение. Когда я запускаю её напрямую со своего локального компьютера, всё работает нормально. Однако, когда я запускаю её изнутри контейнера Docker, она работает нормально, пока не остается без дела слишком долго, но если это случается, я получаю следующую ошибку, и контейнер Docker нужно будет перезапустить:

Невозможно интерпретировать ключ feed_dict как Tensor: Tensor Tensor("Placeholder:0", shape=(3, 3, 512, 512), dtype=float32) не является элементом этого графа.

В коде не кажется, что есть ошибка, и контейнер Docker выглядит нормально. Я не понимаю, почему это происходит только в контейнеризованном API, а не в локально хранимой версии. Если кто-то сталкивался с этим раньше, пожалуйста, помогите!

Вот мой Dockerfile

FROM python:3.7.3
WORKDIR /code
COPY requirements.txt /code
RUN pip install -r requirements.txt
RUN apt update && apt-get install tesseract-ocr -y
COPY . /code
EXPOSE 8000
CMD ["python", "-u", "manage.py", "runserver", "0.0.0.0:8000"]

manage.py, который управляет соответствующим h5 файлом:

if __name__ == '__main__':
    model_getter = os.listdir(".")
    model_list = []

    for names in model_getter:
        if names.endswith(".h5"):
            model_list.append(names)

    if model_list==[]:   
        sys.stdout.write("Нейронная сеть не найдена. Загружается модель.\n")   
        if os.path.exists("../aws-credentials.json"):
            with open("../aws-credentials.json") as f:
                sys.stdout.write("Загрузка учетных данных разработчика.\n")
                data= json.load(f)
                conn = boto.connect_s3(data["accessKeyId"], data["secretAccessKey"])

        bucket = conn.get_bucket('mybucket')
        file_path = bucket.get_key('/developer/model.h5')
        sys.stdout.write("модель готовится к загрузке. Пожалуйста, подождите, пока загрузка не завершится. Это может занять некоторое время.\n")
        file_path.get_contents_to_filename('model.h5')
        sys.stdout.write("Загрузка завершена.\n")
    main()

и код CNN:

def runNetwork(request, encoded_url):
    from keras.preprocessing import image
    from keras.applications.vgg16 import preprocess_input
    import keras.models
    import numpy as np
    import requests
    from io import BytesIO

    model=keras.models.load_model('model.h5')
    uri = urllib.parse.unquote(encoded_url)
    response = requests.get(uri)
    img = image.load_img((BytesIO(response.content)),target_size=(224, 224))
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x = preprocess_input(x)

    features = model.predict_classes(x)
    if features ==[0]:
        code = "foo"
    if features ==[1]:
        code = "bar"
    if features==[2]:
        code = "baz"
    ...

    features=np.int(features[0])   
    obj_json = {"input_uri" : uri, "prediction_index" : features, "prediction_code" : code }
    return JsonResponse(obj_json)

и полный трейс стека:

usr/local/lib/python3.7/site-packages/tensorflow/python/client/session.py in _run
                subfeed, allow_tensor=True, allow_operation=False) …
▶ Local vars
/usr/local/lib/python3.7/site-packages/tensorflow/python/framework/ops.py in as_graph_element
      return self._as_graph_element_locked(obj, allow_tensor, allow_operation) …
▶ Local vars
/usr/local/lib/python3.7/site-packages/tensorflow/python/framework/ops.py in _as_graph_element_locked
        raise ValueError("Tensor %s не является элементом этого графа." % obj) …
▶ Local vars
Во время обработки вышеупомянутого исключения (Tensor Tensor("Placeholder:0", shape=(3, 3, 512, 512), dtype=float32) не является элементом этого графа.) возникло другое исключение:
/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py in inner
            response = get_response(request) …
▶ Local vars
/usr/local/lib/python3.7/site-packages/django/core/handlers/base.py in _get_response
                response = self.process_exception_by_middleware(e, request) …
▶ Local vars
/usr/local/lib/python3.7/site-packages/django/core/handlers/base.py in _get_response
                response = wrapped_callback(request, *callback_args, **callback_kwargs) …
▶ Local vars
/code/SlabIDs/views.py in runNetwork
    model=keras.models.load_model('SlabNet3.h5') …
▶ Local vars
/usr/local/lib/python3.7/site-packages/keras/engine/saving.py in load_model
        model = _deserialize_model(f, custom_objects, compile) …
▶ Local vars
/usr/local/lib/python3.7/site-packages/keras/engine/saving.py in _deserialize_model
    K.batch_set_value(weight_value_tuples) …
▶ Local vars
/usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py in batch_set_value
        get_session().run(assign_ops, feed_dict=feed_dict) …
▶ Local vars
/usr/local/lib/python3.7/site-packages/tensorflow/python/client/session.py in run
                         run_metadata_ptr) …
▶ Local vars
/usr/local/lib/python3.7/site-packages/tensorflow/python/client/session.py in _run
                'Не удалось интерпретировать ключ feed_dict как Tensor: ' + e.args[0]) …
▶ Local vars

Окей, я допустил глупую ошибку. Пожалуйста, проигнорируйте вышеупомянутое паническое бредительство. Однако на случай, если кто-то другой столкнется с чем-то подобным, проблема была решена просто благодаря тому, что я вспомнил о необходимости очищать свою сессию в конце каждого запуска:

from keras import backend as K
...код...
K.clear_session()

Ответ или решение

Интермиттирующая Ошибка При Запуске CNN Внутри Docker-Контейнера: Решение Проблемы

Недавний опыт использования контейнеров Docker для разработки API компьютерного зрения привел к интересной проблеме: ошибка при работе с трансформированным классификатором VGG-16. Эта ситуация подтверждает важность понимания работы с сессиями и графами в Keras и TensorFlow, особенно в условиях контейнеризации.

Проблема

Проблема, с которой вы столкнулись, заключается в следующем сообщении об ошибке:

Cannot interpret feed_dict key as Tensor: Tensor Tensor("Placeholder:0", shape=(3, 3, 512, 512), dtype=float32) is not an element of this graph.

Эта ошибка указывает на то, что попытка обращения к тензору, который не является частью активного графа, завершилась неудачей. Ошибка возникает после продолжительного простоя контейнера, что может свидетельствовать о том, что граф Keras/TensorFlow теряет привязку к сессии или что сессии становятся "мертвыми".

Анализ Кодовой Базы

Ваш API работает по следующему принципу:

  1. Загружает модель, если .h5 файл не найден.
  2. Обрабатывает входящие изображения с помощью Keras.
  3. Возвращает результаты в формате JSON.

Однако, ваша изначальная реализация не очищала сессии Keras после обработки запросов. Это создает множество ненужных графов, которые остаются загруженными, что в итоге приводит к исчерпанию ресурсов и возникновению ошибок при повторном использовании модели.

Решение Проблемы

На основании вашего решения, ключевым моментом был вызов метода K.clear_session() из Keras после завершения обработки каждого запроса. Этот метод очищает текущую сессию и граф, что позволяет избежать конфликтов и уменьшить использование оперативной памяти. Таким образом, исправлений требует не только логика проверки, но и управление ресурсами:

from keras import backend as K

def runNetwork(request, encoded_url):
    # Ваш код обработки изображения...
    model = keras.models.load_model('model.h5')

    # Ваш код предсказания...

    # Очистка сессии для предотвращения ошибок
    K.clear_session()

    return JsonResponse(obj_json)

Рекомендации по Архитектуре

Для улучшения стабильности вашего API в Docker рассмотрите следующие рекомендации:

  1. Изоляция Моделей: Используйте разные инстансы моделей для параллельного обслуживания запросов, если нагрузки высокие.

  2. Управление Памятью: Регулярно проводите мониторинг использования памяти контейнера и настраивайте лимиты на ресурсы в Docker.

  3. Логирование Ошибок: Добавьте механизм логирования для захвата и анализа ошибок, что поможет в дальнейшем диагностировании проблем.

  4. Тестирование: Регулярно тестируйте вашу систему при различных нагрузках, чтобы выявить проблемные места на ранних этапах.

Заключение

Ситуации подобного рода не редкость при работе с глубоким обучением и Docker. Правильное управление сессиями и ресурсами является ключом к развитию надежных и высокопроизводительных приложений. Надеюсь, ваши выводы помогут многим разработчикам в будущем избегать подобных проблем.

Оцените материал
Добавить комментарий

Капча загружается...