Djangoレストフレームワークを使用してイメージ分類APIを構築します.



概要
機械学習(ml)とデータサイエンス応用は需要が高い.MLアルゴリズムが知られている前に情報を提供するとき、ビジネスの利点は重要です.生産システムへの推論のための機械学習アルゴリズムの統合は技術的障壁であるため,MLモデルをAPIとして展開する必要がある

導入
この短い記事では、4つの深い学習アルゴリズム:VGG 16、Reset 50、inceptionv 3とxceptionを使用して、胸部X線とCTスキャンでCOVID - 19を検出するためにAIベースのモデルを実装します.我々は、APIを実装し、モデルの作成ではなく、主に焦点を当ててください.
ライブエンドポイントをテストするには、リクエストの本文に追加されたX線画像を次のURLにポストリクエストを送信します.リクエストが成功した場合は、次のサンプル出力を取得します.
https://alienx.tech/api/v1/xray # for the x-ray images
https://alienx.tech/api/v1/ct # for CT scans
{
    "status": "success",
    "data": {
        "asset_id": "3e978ba830fb266978af20f2bf816f5e",
        "public_id": "vacpxfywfohgfprwhrso",
        "version": 1637699139,
        "version_id": "c9017c7d3b28ce797edefec0b0d72796",
        "signature": "e9c632b832e773cbbcb8906f93aba1d9e859d4bf",
        "width": 1205,
        "height": 1395,
        "format": "png",
        "resource_type": "image",
        "created_at": "2021-11-23T20:25:39Z",
        "tags": [],
        "bytes": 1325222,
        "type": "upload",
        "etag": "86005d3c34202b10949db5569570cd16",
        "placeholder": false,
        "url": "http://res.cloudinary.com/prometheusapi/image/upload/v1637699139/vacpxfywfohgfprwhrso.png",
        "secure_url": "https://res.cloudinary.com/prometheusapi/image/upload/v1637699139/vacpxfywfohgfprwhrso.png",
        "original_filename": "covid-19-pneumonia-22",
        "api_key": "138196782467569"
    },
    "url": "http://res.cloudinary.com/prometheusapi/image/upload/v1637699139/vacpxfywfohgfprwhrso.png",
    "xception_chest_pred": "100.00% COVID",
    "inception_chest_pred": "100.00% COVID",
    "vgg_chest_pred": "100.00% COVID",
    "resnet_chest_pred": "100.00% COVID"
}

モデルビル
プロジェクトのデータセットは2つのオープンソースのgithubリポジトリから集められました.
  • 胸部X線画像(1000の画像)は、以下から得られました:https://github.com/ieee8023/covid-chestxray-dataset
  • CT走査イメージ(750のイメージ)は、以下から得られました:https://github.com/UCSD-AI4H/COVID-CT/tree/master/Data-split
  • つのアルゴリズム:VGG 16、Reset 50、inceptionv 3とxceptionは、胸X線とCTスキャンで別々に訓練されました.モデルの80 %はモデルのトレーニングに使用され,残りの20 %はモデルの精度をテストした.
    8モデルをトレーニングするためのコードは、私のGithub repositoryで利用可能です.プロジェクトのモデルは次のようになります.
    drive
    モデルをRESTful APIに変える
    Pythonベストプラクティスに続いて、プロジェクトの仮想環境を作成し、必要なパッケージをインストールします.
    まず、プロジェクトディレクトリを作成します.
    $ mkdir djangoapp
    $ cd djangoapp
    
    
    ここで、仮想環境を作成し、必要なパッケージをインストールします.
    MacOSとUnixシステムの場合:
    $ python3 -m venv myenv
    $ source myenv/bin/activate
    (myenv) $ pip install django requests djangorestframework tensorflow cloudinary opencv-python
    
    
    Windows用
    $ python3 -m venv myenv
    $ myenv\Scripts\activate
    (myenv) $ pip install django requests djangorestframework tensorflow cloudinary opencv-python
    

    あなたのDjangoアプリケーションを設定する
    まず、作成したディレクトリdjangoappに移動し、djangoプロジェクトを確立します.
    (myenv) $ django-admin startproject mainapp
    
    
    これにより、プロジェクトのスケルトンの一部のファイルが自動生成されます.
    mainapp/
        manage.py
        mainapp/
            __init__.py
            settings.py
            urls.py
            asgi.py
            wsgi.py
    
    さあ、作成したディレクトリに移動してください( py . pyと同じディレクトリにあることを確認してください.
    (myenv) $ python manage.py startapp monitor
    
    これにより、次のようになります.
    monitor/
        __init__.py
        admin.py
        apps.py
        migrations/
            __init__.py
        models.py
        tests.py
        views.py
    
    メインアプリケーション/設定で.Pyファイルは、次の行を見て、我々は上記のアプリを追加します.
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'rest_framework',#new line
        'monitor', #new line
    ]
    
    
    モニタディレクトリにあることを確認し、テンプレートと呼ばれる新しいディレクトリを作成します.Pyモニタアプリケーションのディレクトリ構造は次のようになります
    monitor/
        __init__.py
        admin.py
        apps.py
        migrations/
        templates/
            __init__.py
        models.py
        tests.py
        urls.py
        views.py
    
    メインアプリケーション/URLを確認します.Pyファイル、モニタアプリケーションのURLを追加するには、次のURLをアプリケーションに作成します.
    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        #path('admin/', admin.site.urls),
        path('', include('monitor.urls')),#monitor app url
    ]
    
    
    さて、モニタ/URLに.Pyファイルは、私たちのウェブサイトを追加します.
    from django.urls import path
    from .views import *
    
    urlpatterns = [
        path('api/upload/xray', UploadView.as_view(), name = 'prediction'),
        path('api/upload/ct', CTUploadView.as_view(), name = 'ct_prediction'),
    ]
    
    私たちのマシンの学習モデルを格納する別のディレクトリを作成しましょう.データセット全体を達成したい人のために、データセットをプロジェクトに追加します.(データフォルダを作成する義務はありません)
    (venv)$ mkdir ml
    (venv)$ mkdir ml/models
    (venv)$ mkdir ml/data
    
    また、我々のマシン学習モデルが位置していて、そこに我々のCloudinary構成を加えるDjangoに言う必要もあります.これらの行を設定に追加します.Pyファイル:
    import os
    import cloudinary
    
    cloudinary.config( 
      cloud_name = "prometheusapi", 
      api_key = "GETYOURAPIKEY", 
      api_secret = "GETYOURAPIKEY" 
    )
    
    MODELS = os.path.join(BASE_DIR, 'ml/models')
    

    アプリを介して負荷Kerasモデル.パイ
    あなたのマシンのアプリでモデルをロードロードします.Pyので、アプリケーションが起動すると、訓練されたモデルは一度だけロードされます.さもなければ、終点が呼ばれるたびに、訓練されたモデルはロードされます、そして、それから、応答時間はより遅くなります.
    アプリを更新しましょう.パイ
    import os
    from django.apps import AppConfig
    from django.conf import settings
    from tensorflow.keras.models import load_model
    from tensorflow import keras
    
    
    class ResNetModelConfig(AppConfig):
        name = 'resnetAPI'
        MODEL_FILE = os.path.join(settings.MODELS, "resnet_chest.h5")
        model = keras.models.load_model(MODEL_FILE)
    
    class ResNetCTModelConfig(AppConfig):
        name = 'resnetCTAPI'
        MODEL_FILE = os.path.join(settings.MODELS, "resnet_ct.h5")
        model = keras.models.load_model(MODEL_FILE)
    
    class VGGModelConfig(AppConfig):
        name = 'vggAPI'
        MODEL_FILE = os.path.join(settings.MODELS, "vgg_chest.h5")
        model = keras.models.load_model(MODEL_FILE)
    
    class VGGCTModelConfig(AppConfig):
        name = 'vggCTAPI'
        MODEL_FILE = os.path.join(settings.MODELS, "vgg_ct.h5")
        model = keras.models.load_model(MODEL_FILE)    
    
    class InceptionModelConfig(AppConfig):
        name = 'inceptionv3_chestAPI'
        MODEL_FILE = os.path.join(settings.MODELS, "inceptionv3_chest.h5")    
        model = keras.models.load_model(MODEL_FILE)
    
    class InceptionCTModelConfig(AppConfig):
        name = 'inceptionv3_chestCTAPI'
        MODEL_FILE = os.path.join(settings.MODELS, "inception_ct.h5")    
        model = keras.models.load_model(MODEL_FILE)    
    
    class ExceptionModelConfig(AppConfig):
        name = 'xception_chestAPI'
        MODEL_FILE = os.path.join(settings.MODELS, "xception_chest.h5")    
        model = keras.models.load_model(MODEL_FILE)
    
    class ExceptionCTModelConfig(AppConfig):
        name = 'xception_chestCTAPI'
        MODEL_FILE = os.path.join(settings.MODELS, "xception_ct.h5")    
        model = keras.models.load_model(MODEL_FILE)    
    

    エディット.パイ
    最後のステップはビューを更新することです.Pyビューは主に2つのタスクに対して責任があります.
  • 受信したPOSTリクエストを処理します.
  • 受信データを予測し、結果を応答として与える.
  • import urllib
    from django.shortcuts import render
    import numpy as np
    from .apps import *
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.parsers import MultiPartParser, JSONParser
    import cloudinary.uploader
    import matplotlib.pyplot as plt
    import cv2
    
    # Create your views here.
    class UploadView(APIView):
        parser_classes = (
            MultiPartParser,
            JSONParser,
        )
    
        @staticmethod
        def post(request):
            file = request.data.get('picture')
            upload_data = cloudinary.uploader.upload(file)
            #print(upload_data)
            img = upload_data['url']
    
    
            #load models
            resnet_chest = ResNetModelConfig.model
            vgg_chest = VGGModelConfig.model
            inception_chest = InceptionModelConfig.model
            xception_chest = ExceptionModelConfig.model
    
            req = urllib.request.urlopen(img)
            arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
            image = cv2.imdecode(arr, -1) # 'Load it as it is'
            #image = cv2.imread('upload_chest.jpg') # read file 
            image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # arrange format as per keras
            image = cv2.resize(image,(224,224))
            image = np.array(image) / 255
            image = np.expand_dims(image, axis=0)
    
            resnet_pred = resnet_chest.predict(image)
            probability = resnet_pred[0]
            #print("Resnet Predictions:")
            if probability[0] > 0.5:
                resnet_chest_pred = str('%.2f' % (probability[0]*100) + '% COVID') 
            else:
                resnet_chest_pred = str('%.2f' % ((1-probability[0])*100) + '% NonCOVID')
            #print(resnet_chest_pred)
    
            vgg_pred = vgg_chest.predict(image)
            probability = vgg_pred[0]
            #print("VGG Predictions:")
            if probability[0] > 0.5:
                vgg_chest_pred = str('%.2f' % (probability[0]*100) + '% COVID') 
            else:
                vgg_chest_pred = str('%.2f' % ((1-probability[0])*100) + '% NonCOVID')
            #print(vgg_chest_pred)
    
            inception_pred = inception_chest.predict(image)
            probability = inception_pred[0]
            #print("Inception Predictions:")
            if probability[0] > 0.5:
                inception_chest_pred = str('%.2f' % (probability[0]*100) + '% COVID') 
            else:
                inception_chest_pred = str('%.2f' % ((1-probability[0])*100) + '% NonCOVID')
            #print(inception_chest_pred)
    
            xception_pred = xception_chest.predict(image)
            probability = xception_pred[0]
            #print("Xception Predictions:")
            if probability[0] > 0.5:
                xception_chest_pred = str('%.2f' % (probability[0]*100) + '% COVID') 
            else:
                xception_chest_pred = str('%.2f' % ((1-probability[0])*100) + '% NonCOVID')
            #print(xception_chest_pred)
            return Response({
                'status': 'success',
                'data': upload_data,
                'url':img,
                'xception_chest_pred':xception_chest_pred,
                'inception_chest_pred':inception_chest_pred,
                'vgg_chest_pred':vgg_chest_pred,
                'resnet_chest_pred':resnet_chest_pred,
            }, status=201)
    
    
    class CTUploadView(APIView):
        parser_classes = (
            MultiPartParser,
            JSONParser,
        )
    
        @staticmethod
        def post(request):
            file = request.data.get('picture')
            upload_data = cloudinary.uploader.upload(file)
            #print(upload_data)
            img = upload_data['url']
    
    
            #load models
            resnet_chest = ResNetCTModelConfig.model
            vgg_chest = VGGCTModelConfig.model
            inception_chest = InceptionCTModelConfig.model
            xception_chest = ExceptionCTModelConfig.model
    
            req = urllib.request.urlopen(img)
            arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
            image = cv2.imdecode(arr, -1) # 'Load it as it is'
            #image = cv2.imread('upload_chest.jpg') # read file 
            image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # arrange format as per keras
            image = cv2.resize(image,(224,224))
            image = np.array(image) / 255
            image = np.expand_dims(image, axis=0)
    
            resnet_pred = resnet_chest.predict(image)
            probability = resnet_pred[0]
            #print("Resnet Predictions:")
            if probability[0] > 0.5:
                resnet_chest_pred = str('%.2f' % (probability[0]*100) + '% COVID') 
            else:
                resnet_chest_pred = str('%.2f' % ((1-probability[0])*100) + '% NonCOVID')
            #print(resnet_chest_pred)
    
            vgg_pred = vgg_chest.predict(image)
            probability = vgg_pred[0]
            #print("VGG Predictions:")
            if probability[0] > 0.5:
                vgg_chest_pred = str('%.2f' % (probability[0]*100) + '% COVID') 
            else:
                vgg_chest_pred = str('%.2f' % ((1-probability[0])*100) + '% NonCOVID')
            #print(vgg_chest_pred)
    
            inception_pred = inception_chest.predict(image)
            probability = inception_pred[0]
            #print("Inception Predictions:")
            if probability[0] > 0.5:
                inception_chest_pred = str('%.2f' % (probability[0]*100) + '% COVID') 
            else:
                inception_chest_pred = str('%.2f' % ((1-probability[0])*100) + '% NonCOVID')
            #print(inception_chest_pred)
    
            xception_pred = xception_chest.predict(image)
            probability = xception_pred[0]
            #print("Xception Predictions:")
            if probability[0] > 0.5:
                xception_chest_pred = str('%.2f' % (probability[0]*100) + '% COVID') 
            else:
                xception_chest_pred = str('%.2f' % ((1-probability[0])*100) + '% NonCOVID')
            #print(xception_chest_pred)
            return Response({
                'status': 'success',
                'data': upload_data,
                'url':img,
                'xceptionCT_chest_pred':xception_chest_pred,
                'inceptionCT_chest_pred':inception_chest_pred,
                'vggCT_chest_pred':vgg_chest_pred,
                'resnetCT_chest_pred':resnet_chest_pred,
            }, status=201)
    
    
    

    APIのテスト
    必要な移行を作成し、サーバーを実行します.
    (myenv) $ python manage.py makemigrations
    (myenv) $ python manage.py migrate
    (myenv) $ python manage.py runserver
    
    郵便配達人を解雇して、イメージを体に加えてポストリクエストをしてください.


    おかげでチューニング滞在!