#IntegratedML

0 フォロワー · 19 投稿

InterSystems IntegratedMLは、InterSystems IRISまたはIRIS for HealthのすべてがSQLの機械学習(ML)モジュールであり、次の機能を備えています。 -「最高の」オープンソースおよびDataRobotを含む独自仕様の「AutoML」フレームワークをラップします。 -IRISに簡単にデプロイすることに重点を置いているため、アプリケーションに機械学習を簡単に追加できます。 ビデオや視覚教材を含む詳細な情報については、 でご覧ください。IntegratedMLリソースガイド

記事 Toshihiko Minamoto · 11月 5, 2025 8m read

新しい InterSystems IRIS® Cloud SQL と InterSystems IRIS® Cloud IntegratedML® クラウド製品のユーザーであり、デプロイメントのメトリクスにアクセスして独自の可観測性プラットフォームに送信しようと考えている方のために、メトリクスを Google Cloud Platform Monitoring(旧称 StackDriver)に送信して手っ取り早く行う方法をご紹介します。

クラウドポータルには、概要メトリクス表示用のトップレベルのメトリクスが含まれており、ユーザーに公開されているメトリクスエンドポイントを使用しますが、ある程度探索しなければ、そこにあることには気づきません。

🚩 このアプローチは、「今後名前が付けられる予定の機能」を利用している可能性があるため、それを踏まえると将来性があるものではなく、確実に InterSystemsでサポートされているアプローチではありません。


では、より包括的なセットをエクスポートしたい場合はどうでしょうか?この技術的な記事/例では、メトリクスを取得して可観測性に転送する方法を紹介します。Open Telemetry Collector を使用して、任意のメトリクスターゲットを取得し、任意の可観測性プラットフォーム送信できるように、ニーズに合わせて変更することができます。

上記の結果に導く仕組みは多数の方法で得られますが、ここでは Kubernetes pod を使用して、1 つのコンテナーで Python スクリプトを実行し、もう 1 つのコンテナーで Otel を実行して、メトリクスのプルとプッシュを行います... 自分のやり方を選択することはできますが、この例と記事では、k8s を主人公に Python を使って行います。

手順:

  • 前提条件
  • Python
  • コンテナー
  • Kubernetes
  • Google Cloud Monitoring

前提要件:

  • IRIS®  Cloud SQL の有効なサブスクリプション
  • 実行中の 1 つのデプロイメント(オプションで Integrated ML を使用)
  • 環境に提供するシークレット

環境変数

 
 シークレットの取得
この内容は少し複雑で本題から少し外れているためティーザーに入れましたが、これがシークレットの生成に必要なる値です。
ENV IRIS_CLOUDSQL_USER 'user'
ENV IRIS_CLOUDSQL_PASS 'pass'

☝ これは https://portal.live.isccloud.io の認証情報です。

ENV IRIS_CLOUDSQL_USERPOOLID 'userpoolid'
ENV IRIS_CLOUDSQL_CLIENTID 'clientid'
ENV IRIS_CLOUDSQL_API 'api'

☝ これはブラウザの開発ツールから取得する必要があります。

  • `aud` = clientid
  • `userpoolid`= iss
  • `api` = request utl

ENV IRIS_CLOUDSQL_DEPLOYMENTID 'deploymentid'

☝これはクラウドサービスポータルから取得できます

 

Python:

以下に、クラウドポータルからメトリクスを取得し、それを Otel Collectorが取得するメトリクスとしてローカルにエクスポートする Python ハッキングを示します。

 
iris_cloudsql_exporter.py
import time
import os
import requests
import json

from warrant import Cognito from prometheus_client.core import GaugeMetricFamily, REGISTRY, CounterMetricFamily from prometheus_client import start_http_server from prometheus_client.parser import text_string_to_metric_families

classIRISCloudSQLExporter(object):definit(self): self.access_token = self.get_access_token() self.portal_api = os.environ['IRIS_CLOUDSQL_API'] self.portal_deploymentid = os.environ['IRIS_CLOUDSQL_DEPLOYMENTID']

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">collect</span><span class="hljs-params">(self)</span>:</span>
    <span class="hljs-comment"># Requests fodder</span>
    url = self.portal_api
    deploymentid = self.portal_deploymentid
    print(url)
    print(deploymentid)

    headers = {
        <span class="hljs-string">'Authorization'</span>: self.access_token, <span class="hljs-comment"># needs to be refresh_token, eventually</span>
        <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>
    }

    metrics_response = requests.request(<span class="hljs-string">"GET"</span>, url + <span class="hljs-string">'/metrics/'</span> + deploymentid, headers=headers)
    metrics = metrics_response.content.decode(<span class="hljs-string">"utf-8"</span>)

    <span class="hljs-keyword">for</span> iris_metrics <span class="hljs-keyword">in</span> text_string_to_metric_families(metrics):
        <span class="hljs-keyword">for</span> sample <span class="hljs-keyword">in</span> iris_metrics.samples:

            labels_string = <span class="hljs-string">"{1}"</span>.format(*sample).replace(<span class="hljs-string">'\''</span>,<span class="hljs-string">"\""</span>)
            labels_dict = json.loads(labels_string)
            labels = []

            <span class="hljs-keyword">for</span> d <span class="hljs-keyword">in</span> labels_dict:
                labels.extend(labels_dict)
            <span class="hljs-keyword">if</span> len(labels) &gt; <span class="hljs-number">0</span>:
                g = GaugeMetricFamily(<span class="hljs-string">"{0}"</span>.format(*sample), <span class="hljs-string">'Help text'</span>, labels=labels)
                g.add_metric(list(labels_dict.values()), <span class="hljs-string">"{2}"</span>.format(*sample))
            <span class="hljs-keyword">else</span>:
                g = GaugeMetricFamily(<span class="hljs-string">"{0}"</span>.format(*sample), <span class="hljs-string">'Help text'</span>, labels=labels)
                g.add_metric([<span class="hljs-string">""</span>], <span class="hljs-string">"{2}"</span>.format(*sample))
            <span class="hljs-keyword">yield</span> g

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_access_token</span><span class="hljs-params">(self)</span>:</span>
    <span class="hljs-keyword">try</span>:
        user_pool_id = os.environ[<span class="hljs-string">'IRIS_CLOUDSQL_USERPOOLID'</span>] <span class="hljs-comment"># isc iss </span>
        username = os.environ[<span class="hljs-string">'IRIS_CLOUDSQL_USER'</span>]
        password = os.environ[<span class="hljs-string">'IRIS_CLOUDSQL_PASS'</span>]
        clientid = os.environ[<span class="hljs-string">'IRIS_CLOUDSQL_CLIENTID'</span>] <span class="hljs-comment"># isc aud </span>
        print(user_pool_id)
        print(username)
        print(password)
        print(clientid)
        
        <span class="hljs-keyword">try</span>:
            u = Cognito(
                user_pool_id=user_pool_id,
                client_id=clientid,
                user_pool_region=<span class="hljs-string">"us-east-2"</span>, <span class="hljs-comment"># needed by warrant, should be derived from poolid doh</span>
                username=username
            )
            u.authenticate(password=password)
        <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> p:
            print(p)
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        print(e)

    <span class="hljs-keyword">return</span> u.id_token

ifname == 'main':

start_http_server(<span class="hljs-number">8000</span>)
REGISTRY.register(IRISCloudSQLExporter())
<span class="hljs-keyword">while</span> <span class="hljs-keyword">True</span>:
    REGISTRY.collect()
    print(<span class="hljs-string">"Polling IRIS CloudSQL API for metrics data...."</span>)
    <span class="hljs-comment">#looped e loop</span>
    time.sleep(<span class="hljs-number">120</span>)</code></pre>

 

Docker:

 
Dockerfile
FROM python:3.8ADD src /src
RUN pip install prometheus_client
RUN pip install requests
WORKDIR /src
ENV PYTHONPATH '/src/'ENV PYTHONUNBUFFERED=1ENV IRIS_CLOUDSQL_USERPOOLID 'userpoolid'ENV IRIS_CLOUDSQL_CLIENTID 'clientid'ENV IRIS_CLOUDSQL_USER 'user'ENV IRIS_CLOUDSQL_PASS 'pass'ENV IRIS_CLOUDSQL_API 'api'ENV IRIS_CLOUDSQL_DEPLOYMENTID 'deploymentid'RUN pip install -r requirements.txt
CMD ["python" , "/src/iris_cloudsql_exporter.py"]
docker build -t iris-cloudsql-exporter .
docker image tag iris-cloudsql-exporter sween/iris-cloudsql-exporter:latest
docker push sween/iris-cloudsql-exporter:latest


デプロイメント:

k8s、ネームスペースを作成します:

kubectl create ns iris

k8s、シークレットを追加します:

kubectl create secret generic iris-cloudsql -n iris \
    --from-literal=user=$IRIS_CLOUDSQL_USER \
    --from-literal=pass=$IRIS_CLOUDSQL_PASS \
    --from-literal=clientid=$IRIS_CLOUDSQL_CLIENTID \
    --from-literal=api=$IRIS_CLOUDSQL_API \
    --from-literal=deploymentid=$IRIS_CLOUDSQL_DEPLOYMENTID \
    --from-literal=userpoolid=$IRIS_CLOUDSQL_USERPOOLID

otel、構成を作成します:

apiVersion: v1
data:
  config.yaml: |
    receivers:
      prometheus:
        config:
          scrape_configs:
          - job_name: 'IRIS CloudSQL'
              # Override the global default and scrape targets from this job every 5 seconds.
            scrape_interval: 30s
            scrape_timeout: 30s
            static_configs:
                    - targets: ['192.168.1.96:5000']
            metrics_path: /
exporters:
  googlemanagedprometheus:
    project: "pidtoo-fhir"
service:
  pipelines:
    metrics:
      receivers: [prometheus]
      exporters: [googlemanagedprometheus]

kind: ConfigMap metadata: name: otel-config namespace: iris

k8s、otel 構成を configmap としてロードします:

kubectl -n iris create configmap otel-config --from-file config.yaml

k8s、ロードバランサー(確実にオプション)、MetalLB をデプロイします。これはクラスタ外部からグスクレイピングして検査するために行っています。

cat <<EOF | kubectl apply -f -n iris -
apiVersion: v1
kind: Service
metadata:
  name: iris-cloudsql-exporter-service
spec:
  selector:
    app: iris-cloudsql-exporter
  type: LoadBalancer
  ports:
  - protocol: TCP
    port: 5000
    targetPort: 8000
EOF

gcp、Google Cloud へのキーが必要です。サービスアカウントにスコープを設定する必要があります

  • roles/monitoring.metricWriter
kubectl -n iris create secret generic gmp-test-sa --from-file=key.json=key.json

k8s; deployment/pod そのもの。2 つのコンテナー:

 
deployment.yaml
kubectl -n iris apply -f deployment.yaml

実行

特に問題がなければ、ネームスペースを詳しく調べて、状況を確認してみましょう。

✔ GCP と Otel 用の 2 つの configmap

 

✔ 1 つのロードバランサー

 

✔ 1 つの pod、2 つのコンテナーが正しくスクレイピングされます

  

Google Cloud Monitoring

可観測性を調べてメトリクスが正しく受信されていることを確認し、可観測性を高めましょう!

 

0
0 20
InterSystems公式 Seisuke Nakahashi · 4月 3, 2025

IRIS 2024.3 で発生する2つの製品障害が確認されました。お使いの環境が該当する場合は、それぞれの解決方法にしたがってご対応いただきますよう、よろしくお願いします。

0
0 45
InterSystems公式 Seisuke Nakahashi · 1月 16, 2024

InterSystems IRIS Cloud SQL と InterSystems IRIS Cloud IntegratedML がリリースされました。これらサービスは、実績やエンタープライズクラスのパフォーマンスおよび信頼性を兼ね備えた InterSystems IRIS テクノロジーをもとにした、クラウド環境におけるソリューション開発のベースとなるサービスです。 

InterSystems IRIS Cloud SQL は、多くのエンタープライズのお客様にご利用いただいている InterSystems IRIS のリレーショナル・データベース機能を、アプリケーション開発者やデータ専門家など幅広いみなさまにお届けする、フルマネージドのクラウドサービスです。InterSystems IRIS Cloud IntegratedML は、DBaaS (database-as-a-service) であるこの InterSystems IRIS Cloud SQL のオプション機能であり、SQL ネイティブによる自動機械学習機能への容易なアクセスを提供します。このサービスを利用して、アプリケーション・コードに簡単に組み込めるシンプルなSQLコマンドセットを通じて、データに近いところで実行されるMLモデルを実装することが可能となり、アプリケーションをより強力なものにすることが出来ます。

0
0 76
InterSystems公式 Seisuke Nakahashi · 7月 3, 2023

InterSystems IRIS Cloud SQL は、何千ものエンタープライズのお客様に利用いただいている InterSystems IRIS の優れたリレーショナルデータベース機能を実感いただける、幅広いアプリケーション開発者やデータ専門家のみなさまのためのフルマネージドサービスです。また InterSystems IRIS Cloud IntegratedML は、この DBaaS (Database-as-a-Service) のオプションであり、SQL ネイティブを通じて強力な自動機械学習機能を簡単にご利用いただけるサービスを提供します。シンプルな一連の SQL コマンドは簡単にアプリケーションコードに組み込むことができるため、データに近いところで動作する ML モデルにより、お客様のアプリケーションを拡張することができます。

本日は、これら2製品に関する 開発者アクセスプログラム を発表いたします。アプリケーション開発者は本サービスにみなさまご自身で登録いただくことで、デプロイメントの作成、構成可能なアプリケーションのビルド、そして本サービスによってプロビジョン、構成、システム管理が実行されるスマートデータべースを体験いただけます。

0
0 84
お知らせ Mihoko Iijima · 6月 12, 2023

開発者の皆さん、こんにちは!

InterSystems グランプリコンテスト2023 では、InterSystems IRIS data platform を使用する機能であればどんな内容でもご応募いただけます。

以下の機能を含めた場合、ボーナスポイントを獲得できます。

詳細は以下の通りです。

  • LLM AI や LangChain の使用:Chat GPT、Bard など - 6ポイント
  • InterSystems FHIR SQL Builder- 5ポイント
  • InterSystems FHIR - 3ポイント
  • IntegratedML - 4ポイント
  • Native API - 3ポイント
  • Embedded Python - 4ポイント
  • Interoperability - 3ポイント
  • Production EXtension(PEX) - 2ポイント
  • Adaptive Analytics (AtScale) のキューブの利用 - 3ポイント
  • Tableau, PowerBI, Logi の利用 - 3ポイント
  • InterSystems IRIS BI - 3ポイント
  • Docker container の利用 - 2ポイント 
  • ZPM Package によるデプロイ - 2ポイント
  • オンラインデモ - 2ポイント
  • ユニットテスト - 2ポイント
  • InterSystems Community Idea に投稿された内容の実装 - 4ポイント
  • コミュニティ(USコミュニティ)に記事を投稿する(最初の記事) - 2ポイント
  • コミュニティ(USコミュニティ)に2つ目の記事を投稿する - 1ポイント
  • Code Qualityをパスする - 1ポイント
  • はじめてチャレンジされた方 - 3ポイント
  • YouTubeにビデオを公開- 3ポイント
0
0 107
ディスカッション Miqueias Santos · 5月 18, 2023

こんにちは、大丈夫ですか?

助けを求めに来ました。インターシステムズ ポルトガル語のコンテストに参加しているので、リンクからこの記事を作成しました。私の記事にアクセスしてフィードバックをいただけますか。「いいね!」も歓迎です。

ここ: https://pt.community.intersystems.com/post/veremos-seguir-como-o-intersystems-iris-aliado-com-machine-learning-pode-transformar-para


読むには、ブラジル系ポルトガル語からあなたの言語に翻訳するだけです。

0
0 121
記事 Toshihiko Minamoto · 3月 23, 2023 10m read

腎臓病は、医学会でよく知られるいくつかのパラメーターから発見することが可能です。 この測定により、医学界とコンピューター化されたシステム(特に AI)を支援すべく、科学者である Akshay Singh は、腎臓病の検出/予測における ML アルゴリズムをトレーニングするための非常に便利なデータセットを公開しました。 このデータセットは、ML の最大級のデータリポジトリとして最もよく知られている Kaggle に公開されています。https://www.kaggle.com/datasets/akshayksingh/kidney-disease-dataset

データセットについて

腎臓病データセットには、以下のメタデータ情報が含まれています(出典: https://www.kaggle.com/datasets/akshayksingh/kidney-disease-dataset

  • 赤血球、足浮腫、血糖値などの 25 種類の特徴量を含む 400 行のデータセット。
  • 患者が慢性腎臓病を患っているかどうかを分類することが目的
  • 分類は、'classification' と名付けられた属性が 'ckd'(慢性腎臓病)であるか 'notckd' であるかに基づいて行われます。
  • データセットの作成者は、テキストと数値のマッピングやその他の変更点を含むデータセットのクリーニングを実施しました。 クリーニングの後、データセット作成者は EDA(探索的データ解析)を行い、データセットをトレーニングとテストに分割し、それらにモデルを適用しました。 分類結果は、最初はあまり満足のいくものではないことがわかっています。 そこで、Nan 値のある行をドロップする代わりに、ラムダ関数を使用して、それらの行を各カラムのモードに置き換えて、 もう一度データセットをトレーニングセットとテストセットに分割し、モデルに適用しました。 今度は、結果が改善され、ランダムフォレストと意思決定ツリーが、1.0 と 0 の誤分類の精度で最も良く実行することがわかりました。 分類のパフォーマンスは、混合行列、分類レポート、および制度の出力によって測定されています。

データセットの情報(出典: https://archive.ics.uci.edu/ml/datasets/chronic_kidney_disease )

データセットの収集には以下の表現を使用しています。

age - 年齢 bp - 血圧 sg - 比重 al - アルブミン値 su - 糖分 rbc - 赤血球 pc - 膿細胞 pcc - 膿細胞の塊 ba - 細菌 bgr - ランダム血糖値 bu - 血液尿素 sc - 血清クレアチニン sod - ナトリウム pot - カリウム hemo - ヘモグロビン pcv - ヘマトクリット値 wc - 白血球数 rc - 赤血球数 htn - 高血圧 dm - 糖尿病 cad - 冠動脈疾患 appet - 食欲 pe - 足浮腫 ane - 貧血症 class - クラス

属性の情報(出典: https://archive.ics.uci.edu/ml/datasets/chronic_kidney_disease)

24 + class = 25(数値 11 個、名義尺度 14 個)を使用します。

  1. 年齢(数値) 年数
  2. 血圧(数値) bp(mm/Hg)
  3. 比重(名義尺度) sg - (1.005,1.010,1.015,1.020,1.025)
  4. アルブミン値(名義尺度) al - (0,1,2,3,4,5)
  5. 糖分(名義尺度) su - (0,1,2,3,4,5)
  6. 赤血球(名義尺度) rbc - (normal,abnormal)
  7. 膿細胞(名義尺度) pc - (normal,abnormal)
  8. 膿細胞集塊(名義尺度) pcc - (present,notpresent)
  9. 最近(名義尺度) ba - (present,notpresent)
  10. ランダム血糖値(数値) bgr(mgs/dl)
  11. 血液尿素(数値) bu(mgs/dl)
  12. 血清クレアチニン(数値) sc(mgs/dl)
  13. ナトリウム(数値) sod(mEq/L)
  14. カリウム(数値) pot(mEq/L)
  15. ヘモグロビン(数値) hemo(gms)
  16. ヘマトクリット値(数値)
  17. 白血球数(数値) wc(cells/cumm)
  18. 赤血球数(数値) rc(100万/cmm)
  19. 高血圧(名義尺度) htn - (yes,no)
  20. 糖尿病(名義尺度) dm - (yes,no)
  21. 冠動脈疾患(名義尺度) cad - (yes,no)
  22. 食欲(名義尺度) appet - (good,poor)
  23. 足浮腫(名義尺度) pe - (yes,no)
  24. 貧血症(名義尺度) ane - (yes,no)
  25. 区分(名義尺度) class - (ckd,notckd)

Kaggle から腎臓データを取得する

Kaggle の腎臓データは、Health-Dataset アプリケーション(https://openexchange.intersystems.com/package/Health-Dataset)を使って IRIS テーブルに読み込めます。 これを行うには、module.xml プロジェクトから依存関係(Health Dataset 用の ModuleReference)を設定します。

 
Health Dataset アプリケーションリファレンスを使用した Module.xml
<?xmlversion="1.0" encoding="UTF-8"?>
<Exportgenerator="Cache"version="25">
  <Documentname="predict-diseases.ZPM">
<Module>
      <Name>predict-diseases</Name>
      <Version>1.0.0</Version>
      <Packaging>module</Packaging>
      <SourcesRoot>src/iris</SourcesRoot>
      <ResourceName="dc.predict.disease.PKG"/>
      <Dependencies>
        <ModuleReference>
          <Name>swagger-ui</Name>
          <Version>1.*.*</Version>
        </ModuleReference>
        <ModuleReference>
          <Name>dataset-health</Name>
          <Version>*</Version>
        </ModuleReference>
      </Dependencies>
       <CSPApplication
        Url="/predict-diseases"
        DispatchClass="dc.predict.disease.PredictDiseaseRESTApp"
        MatchRoles=":{$dbrole}"
        PasswordAuthEnabled="1"
        UnauthenticatedEnabled="1"
        Recurse="1"
        UseCookies="2"
        CookiePath="/predict-diseases"
       />
       <CSPApplication
        CookiePath="/disease-predictor/"
        DefaultTimeout="900"
        SourcePath="/src/csp"
        DeployPath="${cspdir}/csp/${namespace}/"
        MatchRoles=":{$dbrole}"
        PasswordAuthEnabled="0"
        Recurse="1"
        ServeFiles="1"
        ServeFilesTimeout="3600"
        UnauthenticatedEnabled="1"
        Url="/disease-predictor"
        UseSessionCookie="2"
      />
    </Module>
   
  </Document>
</Export>

腎臓病を予測するための Web フロントエンドとバックエンドのアプリケーション

Open Exchange アプリのリンク(https://openexchange.intersystems.com/package/Disease-Predictor)に移動し、以下の手順に従います。

  1. リポジトリを任意のローカルディレクトリに Clone/git pull します。
$ git clone https://github.com/yurimarx/predict-diseases.git
  1. このディレクトリで Docker ターミナルを開き、以下を実行します。
$ docker-compose build
  1. IRIS コンテナを実行します。
$ docker-compose up -d
  1. AI モデルをトレーニングするため管理ポータルのクエリ実行(http://localhost:52773/csp/sys/exp/%25CSP.UI.Portal.SQL.Home.zen?$NAMESPACE=USER)に移動します。

  2. トレーニングに使用するビューを作成します。

CREATE VIEW KidneyDiseaseTrain AS SELECT age, al, ane, appet, ba, bgr, bp, bu, cad, classification, dm, hemo, htn, pc, pcc, pcv, pe, pot, rbc, rc, sc, sg, sod, su, wc FROM dc_data_health.KidneyDisease
  1. ビューを使用して AI モデルを作成します。
CREATE MODEL KidneyDiseaseModel PREDICTING (classification) FROM KidneyDiseaseTrain
  1. モデルをトレーニングします。
TRAIN MODEL KidneyDiseaseModel
  1. http://localhost:52773/disease-predictor/index.html に移動し、Disease Predictor フロントエンドを使用して、以下のように疾患を予測します。 Kidney-Predictor

背後の処理

腎臓病を予測するためのバックエンドのクラスメソッド

InterSystems IRIS では、前に作成されたモデルを使って、SELECT の実行により予測することができます。

 
腎臓病を予測するためのバックエンドのクラスメソッド
///腎臓病の予測
ClassMethodPredictKidneyDisease()As%Status
{
    Try{
      Setdata={}.%FromJSON(%request.Content)
      Set%response.Status=200
      Set%response.Headers("Access-Control-Allow-Origin")="*"
     
      Setqry="SELECT PREDICT(KidneyDiseaseModel) As PredictedKidneyDisease, "
                  _"age, al, ane, appet, ba, bgr, bp, bu, cad, dm, "
                  _"hemo, htn, pc, pcc, pcv, pe, pot, rbc, rc, sc, sg, sod, su, wc "
                  _"FROM (SELECT "_data.age_" AS age, "
                  _data.al_" As al, "
                  _"'"_data.ane_"'"_" AS ane, "
                  _"'"_data.appet_"'"_" AS appet, "
                  _"'"_data.ba_"'"_" As ba, "
                  _data.bgr_" As bgr, "
                  _data.bp_" AS bp, "
                  _data.bu_" AS bu, "
                  _"'"_data.cad_"'"_" As cad, "
                  _"'"_data.dm_"'"_" As dm, "
                  _data.hemo_" AS hemo, "
                  _"'"_data.htn_"'"_" AS htn, "
                  _"'"_data.pc_"'"_" As pc, "
                  _"'"_data.pcc_"'"_" As pcc, "
                  _data.pcv_" AS pcv, "
                  _"'"_data.pe_"'"_" AS pe, "
                  _data.pot_" As pot, "
                  _"'"_data.rbc_"'"_" As rbc, "
                  _data.rc_" AS rc, "
                  _data.sc_" AS sc, "
                  _data.sg_" As sg, "
                  _data.sod_" As sod, "
                  _data.su_" AS su, "
                  _data.wc_" AS wc)"
      SettStatement=##class(%SQL.Statement).%New()
      SetqStatus=tStatement.%Prepare(qry)
      IfqStatus'=1{WRITE"%Prepare failed:"DO$System.Status.DisplayError(qStatus)QUIT}
      Setrset=tStatement.%Execute()
      Dorset.%Next()
 
      SetResponse={}
      SetResponse.classification=rset.PredictedKidneyDisease
      SetResponse.age=rset.age
      SetResponse.al=rset.al
      SetResponse.ane=rset.ane
      SetResponse.appet=rset.appet
      SetResponse.ba=rset.ba
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">bgr</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">bgr</span><span style="color: #d4d4d4;"> </span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">bp</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">bp</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">bu</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">bu</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">cad</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">cad</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">dm</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">dm</span><span style="color: #d4d4d4;"> </span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">hemo</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">hemo</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">htn</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">htn</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">pc</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">pc</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">pcc</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">pcc</span><span style="color: #d4d4d4;"> </span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">pcv</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">pcv</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">pe</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">pe</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">pot</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">pot</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">rbc</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">rbc</span><span style="color: #d4d4d4;"> </span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">rc</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">rc</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">sc</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">sc</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">sg</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">sg</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">sod</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">sod</span><span style="color: #d4d4d4;"> </span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">su</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">su</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">wc</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">wc</span>
          </div>   
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Write</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">%ToJSON</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Return</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">1</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">    </span><span style="color: #ffffff;">}</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">Catch</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">err</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">{</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">write</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">!</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">"Error name: "</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">?</span><span style="color: #d4b57c;">20</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">err</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">Name</span><span style="color: #ffffff;">,</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">          </span><span style="color: #ffffff;">!</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">"Error code: "</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">?</span><span style="color: #d4b57c;">20</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">err</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">Code</span><span style="color: #ffffff;">,</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">          </span><span style="color: #ffffff;">!</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">"Error location: "</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">?</span><span style="color: #d4b57c;">20</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">err</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">Location</span><span style="color: #ffffff;">,</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">          </span><span style="color: #ffffff;">!</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">"Additional data: "</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">?</span><span style="color: #d4b57c;">20</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">err</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">Data</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">!</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Return</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;"></span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">    </span><span style="color: #ffffff;">}</span>
          </div>
          
          <div>
            <span style="color: #ffffff;">}</span>
          </div>
        </div>
      </div>
    </div>

これで、どの Web アプリケーションもこの予測を使用して、結果を表示できるようになりました。 predict-diseases アプリケーションのソースコードは、frontend フォルダをご覧ください。

0
0 151
記事 Toshihiko Minamoto · 3月 10, 2023 9m read

糖尿病は、医学会でよく知られるいくつかのパラメーターから発見することが可能です。 この測定により、医学界とコンピューター化されたシステム(特に AI)を支援すべく、(米)国立糖尿病・消化器・腎疾病研究所(NIDDK)は、糖尿病の検出/予測における ML アルゴリズムをトレーニングするための非常に便利なデータセットを公開しました。 このデータセットは、ML の最大級のデータリポジトリとして最もよく知られている Kaggle に公開されています: https://www.kaggle.com/datasets/mathchi/diabetes-data-set

糖尿病データセットには、以下のメタデータ情報が含まれています(出典: https://www.kaggle.com/datasets/mathchi/diabetes-data-set):

  • Pregnancies: 妊娠回数
  • Glucose: 経口ブドウ糖負荷試験における 2 時間後の血漿グルコース濃度
  • BloodPressure: 拡張期血圧(mm Hg)
  • SkinThickness: 上腕三頭筋皮下脂肪厚(mm)
  • Insulin: 2 時間血清インスリン(mu U/ml)
  • BMI: ボディマス指数(体重 kg/(身長 m)^2)
  • DiabetesPedigreeFunction: 糖尿病血統要因(親族の糖尿病歴、およびこれらの親族と患者の遺伝的関係に関するいくつかのデータが提供されました。 この遺伝的影響の測定により、真性糖尿病の発症に伴う遺伝的リスクについての考えが得られました - 出典: https://machinelearningmastery.com/case-study-predicting-the-onset-of-diabetes-within-five-years-part-1-of-3/
  • Age: 年齢
  • Outcome: クラス変数(0 または 1)

インスタンス数: 768

属性数: 8 + class

各属性について:(すべて数値)

  1. 妊娠回数
  2. 経口ブドウ糖負荷試験における 2 時間後の血漿グルコース濃度
  3. 拡張期血圧(mm Hg)
  4. 上腕三頭筋皮下脂肪厚(mm)
  5. 2 時間血清インスリン(mu U/ml)
  6. ボディマス指数(体重 kg/(身長 m)^2)
  7. 糖尿病血統要因
  8. 年齢
  9. クラス変数(0 または 1)

属性値の欠落: あり

クラス分布:(クラス値 1 は「糖尿病の検査で陽性」として解釈)

Kaggle から糖尿病データを取得する

Kaggle の糖尿病データは、Health-Dataset アプリケーション(https://openexchange.intersystems.com/package/Health-Dataset)を使って IRIS テーブルに読み込めます。 これを行うには、module.xml プロジェクトから依存関係(Health Dataset 用の ModuleReference)を設定します。

 
Health Dataset アプリケーションリファレンスを含む Module.xml
<?xml version="1.0" encoding="UTF-8"?>
<Exportgenerator="Cache"version="25">
    <div>
      <span style="color: #d4d4d4;">  </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">Document</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">name</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"predict-diseases.ZPM"</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">    </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">Module</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">      </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">Name</span><span style="color: #808080;">&gt;</span><span style="color: #d4d4d4;">predict-diseases</span><span style="color: #808080;">&lt;/</span><span style="color: #569cd6;">Name</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">      </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">Version</span><span style="color: #808080;">&gt;</span><span style="color: #d4d4d4;">1.0.0</span><span style="color: #808080;">&lt;/</span><span style="color: #569cd6;">Version</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">      </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">Packaging</span><span style="color: #808080;">&gt;</span><span style="color: #d4d4d4;">module</span><span style="color: #808080;">&lt;/</span><span style="color: #569cd6;">Packaging</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">      </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">SourcesRoot</span><span style="color: #808080;">&gt;</span><span style="color: #d4d4d4;">src/iris</span><span style="color: #808080;">&lt;/</span><span style="color: #569cd6;">SourcesRoot</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">      </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">Resource</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">Name</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"dc.predict.disease.PKG"</span><span style="color: #808080;">/&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">      </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">Dependencies</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">ModuleReference</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">          </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">Name</span><span style="color: #808080;">&gt;</span><span style="color: #d4d4d4;">swagger-ui</span><span style="color: #808080;">&lt;/</span><span style="color: #569cd6;">Name</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">          </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">Version</span><span style="color: #808080;">&gt;</span><span style="color: #d4d4d4;">1.*.*</span><span style="color: #808080;">&lt;/</span><span style="color: #569cd6;">Version</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #808080;">&lt;/</span><span style="color: #569cd6;">ModuleReference</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">ModuleReference</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">          </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">Name</span><span style="color: #808080;">&gt;</span><span style="color: #d4d4d4;">dataset-health</span><span style="color: #808080;">&lt;/</span><span style="color: #569cd6;">Name</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">          </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">Version</span><span style="color: #808080;">&gt;</span><span style="color: #d4d4d4;">*</span><span style="color: #808080;">&lt;/</span><span style="color: #569cd6;">Version</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #808080;">&lt;/</span><span style="color: #569cd6;">ModuleReference</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">      </span><span style="color: #808080;">&lt;/</span><span style="color: #569cd6;">Dependencies</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">       </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">CSPApplication</span><span style="color: #d4d4d4;"> </span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">Url</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"/predict-diseases"</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">DispatchClass</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"dc.predict.disease.PredictDiseaseRESTApp"</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">MatchRoles</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">":{$dbrole}"</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">PasswordAuthEnabled</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"1"</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">UnauthenticatedEnabled</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"1"</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">Recurse</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"1"</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">UseCookies</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"2"</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">CookiePath</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"/predict-diseases"</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">       </span><span style="color: #808080;">/></span>
    </div>

    <div>
      <span style="color: #d4d4d4;">       </span><span style="color: #808080;">&lt;</span><span style="color: #569cd6;">CSPApplication</span><span style="color: #d4d4d4;"> </span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">CookiePath</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"/disease-predictor/"</span><span style="color: #d4d4d4;"> </span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">DefaultTimeout</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"900"</span><span style="color: #d4d4d4;"> </span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">SourcePath</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"/src/csp"</span><span style="color: #d4d4d4;"> </span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">DeployPath</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"${cspdir}/csp/${namespace}/"</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">MatchRoles</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">":{$dbrole}"</span><span style="color: #d4d4d4;"> </span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">PasswordAuthEnabled</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"0"</span><span style="color: #d4d4d4;"> </span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">Recurse</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"1"</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">ServeFiles</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"1"</span><span style="color: #d4d4d4;"> </span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">ServeFilesTimeout</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"3600"</span><span style="color: #d4d4d4;"> </span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">UnauthenticatedEnabled</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"1"</span><span style="color: #d4d4d4;"> </span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">Url</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"/disease-predictor"</span><span style="color: #d4d4d4;"> </span>
    </div>

    <div>
      <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">UseSessionCookie</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"2"</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">      </span><span style="color: #808080;">/></span>
    </div>

    <div>
      <span style="color: #d4d4d4;">    </span><span style="color: #808080;">&lt;/</span><span style="color: #569cd6;">Module</span><span style="color: #808080;">&gt;</span>
    </div>

    <div>
      <span style="color: #d4d4d4;">    </span>
    </div>

    <div>
      <span style="color: #d4d4d4;">  </span><span style="color: #808080;">&lt;/</span><span style="color: #569cd6;">Document</span><span style="color: #808080;">&gt;</span>
    </div>
</Export>

糖尿病を予測するための Web フロントエンドとバックエンドのアプリケーション

Open Exchange アプリのリンク(https://openexchange.intersystems.com/package/Disease-Predictor)に移動し、以下の手順に従います。

  1. リポジトリを任意のローカルディレクトリに Git pull します。
$ git clone https://github.com/yurimarx/predict-diseases.git
  1. このディレクトリで Docker ターミナルを開き、以下を実行します。
$ docker-compose build
  1. IRIS コンテナを実行します。
$ docker-compose up -d 
  1. AI モデルをトレーニングするための Execute Query into Management Portal(http://localhost:52773/csp/sys/exp/%25CSP.UI.Portal.SQL.Home.zen?$NAMESPACE=USER)に移動します。
  2. トレーニングに使用するビューを作成します。
CREATE VIEW DiabetesTrain AS SELECT Outcome, age, bloodpressure, bmi, diabetespedigree, glucose, insulin, pregnancies, skinthickness FROM dc_data_health.Diabetes
  1. ビューを使用して AI モデルを作成します。
CREATE MODEL DiabetesModel PREDICTING (Outcome) FROM DiabetesTrain
  1. モデルをトレーニングします。
TRAIN MODEL DiabetesModel
  1. http://localhost:52773/disease-predictor/index.html に移動し、Disease Predictor フロントエンドを使用して、以下のように疾患を予測します。 Disease-Predictor

背後の処理

糖尿病を予測するためのバックエンドのクラスメソッド

InterSystems IRIS では、前に作成されたモデルを使って予測するSELECT を実行することができます。

 
糖尿病を予測するためのバックエンドのクラスメソッド
///Predict Diabetes
ClassMethodPredictDiabetes()As%Status
          <div>
            <span style="color: #ffffff;">{</span>
          </div>
          <div>

    Try{

          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">data</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">{</span><span style="color: #ffffff;">}</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">%FromJSON</span><span style="color: #ffffff;">(</span><span style="color: #64c9ff;">%request</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">Content</span><span style="color: #ffffff;">)</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">qry</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">"SELECT PREDICT(DiabetesModel) As PredictedDiabetes, "</span>
          </div>
          <div>
            <span style="color: #d4d4d4;">                  </span><span style="color: #ffffff;">_</span><span style="color: #d4b57c;">"age, bloodpressure, bmi, diabetespedigree, glucose, insulin, "</span>
          </div>
          <div>
            <span style="color: #d4d4d4;">                  </span><span style="color: #ffffff;">_</span><span style="color: #d4b57c;">"pregnancies, skinthickness "</span><span style="color: #d4d4d4;"> </span>
          </div>
          <div>
            <span style="color: #d4d4d4;">                  </span><span style="color: #ffffff;">_</span><span style="color: #d4b57c;">"FROM (SELECT "</span><span style="color: #ffffff;">_</span><span style="color: #ade2ff;">data</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">age</span><span style="color: #ffffff;">_</span><span style="color: #d4b57c;">" AS age, "</span>
          </div>
          <div>
            <span style="color: #d4d4d4;">                  </span><span style="color: #ffffff;">_</span><span style="color: #ade2ff;">data</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">bloodpressure</span><span style="color: #ffffff;">_</span><span style="color: #d4b57c;">" As bloodpressure, "</span><span style="color: #d4d4d4;"> </span>
          </div>
          <div>
            <span style="color: #d4d4d4;">                  </span><span style="color: #ffffff;">_</span><span style="color: #ade2ff;">data</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">bmi</span><span style="color: #ffffff;">_</span><span style="color: #d4b57c;">" AS bmi, "</span>
          </div>
          <div>
            <span style="color: #d4d4d4;">                  </span><span style="color: #ffffff;">_</span><span style="color: #ade2ff;">data</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">diabetespedigree</span><span style="color: #ffffff;">_</span><span style="color: #d4b57c;">" AS diabetespedigree, "</span>
          </div>
          <div>
            <span style="color: #d4d4d4;">                  </span><span style="color: #ffffff;">_</span><span style="color: #ade2ff;">data</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">glucose</span><span style="color: #ffffff;">_</span><span style="color: #d4b57c;">" As glucose, "</span>
          </div>
          <div>
            <span style="color: #d4d4d4;">                  </span><span style="color: #ffffff;">_</span><span style="color: #ade2ff;">data</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">insulin</span><span style="color: #ffffff;">_</span><span style="color: #d4b57c;">" AS insulin, "</span>
          </div>
          <div>
            <span style="color: #d4d4d4;">                  </span><span style="color: #ffffff;">_</span><span style="color: #ade2ff;">data</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">pregnancies</span><span style="color: #ffffff;">_</span><span style="color: #d4b57c;">" As pregnancies, "</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">                  </span><span style="color: #ffffff;">_</span><span style="color: #ade2ff;">data</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">skinthickness</span><span style="color: #ffffff;">_</span><span style="color: #d4b57c;">" AS skinthickness)"</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">tStatement</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #85a6ff;">##class</span><span style="color: #ffffff;">(</span><span style="color: #4ec9b0;">%SQL</span><span style="color: #4ec9b0;">.</span><span style="color: #4ec9b0;">Statement</span><span style="color: #ffffff;">)</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">%New</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">qStatus</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">tStatement</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">%Prepare</span><span style="color: #ffffff;">(</span><span style="color: #ade2ff;">qry</span><span style="color: #ffffff;">)</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">If</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">qStatus</span><span style="color: #ffffff;">'=</span><span style="color: #d4b57c;">1</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">{</span><span style="color: #ffffff;">WRITE</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">"%Prepare failed:"</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">DO</span><span style="color: #d4d4d4;"> </span><span style="color: #85a6ff;">$System</span><span style="color: #4ec9b0;">.</span><span style="color: #4ec9b0;">Status</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">DisplayError</span><span style="color: #ffffff;">(</span><span style="color: #ade2ff;">qStatus</span><span style="color: #ffffff;">)</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">QUIT</span><span style="color: #ffffff;">}</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">tStatement</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">%Execute</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Do</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">%Next</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span>
          </div>   
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">{</span><span style="color: #ffffff;">}</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">PredictedDiabetes</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">PredictedDiabetes</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">age</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">age</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">bloodpressure</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">bloodpressure</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">bmi</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">bmi</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">diabetespedigree</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">diabetespedigree</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">glucose</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">glucose</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">insulin</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">insulin</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">pregnancies</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">pregnancies</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">skinthickness</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">rset</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">skinthickness</span>
          </div>   
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #64c9ff;">%response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">Status</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">200</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #64c9ff;">%response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">Headers</span><span style="color: #ffffff;">(</span><span style="color: #d4b57c;">"Access-Control-Allow-Origin"</span><span style="color: #ffffff;">)</span><span style="color: #ffffff;">=</span><span style="color: #d4b57c;">"*"</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Write</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">%ToJSON</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Return</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">1</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">    </span><span style="color: #ffffff;">}</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">Catch</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">err</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">{</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">write</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">!</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">"Error name: "</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">?</span><span style="color: #d4b57c;">20</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">err</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">Name</span><span style="color: #ffffff;">,</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">          </span><span style="color: #ffffff;">!</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">"Error code: "</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">?</span><span style="color: #d4b57c;">20</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">err</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">Code</span><span style="color: #ffffff;">,</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">          </span><span style="color: #ffffff;">!</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">"Error location: "</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">?</span><span style="color: #d4b57c;">20</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">err</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">Location</span><span style="color: #ffffff;">,</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">          </span><span style="color: #ffffff;">!</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">"Additional data: "</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">?</span><span style="color: #d4b57c;">20</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">err</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">Data</span><span style="color: #ffffff;">,</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">!</span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">      </span><span style="color: #ffffff;">Return</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;"></span>
          </div>
          
          <div>
            <span style="color: #d4d4d4;">    </span><span style="color: #ffffff;">}</span>
          </div>
          
          <div>
            <span style="color: #ffffff;">}</span>
          </div>
        </div>
      </div>
    </div>

これで、どの Web アプリケーションもこの予測を使用して、結果を表示できるようになりました。 predict-diseases アプリケーションのソースコードは、frontend フォルダをご覧ください。

0
0 399
記事 Mihoko Iijima · 3月 9, 2023 2m read

開発者の皆さん、こんにちは!

前の記事では、開発者向け情報を集めた「Developer Hub」をご紹介しましたが、この記事では Developer Hub のチュートリアルの中から「機械学習」をテーマとしたチュートリアル:IntegratedML についてご紹介します

 InterSystems IRISには、機械学習を行うために必要なプロセスのいくつかを自動化するAutoMLの機能が組み込まれていて、機能名として「IntegratedML」と呼んでいます。機能概要については、末尾のビデオをご参照さい。

チュートリアルを始めるための準備は不要で、 ボタンをクリックするだけでチュートリアルを開始できます。

0
0 209
記事 Toshihiko Minamoto · 12月 16, 2022 6m read

母体リスクは、医学界でよく知られているいくつかのパラメーターから測定できます。 この測定により、医学界とコンピューター化されたシステム(特に AI)を支援すべく、科学者である Yasir Hussein Shakir は、母体リスクの検出/予測における ML アルゴリズムをトレーニングするための非常に便利なデータセットを公開しました。 このデータセットは、ML の最大級のデータリポジトリとして最もよく知られている Kaggle に公開されています。

https://www.kaggle.com/code/yasserhessein/classification-maternal-health-5-algorithms-ml

データセットについて

妊娠中と出産後の母体のヘルスケアに関する情報の不足により、妊娠中の女性の多くは、妊娠に関わる問題で死亡しています。 これは、農村地域や新興国の下位中流家庭の間でより一般的に起きている問題です。 妊娠中は、状態を絶えず観察することで、胎児の適切な成長と安全な出産を保証する必要があります(出典: https://www.kaggle.com/code/yasserhessein/classification-maternal-health-5-algorithms-ml)。

データは、IoT ベースのリスク監視システムを通じて、様々な病院、地域の診療所、妊産婦ヘルスケアから収集されています。

  • Age: 女性が妊娠したときの年齢
  • SystolicBP: 最高血圧(mmHg)。妊娠中に重要な属性の 1 つ。
  • DiastolicBP: 最低血圧(mmHg)。妊娠中に重要な属性の 1 つ。
  • BS: モル濃度(mmol/L)による血糖値。
  • HeartRate: 1 分あたりの通常の安静時心拍数。
  • Risk Level: 前の属性を考慮した妊娠中の予測リスク強度レベル。

Kaggle から母体リスクデータを取得する

Kaggle の母体リスクデータは、Health-Dataset アプリケーション(https://openexchange.intersystems.com/package/Health-Dataset)を使って IRIS テーブルに読み込めます。 これを行うには、module.xml プロジェクトから依存関係(Health Dataset 用の ModuleReference)を設定します。

 
Health Dataset アプリケーションリファレンスを含む Module.xml
<?xml version="1.0" encoding="UTF-8"?>
<Exportgenerator="Cache"version="25">
  <Documentname="predict-diseases.ZPM">
    <Module>
      <Name>predict-diseases</Name>
      <Version>1.0.0</Version>
      <Packaging>module</Packaging>
      <SourcesRoot<src/iris</SourcesRoot>
      <ResourceName="dc.predict.disease.PKG"/>
      <Dependencies>
        <ModuleReference>
          <Name>swagger-ui</Name>
          <Version>1.*.*</Version>
        </ModuleReference>
        <ModuleReference>
          <Name>dataset-health</Name>
          <Version>*</Version>
        </ModuleReference>
      </Dependencies>
       <CSPApplication
        Url="/predict-diseases"
        DispatchClass="dc.predict.disease.PredictDiseaseRESTApp"
        MatchRoles=":{$dbrole}"
        PasswordAuthEnabled="1"
        UnauthenticatedEnabled="1"
        Recurse="1"
        UseCookies="2"
        CookiePath="/predict-diseases"
       />
       <CSPApplication
        CookiePath="/disease-predictor/"
        DefaultTimeout="900"
        SourcePath="/src/csp"
        DeployPath="${cspdir}/csp/${namespace}/"
        MatchRoles=":{$dbrole}"
        PasswordAuthEnabled="0"
        Recurse="1"
        ServeFiles="1"
        ServeFilesTimeout="3600"
        UnauthenticatedEnabled="1"
        Url="/disease-predictor"
        UseSessionCookie="2"
      />
    </Module>
   
  </Document>
</Export>

母体リスクを予測するための Web フロントエンドとバックエンドのアプリケーション

Open Exchange アプリのリンク(https://openexchange.intersystems.com/package/Disease-Predictor)に移動し、以下の手順に従います。

  • リポジトリを任意のローカルディレクトリに Clone/git pull します。
$ git clone https://github.com/yurimarx/predict-diseases.git
  • このディレクトリで Docker ターミナルを開き、以下を実行します。
$ docker-compose build
  • IRIS コンテナを実行します。
$ docker-compose up -d 
CREATE VIEW MaternalRiskTrain AS SELECT BS, BodyTemp, DiastolicBP, HeartRate, RiskLevel, SystolicBP, age FROM dc_data_health.MaternalHealthRisk
  • ビューを使用して AI モデルを作成します。
CREATE MODEL MaternalRiskModel PREDICTING (RiskLevel) FROM MaternalRiskTrain 
  • モデルをトレーニングします。
TRAIN MODEL MaternalRiskModel

背後の処理

母体リスク疾患を予測するためのバックエンドのクラスメソッド

InterSystems IRIS では、前に作成されたモデルを使って、SELECT の実行により予測することができます。

 
母体リスク疾患を予測するためのバックエンドのクラスメソッド
///母体リスクの予測
ClassMethodPredictMaternalRisk()As%Status
{
    Try{
      Setdata={}.%FromJSON(%request.Content)
      Set%response.Status=200
      Set%response.Headers("Access-Control-Allow-Origin")="*"
     
      Setqry="SELECT PREDICT(MaternalRiskModel) As PredictedMaternalRisk, "
                  _"age, BS, BodyTemp, DiastolicBP, HeartRate, SystolicBP "
                  _"FROM (SELECT "_data.BS_" AS BS, "
                  _data.BodyTemp_" As BodyTemp, "
                  _data.DiastolicBP_" AS DiastolicBP, "
                  _data.HeartRate_" AS HeartRate, "
                  _data.SystolicBP_" As SystolicBP, "
                  _data.Age_" AS age)"
      SettStatement=##class(%SQL.Statement).%New()
      SetqStatus=tStatement.%Prepare(qry)
      IfqStatus'=1{WRITE"%Prepare failed:"DO$System.Status.DisplayError(qStatus)QUIT}
      Setrset=tStatement.%Execute()
      Dorset.%Next()
 
      SetResponse={}
      SetResponse.PredictedMaternalRisk=rset.PredictedMaternalRisk
      SetResponse.Age=rset.Age
      SetResponse.SystolicBP=rset.SystolicBP
      SetResponse.DiastolicBP=rset.DiastolicBP
      SetResponse.BS=rset.BS
      SetResponse.BodyTemp=rset.BodyTemp
      SetResponse.HeartRate=rset.HeartRate
 
      WriteResponse.%ToJSON()
      Return1
     
    }Catcherr{
      write!,"Error name: ",?20,err.Name,
          !,"Error code: ",?20,err.Code,
          !,"Error location: ",?20,err.Location,
          !,"Additional data: ",?20,err.Data,!
      Return
    }
}

これで、どの Web アプリケーションもこの予測を使用して、結果を表示できるようになりました。 predict-diseases アプリケーションのソースコードは、frontend フォルダをご覧ください。

0
0 144
お知らせ Mihoko Iijima · 5月 29, 2022

開発者のみなさん、こんにちは!

2022年3月9日開催「InterSystems Japan Virtual Summit 2022」のセッション「SQLでどこまでできる? ~データロードから機械学習まで~」のアーカイブを YouTube に公開いたしました。

(プレイリストはこちら


データベースのテーブルにアクセスするためにSQLを利用するのは「ご飯を食べるときは箸を使います」と同じぐらい開発者にとって当たり前のことだと思いますが、SQLで分析や機械学習まで行えたらどうでしょうか。

便利ですよね?

本セッションではInterSystems IRISのSQLを使って、どこまでの操作ができるのかについて、デモを交えながらご紹介します。

ぜひ、動画をご参照ください。

<iframe width="521" height="293" src="https://www.youtube.com/embed/H4D4tUNQSnw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

【目次】

00:44 貯めたデータの使い道

02:39 分析(Window)関数を新たに追加された便利な SQL コマンドについて

03:59 分析(Window)関数のデモ

11:07 SQL に似た文法で機械学習ができる機能のご紹介

14:58 モデル作成・学習・検証・予測の構文紹介

16:31 Integrated ML のデモ

19:40 Interoperability(相互運用性機能)を利用した検証結果の通知例ご紹介

23:24 検証結果の通知例 デモ

27:37 まとめ
 ご参考:Embedded Python で広がる InterSystems IRIS の世界(2022年3月9日開催)

0
0 157
お知らせ Mihoko Iijima · 4月 4, 2022

開発者のみなさん、こんにちは!

2021年10月に4回シリーズで開催した「InterSystems IRIS 開発者向けウェビナー」第3回目の「SQLから始める機械学習 ~IntegratedMLのご紹介~」のアーカイブをYouTubeに公開いたしました。

InterSystemsは、アプリケーション開発者の方々が、IRIS data platformに保存されているデータとSQLを用いて、機械学習を容易に利用できる仕組み「IntegratedML」を開発しました。
このビデオでは、IntegratedMLの概要についてご紹介いたします。

ぜひご覧ください!

(IRIS 2021.1新機能全体のご紹介については、こちらのYouTubeをご参照ください。)

【目次】

0:00 機械学習の概要と課題、AutoMLについて

8:30 IntegratedMLについて

13:20 IntegratedMLの文法

18:32 デモ

26:50 まとめ

0
0 90
記事 Toshihiko Minamoto · 2月 14, 2022 19m read

キーワード: IRIS、IntegratedML、Flask、FastAPI、Tensorflow Serving、HAProxy、Docker、Covid-19

目的:

過去数か月に渡り、潜在的なICU入室を予測するための単純なCovid-19 X線画像分類器やCovid-19ラボ結果分類器など、ディープラーニングと機械学習の簡単なデモをいくつか見てきました。  また、ICU分類器のIntegratedMLデモ実装についても見てきました。  「データサイエンス」の旅路はまだ続いていますが、「データエンジニアリング」の観点から、AIサービスデプロイメントを試す時期が来たかもしれません。これまでに見てきたことすべてを、一式のサービスAPIにまとめることはできるでしょうか。  このようなサービススタックを最も単純なアプローチで達成するには、どういった一般的なツール、コンポーネント、およびインフラストラクチャを活用できるでしょうか。

対象範囲

対象:

ジャンプスタートとして、docker-composeを使用して、次のDocker化されたコンポーネントをAWS Ubuntuサーバーにデプロイできます。

  • **HAProxy ** - ロードバランサー
  • Gunicorn と **Univorn ** - Webゲートウェイ****サーバー
  • FlaskFastAPI - WebアプリケーションUI、サービスAPI定義、およびヒートマップ生成などのアプリケーションサーバー
  • Tensorflow Model ServingTensorflow-GPU Model Serving - 画像や分類などのアプリケーションバックエンドサーバー
  • IRIS IntegratedML - SQL インターフェースを備えたアプリとデータベースを統合した AutoML
  • ベンチマーキング用クライアントをエミュレートする、JupyterノートブックのPython3
  •  Dockerとdocker-compose
  • Testla T4 GPU搭載のAWS Ubuntu 16.04 

注意: GPUを使用したTensorflow Servingはデモのみを目的としています。GPU関連の画像(dockerfile)と構成(docker-compose.yml)は、単純にオフにできます。

対象外またはウィッシュリスト:

  • Nginx またはApacheなどのWebサーバーは、今のところこのデモでは省略されています。
  • RabbitMQとRedis  - IRISまたはEnsembleと置き換えられる、信頼性の高いメッセージングキューブローカー。   
  • IAMIntersystems API Manger)またはKongはウィッシュリストに含まれます。
  • **SAM **(InterSystemsのシステムアラートと監視) 
  • Kubernetes Operator付きのICMInterSystems Cloud Manager)- 誕生したときからずっとお気に入りの1つです。
  • FHIR(IntesyStems IRISベースのFHIR R4サーバーとFHIRアプリのSMART用FHIRサンドボックス)
  • CI/CD開発ツールまたはGithub Actions

「機械学習エンジニア」は、サービスのライフサイクルに沿って本番環境をプロビジョニングする際に、必然的にこれらのすべてのコンポーネントを操作しなければならないでしょう。 今後徐々に、焦点を当てていきたいと思います。

GitHubリポジトリ

全ソースコードの場所: https://github.com/zhongli1990/covid-ai-demo-deployment

また、新しいリポジトリとともに、integratedML-demo-templateリポジトリも再利用します。
 

デプロイメントのパターン

以下に、この「DockerでのAIデモ」テストフレームワークの論理的なデプロイパターンを示します。

デモの目的により、意図的にディープラーニング分類とWebレンダリング用に個別のスタックを2つ作成し、HAProxyをソフトロードバランサーとして使用して、受信するAPIリクエストをこれらの2つのスタックでステートレスに分散できるようにしました。

  • Guniorn + Flask + Tensorflow Serving
  • Univcorn + FaskAPI + Tensorflow Serving GPU

前の記事のICU入室予測と同様に、機械学習デモのサンプルには、IntegratedMLを使用したIRISを使用します。

現在のデモでは、本番サービスでは必要または検討される共通コンポーネントをいくつか省略しました。

  • Webサーバー: NginxまたはApacheなど。 HAProxyとGunicorn/Uvicornの間で、適切なHTTPセッション処理を行うために必要となります(DoS攻撃を防止するなど)。
  • キューマネージャーとDB: RabbitMQやRedisなど。Flask/FastAPIとバックエンドサービングの間で、信頼性のある非同期サービングとデータ/構成の永続性などに使用されます。  
  • APIゲートウェイ: IAMまたはKongクラスター。単一障害点を作らないように、HAProxyロードバランサーとAPI管理用Webサーバーの間に使用されます。
  • 監視とアラート: SAMが適切でしょう。
  • CI/CD開発のプロビジョニング: クラウドニューラルデプロイメントと管理、およびその他の一般的な開発ツールによるCI/CDにはK8を使用したICMが必要です。

実際のところ、IRIS自体は、信頼性の高いメッセージングのためのエンタープライズ級のキューマネージャーとしても、高性能データベースとしても確実に使用することができます。 パターン分析では、IRISがRabbitMQ/Redis/MongoDBなどのキューブローカーとデータベースの代わりになることは明らかであるため、レイテンシが大幅に低く、より優れたスループットパフォーマンスとさらに統合する方が良いでしょう。  さらに、IRIS Webゲートウェイ(旧CSPゲートウェイ)は、GunicornやUvicornなどの代わりに配置できますよね?  

環境トポロジー

上記の論理パターンを全Dockerコンポーネントに実装するには、いくつかの一般的なオプションがあります。 頭に思い浮かぶものとしては以下のものがあります。  

  • docker-compose
  • docker swarmなど
  • Kubernetesなど 
  • K8演算を使用したICM

このデモは、機能的なPoCといくつかのベンチマーキングを行うために、「docker-compose」から始めます。 もちろん、いつかはK8やICMを使いたいとも考えています。 

docker-compose.ymlファイルに説明されているように、AWS Ubuntuサーバーでの環境トポロジーの物理的な実装は、以下のようになります。  

上図は、全Dockerインスタンスのサービスポートが、デモの目的でどのようにマッピングされており、Ubuntuサーバーで直接公開されているかを示したものです。 本番環境では、すべてセキュリティ強化される必要があります。 また、純粋なデモの目的により、すべてのコンテナは同じDockerネットワークに接続されています。本番環境では、外部ルーティング可能と内部ルーティング不可能として分離されます。

Docker化コンポーネント 

以下は、docker-compose.ymlファイルに示されるとおり、ホストマシン内でこれらのストレージボリュームが各コンテナインスタンスにどのようにマウントされているかを示します。 

ubuntu@ip-172-31-35-104:/zhong/flask-xray$ tree ./ -L 2

./├── covid19                             (Flask+GunicornコンテナとTensorflow Servingコンテナがここにマウントされます)├── app.py                                (Flaskメインアプリ:  WebアプリケーションとAPIサービスインターフェースの両方がここに定義されて実装されます)├── covid19_models               (CPU使用の画像分類Tensorflow Servingコンテナ用のTensorflowモデルはここに公開されてバージョン管理されます)├── Dockerfile                          (Flask サーバーとGunicorn:      CMD ["gunicorn", "app:app", "--bind", "0.0.0.0:5000", "--workers", "4", "--threads", "2"]├── models                               (.h5形式のFlaskアプリ用モデルとX線画像へのGrad-CAMによるヒートマップ生成のAPIデモ)├── __pycache__├── README.md├── requirements.txt             (全Flask+Gunicornアプリに必要なPythonパッケージ) ├── scripts├── static                                  (Web静的ファイル)├── templates                         (Webレンダリングテンプレート)├── tensorflow_serving        (TensorFlow Servingサービスの構成ファイル)└── test_images├── covid-fastapi                   (FastAPI+UvicornコンテナとGPU使用のTensorflow Servingコンテナはここにマウントされます)├── covid19_models            (画像分類用のTensorflow Serving GPUモデルは、ここに公開されてバージョン管理されます)├── Dockerfile                       (Uvicorn+FastAPIサーバーはここから起動されます: CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4" ]├── main.py                           (FastAPIアプリ: WebアプリケーションとAPIサービスインターフェースの両方がここに定義されて実装されます)├── models                            (.h5形式のFastAPIアプリ用モデルとX線画像へのGrad-CAMによるヒートマップ生成のAPIデモ)├── __pycache__├── README.md├── requirements.txt├── scripts├── static├── templates├── tensorflow_serving└── test_images├── docker-compose.yml      (フルスタックDocker定義ファイル。  Docker GPU「nvidia runtime」用にバージョン2.3を使用。そうでない場合はバージョン3.xを使用可)├── haproxy                             (HAProxy dockerサービスはここに定義されます。  注意: バックエンドLBにはスティッキーセッションを定義できます。 )                             ├── Dockerfile└── haproxy.cfg└── notebooks                       (TensorFlow 2.2とTensorBoardなどを含むJupyterノートブックコンテナサービス)├── Dockerfile├── notebooks                  (機能テスト用に外部APIクライアントアプリをエミュレートするサンプルノートブックファイルとロードバランサーに対してPythonによるAPIベンチマークテストを行うサンプルノートブックファイル)└── requirements.txt

注意: 上記のdocker-compose.ymlはCovid-19 X線画像のディープラーニングデモ用です。  別のintegratedML-demo-templatedocker-compose.ymlとともに、環境トポロジーに表示されるフルサービススタックを形成するために使用されています。  

サービスの起動 

すべてのコンテナサービスを起動するには、単純なdocker-compose up -dを使用します。

ubuntu@ip-172-31-35-104:~$ docker ps
CONTAINER ID        IMAGE                                 COMMAND                  CREATED             STATUS                PORTS                                                                              NAMES
31b682b6961d        iris-aa-server:2020.3AA               "/iris-main"             7 weeks ago         Up 2 days (healthy)   2188/tcp, 53773/tcp, 54773/tcp, 0.0.0.0:8091->51773/tcp, 0.0.0.0:8092->52773/tcp   iml-template-master_irisimlsvr_1
6a0f22ad3ffc        haproxy:0.0.1                         "/docker-entrypoint.…"   8 weeks ago         Up 2 days             0.0.0.0:8088->8088/tcp                                                             flask-xray_lb_1
71b5163d8960        ai-service-fastapi:0.2.0              "uvicorn main:app --…"   8 weeks ago         Up 2 days             0.0.0.0:8056->8000/tcp                                                             flask-xray_fastapi_1
400e1d6c0f69        tensorflow/serving:latest-gpu         "/usr/bin/tf_serving…"   8 weeks ago         Up 2 days             0.0.0.0:8520->8500/tcp, 0.0.0.0:8521->8501/tcp                                     flask-xray_tf2svg2_1
eaac88e9b1a7        ai-service-flask:0.1.0                "gunicorn app:app --…"   8 weeks ago         Up 2 days             0.0.0.0:8051->5000/tcp                                                             flask-xray_flask_1
e07ccd30a32b        tensorflow/serving                    "/usr/bin/tf_serving…"   8 weeks ago         Up 2 days             0.0.0.0:8510->8500/tcp, 0.0.0.0:8511->8501/tcp                                     flask-xray_tf2svg1_1
390dc13023f2        tf2-jupyter:0.1.0                     "/bin/sh -c '/bin/ba…"   8 weeks ago         Up 2 days             0.0.0.0:8506->6006/tcp, 0.0.0.0:8586->8888/tcp                                     flask-xray_tf2jpt_1
88e8709404ac        tf2-jupyter-jdbc:1.0.0-iml-template   "/bin/sh -c '/bin/ba…"   2 months ago        Up 2 days             0.0.0.0:6026->6006/tcp, 0.0.0.0:8896->8888/tcp                                     iml-template-master_tf2jupyter_1

docker-compose up --scale fastapi=2 --scale flask=2 -d   for example will horizontally scale up to 2x Gunicorn+Flask containers and 2x Univcorn+FastAPI containers:

ubuntu@ip-172-31-35-104:/zhong/flask-xray$ docker ps
CONTAINER ID        IMAGE                                 COMMAND                  CREATED             STATUS                PORTS                                                                              NAMES
dbee3c20ea95        ai-service-fastapi:0.2.0              "uvicorn main:app --…"   4 minutes ago       Up 4 minutes          0.0.0.0:8057->8000/tcp                                                             flask-xray_fastapi_2
95bcd8535aa6        ai-service-flask:0.1.0                "gunicorn app:app --…"   4 minutes ago       Up 4 minutes          0.0.0.0:8052->5000/tcp                                                             flask-xray_flask_2

... ...

「integrtedML-demo-template」の作業ディレクトリで別の「docker-compose up -d」を実行することで、上記リストのirisimlsvrとtf2jupyterコンテナが起動されています。

テスト

1. 単純なUIを備えたAIデモWebアプリ

上記のdockerサービスを起動したら、一時アドレスhttp://ec2-18-134-16-118.eu-west-2.compute.amazonaws.com:8056/のAWS EC2インスタンスにホストされているCovid-19に感染した胸部X線画像の検出用デモWebアプリにアクセスできます。

以下は、私の携帯でキャプチャした画面です。  デモUIは非常に単純です。基本的に「Choose File」をクリックして「Submit」ボタンを押せば、X線画像がアップロードされて分類レポートが表示されます。 Covid-19感染のX線画像として分類されたら、DLによって「検出された」病変領域をエミュレートするヒートマップが表示されます。そうでない場合は、分類レポートにはアップロードされたX線画像のみが表示されます。

        

このWebアプリはPythonサーバーページです。このロジックは主にFastAPI's main.pyファイルとFlask's app.pyファイルにコーディングされています。

もう少し時間に余裕がある際には、FlaskとFastAPIのコーディングと規則の違いを詳しく説明かもしれません。  実は、AIデモホスティングについて、FlaskとFastAPIとIRISの比較を行いたいと思っています。 

2. テストデモAPI      

FastAPI(ポート8056で公開)には、以下に示すSwagger APIドキュメントが組み込まれています。 これは非常に便利です。 以下のようにURLに「/docs」を指定するだけで、利用することができます。 

いくつかのプレースホルダー(/helloや/itemsなど)と実際のデモAPIインターフェース(/healthcheck、/predict、predict/heatmapなど)を組み込みました。

これらのAPIに簡単なテストを実行してみましょう私がこのAIデモサービス用に作成したJupyterノートブックサンプルの1つで、Python行を(APIクライアントアプリエミュレーターとして)いくつか実行します。  

以下では、例としてこちらのファイルを実行しています。 https://github.com/zhongli1990/covid-ai-demo-deployment/blob/master/notebooks/notebooks/Covid19-3class-Heatmap-Flask-FastAPI-TF-serving-all-in-one-HAProxy2.ipynb

まず、バックエンドのTF-Serving(ポート8511)とTF-Serving-GPU(ポート8521)が稼働していることをテストします。 

!curl http://172.17.0.1:8511/v1/models/covid19  # tensorflow serving
!curl http://172.17.0.1:8521/v1/models/covid19  # tensorflow-gpu serving
{
 "model_version_status": [
  {
   "version": "2",
   "state": "AVAILABLE",
   "status": {
    "error_code": "OK",
    "error_message": ""
   }
  }
 ]
}
{
 "model_version_status": [
  {
   "version": "2",
   "state": "AVAILABLE",
   "status": {
    "error_code": "OK",
    "error_message": ""
   }
  }
 ]
}

 

次に、以下のサービスAPIが稼働していることをテストします。

  • Gunicorn+Flask+TF-Serving
  • Unicorn+FastAPI+TF-Serving-GPU
  • 上記の両サービスの手間にあるHAProxyロードバランサー
  • r = requests.get('http://172.17.0.1:8051/covid19/api/v1/healthcheck')  # tf srving docker with cpu 
    print(r.status_code, r.text)
    r = requests.get('http://172.17.0.1:8056/covid19/api/v1/healthcheck')  # tf-serving docker with gpu
    print(r.status_code, r.text)
    r = requests.get('http://172.17.0.1:8088/covid19/api/v1/healthcheck')  # tf-serving docker with HAproxy
    print(r.status_code, r.text)

    そして、以下のような結果が期待されます。

    200 Covid19 detector API is live!
    200 "Covid19 detector API is live!\n\n"
    200 "Covid19 detector API is live!\n\n"

     

    入力X線画像の分類とヒートマップ結果を返す、/predict/heatmapなどの機能的なAPIインターフェースをテストします。  受信する画像は、API定義に従ってHTTP POST経由で送信される前にbased64にエンコードされています。

    %%time# リクエストライブラリをインポート
    import argparse
    import base64import requests# api-endpointを定義
    API_ENDPOINT = "http://172.17.0.1:8051/covid19/api/v1/predict/heatmap"image_path = './Covid_M/all/test/covid/nejmoa2001191_f3-PA.jpeg'
    #image_path = './Covid_M/all/test/normal/NORMAL2-IM-1400-0001.jpeg'
    #image_path = './Covid_M/all/test/pneumonia_bac/person1940_bacteria_4859.jpeg'
    b64_image = ""
    # JPGやPNGなどの画像をbase64形式にエンコード
    with open(image_path, "rb") as imageFile:
        b64_image = base64.b64encode(imageFile.read())# APIに送信されるデータ
    data = {'b64': b64_image}# POSTリクエストを送信しレスポンスをレスポンスオブジェクトとして保存
    r = requests.post(url=API_ENDPOINT, data=data)print(r.status_code, r.text)# レスポンスを抽出
    print("{}".format(r.text))

    このようなすべてのテスト画像もGitHubにアップロード済みです。  上記のコードの結果は以下のようになります。

    200 {"Input_Image":"http://localhost:8051/static/source/0198f0ae-85a0-470b-bc31-dc1918c15b9620200906-170443.png","Output_Heatmap":"http://localhost:8051/static/result/Covid19_98_0198f0ae-85a0-470b-bc31-dc1918c15b9620200906-170443.png.png","X-Ray_Classfication_Raw_Result":[[0.805902302,0.15601939,0.038078323]],"X-Ray_Classification_Covid19_Probability":0.98,"X-Ray_Classification_Result":"Covid-19 POSITIVE","model_name":"Customised Incpetion V3"}
    
    {"Input_Image":"http://localhost:8051/static/source/0198f0ae-85a0-470b-bc31-dc1918c15b9620200906-170443.png","Output_Heatmap":"http://localhost:8051/static/result/Covid19_98_0198f0ae-85a0-470b-bc31-dc1918c15b9620200906-170443.png.png","X-Ray_Classfication_Raw_Result":[[0.805902302,0.15601939,0.038078323]],"X-Ray_Classification_Covid19_Probability":0.98,"X-Ray_Classification_Result":"Covid-19 POSITIVE","model_name":"Customised Incpetion V3"}
    
    CPU times: user 16 ms, sys: 0 ns, total: 16 ms
    Wall time: 946 ms

     

    3. デモサービスAPIをベンチマークテストする

    HAProxyロードバランサーインスタンスをセットアップします。 また、Flaskサービスを4個のワーカーで開始し、FastAPIサービスも4個のワーカーで開始しました。

    ノートブックファイルで直接8個のPythonプロセスを作成し、8個の同時APIクライアントがデモサービスAPIにリクエストを送信する様子をエミュレートしてみてはどうでしょうか。 

    #from concurrent.futures import ThreadPoolExecutor as PoolExecutor
    from concurrent.futures import ProcessPoolExecutor as PoolExecutor
    import http.client
    import socket
    import timestart = time.time()#laodbalancer:
    API_ENDPOINT_LB = "http://172.17.0.1:8088/covid19/api/v1/predict/heatmap"
    API_ENDPOINT_FLASK = "http://172.17.0.1:8052/covid19/api/v1/predict/heatmap"
    API_ENDPOINT_FastAPI = "http://172.17.0.1:8057/covid19/api/v1/predict/heatmap"
    def get_it(url):
        try:
            # 画像をループ
            for imagePathTest in imagePathsTest:
                b64_image = ""
                with open(imagePathTest, "rb") as imageFile:
                    b64_image = base64.b64encode(imageFile.read())
        
                data = {'b64': b64_image}
                r = requests.post(url, data=data)
                #print(imagePathTest, r.status_code, r.text)
            return r
        except socket.timeout:
            # 実際のケースではおそらく
            # ソケットがタイムアウトする場合に何かを行うでしょう
            passurls = [API_ENDPOINT_LB, API_ENDPOINT_LB, 
            API_ENDPOINT_LB, API_ENDPOINT_LB, 
            API_ENDPOINT_LB, API_ENDPOINT_LB, 
            API_ENDPOINT_LB, API_ENDPOINT_LB]with PoolExecutor(max_workers=16) as executor:
        for _ in executor.map(get_it, urls):
            pass
        
    print("--- %s seconds ---" % (time.time() - start))

    したがって、8x27 = 216個のテスト画像を処理するのに74秒かかっています。 これは負荷分散されたデモスタックが、(分類とヒートマップの結果をクライアントに返すことで)1秒間に3個の画像を処理できています。

    --- 74.37691688537598 seconds ---

    PuttyセッションのTopコマンドから、上記のベンチマークスクリプトが実行開始されるとすぐに8個のサーバープロセス(4個のGunicornと4個のUvicorn/Python)がランプアップし始めたことがわかります。

    今後の内容

    この記事は、テストフレームワークとして「全DockerによるAIデモ」のデプロイメントスタックをまとめるための出発点に過ぎません。 次は、Covid-19 ICU入室予測インターフェースなどさらに多くのAPIデモインターフェースを理想としてはFHIR R4などによって追加し、サポートDICOM入力形式を追加したいと思います。 これは、IRISがホストするML機能とのより緊密な統合を検討するためのテストベンチになる可能性もあります。 医用画像、公衆衛生、またはパーソナル化された予測やNLPなど、さまざまなAIフロントを見ていく過程で、徐々に、より多くのMLまたはDL特殊モデルを傍受するためのテストフレームワーク(非常に単純なテストフレーム)として使用していけるでしょう。 ウィッシュリストは、前の投稿(「今後の内容」セクション)の最後にも掲載しています。 

    0
    0 550
    記事 Toshihiko Minamoto · 12月 9, 2021 23m read

    キーワード: IRIS、IntegratedML、機械学習、Covid-19、Kaggle 

    前のパート1の続き... パート1では、Kaggleに掲載されているこのCovid-19データセットにおける従来型MLのアプローチを説明しました。 

    今回のパート2では、IRISのIntegratedMLを使用して、可能な限り単純な形態で同じデータとタスクを実行しましょう。IntegratedMLは、バックエンドAutoMLオプション用に洗練された優れたSQLインターフェースです。 同じ環境を使用します。 

    IntegratedMLアプローチとは

    IRISにデータを読み込む方法

    integredML-demo-templateには、IRISにデータを読み込む様々な方法が定義されています。 たとえば、このCSV形式のxlsファイルに固有のカスタムIRISクラスを定義し、それをIRISテーブルに読み込むことができます。 大量のデータをより適切に制御することができます。 

    ただし、この記事では、単純化された怠惰な方法を使用します。データフレーム全体を私が作成したカスタムPython関数で読み込む方法です。  そうすることで、生のデータフレームや処理されたデータフレームのさまざまなステージをいつでもIRISに保存し、前のMLアプローチを使用して、類似性比較を行えます。

    def to_sql_iris(cursor, dataFrame, tableName, schemaName='SQLUser', drop_table=False ):
            """"
            Dynamically insert dataframe into an IRIS table via SQL by "excutemany" 
            
            Inputs:
                cursor:      Python JDBC or PyODBC cursor from a valid and establised DB connection
                dataFrame:   Pandas dataframe
                tablename:   IRIS SQL table to be created, inserted or apended
                schemaName:  IRIS schemaName, default to "SQLUser"
                drop_table:  If the table already exsits, drop it and re-create it if True; othrewise keep it and appen 
            Output:
                True is successful; False if there is any exception.
            """
            if drop_table:   
                try:                 
                    curs.execute("DROP TABLE %s.%s" %(schemaName, tableName))
                except Exception:
                    pass
            
            try: 
                dataFrame.columns = dataFrame.columns.str.replace("[() -]", "_")
                curs.execute(pd.io.sql.get_schema(dataFrame, tableName))
            except Exception:
                pass
            
            curs.fast_executemany = True
            cols = ", ".join([str(i) for i in dataFrame.columns.tolist()])
            wildc =''.join('?, ' * len(dataFrame.columns))
            wildc = '(' + wildc[:-2] + ')'
            sql = "INSERT INTO " + tableName + " ( " + cols.replace('-', '_') + " ) VALUES" + wildc
            #print(sql)
            curs.executemany(sql, list(dataFrame.itertuples(index=False, name=None)) )
            return True

    Python JDBC接続のセットアップ

    import numpy as np 
    import pandas as pd 
    from sklearn.impute import SimpleImputer
    import matplotlib.pyplot as plt
    from sklearn.linear_model import LogisticRegression
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import classification_report, roc_auc_score, roc_curve
    import seaborn as sns
    sns.set(style="whitegrid")import jaydebeapi
    url = "jdbc:IRIS://irisimlsvr:51773/USER" 
    driver = 'com.intersystems.jdbc.IRISDriver'
    user = "SUPERUSER"
    password = "SYS"
    jarfile = "./intersystems-jdbc-3.1.0.jar"conn = jaydebeapi.connect(driver, url, [user, password], jarfile)
    curs = conn.cursor()

     

    開始データポイントをセットアップする

    類似性比較を行うために、前の記事の特徴量選択(「特徴量の選択 - 最終的な選択」セクション)の後のデータフレームから始めました。「DataS」はここで実際に開始するデータフレームです。

    data = dataS
    data = pd.get_dummies(data)
    data.AGE_ABOVE65 = data.AGE_ABOVE65.astype(int)
    data.ICU = data.ICU.astype(int)
    data_new = data
    data_new
    <th>
      AGE_ABOVE65
    </th>
    
    <th>
      GENDER
    </th>
    
    <th>
      HTN
    </th>
    
    <th>
      OTHER
    </th>
    
    <th>
      CALCIUM_MEDIAN
    </th>
    
    <th>
      CALCIUM_MIN
    </th>
    
    <th>
      CALCIUM_MAX
    </th>
    
    <th>
      CREATININ_MEDIAN
    </th>
    
    <th>
      CREATININ_MEAN
    </th>
    
    <th>
      CREATININ_MIN
    </th>
    
    <th>
      ...
    </th>
    
    <th>
      HEART_RATE_DIFF_REL
    </th>
    
    <th>
      RESPIRATORY_RATE_DIFF_REL
    </th>
    
    <th>
      TEMPERATURE_DIFF_REL
    </th>
    
    <th>
      OXYGEN_SATURATION_DIFF_REL
    </th>
    
    <th>
      ICU
    </th>
    
    <th>
      WINDOW_0-2
    </th>
    
    <th>
      WINDOW_2-4
    </th>
    
    <th>
      WINDOW_4-6
    </th>
    
    <th>
      WINDOW_6-12
    </th>
    
    <th>
      WINDOW_ABOVE_12
    </th>
    
    <td>
      1
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.183673
    </td>
    
    <td>
      0.183673
    </td>
    
    <td>
      0.183673
    </td>
    
    <td>
      -0.868365
    </td>
    
    <td>
      -0.868365
    </td>
    
    <td>
      -0.868365
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -0.817800
    </td>
    
    <td>
      -0.719147
    </td>
    
    <td>
      -0.771327
    </td>
    
    <td>
      -0.886982
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -0.817800
    </td>
    
    <td>
      -0.719147
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.326531
    </td>
    
    <td>
      0.326531
    </td>
    
    <td>
      0.326531
    </td>
    
    <td>
      -0.926398
    </td>
    
    <td>
      -0.926398
    </td>
    
    <td>
      -0.926398
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -0.230462
    </td>
    
    <td>
      0.096774
    </td>
    
    <td>
      -0.242282
    </td>
    
    <td>
      -0.814433
    </td>
    
    <td>
      1
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.244898
    </td>
    
    <td>
      0.244898
    </td>
    
    <td>
      0.244898
    </td>
    
    <td>
      -0.934890
    </td>
    
    <td>
      -0.934890
    </td>
    
    <td>
      -0.934890
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      0.330359
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      -0.891078
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.306122
    </td>
    
    <td>
      0.306122
    </td>
    
    <td>
      0.306122
    </td>
    
    <td>
      -0.944798
    </td>
    
    <td>
      -0.944798
    </td>
    
    <td>
      -0.944798
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -0.763868
    </td>
    
    <td>
      -0.612903
    </td>
    
    <td>
      -0.551337
    </td>
    
    <td>
      -0.835052
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
     
    1
    2
    3
    4
    ...
    1920
    1921
    1922
    1923
    1924

    1925 rows × 62 columns

    上記には、選択された58個の特徴量と、前の非数値列(WINDOW)から変換された4つの特徴量があることを示します。  

    IRISテーブルにデータを保存する

    上記のto_sql_iris関数を使用して、IRISテーブル「CovidPPP62」にデータを保存します。

    iris_schema = 'SQLUser'
    iris_table = 'CovidPPP62'to_sql_iris(curs, data_new, iris_table, iris_schema, drop_table=True) df2 = pd.read_sql("SELECT COUNT(*) from %s.%s" %(iris_schema, iris_table),conn)
    display(df2)
    <th>
      Aggregate_1
    </th>
    
    <td>
      1925
    </td>
    
     

    次に、トレーニングビュー名、モデル名、およびトレーニングターゲット列(この場合は「ICU」)を定義します。  

    dataTable = iris_table
    dataTableViewTrain = dataTable + 'Train1'
    dataTablePredict = dataTable + 'Predict1'
    dataColumn =  'ICU'
    dataColumnPredict = 'ICUPredicted'
    modelName = "ICUP621" #名前を選択 - サーバー側で一意である必要があります

    すると、このデータをトレーニングビュー(1700行)とテストビュー(225行)に分割できます。 IntegratedMLではこれを行う必要はありませんが、前の記事との比較目的で行っています。

    curs.execute("CREATE VIEW %s AS SELECT * FROM %s WHERE ID&lt;=1700" % (dataTableViewTrain, dataTable))df62 = pd.read_sql("SELECT * from %s" % dataTableViewTrain, conn)
    display(df62)
    print(dataTableViewTrain, modelName, dataColumn)
    CovidPPP62Train1 ICUP621 ICU

     

    IntegratedMLのデフォルトのAutoMLでモデルをトレーニングする

    curs.execute("CREATE MODEL %s PREDICTING (%s)  FROM %s" % (modelName, dataColumn, dataTableViewTrain))curs.execute("TRAIN MODEL %s FROM %s" % (modelName, dataTableViewTrain))df3 = pd.read_sql("SELECT * FROM INFORMATION_SCHEMA.ML_TRAINED_MODELS", conn)
    display(df3)
    <th>
      MODEL_NAME
    </th>
    
    <th>
      TRAINED_MODEL_NAME
    </th>
    
    <th>
      PROVIDER
    </th>
    
    <th>
      TRAINED_TIMESTAMP
    </th>
    
    <th>
      MODEL_TYPE
    </th>
    
    <th>
      MODEL_INFO
    </th>
    
    <td>
      ICUP621
    </td>
    
    <td>
      ICUP6212
    </td>
    
    <td>
      AutoML
    </td>
    
    <td>
      2020-07-22 19:28:16.174000
    </td>
    
    <td>
      classification
    </td>
    
    <td>
      ModelType:Random Forest, Package:sklearn, Prob...
    </td>
    
     
    9

    したがって、IntegratedMLは「ModelType」を自動的に「Random Forrest」(ランダムフォレスト)として選択し、問題を「Classification」(分類)タスクとして扱っているという結果がわかります。  前の記事では、箱ひげ図を使った長々としたモデル比較と選択、およびグリッド検索による長々としたモデルパラメーターのチューニングなど、これとまったく同じことを達成しましたよね。

    注意: 上記はIntergratedML構文による最低限のSQLです。  トレーニングアプローチやモデルの選択を指定していませんし、バックエンドMLプラットフォームも設定していません。 すべてはIMLの決定に委ねられており、IMLは内部トレーニングストラテジーをある程度達成して、適切な最終結果を備えた合理的なモデルに落ち着いています。 わずかながら、私の期待を超えたと言ってよいでしょう。   

    では、予約しておいたテストセットに対し、現在トレーニングされているモデルの簡単な類似性テストランを実行してみましょう。

    テストデータの結果を予測する

    トレーニングには1700行を使用しました。 以下では、残りの225行を使用してテストデータのビューを作成し、これらのレコードにSELECT PREDICTを実行します。 その予測結果を「dataTablePredict」に保存して、データフレームとして「df62」に読み込みます。

    dataTableViewTest = "SQLUSER.DTT621"
    curs.execute("CREATE VIEW %s AS SELECT * FROM %s WHERE ID > 1700" % (dataTableViewTest, dataTable))curs.execute("DROP TABLE %s" % dataTablePredict )
    curs.execute("Create Table %s (%s VARCHAR(100), %s VARCHAR(100))" % (dataTablePredict, dataColumnPredict, dataColumn))curs.execute("INSERT INTO %s  SELECT PREDICT(%s) AS %s, %s FROM %s" % (dataTablePredict, modelName, dataColumnPredict, dataColumn, dataTableViewTest)) df62 = pd.read_sql("SELECT * from %s ORDER BY ID" % dataTablePredict, conn)
    display(df62)

    その混同行列を手動で計算します。これを行う必要はありません。 これは比較のみを目的としています。

    TP = df62[(df62['ICUPredicted'] == '1') & (df62['ICU']=='1')].count()['ICU']  
    TN = df62[(df62['ICUPredicted'] == '0') & (df62['ICU']=='0')].count()["ICU"]
    FN = df62[(df62['ICU'] == '1') & (df62['ICUPredicted']=='0')].count()["ICU"]
    FP = df62[(df62['ICUPredicted'] == '1') & (df62['ICU']=='0')].count()["ICU"]
    print(TP, FN, '\n', FP, TN)
    precision = (TP)/(TP+FP)
    recall = (TP)/(TP+FN)
    f1 = ((precision*recall)/(precision+recall))*2
    accuracy = (TP+TN) / (TP+TN+FP+FN)
    print("Precision: ", precision, " Recall: ", recall, " F1: ", f1, " Accuracy: ", accuracy)
    34 20 
     8 163
    Precision:  0.8095238095238095  Recall:  0.6296296296296297  F1:  0.7083333333333334  Accuracy:  0.8755555555555555

    または、IntegratedMLの組み込みの混同行列を取得する構文を使用することができます。

    # テストデータを検証する
    curs.execute("VALIDATE MODEL %s FROM %s" % (modelName, dataTableViewTest) )  
    df5 = pd.read_sql("SELECT * FROM INFORMATION_SCHEMA.ML_VALIDATION_METRICS", conn)
    df6 = df5.pivot(index='VALIDATION_RUN_NAME', columns='METRIC_NAME', values='METRIC_VALUE')
    display(df6)
    <th>
      Accuracy
    </th>
    
    <th>
      F-Measure
    </th>
    
    <th>
      Precision
    </th>
    
    <th>
      Recall
    </th>
    
    <th>
       
    </th>
    
    <th>
       
    </th>
    
    <th>
       
    </th>
    
    <th>
       
    </th>
    
    <td>
      0.88
    </td>
    
    <td>
      0.71
    </td>
    
    <td>
      0.81
    </td>
    
    <td>
      0.63
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    METRIC_NAME
    VALIDATION_RUN_NAME
    ICUP62121
    ...

    パート1の「基本的なLRトレーニングを実行する」セクションにあった「元の結果」と比較すると、Recall は57%に対して63%、Accuracyは85%に対して88%という結果になっています。  したがって、IntegratedMLではより良い結果が得られています。

    SMOTEを介して再調整されたトレーニングデータでIntegratedMLを再トレーニングする

    上記のテストは、ICU入室と非入室の比率が1:3という不均衡なデータで行われました。  そこで、前の記事と同様に、SMOTEを適用してデータを均衡化し、その上で上記のIMLパイプラインを再実行することにしましょう。

    「X_train_res' and 'y_train_res」は、前のパート1の「基本的なLRトレーニングを実行する」セクションにあったSMOTE後のデータフレームです。 

    df_x_train = pd.DataFrame(X_train_res)
    df_y_train = pd.DataFrame(y_train_res)
    df_y_train.columns=['ICU']df_smote = pd.concat([df_x_train, df_y_train], 1)
    display(df_smote)
    iris_schema = 'SQLUser'
    iris_table = 'CovidSmote'
    to_sql_iris(curs, df_smote, iris_table, iris_schema, drop_table=True) # save it into a new IRIS table of specified name
    df2 = pd.read_sql("SELECT COUNT(*) from %s.%s" %(iris_schema, iris_table),conn)
    display(df2)
    <th>
      Aggregate_1
    </th>
    
    <td>
      2490
    </td>
    
     

    SMOTEによって、ICU=1のレコードが増やされたため、データセットの行数は1700ではなく2490になりました。

    dataTable = iris_table
    dataTableViewTrain = dataTable + 'TrainSmote'
    dataTablePredict = dataTable + 'PredictSmote'
    dataColumn =  'ICU'
    dataColumnPredict = 'ICUPredictedSmote'
    modelName = "ICUSmote1" #名前を選択 - サーバー側で一意である必要があります endcurs.execute("CREATE VIEW %s AS SELECT * FROM %s" % (dataTableViewTrain, dataTable))df_smote = pd.read_sql("SELECT * from %s" % dataTableViewTrain, conn)
    display(df_smote)
    print(dataTableViewTrain, modelName, dataColumn)
    CovidSmoteTrainSmote ICUSmote1 ICU
    curs.execute("CREATE MODEL %s PREDICTING (%s)  FROM %s" % (modelName, dataColumn, dataTableViewTrain))curs.execute("TRAIN MODEL %s FROM %s" % (modelName, dataTableViewTrain))
    
    df3 = pd.read_sql("SELECT * FROM INFORMATION_SCHEMA.ML_TRAINED_MODELS", conn)
    display(df3)
    <th>
      MODEL_NAME
    </th>
    
    <th>
      TRAINED_MODEL_NAME
    </th>
    
    <th>
      PROVIDER
    </th>
    
    <th>
      TRAINED_TIMESTAMP
    </th>
    
    <th>
      MODEL_TYPE
    </th>
    
    <th>
      MODEL_INFO
    </th>
    
    <td>
      ICUP621
    </td>
    
    <td>
      ICUP6212
    </td>
    
    <td>
      AutoML
    </td>
    
    <td>
      2020-07-22 19:28:16.174000
    </td>
    
    <td>
      classification
    </td>
    
    <td>
      ModelType:Random Forest, Package:sklearn, Prob...
    </td>
    
    <td>
      ICUSmote1
    </td>
    
    <td>
      ICUSmote12
    </td>
    
    <td>
      AutoML
    </td>
    
    <td>
      2020-07-22 20:49:13.980000
    </td>
    
    <td>
      classification
    </td>
    
    <td>
      ModelType:Random Forest, Package:sklearn, Prob...
    </td>
    
     
    9
    12

    次に、予約済みの225件のテストデータ行を再準備し、それに対してSMOTE再トレーニング済みモデルを実行します。

    df_x_test = pd.DataFrame(X3_test)
    df_y_test = pd.DataFrame(y3_test)
    df_y_test.columns=['ICU']df_test_smote = pd.concat([df_x_test, df_y_test], 1)
    display(df_test_smote)iris_schema = 'SQLUser'
    iris_table = 'CovidTestSmote'to_sql_iris(curs, df_test_smote, iris_table, iris_schema, drop_table=True) dataTableViewTest = "SQLUSER.DTestSmote225"
    curs.execute("CREATE VIEW %s AS SELECT * FROM %s" % (dataTableViewTest, iris_table))
    curs.execute("Create Table %s (%s VARCHAR(100), %s VARCHAR(100))" % (dataTablePredict, dataColumnPredict, dataColumn))
    curs.execute("INSERT INTO %s  SELECT PREDICT(%s) AS %s, %s FROM %s" % (dataTablePredict, modelName, dataColumnPredict, dataColumn, dataTableViewTest)) 
    
    df62 = pd.read_sql("SELECT * from %s ORDER BY ID" % dataTablePredict, conn)
    display(df62)
    
    TP = df62[(df62['ICUPredictedSmote'] == '1') & (df62['ICU']=='1')].count()['ICU']  
    TN = df62[(df62['ICUPredictedSmote'] == '0') & (df62['ICU']=='0')].count()["ICU"]
    FN = df62[(df62['ICU'] == '1') & (df62['ICUPredictedSmote']=='0')].count()["ICU"]
    FP = df62[(df62['ICUPredictedSmote'] == '1') & (df62['ICU']=='0')].count()["ICU"]
    print(TP, FN, '\n', FP, TN)
    precision = (TP)/(TP+FP)
    recall = (TP)/(TP+FN)
    f1 = ((precision*recall)/(precision+recall))*2
    accuracy = (TP+TN) / (TP+TN+FP+FN)
    print("Precision: ", precision, " Recall: ", recall, " F1: ", f1, " Accuracy: ", accuracy)
    45 15 
     9 156
    Precision:  0.8333333333333334  Recall:  0.75  F1:  0.7894736842105262  Accuracy:  0.8933333333333333
    
    # SMOTE再トレーニング済みモデルでテストデータを検証する
    curs.execute("VALIDATE MODEL %s FROM %s" % (modelName, dataTableViewTest) )  #Covid19aTest500, Covid19aTrain1000
    df5 = pd.read_sql("SELECT * FROM INFORMATION_SCHEMA.ML_VALIDATION_METRICS", conn)
    df6 = df5.pivot(index='VALIDATION_RUN_NAME', columns='METRIC_NAME', values='METRIC_VALUE')
    display(df6)
    <th>
      Accuracy
    </th>
    
    <th>
      F-Measure
    </th>
    
    <th>
      Precision
    </th>
    
    <th>
      Recall
    </th>
    
    <th>
       
    </th>
    
    <th>
       
    </th>
    
    <th>
       
    </th>
    
    <th>
       
    </th>
    
    <td>
      0.88
    </td>
    
    <td>
      0.71
    </td>
    
    <td>
      0.81
    </td>
    
    <td>
      0.63
    </td>
    
    <td>
      0.89
    </td>
    
    <td>
      0.79
    </td>
    
    <td>
      0.83
    </td>
    
    <td>
      0.75
    </td>
    
    METRIC_NAME
    VALIDATION_RUN_NAME
    ICUP62121
    ICUSmote122

    前の63%に比べてはるかに優れた75%のRecallと、わずかに優れたAccuracyとF1スコアが得られました。 

    さらに注目すべきことは、この結果が、前の記事の「「グリッド検索によるパラメーターチューニング」をさらに行って、選択されたモデルを実行する」セクションに記録されたとおりに、「モデルの選択」と「グリッド検索によるパラメーターのチューニング」を集中的に行った「従来型MLアプローチ」と一致しているということです。  したがって、IMLの結果は全く悪くないということです。

    **IntegratedMLのH2Oプロバイダーに変更する **

    IMLのAutoMLプロバイダーを1行で変更してから、前のステップで行った通りにモデルを再トレーニングできます。   

    curs.execute("SET ML CONFIGURATION %H2O;  ")modelName = 'ICUSmoteH2O'
    print(dataTableViewTrain)
    curs.execute("CREATE MODEL %s PREDICTING (%s)  FROM %s" % (modelName, dataColumn, dataTableViewTrain))
    curs.execute("TRAIN MODEL %s FROM %s" % (modelName, dataTableViewTrain))df3 = pd.read_sql("SELECT * FROM INFORMATION_SCHEMA.ML_TRAINED_MODELS", conn)
    display(df3)
    <th>
      MODEL_NAME
    </th>
    
    <th>
      TRAINED_MODEL_NAME
    </th>
    
    <th>
      PROVIDER
    </th>
    
    <th>
      TRAINED_TIMESTAMP
    </th>
    
    <th>
      MODEL_TYPE
    </th>
    
    <th>
      MODEL_INFO
    </th>
    
    <td>
      ICUSmote1
    </td>
    
    <td>
      ICUSmote12
    </td>
    
    <td>
      AutoML
    </td>
    
    <td>
      2020-07-22 20:49:13.980000
    </td>
    
    <td>
      classification
    </td>
    
    <td>
      ModelType:Random Forest, Package:sklearn, Prob...
    </td>
    
    <td>
      ICUPPP62
    </td>
    
    <td>
      ICUPPP622
    </td>
    
    <td>
      AutoML
    </td>
    
    <td>
      2020-07-22 17:48:10.964000
    </td>
    
    <td>
      classification
    </td>
    
    <td>
      ModelType:Random Forest, Package:sklearn, Prob...
    </td>
    
    <td>
      ICUSmoteH2O
    </td>
    
    <td>
      ICUSmoteH2O2
    </td>
    
    <td>
      H2O
    </td>
    
    <td>
      2020-07-22 21:17:06.990000
    </td>
    
    <td>
      classification
    </td>
    
    <td>
      None
    </td>
    
     
    12
    13
    14
    # テストデータを検証する
    curs.execute("VALIDATE MODEL %s FROM %s" % (modelName, dataTableViewTest) )  #Covid19aTest500, Covid19aTrain1000
    df5 = pd.read_sql("SELECT * FROM INFORMATION_SCHEMA.ML_VALIDATION_METRICS", conn)
    df6 = df5.pivot(index='VALIDATION_RUN_NAME', columns='METRIC_NAME', values='METRIC_VALUE')
    display(df6)
    <th>
      Accuracy
    </th>
    
    <th>
      F-Measure
    </th>
    
    <th>
      Precision
    </th>
    
    <th>
      Recall
    </th>
    
    <th>
       
    </th>
    
    <th>
       
    </th>
    
    <th>
       
    </th>
    
    <th>
       
    </th>
    
    <td>
      0.88
    </td>
    
    <td>
      0.71
    </td>
    
    <td>
      0.81
    </td>
    
    <td>
      0.63
    </td>
    
    <td>
      0.89
    </td>
    
    <td>
      0.79
    </td>
    
    <td>
      0.83
    </td>
    
    <td>
      0.75
    </td>
    
    <td>
      0.90
    </td>
    
    <td>
      0.79
    </td>
    
    <td>
      0.86
    </td>
    
    <td>
      0.73
    </td>
    
    METRIC_NAME
    VALIDATION_RUN_NAME
    ICUP62121
    ICUSmote122
    ICUSmoteH2O21

    H2O AutoMLでは、F1は同じですが、Accuracyがわずかに高く、Recallがわずかに減少していることがわかります。  ただし、このCovid19 ICUタスクの主な目的は、可能であれば偽陰性を最小限に抑えることであるため、  プロバイダーをH2Oに変更しても、ターゲットパフォーマンスは向上しなかったようです。

    もちろん、IntegratedMLのDataRobotプロバイダーもテストしたいのですが、残念ながらDataRobotのAPIキーは持っていないため、ここでストップとします。 

    まとめ:

    1. パフォーマンス: この特定のCovid-19 ICUタスクでは、比較テストによって、IRIS IntegratedMLのパフォーマンスは従来型MLの類似性の結果に少なくとも同等か類似していることが示されています。 この特定のケースでは、IntegratedMLは内部トレーニングストラテジーを自動的に正しく選択することができ、適切なモデルに落ち着いて、期待される結果を出したように見えました。

    2. 単純さ: IntegratedMLのプロセスは、従来型MLのパイプラインよりもはるかに単純です。 上記に示されるとおり、モデルの選択やパラメーターのチューニングなどの通常のデータサイエンティスト作業を行わずに、同等のパフォーマンスを達成することができました。  比較の為でなければ、実際には特徴量の選択の不要です。 また、Integrated-demo-templateデモノートブックに示されているIntegratedMLの最低限の構文しか使用していません。 もちろん、従来型パイプラインで使用できる一般的なデータサイエンスツールのカスタマイズ性とファインチューニング機能は失われるという欠点はありますが、これは他のAutoMLプラットフォームにも多かれ少なかれ当てはまることです。 

    3. データ前処理は依然として重要: 残念ながら特効薬はありません。または、特効薬には時間が必要でしょう。 このCovid-19 ICUタスクに限定して言えば、上記のテストでは、データが現在のIntegratedMLにとって依然として重要であることが示されています。生のデータ、欠落したデータを代入して選択された特徴量、および基本的なSMOTEオーバーサンプリングによる再調整データはすべて大幅に異なるパフォーマンスを見せました。 これは、IMLのデフォルトAutoMLとそのH2Oプロバイダーの両方に当てはまります。 DataRobotはわずかに優れたパフォーマンスを主張するかもしれませんが、IntegratedMLのSQLラッパーでさらにテストされると思います。 要するに、データ正規化は、IntegratedMLでも依然として重要であるということです。

    4. デプロイ可能性: デプロイ可能性、API管理、モニタリング、および非関数サービス可能性などについてはまだ比較していません。次の記事で行えるでしょう。

    今後の内容

    1. モデルのデプロイ: これまで、Covid-19のX線画像に対するデモAIと、バイタルサインおよび観測に対するCovid-19 ICU予測を実行しました。 これらをFlask/FastAPIおよびIRISサービススタックにデプロイし、REST/JSON APIを介してデモML/DL機能を開会できるでしょうか?  もちろん、次の記事でそのようなことを試すことはできます。 その後で、NLP APIなどを含むさらに多くのデモAI機能を徐々に追加していくことができます。 

    2. FHIRラップAPIの相互運用性: この開発者コミュニティには、FHIRテンプレートやIRISネイティブAPIなどもあります。 デモAIサービスをFHIRアプリでSMARTに、または対応する標準に従ってFHIRラップAIサービスに変換することはできるでしょうか?  IRIS製品ラインには、AIデモスタックで利用できるAPIゲートウェイ、Kubernetesサポート付きのICM、SAMなどがあることも忘れないでください。

    3. HealthShare Clinical ViewerやTrakなどとのデモ統合は?サードパーティAIベンダーのPACS Viewer(Covid-19 CT用)とHealthShare Clinical Viewerのデモ統合は簡単に説明しました。したがって、おそらくいずれは、さまざまな専門分野での独自のAIデモサービスを最後まで説明することはできるでしょう。

    0
    0 132
    記事 Toshihiko Minamoto · 12月 7, 2021 31m read

    キーワード: IRIS、IntegratedML、機械学習、Covid-19、Kaggle 

    目的

    最近、Covid-19患者がICU(集中治療室)に入室するかどうかを予測するKaggleデータセットがあることに気づきました。  231列のバイタルサインや観測で構成される1925件の遭遇記録が含まれる表計算シートで、最後の「ICU」列では「Yes」を示す1と「No」を示す0が使用されています。 既知のデータに基づいて、患者がICUに入室するかどうかを予測することがタスクです。

    このデータセットは、「従来型ML」タスクと呼ばれるものの良い例のようです。 データ量は適切で、品質も比較的適切なようです。 IntegratedMLデモキットに直接適用できる可能性が高いようなのですが、通常のMLパイプラインと潜在的なIntegratedMLアプローチに基づいて簡易テストを行うには、どのようなアプローチが最も単純なのでしょうか。

    範囲

    次のような通常のMLステップを簡単に実行します。

    • データのEDA(探索的データ分析) 
    • 特徴量の選択
    • モデルの選択
    • グリッド検索によるモデルパラメーターのチューニング

    上記との比較で、次を実行します。 

    • SQLを介したIntegratedMLアプローチ

    Docker-composeなどを使用して、AWS Ubuntu 16.04サーバーで実行します。   

    環境

    integredML-demo-templateのDocker環境を再利用します。

    以下のノートブックファイルは「tf2jupyter」で実行しており、IRISとIntegratedMLは「irismlsrv」で実行しています。  Docker-composeはAWS Ubuntu 16.04で実行します。

    データとタスク

    このデータセットには、385人の患者から収集した1925件のレコードが含まれます。各患者にはちょうど5つの遭遇レコードがあります。 231列のうちの1つの列は、このトレーニングと予測のターゲットである「ICU」で、残りの230列は入力として使用することが可能です。 ICUは1または0のバイナリー値です。 カテゴリカル文字列(データフレームでは「オブジェクト」として表されます)のような2つの列を除くと、すべては数値データです。

    import numpy as np 
    import pandas as pd 
    from sklearn.impute import SimpleImputer
    import matplotlib.pyplot as plt
    from sklearn.linear_model import LogisticRegression
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import classification_report, roc_auc_score, roc_curve
    import seaborn as sns
    sns.set(style="whitegrid")
    
    import os
    for dirname, _, filenames in os.walk('./input'):
        for filename in filenames:
            print(os.path.join(dirname, filename))
    ./input/datasets_605991_1272346_Kaggle_Sirio_Libanes_ICU_Prediction.xlsx

     

    df = pd.read_excel("./input/datasets_605991_1272346_Kaggle_Sirio_Libanes_ICU_Prediction.xlsx")
    df
    <th>
      PATIENT_VISIT_IDENTIFIER
    </th>
    
    <th>
      AGE_ABOVE65
    </th>
    
    <th>
      AGE_PERCENTIL
    </th>
    
    <th>
      GENDER
    </th>
    
    <th>
      DISEASE GROUPING 1
    </th>
    
    <th>
      DISEASE GROUPING 2
    </th>
    
    <th>
      DISEASE GROUPING 3
    </th>
    
    <th>
      DISEASE GROUPING 4
    </th>
    
    <th>
      DISEASE GROUPING 5
    </th>
    
    <th>
      DISEASE GROUPING 6
    </th>
    
    <th>
      ...
    </th>
    
    <th>
      TEMPERATURE_DIFF
    </th>
    
    <th>
      OXYGEN_SATURATION_DIFF
    </th>
    
    <th>
      BLOODPRESSURE_DIASTOLIC_DIFF_REL
    </th>
    
    <th>
      BLOODPRESSURE_SISTOLIC_DIFF_REL
    </th>
    
    <th>
      HEART_RATE_DIFF_REL
    </th>
    
    <th>
      RESPIRATORY_RATE_DIFF_REL
    </th>
    
    <th>
      TEMPERATURE_DIFF_REL
    </th>
    
    <th>
      OXYGEN_SATURATION_DIFF_REL
    </th>
    
    <th>
      WINDOW
    </th>
    
    <th>
      ICU
    </th>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
      60th
    </td>
    
    <td>
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      0-2
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
      60th
    </td>
    
    <td>
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      2-4
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
      60th
    </td>
    
    <td>
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      NaN
    </td>
    
    <td>
      NaN
    </td>
    
    <td>
      NaN
    </td>
    
    <td>
      NaN
    </td>
    
    <td>
      NaN
    </td>
    
    <td>
      NaN
    </td>
    
    <td>
      NaN
    </td>
    
    <td>
      NaN
    </td>
    
    <td>
      4-6
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
      60th
    </td>
    
    <td>
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      NaN
    </td>
    
    <td>
      NaN
    </td>
    
    <td>
      NaN
    </td>
    
    <td>
      NaN
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      6-12
    </td>
    
    <td>
    </td>
    
    <td>
    </td>
    
    <td>
      1
    </td>
    
    <td>
      60th
    </td>
    
    <td>
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -0.238095
    </td>
    
    <td>
      -0.818182
    </td>
    
    <td>
      -0.389967
    </td>
    
    <td>
      0.407558
    </td>
    
    <td>
      -0.230462
    </td>
    
    <td>
      0.096774
    </td>
    
    <td>
      -0.242282
    </td>
    
    <td>
      -0.814433
    </td>
    
    <td>
      ABOVE_12
    </td>
    
    <td>
      1
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      384
    </td>
    
    <td>
    </td>
    
    <td>
      50th
    </td>
    
    <td>
      1
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      0-2
    </td>
    
    <td>
    </td>
    
    <td>
      384
    </td>
    
    <td>
    </td>
    
    <td>
      50th
    </td>
    
    <td>
      1
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      2-4
    </td>
    
    <td>
    </td>
    
    <td>
      384
    </td>
    
    <td>
    </td>
    
    <td>
      50th
    </td>
    
    <td>
      1
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      4-6
    </td>
    
    <td>
    </td>
    
    <td>
      384
    </td>
    
    <td>
    </td>
    
    <td>
      50th
    </td>
    
    <td>
      1
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      -1.000000
    </td>
    
    <td>
      6-12
    </td>
    
    <td>
    </td>
    
    <td>
      384
    </td>
    
    <td>
    </td>
    
    <td>
      50th
    </td>
    
    <td>
      1
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      1.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      0.0
    </td>
    
    <td>
      ...
    </td>
    
    <td>
      -0.547619
    </td>
    
    <td>
      -0.838384
    </td>
    
    <td>
      -0.701863
    </td>
    
    <td>
      -0.585967
    </td>
    
    <td>
      -0.763868
    </td>
    
    <td>
      -0.612903
    </td>
    
    <td>
      -0.551337
    </td>
    
    <td>
      -0.835052
    </td>
    
    <td>
      ABOVE_12
    </td>
    
    <td>
    </td>
    
     
    1
    2
    3
    4
    ...
    1920
    1921
    1922
    1923
    1924

    1925 rows × 231 columns

    df.dtypes
    PATIENT_VISIT_IDENTIFIER        int64
    AGE_ABOVE65                     int64
    AGE_PERCENTIL                  object
    GENDER                          int64
    DISEASE GROUPING 1            float64
                                   ...   
    RESPIRATORY_RATE_DIFF_REL     float64
    TEMPERATURE_DIFF_REL          float64
    OXYGEN_SATURATION_DIFF_REL    float64
    WINDOW                         object
    ICU                             int64
    Length: 231, dtype: object

    この問題とそのアプローチを組むには、確実にいくつかのオプションがあります。 最初に頭に浮かぶのは、これが「二項分類」の問題と考えられることです。 すべての1925件のレコードを、同じ患者のレコードであるかに関係なく、「ステートレス」の個別のレコードとして扱うことができます。 もちろん、ICUと他の値をすべて数値として扱うのであれば、「回帰」問題としても考えられるでしょう。

    確かにほかのアプローチもあります。 たとえば、データセットに、患者ごとに異なる385件の短い「時系列」があるというように扱うこともできます。 セット全体をTrain/Val/Test用の385個の個別のセットに分解した場合は、CNNやLSTMなどのディープラーニングモデルを使って、個々の患者ごとに各セットに隠れた「症状の発展段階またはパターン」をキャプチャできるでしょうか? できるかもしれませんね。 それを行えば、データ拡張も適用して、様々な方法でテストデータを充実させることができるかもしれません。 これについては、この記事の対象外として別のトピックとしましょう。

    この記事では、いわゆる「従来型ML」とIntegratedML(AutoML)アプローチのクイックランをテストします。  

    「従来型」MLアプローチとは

    このデータセットは、いくつかの値が欠落していることを除き、ほとんどの実際のケースより比較的正規化されたものであるため、特徴量エンジニアリングの部分を省略して、直接列を特徴量として使用できる可能性があります。 では早速、特徴量の選択に進みましょう。

    欠落しているデータを代入する

    まず、すべての欠落している値が単純な代入で埋められていることを確認します。

    df_cat = df.select_dtypes(include=['object'])
    df_numeric = df.select_dtypes(exclude=['object'])
    imp = SimpleImputer(missing_values=np.nan, strategy='mean')
    idf = pd.DataFrame(imp.fit_transform(df_numeric))
    idf.columns = df_numeric.columns
    idf.index = df_numeric.index
    idf.isnull().sum()

     

    特徴量の選択

    データフレームに組み込まれている正規相関関数を使用して、ICUに対する各列の値の相関を計算できます。

    特徴量エンジニアリング - 相関 {#featuring-engineering---correlation}

    idf.drop(["PATIENT_VISIT_IDENTIFIER"],1)
    idf = pd.concat([idf,df_cat ], axis=1)
    cor = idf.corr()
    cor_target = abs(cor["ICU"])
    relevant_features = cor_target[cor_target>0.1]   # correlation above 0.1
    print(cor.shape, cor_target.shape, relevant_features.shape)
    #relevant_features.index
    #relevant_features.index.shape

    これにより、ICUのターゲット値との相関が >0.1である88個の特徴量がリストされます。  これらの列は、モデル入力として直接利用できます。

    また、従来型MLタスクで通常使用されているほかの「特徴量選択手法」もいくつか実行してみました。

    特徴量の選択 - カイ二乗 {#feature-selection---Chi-squared}

    from sklearn.feature_selection import SelectKBest
    from sklearn.feature_selection import chi2
    from sklearn.preprocessing import MinMaxScaler
    X_norm = MinMaxScaler().fit_transform(X)
    chi_selector = SelectKBest(chi2, k=88)
    chi_selector.fit(X_norm, y)
    chi_support = chi_selector.get_support()
    chi_feature = X.loc[:,chi_support].columns.tolist()
    print(str(len(chi_feature)), 'selected features', chi_feature)
    88 selected features ['AGE_ABOVE65', 'GENDER', 'DISEASE GROUPING 1', ... ... 'P02_VENOUS_MIN', 'P02_VENOUS_MAX', ... ... RATURE_MAX', 'BLOODPRESSURE_DIASTOLIC_DIFF', ... ... 'TEMPERATURE_DIFF_REL', 'OXYGEN_SATURATION_DIFF_REL']

    特徴量の選択 - ピアソン相関 

    def cor_selector(X, y,num_feats):
        cor_list = []
        feature_name = X.columns.tolist()
        # calculate the correlation with y for each feature
        for i in X.columns.tolist():
            cor = np.corrcoef(X[i], y)[0, 1]
            cor_list.append(cor)
        # replace NaN with 0
        cor_list = [0 if np.isnan(i) else i for i in cor_list]
        # feature name
        cor_feature = X.iloc[:,np.argsort(np.abs(cor_list))[-num_feats:]].columns.tolist()
        # feature selection? 0 for not select, 1 for select
        cor_support = [True if i in cor_feature else False for i in feature_name]
        return cor_support, cor_featurecor_support, cor_feature = cor_selector(X, y, 88)
    print(str(len(cor_feature)), 'selected features:  ', cor_feature)
    88 selected features:   ['TEMPERATURE_MEAN', 'BLOODPRESSURE_DIASTOLIC_MAX', ... ... 'RESPIRATORY_RATE_DIFF', 'RESPIRATORY_RATE_MAX']

    特徴量の選択 - 再帰的特徴量除去(RFE){#feature-selection---Recursive-Feature-Elimination-(RFE)}

    from sklearn.feature_selection import RFE
    from sklearn.linear_model import LogisticRegression
    rfe_selector = RFE(estimator=LogisticRegression(), n_features_to_select=88, step=100, verbose=5)
    rfe_selector.fit(X_norm, y)
    rfe_support = rfe_selector.get_support()
    rfe_feature = X.loc[:,rfe_support].columns.tolist()
    print(str(len(rfe_feature)), 'selected features: ', rfe_feature)
    Fitting estimator with 127 features.
    88 selected features:  ['AGE_ABOVE65', 'GENDER', ... ... 'RESPIRATORY_RATE_DIFF_REL', 'TEMPERATURE_DIFF_REL']

    特徴量の選択 - Lasso

    ffrom sklearn.feature_selection import SelectFromModel
    from sklearn.linear_model import LogisticRegression
    from sklearn.preprocessing import MinMaxScaler
    X_norm = MinMaxScaler().fit_transform(X)
    embeded_lr_selector = SelectFromModel(LogisticRegression(penalty="l2"), max_features=88)
    embeded_lr_selector.fit(X_norm, y)
    embeded_lr_support = embeded_lr_selector.get_support()
    embeded_lr_feature = X.loc[:,embeded_lr_support].columns.tolist()
    print(str(len(embeded_lr_feature)), 'selected features', embeded_lr_feature)
    65 selected features ['AGE_ABOVE65', 'GENDER', ... ... 'RESPIRATORY_RATE_DIFF_REL', 'TEMPERATURE_DIFF_REL']

    特徴量の選択 - RFツリーベース: SelectFromModel

    from sklearn.feature_selection import SelectFromModel
    from sklearn.ensemble import RandomForestClassifier
    embeded_rf_selector = SelectFromModel(RandomForestClassifier(n_estimators=100), max_features=227)
    embeded_rf_selector.fit(X, y)
    embeded_rf_support = embeded_rf_selector.get_support()
    embeded_rf_feature = X.loc[:,embeded_rf_support].columns.tolist()
    print(str(len(embeded_rf_feature)), 'selected features', embeded_rf_feature)
    48 selected features ['AGE_ABOVE65', 'GENDER', ... ... 'TEMPERATURE_DIFF_REL', 'OXYGEN_SATURATION_DIFF_REL']

    特徴量の選択 - LightGBMまたはXGBoost {#feature-selection---LightGBM-or-XGBoost}

    from sklearn.feature_selection import SelectFromModel
    from lightgbm import LGBMClassifierlgbc=LGBMClassifier(n_estimators=500, learning_rate=0.05, num_leaves=32, colsample_bytree=0.2,
                reg_alpha=3, reg_lambda=1, min_split_gain=0.01, min_child_weight=40)embeded_lgb_selector = SelectFromModel(lgbc, max_features=128)
    embeded_lgb_selector.fit(X, y)embeded_lgb_support = embeded_lgb_selector.get_support()
    embeded_lgb_feature = X.loc[:,embeded_lgb_support].columns.tolist()
    print(str(len(embeded_lgb_feature)), 'selected features:  ', embeded_lgb_feature)
    embeded_lgb_feature.index
    56 selected features:   ['AGE_ABOVE65', 'GENDER', 'HTN', ... ... 'TEMPERATURE_DIFF_REL', 'OXYGEN_SATURATION_DIFF_REL']

    特徴量の選択 - すべてを一緒に {#feature-selection---Ensemble-them-all}

    feature_name = X.columns.tolist()
    # put all selection together
    feature_selection_df = pd.DataFrame({'Feature':feature_name, 'Pearson':cor_support, 'Chi-2':chi_support, 'RFE':rfe_support, 'Logistics':embeded_lr_support, 'Random Forest':embeded_rf_support, 'LightGBM':embeded_lgb_support})
    # count the selected times for each feature
    feature_selection_df['Total'] = np.sum(feature_selection_df, axis=1)
    # display the top 100
    num_feats = 227
    feature_selection_df = feature_selection_df.sort_values(['Total','Feature'] , ascending=False)
    feature_selection_df.index = range(1, len(feature_selection_df)+1)
    feature_selection_df.head(num_feats)
    df_selected_columns = feature_selection_df.loc[(feature_selection_df['Total'] > 3)]
    df_selected_columns

    少なくとも4つの方法で選択された特徴量をリストできます。

    ... ...

    これらの58個の特徴量を選択できます。 一方で、経験からして、特徴量の選択は、必ずしも民主的投票だとは限りません。多くの場合はドメインの問題や特定のデータに特化するものであり、時には、この記事で後で採用する特定のMLモデルやアプローチに特化した選択手法であることもあります。

    特徴量の選択 - サードパーティツール 

    広く使用されている業界ツールやAutoMLツールがあり、たとえば、DataRobotは特徴量の適切な自動選択を行うことができます。  

    当然ながら、上記のDataRobotグラフから、さまざまなRespiratoryRate値とBloodPressure値がICU入室に最も関連性の高い特徴量であることがわかります。    

    特徴量の選択 - 最終選択
    この記事では、簡単な実験を行い、LightGBMによる特徴量の選択が実際にほんの少し良い結果を出したことに気づいたので、この選択方法のみを使用することにします。   

    df_selected_columns = embeded_lgb_feature  # better than ensembled selectiondataS = pd.concat([idf[df_selected_columns],idf['ICU'], df_cat['WINDOW']],1)
    dataS.ICU.value_counts()
    print(dataS.shape)
    (1925, 58)

    58個の特徴量が選択されていることがわかります。多すぎず、少なからず、この特定のシングルターゲット二項分類問題には適切な量だと言えます。 

    データの不均衡

    plt.figure(figsize=(10,5))
    count = sns.countplot(x = "ICU",data=data)
    count.set_xticklabels(["Not Admitted","Admitted"])
    plt.xlabel("ICU Admission")
    plt.ylabel("Patient Count")
    plt.show()

    これはデータが不均衡であることを示し、ICUに入室したというレコードは26%のみです。 これは結果に影響を及ぼすため、SMOTEなどの通常のデータ均衡化アプローチを考えられます。

    ここでは、他のあらゆる種類のEDAを試し、それに応じてさまざまなデータ分布を理解することができます。 

    基本的なLRトレーニングを実行する

    Kaggleサイトには、独自の特徴量カラムの選択に基づいて素早く実行できる優れた簡易トレーニングノートブックがいくつかあります。  とりあえず、トレーニングパイプラインのLR分類器をさっと実行することから始めましょう。 

    data2 = pd.concat([idf[df_selected_columns],idf['ICU'], df_cat['WINDOW']],1)   
    data2.AGE_ABOVE65 = data2.AGE_ABOVE65.astype(int)
    data2.ICU = data2.ICU.astype(int)
    X2 = data2.drop("ICU",1)
    y2 = data2.ICU
    
    from sklearn.preprocessing import LabelEncoder
    label_encoder = LabelEncoder()
    X2.WINDOW = label_encoder.fit_transform(np.array(X2["WINDOW"].astype(str)).reshape((-1,)))
    
    confusion_matrix2 = pd.crosstab(y2_test, y2_hat, rownames=['Actual'], colnames=['Predicted'])
    sns.heatmap(confusion_matrix2, annot=True, fmt = 'g', cmap = 'Reds') print("ORIGINAL")
    print(classification_report(y_test, y_hat))
    print("AUC = ",roc_auc_score(y_test, y_hat),'\n\n')
    print("LABEL ENCODING")
    print(classification_report(y2_test, y2_hat))
    print("AUC = ",roc_auc_score(y2_test, y2_hat))
    y2hat_probs = LR.predict_proba(X2_test)
    y2hat_probs = y2hat_probs[:, 1] fpr2, tpr2, _ = roc_curve(y2_test, y2hat_probs) plt.figure(figsize=(10,7))
    plt.plot([0, 1], [0, 1], 'k--')
    plt.plot(fpr, tpr, label="Base")
    plt.plot(fpr2,tpr2,label="Label Encoded")
    plt.xlabel('False positive rate')
    plt.ylabel('True positive rate')
    plt.title('ROC curve')
    plt.legend(loc="best")
    plt.show()
    
    
    ORIGINAL
                  precision    recall  f1-score   support
               0       0.88      0.94      0.91       171
               1       0.76      0.57      0.65        54
        accuracy                           0.85       225
       macro avg       0.82      0.76      0.78       225
    weighted avg       0.85      0.85      0.85       225
    AUC =  0.7577972709551657 
    LABEL ENCODING
                  precision    recall  f1-score   support
               0       0.88      0.93      0.90       171
               1       0.73      0.59      0.65        54
        accuracy                           0.85       225
       macro avg       0.80      0.76      0.78       225
    weighted avg       0.84      0.85      0.84       225
    AUC =  0.7612085769980507

            

    85%の精度でAUC 76%を達成しているようですが、ICU入院のRecallは59%のみで、偽陰性が多すぎるようです。 それは確かに理想的ではありません。患者のレコードに対して実際のICUリスクを見落とすわけにはいきません。 そこで、すべての後続のタスクでは、うまく行けばある程度均衡のとれた全体的精度でFNを下げてRecallレートを引き上げる方法に目標を定めることにします。

    前のセクションでは、不均衡データについて触れました。最初の直感は、テストセットを層別化(Stratify)し、SMOTEしてより均衡のとれたデータセットを作成することです。

    #テストデータを層別化し、TrainデータとTestデータの比率が同じ1:0になるようにする
    X3_train,X3_test,y3_train,y3_test = train_test_split(X2,y2,test_size=225/1925,random_state=42, stratify = y2, shuffle = True) &lt;span> &lt;/span>
    # train and predict
    LR.fit(X3_train,y3_train)
    y3_hat = LR.predict(X3_test)
    
    #データをSMOTEし、ICU 1:0を均衡のとれた分布にする
    from imblearn.over_sampling import SMOTE sm = SMOTE(random_state = 42)
    X_train_res, y_train_res = sm.fit_sample(X3_train,y3_train.ravel())
    LR.fit(X_train_res, y_train_res)
    y_res_hat = LR.predict(X3_test)
    
    #混同行列などをもう一度描画する
    confusion_matrix3 = pd.crosstab(y3_test, y_res_hat, rownames=['Actual'], colnames=['Predicted'])
    sns.heatmap(confusion_matrix3, annot=True, fmt = 'g', cmap="YlOrBr") 
    print("LABEL ENCODING + STRATIFY")
    print(classification_report(y3_test, y3_hat))
    print("AUC = ",roc_auc_score(y3_test, y3_hat),'\n\n') 
    print("SMOTE")
    print(classification_report(y3_test, y_res_hat))
    print("AUC = ",roc_auc_score(y3_test, y_res_hat)) 
    y_res_hat_probs = LR.predict_proba(X3_test)
    y_res_hat_probs = y_res_hat_probs[:, 1] 
    fpr_res, tpr_res, _ = roc_curve(y3_test, y_res_hat_probs) plt.figure(figsize=(10,10))
    
    #前のようにROC曲線をプロットする

     

    LABEL ENCODING + STRATIFY
                  precision    recall  f1-score   support
               0       0.87      0.99      0.92       165
               1       0.95      0.58      0.72        60
        accuracy                           0.88       225
       macro avg       0.91      0.79      0.82       225
    weighted avg       0.89      0.88      0.87       225
    AUC =  0.7856060606060606 
    SMOTE
                  precision    recall  f1-score   support
               0       0.91      0.88      0.89       165
               1       0.69      0.75      0.72        60
        accuracy                           0.84       225
       macro avg       0.80      0.81      0.81       225
    weighted avg       0.85      0.84      0.85       225
    AUC =  0.8143939393939393

                

    したがって、データのSTRATIFY処理とSMOTE処理はRecallを0.59から 0.75、全体的な精度を0.84に改善しているようです。 

    従来型MLのデータ処理の大半がいつも通り完了したので、このケースの最善のモデルが何であるかを知りたいと思います。それらはもっと優れているのでしょうか。また、比較的包括的な比較を試みることができるでしょうか。

    さまざまなモデルのトレーニング比較を実行する 

    一般的に使用されているMLアルゴリズムを評価し、箱ひげ図によって、結果の比較ダッシュボードを生成してみましょう。

    # アルゴリズムを比較
    from matplotlib import pyplot
    from sklearn.model_selection import train_test_split
    from sklearn.model_selection import cross_val_score
    from sklearn.model_selection import StratifiedKFold
    from sklearn.linear_model import LogisticRegression
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
    from sklearn.naive_bayes import GaussianNB
    from sklearn.svm import SVC
    #ランダムフォレストモデルをインポートする
    from sklearn.ensemble import RandomForestClassifier
    from xgboost import XGBClassifier# アルゴリズムを合わせてリストする
    models = []
    models.append(('LR', &lt;strong>LogisticRegression&lt;/strong>(solver='liblinear', multi_class='ovr')))
    models.append(('LDA', LinearDiscriminantAnalysis()))
    models.append(('KNN', &lt;strong>KNeighborsClassifier&lt;/strong>()))
    models.append(('CART', &lt;strong>DecisionTreeClassifier&lt;/strong>()))
    models.append(('NB', &lt;strong>GaussianNB&lt;/strong>()))
    models.append(('SVM', &lt;strong>SVC&lt;/strong>(gamma='auto')))
    models.append(('RF', &lt;strong>RandomForestClassifier&lt;/strong>(n_estimators=100)))
    models.append(('XGB', &lt;strong>XGBClassifier&lt;/strong>())) #clf = XGBClassifier()
    # 代わりに各モデルを評価する
    results = []
    names = []
    for name, model in models:
        kfold = StratifiedKFold(n_splits=10, random_state=1)
        cv_results = cross_val_score(model, X_train_res, y_train_res, cv=kfold, scoring='f1')  ## accuracy, precision,recall 
        results.append(cv_results)
        names.append(name)
        print('%s: %f (%f)' % (name, cv_results.mean(), cv_results.std()))# すべてのモデルのパフォーマンスを比較する。 質問 - それに関する統合アイテムを見たいですか?
    pyplot.figure(4, figsize=(12, 8))
    pyplot.boxplot(results, labels=names)
    pyplot.title('Algorithm Comparison')
    pyplot.show()
    LR: 0.805390 (0.021905) LDA: 0.803804 (0.027671) KNN: 0.841824 (0.032945) CART: 0.845596 (0.053828)
    NB: 0.622540 (0.060390) SVM: 0.793754 (0.023050) RF: 0.896222 (0.033732) XGB: 0.907529 (0.040693)

    上記は、XGB分類子とランダムフォレスト分類子に他のモデルよりも優れたF1スコアがあるように見えます。 

    同じセットの正規化されたテストデータで実際のテスト結果を比較して見ましょう。

    import time
    from pandas import read_csv
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import classification_report
    from sklearn.metrics import confusion_matrix
    from sklearn.metrics import accuracy_score
    from sklearn.svm import SVCfor name, model in models:
        print(name + ':\n\r')
        start = time.clock()
        model.fit(X_train_res, y_train_res)
        print("Train time for ", model, " ", time.clock() - start)
        predictions = model.predict(X3_test) #(X_validation)
        # Evaluate predictions
        print(accuracy_score(y3_test, predictions))  # Y_validation
        print(confusion_matrix(y3_test, predictions))
        print(classification_report(y3_test, predictions))
    LR:
    Train time for  LogisticRegression(multi_class='ovr', solver='liblinear')   0.02814499999999498
    0.8444444444444444
    [[145  20]
     [ 15  45]]
                  precision    recall  f1-score   support
               0       0.91      0.88      0.89       165
               1       0.69      0.75      0.72        60
        accuracy                           0.84       225
       macro avg       0.80      0.81      0.81       225
    weighted avg       0.85      0.84      0.85       225
    
    LDA:
    Train time for  LinearDiscriminantAnalysis()   0.2280070000000194
    0.8488888888888889
    [[147  18]
     [ 16  44]]
                  precision    recall  f1-score   support
               0       0.90      0.89      0.90       165
               1       0.71      0.73      0.72        60
        accuracy                           0.85       225
       macro avg       0.81      0.81      0.81       225
    weighted avg       0.85      0.85      0.85       225
    
    KNN:
    Train time for  KNeighborsClassifier()   0.13023699999999394
    0.8355555555555556
    [[145  20]
     [ 17  43]]
                  precision    recall  f1-score   support
               0       0.90      0.88      0.89       165
               1       0.68      0.72      0.70        60
        accuracy                           0.84       225
       macro avg       0.79      0.80      0.79       225
    weighted avg       0.84      0.84      0.84       225
    
    CART:
    Train time for  DecisionTreeClassifier()   0.32616000000001577
    0.8266666666666667
    [[147  18]
     [ 21  39]]
                  precision    recall  f1-score   support
               0       0.88      0.89      0.88       165
               1       0.68      0.65      0.67        60
        accuracy                           0.83       225
       macro avg       0.78      0.77      0.77       225
    weighted avg       0.82      0.83      0.83       225
    
    NB:
    Train time for  GaussianNB()   0.0034229999999979555
    0.8355555555555556
    [[154  11]
     [ 26  34]]
                  precision    recall  f1-score   support
               0       0.86      0.93      0.89       165
               1       0.76      0.57      0.65        60
        accuracy                           0.84       225
       macro avg       0.81      0.75      0.77       225
    weighted avg       0.83      0.84      0.83       225
    
    SVM:
    Train time for  SVC(gamma='auto')   0.3596520000000112
    0.8977777777777778
    [[157   8]
     [ 15  45]]
                  precision    recall  f1-score   support
               0       0.91      0.95      0.93       165
               1       0.85      0.75      0.80        60
        accuracy                           0.90       225
       macro avg       0.88      0.85      0.86       225
    weighted avg       0.90      0.90      0.90       225
    
    RF:
    Train time for  RandomForestClassifier()   0.50123099999999
    0.9066666666666666
    [[158   7]
     [ 14  46]]
                  precision    recall  f1-score   support
               0       0.92      0.96      0.94       165
               1       0.87      0.77      0.81        60
        accuracy                           0.91       225
       macro avg       0.89      0.86      0.88       225
    weighted avg       0.91      0.91      0.90       225
    
    XGB:
    Train time for  XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1,
                  colsample_bynode=1, colsample_bytree=1, gamma=0, gpu_id=-1,
                  importance_type='gain', interaction_constraints='',
                  learning_rate=0.300000012, max_delta_step=0, max_depth=6,
                  min_child_weight=1, missing=nan, monotone_constraints='()',
                  n_estimators=100, n_jobs=0, num_parallel_tree=1, random_state=0,
                  reg_alpha=0, reg_lambda=1, scale_pos_weight=1, subsample=1,
                  tree_method='exact', validate_parameters=1, verbosity=None)   1.649520999999993
    0.8844444444444445
    [[155  10]
     [ 16  44]]
                  precision    recall  f1-score   support
               0       0.91      0.94      0.92       165
               1       0.81      0.73      0.77        60
        accuracy                           0.88       225
       macro avg       0.86      0.84      0.85       225
    weighted avg       0.88      0.88      0.88       225

    RFが実際にXGBよりも優れているという結果が出たようです。 XGBが何らかの形で過学習している可能性を示唆しているかもしれません。 RFCの結果はLRよりもわずかに改善されています。

    「グリッド検索によるパラメーターチューニング」をさらに行って、選択されたモデルを実行する

    では、ランダムフォレスト分類子がここで選ばれたモデルと仮定しましょう。  このモデルにさらにグリッド検索を実行して、結果のパフォーマンスをわずかにでも向上させられるかを確認することができます。 

    ここでの目標は、患者が遭遇する潜在的なICUリスクの偽陰性を最小限に抑えることで、このケースのRecallを最適化することに変わりはありませんので、「recall_score」を使用して、グリッド検索を再適合させます。 繰り返しますが、上記のテストセットは常に2915件のレコードの約12%に設定されていたため、ここでも10倍の交差検定を使用します。

    from sklearn.model_selection import GridSearchCV
    # ランダム検索の結果に基づいてパラメーターグリッドを作成する
    
    param_grid = {'bootstrap': [True],
     'ccp_alpha': [0.0],
     'class_weight': [None],
     'criterion': ['gini', 'entropy'],
     'max_depth': [None],
     'max_features': ['auto', 'log2'],             
     'max_leaf_nodes': [None],
     'max_samples': [None],
     'min_impurity_decrease': [0.0],
     'min_impurity_split': [None],
     'min_samples_leaf': [1, 2, 4],
     'min_samples_split': [2, 4],
     'min_weight_fraction_leaf': [0.0],
     'n_estimators': [100, 125],
     #'n_jobs': [None],
     'oob_score': [False],
     'random_state': [None],
     #'verbose': 0,
     'warm_start': [False]
    }#混同行列でファインチューニングする 
    from sklearn.metrics import roc_curve, precision_recall_curve, auc, make_scorer, recall_score, accuracy_score, precision_score, confusion_matrix
    scorers = {
        'recall_score': make_scorer(recall_score),
        'precision_score': make_scorer(precision_score),
        'accuracy_score': make_scorer(accuracy_score)
    }# ベースモデルを作成する
    rfc = RandomForestClassifier()
    # Instantiate the grid search model
    grid_search = GridSearchCV(estimator = rfc, param_grid = param_grid, 
                               scoring=scorers, refit='recall_score', 
                               cv = 10, n_jobs = -1, verbose = 2)train_features = X_train_resgrid_search.fit(train_features, train_labels)
    rf_best_grid = grid_search.best_estimator_rf_best_grid.fit(train_features, train_labels)
    rf_predictions = rf_best_grid.predict(X3_test) 
    print(accuracy_score(y3_test, rf_predictions))  
    print(confusion_matrix(y3_test, rf_predictions))
    print(classification_report(y3_test, rf_predictions))
    0.92
    [[ 46  14]
     [  4 161]]
                  precision    recall  f1-score   support
               0       0.92      0.77      0.84        60
               1       0.92      0.98      0.95       165
        accuracy                           0.92       225
       macro avg       0.92      0.87      0.89       225
    weighted avg       0.92      0.92      0.92       225

    グリッド検索は、FNを同じに保ちながら、実際に全体的な精度を少し上げることができるという結果が得られました。 

    AUC比較もプロットしてみましょう。

    confusion_matrix4 = pd.crosstab(y3_test, rf_predictions, rownames=['Actual'], colnames=['Predicted'])
    sns.heatmap(confusion_matrix4, annot=True, fmt = 'g', cmap="YlOrBr")print("LABEL ENCODING + STRATIFY")
    print(classification_report(y3_test, 1-y3_hat))
    print("AUC = ",roc_auc_score(y3_test, 1-y3_hat),'\n\n')print("SMOTE")
    print(classification_report(y3_test, 1-y_res_hat))
    print("AUC = ",roc_auc_score(y3_test, 1-y_res_hat), '\n\n')print("SMOTE + LBG Selected Weights + RF Grid Search")
    print(classification_report(y3_test, rf_predictions))
    print("AUC = ",roc_auc_score(y3_test, rf_predictions), '\n\n\n')y_res_hat_probs = LR.predict_proba(X3_test)
    y_res_hat_probs = y_res_hat_probs[:, 1]predictions_rf_probs = rf_best_grid.predict_proba(X3_test) #(X_validation)
    predictions_rf_probs = predictions_rf_probs[:, 1]fpr_res, tpr_res, _ = roc_curve(y3_test, 1-y_res_hat_probs)
    fpr_rf_res, tpr_rf_res, _ = roc_curve(y3_test, predictions_rf_probs)plt.figure(figsize=(10,10))
    plt.plot([0, 1], [0, 1], 'k--')
    plt.plot(fpr, tpr, label="Base")
    plt.plot(fpr2,tpr2,label="Label Encoded")
    plt.plot(fpr3,tpr3,label="Stratify")
    plt.plot(fpr_res,tpr_res,label="SMOTE")
    plt.plot(fpr_rf_res,tpr_rf_res,label="SMOTE + RF GRID")
    plt.xlabel('False positive rate')
    plt.ylabel('True positive rate')
    plt.title('ROC curve')
    plt.legend(loc="best")
    plt.show()
    LABEL ENCODING + STRATIFY
                  precision    recall  f1-score   support
               0       0.95      0.58      0.72        60
               1       0.87      0.99      0.92       165
        accuracy                           0.88       225
       macro avg       0.91      0.79      0.82       225
    weighted avg       0.89      0.88      0.87       225
    AUC =  0.7856060606060606 
    
    SMOTE
                  precision    recall  f1-score   support
               0       0.69      0.75      0.72        60
               1       0.91      0.88      0.89       165
        accuracy                           0.84       225
       macro avg       0.80      0.81      0.81       225
    weighted avg       0.85      0.84      0.85       225
    AUC =  0.8143939393939394 
    
    SMOTE + LBG Selected Weights + RF Grid Search
                  precision    recall  f1-score   support
               0       0.92      0.77      0.84        60
               1       0.92      0.98      0.95       165
        accuracy                           0.92       225
       macro avg       0.92      0.87      0.89       225
    weighted avg       0.92      0.92      0.92       225
    AUC =  0.8712121212121211

         

    アルゴリズム比較とさらなるグリッド検索の結果、AUCを78%から87%に引き上げることができ、全体の精度は92%、Recallは77%という結果を得られました。

    「従来型ML」アプローチのまとめ

    では、実際のところこの結果はどうなのでしょうか。 従来型MLアルゴリズムを使った基本的な手動プロセスとしては十分と言えます。  Kaggleコンペティションではどのように見えるでしょうか。 まぁ、リーダーボードには上がらないでしょう。 DataRobotの現在のAutoMLサービスから生のデータセットを実行したところ、最良の結果は、上位43個のモデルを比較したうち、「教師なし学習特徴によるXGBツリー分類子」モデルで、約90%以上相当のAUCを達成すると主張するでしょう。 本当にKaggleに参戦したいのであれば、これが私たちが狙いとする実用的なモデルと言えるでしょう。  最高の結果とモデルの上位リストもGitHubに添付しておきます。 最終的には、ケアサイトに特化した実際のケースについて言えば、この記事の「データとタスク」セクションで述べたように、ある程度カスタマイズされたディープラーニングアプローチにも焦点を当てる必要があると感じています。 もちろん、実際のケースでは、質の高いデータカラムをどこで収集するのかという手前の問題もあるでしょうが。

    IntegratedMLアプローチとは

    上記では、いわゆる従来型MLと呼ばれるプロセスを説明しました。通常は、データEDA、特徴量エンジニアリング、特徴量の選択、モデルの選択、およびグリッド検索などによるパフォーマンスの最適化が含まれるプロセスです。 これがこのタスクにおいて、今のところ思いつく最も単純なアプローチです。まだモデルのデプロイやサービス管理のライフサイクルについては触れていません。これについては次の記事で、Flask/FlasAPI/IRISを利用して、この基本MLモデルをCovid-19X線画像デモサービススタックにデプロイする方法を探りながら、説明したいと思います。

    IRISにはIntegratedMLが組み込まれており、強力なAutoMLオプションの洗練されたSQLラッパーとして用意されています。 パート2では、ビジネスのメリットとして同等のML結果を引き出しながら、特徴量の選択、モデルの選択、パフォーマンスの最適化などを行わずに済むように、上記のタスクを大幅に単純化したプロセスで達成する方法を調べます。

    以上です。同じデータでintegratedMLのクイックランをこの記事に追加するには、10分メモとしては長すぎてしまうため、次のパート2の記事で話すことにします。 

    0
    0 314
    お知らせ Makiko Kokubun · 9月 17, 2021

    開発者のみなさん、こんにちは!
    インターシステムズ開発者コミュニティでは、4回に渡り、InterSystems IRIS 2021.1の新機能や、開発を行う上で役に立つ機能をご紹介するウェビナーを開催します。10月の火曜と木曜のお昼に、弊社の技術者が30分でインターシステムズの最新テクノロジーについて解説します。
    ぜひお気軽にご視聴ください!

    ※ (2022/4/1更新)YouTubeにアーカイブを公開しました。こちらよりご覧いただけます。

    開催予定

    第1回:10/12(火)InterSystems IRIS Adaptive Analytics のご紹介
    第2回:10/14(木)Python Gateway のご紹介
    第3回:10/19(火)SQL から始める機械学習 – IntegratedML のご紹介
    第4回:10/21(木)FHIR 新機能

    時間:12:30~13:00予定(約30分)
    配信形式:ON24を使用したオンライン配信
    参加費:無料

    詳細・事前登録はこちらから

    プレビュー:IRIS & InterSystems IRIS for Health 2021.1 新機能のご紹介

    このビデオでは、昨年リリースされたバージョン2020.1から、新バージョン2021.1の間で追加/改善/強化された機能についてご紹介しています。合わせてご覧ください。

    0
    0 228
    記事 Makiko Kokubun · 4月 27, 2021 1m read

    *この動画は、2021年2月に開催された「InterSystems Japan Virtual Summit 2021」のアーカイブです。
     

    機械学習やAIの進歩が、社会的にも大きな話題になっています。 しかしながら、実際に機械学習を活用したシステムを開発し、ビジネスに生かすところに到達するまでには様々な課題があります。例えば、データサイエンティストと呼ばれる高度なスキルを持った人材の不足もその一つです。

    InterSystems は、アプリケーション開発者の方々が、IRIS data platform に保存されているデータとSQLを用いて、機械学習を容易に利用できる仕組み「IntegratedML」を開発しました。この動画では、IntegratedML の仕組みや使い方について解説します。

    間もなくリリース予定の InterSystems IRIS 2021.1 に、IntegratedML が含まれます。
    現在 2021.1のプレビュー版を公開中です。 詳しくはこちらをご覧ください。

    本動画ではデモを行っています。デモをご覧になりたい方は 16:36 からご覧ください。

    0
    0 142
    お知らせ Mihoko Iijima · 9月 13, 2020

    開発者の皆さんこんにちは!IRIS プログラミングコンテストも 6 回目を迎えました!

    今回のコンテストのテーマは

    「InterSystems IRIS をバックエンドとし Web またはモバイル・ソリューションをフロントエンドとして使用する⚡️フル・スタック・アプリケーション⚡️」

    です。日本からのご応募お待ちしております!

    Open Exchange(アプリケーション登録/参考となる開発テンプレート)のページはこちら➡ ⚡️ InterSystems Full Stack Contest ⚡️

    応募期間は 2020年9月21日~10月4日 です!

    (投票期間は 2020年10月5日~11日、勝者発表は 10月12日を予定しています)

    優勝特典

    1、審査員から多く票を集めたアプリケーションには、以下の賞金が贈られます。

    🥇 1位 - $2,000 

    🥈 2位 - $1,000 

    🥉 3位 - $500

    2、Developer Community で多く票を集めたソリューションには、以下の賞金が贈られます。

    🥇 1位 - $1,000 

    🥈 2位 - $500 

    複数の参加者が同数の票を獲得した場合、全参加者が勝者となり賞金は勝者間で分配されます。

    参加資格

    どなたでもご参加いただけます!(InterSystems 開発者コミュニティのアカウントを作成するだけでご応募いただけます)

    コンテストのスケジュール

    1
    0 325
    お知らせ Mihoko Iijima · 7月 22, 2020

    皆さんこんにちは。

    第4回 InterSystems IRIS プログラミングコンテスト(AI/MLコンテスト) への応募は終了しました。コンテストへのご参加、またご興味をお持ちいただきありがとうございました。

    この記事では、見事受賞されたアプリケーションと開発者の方々を発表します!

    🏆 審査員賞 - 特別に選ばれた審査員から最も多くの票を獲得したアプリケーションに贈られます。

    🥇 1位 - $2,000 は iris-integratedml-monitor-example を開発された José Roberto Pereir さんに贈られました!

    🥈 2位 - $1,000 は iris-ml-suite を開発された Renato Banza さんに贈られました!

    🥉 3位 - $500 は ESKLP を開発された Aleksandr Kalinin さんに贈られました!

    🏆 開発者コミュニティ賞 - 最も多くの票を獲得したアプリケーションに贈られます。

    🥇 1位 - $1,000 は iris-ml-suite を開発された Renato Banza さんに贈られました!

    🥈 2位 - $250 は iris-integratedml-monitor-example を開発された José Roberto Pereir さんに贈られました!

    0
    0 169