#Machine Learning (ML)

0 フォロワー · 34 投稿

機械学習(ML)は、コンピューターサイエンスの分野における人工知能のサブセットであり、明示的なプログラミングを行わなくても、統計的手法を使用してコンピューターにデータを「学習」させる機能を提供します。 詳細はこちら

記事 Hisa Unoura · 9月 4, 2025 9m read

開発者の皆様こんにちは。先日のWebinar「ベクトルであそぼう!」では、以下の内容でデータをベクトル化することの可能性をご紹介しました。

写真から魚の名前をあててみる

  • マルチモーダルモデル CLIP を利用して画像によるテキストの検索

ベクトルを「見える化」する

  • ベクトルを次元削減して 3 次元ベクトルに変換し、可視化

データの集まりを見る

  • K-Means によるデータのクラスタリング

変なデータ (=アノマリ) を見つける

  • K-Means による教師なしアノマリ検知や半教師ありアノマリ検知


一番お伝えしたかったのは 「データをベクトルに変換することで、データ利活用の幅が大きく広がる」 ということです。
本記事ではマルチモーダルAIおよびCLIPについておさらいし、Webinarでは時間の都合で触れきれなかったTips  - モダリティギャップというマルチモーダルモデル特有の現象についてお伝えします。

なお筆者は AI/機械学習の専門家ではありませんが、機械学習を利用したプロダクト・プロジェクトに携わり親しんでまいりました。ご質問・ご指摘などありましたらお気軽にコメント欄からお願いします。

マルチモーダル AI

近年、AI 分野では マルチモーダル AI が大きな注目を集めています。
「モーダル」とはデータの種類のことを指します。

0
0 45
お知らせ Mihoko Iijima · 4月 9, 2024

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

(2024.4.17更新:コンテストタイトルに「ベクトル検索」を追加しました)

次の InterSystems オンラインプログラミングコンテストのテーマが決定しました!👉生成 AI、ベクトル検索、機械学習 です!

🏆 InterSystems ベクトル検索、GenAI、ML コンテスト(USコミュニティ) 🏆

期間: 2024年4月22日~5月19日 

賞金総額: $14,000


0
0 125
記事 Toshihiko Minamoto · 7月 5, 2023 39m read

この記事では、InterSystems IRIS の学習に関連したトピックについて、開発者コミュニティでの厳選された記事にアクセスすることができます。機械学習や Embedded Python、JSON、API と REST アプリ、InterSystems環境の構築と管理、DockerとCloud、VSCode、SQL、Analytics/BI、グローバル、セキュリティ、DevOps、インターオペラビリティNative API、それぞれでランク付けされたトップの記事を見ることができます。ぜひ、楽しみながら学んでください!  

機械学習

機械学習は、高度なデータ分析を構築し、優れた効率で手動活動を自動化するための必須技術です。既存のデータから学習する認知モデルを作成し、自己調整されたアルゴリズムに基づいて予測、確率計算、分類、識別、「非創造的」な人間の活動の自動化を実行します。

すべてのシナリオにおいて、InterSystems IRISは、これらのマシンラーニングモデルを作成、実行、利用可能にし、使用するためのデータプラットフォームおよび環境として機能します。IRISは、SQLコマンドからのML利用(IntegratedML)、Embedded PythonやPMML(Predictive Model Markup Language)による機械学習が可能です。以下の記事でその機能を確認することができます。

名称概要URL
IntegratedMLハンズオンラボIntegratedMLの実践的な概要https://community.intersystems.com/post/integratedml-hands-lab
InterSystems IRISデータプラットフォームによるAIロボット化IRISプロダクションのAIhttps://community.intersystems.com/post/ai-robotization-intersystems-iris-data-platform
IRIS IntegratedMLを使った糖尿病予測WebアプリIntegratedMLサンプルhttps://jp.community.intersystems.com/node/535221
妊産婦の健康リスクの予測IntegratedMLサンプルhttps://community.intersystems.com/post/predict-maternal-health-risks
機械学習によるコミュニティー記事の整理 - 1Python MLライブラリの利用https://community.intersystems.com/post/using-machine-learning-organize-community-1

 

ObjectScript言語

ObjectScript は InterSystems のオフィシャルプログラミング言語です。簡単で柔軟性があり、バックエンド、統合、および分析アプリケーションの作成に非常に強力です。詳細については、以下の記事を参照してください。

名称概要URL
InterSystems ObjectScript 101++ (EN)ObjectScriptを学ぶビデオシリーズhttps://community.intersystems.com/post/intersystems-objectscript-101-en
$Sequence関数について数列の作成するhttps://community.intersystems.com/post/sequence-function
Caché ObjectScript でのパフォーマンスの高いループの作成ループの作成https://jp.community.intersystems.com/node/481811
データの匿名化、iris-Disguiseの導入ObjectScript の永続的なクラスとプロパティをカスタマイズする方法について説明するhttps://jp.community.intersystems.com/node/510731
ObjectScriptのエラー処理に関するスニペット例外処理https://jp.community.intersystems.com/node/491451
ObjectScriptにおける従来のデバッグデバッグ手法https://community.intersystems.com/post/traditional-debugging-objectscript
Caché での正規表現の使用正規表現を使った作業https://jp.community.intersystems.com/node/481816
ObjectScript における堅牢なエラー処理とクリーンアップ品質の高いコードを書くhttps://jp.community.intersystems.com/node/486226
InterSystems Ensembleを愛し、心配することをやめた理由プロダクションでのJSON処理https://community.intersystems.com/post/how-we-learned-stop-worrying-and-love-intersystems-ensemble
より使いやすくなったオブジェクト・ダンプダンプするオブジェクトhttps://community.intersystems.com/post/more-usefull-object-dump
InterSystems IRISのマクロを使ったロギングマクロを使ったロギングhttps://jp.community.intersystems.com/node/503796
SYSLOG - その実態と意味することシスログのデバッグ情報https://jp.community.intersystems.com/node/492146
%Statusを使ったデバッグのヒント%Statusを使ったデバッグhttps://jp.community.intersystems.com/node/503801
$Queryの有効活用$Query を使ってデータを探すhttps://community.intersystems.com/post/making-most-query
多次元プロパティの永続性 - Part 1 (クラシック)多次元永続プロパティhttps://community.intersystems.com/post/multidimensional-property-persistence-part-1-classic
採用されたBitmapBitmap インデックスhttps://community.intersystems.com/post/adopted-bitmap
タイムロードになる方法 - 誕生日付と時刻のAPIhttps://jp.community.intersystems.com/node/527796
正確なバージョン情報($zv / $zversion)の重要性と収集についてIRISバージョン取得https://community.intersystems.com/post/importance-and-collection-exact-version-information-zv-zversion
1840年12月以前の日付 ? $H( orolog )がネガティブ?ネガティブな日付https://community.intersystems.com/post/date-dec1840-negative-horolog
Caché でのカスタム・インデックス・タイプの作成カスタムインデックスの作成https://jp.community.intersystems.com/node/479316
$LIST 文字列フォーマットと %DynamicArray および %DynamicObject クラス$LIST、%DynamicObject、%DynamicArrayの使用法https://jp.community.intersystems.com/node/483711
^ERRORグローバルに対するSQLSQLを使ってエラーの内容の確認https://community.intersystems.com/post/sql-error-global
コードによるデフォルト設定値の追加デフォルト値の設定https://community.intersystems.com/post/add-default-setting-value-code
ダイナミックオブジェクトの反復処理イテレート(反復処理)の使用https://community.intersystems.com/post/iterate-over-dynamic-object
クラスのすべてのプロパティをリストアップする (ObjectScriptがお気に入りな理由)ObjectScriptプロパティの反復使用https://jp.community.intersystems.com/node/515786
いつも使っているtry catchブロックTry Catchのハンドリングhttps://community.intersystems.com/post/try-catch-block-i-usually-use-intersystems-objectscript
ObjectScriptでシェルコマンドの実行ObjectScriptでシェルコマンドの実行https://community.intersystems.com/post/running-shell-commands-objectscript

Embedded Python

Python は、世界で最も人気があり、よく使われているプログラミング言語の 1 つです (https://www.tiobe.com/tiobe-index/)。InterSystems IRIS は、すべての主要なプログラミング言語に対して開かれたデータ・プラットフォームです。しかし、Python は、この素晴らしい言語とそのライブラリは、クラス、SQL、および統合/プロダクショ ンなど、IRIS のあらゆる場所で使用することができます。ObjectScript ( InterSystems のプログラミング言語 ) を知らない、または知りたくない人にとって、Python は素晴らしい選択肢となります。そのやり方については、以下の記事を参照してください。

名称概要URL
機械と戦おうEmbedded Pythonを使ったチックタックトー・ゲームの構築https://community.intersystems.com/post/lets-fight-against-machines
InterSystems IRIS 2021.2+ Python サンプル ( Embedded, Native API およびノートPC)複数のPythonノートPCでPythonとIRISを見るhttps://community.intersystems.com/post/intersystems-iris-20212-python-examples-embedded-native-apis-and-notebooks
Embedded PythonによるWebSocketクライアントCustom Socket サンプルhttps://community.intersystems.com/post/websocket-client-embedded-python
AWS LambdaにおけるIRIS Python Native APIAWSでのPythonhttps://community.intersystems.com/node/485361
JupyterノートPCにObjectScriptを追加する方法ノートPCでのIRIShttps://jp.community.intersystems.com/node/521496
ようこそDjangoIRISをデータベースとしたPython Djangoアプリの作成https://jp.community.intersystems.com/node/527801
IRISとGoogle Maps APIによるジオコーディングGeocoding python ライブラリの使用https://community.intersystems.com/post/geocoding-iris-and-google-maps-api
IRISとPython gTTSを用いたテキストから音声への変換のためのRESTサービスgTTSを使用したPythonサンプルhttps://community.intersystems.com/post/rest-service-convert-text-audio-using-iris-and-python-gtts
Python Flask WebフレームワークによるIRISレスポンシブダッシュボードの作成IRISによるFlask Webアプリhttps://community.intersystems.com/post/building-iris-responsive-dashboard-python-flask-web-framework

JSON

JSON は、マーケットで最も広く使用されている、データの送受信のための相互運用性フォーマットの 1 つです。InterSystems IRIS は、いくつかの方法でこの形式をサポートしています。JSON (DocDB) でネイティブ・データベースを持ち、オブジェクトを直列化および非直列化し、特に REST サービスからの要求と応答を JSON で処理することが可能です。以下の記事を確認してください。

名称概要URL
Caché 2016.1における新しいJSON機能の紹介ObjectScript JSON API の紹介https://community.intersystems.com/post/introducing-new-json-capabilities-cach%C3%A9-20161
JSONの機能強化JSON Adaptor APIhttps://jp.community.intersystems.com/node/481776

APIとRESTアプリ

バックグラウンドアプリケーションは現在、REST(Representational State Transfer)パラダイムで開発され、Web APIとして公開されています。以下の記事で、その仕組みを確認してください。

名称概要URL
InterSystemsのデータプラットフォームのためのGraphQLGraphQLスタイルでREST APIの作成https://jp.community.intersystems.com/node/481796
InterSystems API Managerの紹介API Managementの概要https://community.intersystems.com/post/introducing-intersystems-api-manager
RESTの高度なURLマッピングAPIへの経路のマッピングhttps://jp.community.intersystems.com/node/497976
AppS.REST: InterSystems IRISのための新しいRESTフレームワークRESTアプリを簡単に作成https://jp.community.intersystems.com/node/497991
RESTForms : クラスのためのREST APICRUDアプリケーションのためのREST APIの開発https://jp.community.intersystems.com/node/479226
スペックファーストのアプローチによるREST APIの作成Contract First ApproachによるAPI開発https://jp.community.intersystems.com/node/476556
ObjectScript REST API クックブックREST API 開発のヒントhttps://community.intersystems.com/post/objectscript-rest-api-cookbook
永続クラスとシリアルクラスからSwaggerスペックを生成するContract First ApproachによるAPI開発https://jp.community.intersystems.com/node/490976
InterSystems IRIS REST アプリケーションのパターンIRISによるAPI RESTの作成https://community.intersystems.com/post/intersystems-iris-rest-application-patterns
SUSHIでFHIRプロファイルを作成しよう 第1回カスタムFHIRプロファイルの作成https://jp.community.intersystems.com/node/493351
ゼロから使いこなすIAMIAMでAPIの管理https://jp.community.intersystems.com/node/493416
InterSystems API Management を使用してAPIの負荷を分散するAPIMによるAPIのロードバランスhttps://jp.community.intersystems.com/node/482711
InterSystems API Management で OAuth 2.0 による API のセキュリティの確保 - 第1回APIMによるAPI のセキュリティの確保hhttps://jp.community.intersystems.com/node/497946
InterSystems IRISアプリケーションのAngular UIを5分で取得IRISとAngularによるFull Stackアプリhttps://community.intersystems.com/post/getting-angular-ui-your-intersystems-iris-application-5-minutes
InterSystems IRIS REST APIへのアップロードREST APIによるファイル保存https://community.intersystems.com/post/upload-intersystems-iris-rest-api

InterSystems 環境の管理と設定

IRIS環境を適切に管理・設定することは、ユーザーが使用するアプリケーションのパフォーマンス、セキュリティ、可用性、信頼性にとって不可欠です。これらの記事は、これを行うための優れたヒントを与えてくれるでしょう。

名称概要URL
InterSystemsデータプラットフォームにおける容量計画およびパフォーマンスのシリーズのインデックス性能とパフォーマンスの向上https://jp.community.intersystems.com/node/477596
InterSystems Cache での %Installer によるアプリケーションのデプロイメント%Installer によるネームスペース、データベース、およびアプリケーションの構成の作成https://jp.community.intersystems.com/node/478966
InterSystems IRISによる水平方向のスケーラビリティIRISインスタンスを設定し、水平方向のスケーラビリティの実現https://jp.community.intersystems.com/node/477591
Raspberry Pi Raspberry で動作する InterSystems Iris Fhirserver が FHIRserver として動作Raspberry PI内部でIRISの動作https://jp.community.intersystems.com/node/516361
バーチャルIPアドレスを使用しないデータベースミラーリングVIPによるミラーの設定https://jp.community.intersystems.com/node/493401
DockerによるApache Web GatewayWebアプリケーションのSSLとWeb Gatewayの設定https://jp.community.intersystems.com/node/542181
IRISにおけるSAMLとの連携Webサービス向けSAMLhttps://community.intersystems.com/post/work-saml-iris
SYSTEM.Encryption クラスの習得IRISによる暗号化・復号化https://jp.community.intersystems.com/node/523406

Docker と Cloud

新しいアプリケーション・アーキテクチャは、コンテナ Docker と Cloud において動作し、弾力的なスケーラビリティ、インストール、設定、プロビジョニング時間の短縮、インフラの複雑性とコストの削減を実現することを目的としています。これらの記事を読んで、IRISをクラウド化する方法を学んでください。

名称概要URL
Kubernetesにおけるミラーリングを使用しない高可用性IRISデプロイKubernetesによるIRISをクラウドクラスターで利用するhttps://jp.community.intersystems.com/node/490971
Amazon Web Services (AWS)のためのInterSystems IRISリファレンス・アーキテクチャAWSでのIRIShttps://jp.community.intersystems.com/node/481326
Microsoft Azure Resource Manager (ARM)のInterSystems製リファレンス・アーキテクチャ安価なマシン(ARM machine)を使ったAzureでのIRIShttps://jp.community.intersystems.com/node/478971
Dockerfileと仲間たち、またはInterSystems IRISでのObjectScriptプロジェクトの実行と共同作業の方法Dockerプロジェクトにおける重要なファイルについて知ることhttps://community.intersystems.com/post/dockerfile-and-friends-or-how-run-and-collaborate-objectscript-projects-intersystems-iris
CloudFormationテンプレートを使用したAWS向けInterSystems IRISデプロイメントガイドCloudFormationを使ったAWSで使うIRIShttps://jp.community.intersystems.com/node/486206
Google Cloud Platform(GCP) におけるInterSystems IRIS のリファレンス・アーキテクチャGoogle Cloudで使うIRIShttps://jp.community.intersystems.com/node/479806
InterSystems IRISでAWS Glueの使用IRISとAWS Glue(AWSのETLツール)の利用https://jp.community.intersystems.com/node/485971
AmazonのEKSとIRIS。高可用性とバックアップAWSによるHAで使うIRIShttps://jp.community.intersystems.com/node/501186 AWSによるHAでのIRIS
コンテナでの InterSystems レポートの動かしてみるDockerに関するIRISのレポートhttps://jp.community.intersystems.com/node/501656
InterSystems IRIS を Kubeless を使って FaaS モードで実行Kubernetesで使うIRIShttps://jp.community.intersystems.com/node/523446
InterSystems Kubernetes Operator Deep Dive ‐ Kubernetes Operatorの紹介Kubernetesで使うIRIShttps://community.intersystems.com/post/intersystems-kubernetes-operator-deep-dive-introduction-kubernetes-operators
クラウドホストのスケーリングとInterSystems IRISの再構築AWS、Azure、またはGCPでのIRISのスケーリングhttps://community.intersystems.com/post/scaling-cloud-hosts-and-reconfiguring-intersystems-iris
Amazon EKSを用いたシンプルなIRISベースのWebアプリケーションのデプロイメントAWSで使うIRIShttps://jp.community.intersystems.com/node/478961

VSCode

VSCodeは世界で最も使われているIDEの1つです。IRISはこのIDEをフルサポートしています。以下の記事をご覧ください。

名称概要URL
VSCode-ObjectScriptのGitHubでの使用Web Github VSCodeでIRISアプリの開発https://jp.community.intersystems.com/node/510736
IRISによるGitHubのコードスペースGithubでIRISアプリの開発https://jp.community.intersystems.com/node/510736
VSCodeのヒントとコツ - SOAPウィザードVSCodeにショートカットのオプションの作成https://community.intersystems.com/post/vscode-tips-tricks-soap-wizard
VS Codeへの独自のスニペットの追加スニペットの作成https://community.intersystems.com/post/adding-your-own-snippets-vs-code

SQL

SQLは、リレーショナルデータベースを扱うのに最もよく使われる言語の1つです。これらの記事は、クエリの実行方法とデータの永続性を示しています。

名称概要URL
フリーテキスト検索:SQL開発者が隠しているテキストフィールドの検索方法*インデックスの活用で高度な検索を促進https://jp.community.intersystems.com/node/479321
日付範囲クエリのSQLパフォーマンスの向上日付を使ったSQLクエリの実行https://jp.community.intersystems.com/node/479286
スタティックWHERE条件永続的なクラ使うWherehttps://community.intersystems.com/post/static-where-conditions
2021.2 SQL機能スポットライト - ランタイムプランの選択ランタイムSQL実行プランの選択https://jp.community.intersystems.com/node/510746
2020.1 の新機能:ユニバーサルクエリキャッシュSQL Cachehttps://jp.community.intersystems.com/node/535211
マテリアライズド・ビュー永続的なクラスの中にビューの作成https://community.intersystems.com/post/materialized-views
SQLを使ったデバッグのコツSQLコマンドのデバッグhttps://community.intersystems.com/post/debugging-trick-sql
ClassQueries()をテーブルとして使用ビューの作成https://community.intersystems.com/post/using-classqueries-tables
M:Nの関係N対Nの関係性のマッピングhttps://community.intersystems.com/post/mn-relationship
IRISでCOVIDにたいしてのAWS S3データをSQLテーブルとして読み込むAWS S3からCSVデータをIRISのテーブルに取得https://community.intersystems.com/post/reading-aws-s3-data-covid-sql-table-iris
知っておくと便利なクエリパフォーマンスのコツ - Tune TableSQLチューニングhttps://jp.community.intersystems.com/node/535211
データストレージ:開発がうまくいくために知っておくべき情報より高いパフォーマンスを得るために、データストレージ部を永続的なクラスで構成するhttps://community.intersystems.com/post/data-storage-information-you-must-know-make-good-decisions-when-developing
日付範囲クエリのSQLパフォーマンスを改善する vol2SQLクエリの日付に関するチューニングhttps://jp.community.intersystems.com/node/479291
スクロール可能なResultSetのページネーションのサンプルSQLの結果をページ分割する(コメントも参照)https://community.intersystems.com/post/scrollable-resultset-pagination-sample
1日目 InterSystems ObjectsとSQLを用いた開発InterSystems IRISへのSQLに関するコンセプトhttps://community.intersystems.com/post/day-1-developing-intersystems-objects-and-sql
SQLgatewayを利用したDBマイグレーションPostgreSQL、MySQL、その他のデータベースからIRISへのマイグレーションhttps://jp.community.intersystems.com/node/518861
InterSystems IRIS の既存のテーブルに CSV のインポートCSVからSQLテーブルへのインポートhttps://community.intersystems.com/post/importing-csv-existing-table-intersystems-iris
データベースの4つのAPISQLの APIhttps://community.intersystems.com/post/four-database-apis
アトミックでない属性のインデックス作成高度なインデックスのオプションの作成https://jp.community.intersystems.com/node/486236
インデックスについてインデックス作成の基礎知識https://jp.community.intersystems.com/node/492126
Dynamic SQLからDynamic ObjectへDynamicSQLの使用https://community.intersystems.com/post/dynamic-sql-dynamic-object
データ移行ツール - その1:PostgresからIRISへ一般的なデータベースからIRISデータベースへの移行方法を紹介する連載記事https://jp.community.intersystems.com/node/518871

アナリティクスとビジネスインテリジェンス(BI)

アナリティクスとBIは、グラフ、ダッシュボード、サマリー、詳細表などのデータ分析、およびアナリスト・ユーザーによるナビゲーションとデータ探索に基づいて意思決定を行うことを可能にします。ここでは、IRISを使った分析アプリケーションの構築方法を紹介します。

名称概要URL
InterSystems IRISのCOVID-19アナリティクスInterSystems IRISにおけるCOVID-19アナリティクスhttps://community.intersystems.com/post/covid-19-analytics-intersystems-iris
DeepSeeトラブルシューティングガイド不具合修正https://jp.community.intersystems.com/node/542206
AnalyzeThis - InterSystems BIへのクイックスタートInterSystems BIへのクイックスタートhttps://community.intersystems.com/post/analyzethis-%E2%80%93-quick-start-intersystems-bi
InterSystems IRIS用のPower BIコネクタ パート1Power BIでIRISのデータの利用https://jp.community.intersystems.com/node/482606
DeepSee でのポートレットの作成IRIS BIによるアナリティクスポートレットhttps://community.intersystems.com/post/creating-portlets-deepsee
Game Of Throne Analytics、またはアリア スタークリストの長さアナリティクスのサンプルhttps://community.intersystems.com/post/game-throne-analytics-or-how-long-aryas-stark-list
DeepSee Web。AngularJSによるInterSystems Analyticsのビジュアライゼーション。第 1 部Angularを使用するWebダッシュボードhttps://community.intersystems.com/post/deepsee-web-intersystems-analytics-visualization-angularjs-part-1
IRIS でアナリティクスソリューションを構築するIRISでアナリティクスを行うための主なオプションの紹介https://jp.community.intersystems.com/node/501571

グローバル

IRIS では、SQL、クラス、JSON ドキュメント、BI キューブ、その他のカスタム形式など、データを柔軟に保存および取得するための重要なメカニズムとして、グローバルが使用されています。以下の記事で、その方法を垣間見てください:

名称概要URL
グローバルをクラスにマッピングする技術 :1 / 3グローバルの SQL テーブルおよびオブジェクトへのマッピングhttps://jp.community.intersystems.com/node/486176
グローバルは、データ管理の魔法の剣。第1回グローバルに関する基礎知識https://jp.community.intersystems.com/node/476486
GlobalToJSON-embeddedPython-pureグローバルをJSONへの書き出しhttps://community.intersystems.com/post/globaltojson-embeddedpython-pure
InterSystems IRIS のグローバルを使ったトランザクショングローバルパーシスタンスのトランザクション管理https://jp.community.intersystems.com/node/486476
グローバルによる マインドマップの保存グローバルを使ってマインドマップデータの永続化https://jp.community.intersystems.com/node/516226

セキュリティ

どのようなアプリケーションでも、セキュリティを確保することは非常に重要です。セキュリティは、アクセスや承認の管理、トランザクションの追跡と監査、保存および転送されるコンテンツの暗号化、感性的なリソースの保護を保証するための正しい設定パラメータに関連しています。これらの記事を読んで、セキュリティを確立する方法について理解を深めてください。

名称概要URL
InterSystems IRIS Open Authorization Framework (OAuth 2.0) の実装 - 第1回OAuthの使用https://jp.community.intersystems.com/node/478821
WebのデバッグCSPおよびRESTアプリのデバッグhttps://jp.community.intersystems.com/node/501166
InterSystems IRIS のクラスクエリ永続クラス内部でのSQL Queryの定義https://jp.community.intersystems.com/node/483716
TLS/SSLでOSの証明書ストアの使用SSLを行うためにOSの証明書の使用https://community.intersystems.com/post/using-os-certificate-store-tlsssl
インテグリティチェック :スピードアップまたはスピードダウンインテグリティの確保https://community.intersystems.com/post/integrity-check-speeding-it-or-slowing-it-down
データ変更の追跡 - 監査ログ - 1 / 2監査データの保存https://jp.community.intersystems.com/node/483691
TLS/SSL/HTTPS による管理ポータル(プライベート Web サーバー)の運用IRIS Web サーバーへの SSL の設定https://community.intersystems.com/post/running-management-portal-private-web-server-over-tlssslhttps
OAuth認証とInterSystems IRIS:信頼プロトコルのテイム化OAuthの使用https://community.intersystems.com/post/oauth-https://jp.community.intersystems.com/node/493421
SOAP(Web)サービスでのOauth2の利用についてSOAPサービスにおけるOauthの設定https://jp.community.intersystems.com/node/483696
DeepSee: セキュリティの設定 - 1/5IRIS BIにおけるセキュリティhttps://community.intersystems.com/post/deepsee-setting-security-part-1-5
システムのセキュリティレベルの変更についてデフォルトでセキュリティhttps://community.intersystems.com/post/changes-security-level-system

DevOps

DevOpsとは、ソースコードの開発(Dev)から本番運用(Ops)への高速かつ高品質な移行を自動化することを可能にするプラクティスやツールを採用する方法です。IRISでその方法をご覧ください。

名称概要URL
GitLabを使ったInterSystemsソリューションの継続的デリバリー - 第1回:GitGitLabによる継続的デリバリーhttps://jp.community.intersystems.com/node/476396
InterSystems ObjectScripts パッケージ・マネージャの紹介ZPMを使用して、アプリケーション内のサードパーティパッケージを設定およびインストールhttps://jp.community.intersystems.com/node/486186
ZPMshow - 疲れた指のためのヘルパーZPM - IRISパッケージマネージャの使用方法https://community.intersystems.com/post/zpmshow-helper-tired-fingers
プログラムによるミラーのセットアップ方法新しいミラーの作成を自動化するhttps://jp.community.intersystems.com/node/516091
ObjectScript パッケージマネージャにおけるユニットテストとテストカバレッジObjectScriptのコード品質のためのUnit Testsの作成https://jp.community.intersystems.com/node/516111
DockerとMergeCPFを使ったシャードクラスターの展開cpfファイルによる設定の自動化https://community.intersystems.com/post/deploying-sharded-cluster-docker-and-mergecpf
Caché ObjectScript クイックリファレンスObjectScriptリファレンスpdfドキュメントhttps://community.intersystems.com/post/cach%C3%A9-objectscript-quick-reference
ZPMモジュールの解剖学:InterSystems Solution のパッケージングZPMを使用してデプロイメントの自動化https://jp.community.intersystems.com/node/487071
IRISコンテナへのVSCodeの追加VSCodeをdockerインスタンスに埋め込むhttps://community.intersystems.com/post/adding-vscode-your-iris-container
InterSystems IRIS用の新しいデータベース、ネームスペース、およびWebアプリケーションをプログラムによって作成する方法データベースとネームスペースの作成の自動化https://community.intersystems.com/post/how-create-new-database-namespace-and-web-application-intersystems-iris-programmatically
ユニットテスト: ObjectScript コードの品質ユニットテストによる品質保証https://community.intersystems.com/post/unit-tests-quality-your-objectscript-code
インターシステムズ開発者コミュニティのDockerイメージDockerコミュニティイメージhttps://community.intersystems.com/post/some-intersystems-developer-community-docker-images

インターオペラビリティ

IRISは、強力なデータおよびアプリケーションのインタラクティブなバスを備えています。以下の記事でその使い方をご覧ください。

名称概要URL
EnsembleからTelegramでアラートの送信テレグラムにデータを送信するためのプロダクションhttps://community.intersystems.com/post/sending-alerts-ensemble-telegram
[初めてのInterSystems IRIS] インターオペラビリティを使ってみようビジネスサービス、オペレーション、プロセス、プロダクションの作成https://jp.community.intersystems.com/node/483021
Embedded PythonによるInterSystems IRISのインターオペラビリティーPythonによるビジネスサービス、オペレーション、プロセス、プロダクションの作成https://jp.community.intersystems.com/node/518846
Ensemble / Interoperabilityトレーニングコースプロダクションの作り方を学ぶのに最適なサンプルhttps://community.intersystems.com/post/ensemble-interoperability-training-course
プログラムによるインターオペラビリティーのサンプルPythonまたはObjectScriptを使用したプログラムによるプロダクションhttps://jp.community.intersystems.com/node/521511
フォルダ内のファイルのリスティングフォルダー内のファイルをリスト化するhttps://community.intersystems.com/post/listing-files-folder
.Net/Java Gatewayのコンテナ化(またはKafka統合のデモ)Javaまたは.Net Native APIを使用したKafkaサポートhttps://jp.community.intersystems.com/node/542191
PEXを使用した.NETまたはJavaでのIRIS統合の実装PEXによるJavaまたは.Netを使ったプロダクションの作成https://community.intersystems.com/post/implementing-iris-integrations-net-or-java-using-pex
Java Business HostからPEXへの移行PEXの使用https://jp.community.intersystems.com/node/486231
Tesseract OCRとJava Gatewayの使用についてJava PEXの使用https://community.intersystems.com/post/using-tesseract-ocr-and-java-gateway
PEXのビジネスオペレーションを作成についてCreate Java PEX Business Operationhttps://community.intersystems.com/post/creating-pex-business-operation
OCRとNLPを統合したInterSystems IRISJava PEX のサンプルhttps://community.intersystems.com/post/ocr-and-nlp-together-intersystems-iris
HTTP Adapterを使用したカスタムインターオペラビリティビジネスサービスの作成ビジネスサービスの作成https://community.intersystems.com/post/creating-custom-interoperability-business-service-using-http-adapter

Native API

IRISは、市場で最も使用されているプログラミング言語(Java、Javascript/NodeJS、.Net、C++、Python)を使用することに前向きです。これを実現するために、これらの言語ごとにNative APIを使用しています。以下の記事をご覧ください。

名称概要URL
Docker Micro ServerとしてIRIS Native APIを使用したWebSocket Client JSIRISとNodeJSを使ってWebSocketを行うhttps://jp.community.intersystems.com/node/507846
ObjectScript用IRIS Native APINative APIの使用https://community.intersystems.com/post/iris-native-api-objectscript
Node.jsでのZPMの使用Node.jsプロジェクトでのZPMの使用https://jp.community.intersystems.com/node/507866
テキストファイルからPDFファイルの作成PDFファイルの生成用Java Native APIhttps://community.intersystems.com/post/creating-pdf-text-file
InterSystems IRISを使った開発を1分以内に始める方法IRISを使った開発の開始https://community.intersystems.com/post/how-start-development-intersystems-iris-less-minute
Python + IRIS Globals を使ったブログの作成Python Native API用ブログhttps://jp.community.intersystems.com/node/501856
0
2 245
お知らせ Mihoko Iijima · 4月 4, 2023

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

技術文書ライティングコンテストの受賞者が発表されたばかりですが、次のコンテスト:InterSystems IRIS Cloud SQL and IntegratedML コンテスト 2023 のテクノロジーボーナス詳細が決定しましたのでお知らせします📣

  • IntegratedML の利用
  • オンラインデモ
  • コミュニティに記事を投稿する
  • コミュニティに2つ目の記事を投稿する
  • YouTubeにビデオを公開する
  • はじめてチャレンジされた方
  • InterSystems Idea 内 Community Opportunityの実装

獲得ポイントについて詳細は、以下ご参照ください。

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

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

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

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

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

0
0 209
記事 Mihoko Iijima · 2月 21, 2023 3m read

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

開発者向け情報を集めた「Developer Hub」ページが新たに登場しました!

(2025/10/9更新: 新たなチュートリアルが加わりましたので情報更新しました。)

このページには、5種類のチュートリアルが用意されています。チュートリアはブラウザ上で動作し、VSCodeやIRISターミナル、管理ポータルなどチュートリアルで使用するすべての画面が1つのタブ内で開くようになっています。

チュートリアルを試すための事前準備は不要で、クリック1回ですぐにお試しいただけます!(ユーザ登録も不要です)(チュートリアル開始方法は、ページ末尾をご覧ください。)

0
0 335
お知らせ 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 · 2月 3, 2022 12m read

    キーワード: Pandasデータフレーム、IRIS、Python、JDBS

    目的

    PandasデータフレームはEDA(探索的データ分析)に一般的に使用されるツールです。 MLタスクは通常、データをもう少し理解することから始まります。 先週、私はKaggleにあるこちらのCovid19データセットを試していました。 基本的に、このデータは1925件の遭遇の行と231列で構成されており、タスクは、患者(1つ以上の遭遇レコードにリンク)がICUに入室するかどうかを予測するものです。 つまりこれは、いつものようにpandas.DataFrameを使用して、まず簡単にデータを確認する、通常の分類タスクです。  

    現在では、IRIS IntegratedMLが提供されています。これには強力な「AutoML」のオプションに関する洗練されたSQLラッパーがあるため、従来型のMLアルゴリズムに対抗して、多様なデータフレームのステージをIRISデータベーステーブルに保存してから、IntegratedMLを実行する方法を頻繁に採用しています。  ただし、dataframe.to_sql()はまだIRISで機能しないため、実際には、ほとんどの時間を他のデータ保存手段をいじることに充てていました。 いわば、土曜の朝の楽しい朝食の時間に素敵なオムレツを作ろうとしていたのに、一日中コンロの下で、ガスとシンクの配管作業をしていたような状況です。 さて、完璧ではありませんが、数週間後に忘れてしまわないように、簡単なメモを残しておくことにします。

    範囲

     IRISでdataframe.to_sql()を作成しませんでした。残念ながら、まだそこにはたどり着いていませんが、JDBC(JayDeBeApi)を介してデータフレームを動的に直接IRISに保存する簡単なPython関数をできるだけ単純かつ生の状態を維持してさくせいしました。  既知の問題(「MemoryError」)により、PyODBCではまだ機能しない可能性があります。

    環境

    以下のスクリプトのベースとして、単純なdocker-coposeを介したこちらのIntegratedMLテンプレートを使って、テストしています。 環境トポロジーはGitHubリポジトリに含まれます。 IRISコンテナーに接続するには、こちらのJDBC Jupyterノートブックを使用しています。 

    テスト

     1. dataframe.to_sql() をエミュレートするPython関数を定義する

    ノートブックのセルで以下を実行しました。

    def to_sql_iris(cursor, dataFrame, tableName, schemaName='SQLUser', drop_table=False ):
    &lt;span style="color:#999999;">        """"
            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.
            """&lt;/span>
            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

    基本的に、上記はIRISテーブルにデータフレームを動的に挿入しようとしています。 テーブルがすでに存在する場合は、完全なデータフレームがその最後にアペンドされますが、存在しない場合は、データフレームの次元(列名と列の型)に基づく新しいテーブルが作成され、その全コンテンツが挿入されます。  executemanyメソッドを使用しているだけです。

    2. テスト - 生データファイルをデータフレームに読み込む

    ノートブックで以下のコードを実行し、ローカルのドライブからデータフレームに生データを読み込みます。 生データは、こちらのKaggleサイトからダウンロード可能です。

    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))
            
    df = pd.read_excel("./input/raw_data_kaggle_covid_icu.xlsx")df
    ./input/datasets_605991_1272346_Kaggle_Sirio_Libanes_ICU_Prediction.xlsx
    Out[2]:
    <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>
    
      PATIENT_VISIT_IDENTIFIER
    1
    2
    3
    4
    ...
    1920
    1921
    1922
    1923
    1924
    1925 rows × 231 columns

     

    3. テスト - Python over JDBCでIRIS DBに接続する

    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()

    4. テスト - データフレームをIRISテーブルに保存する

    iris_schema = 'SQLUser'
    iris_table = 'Covid19RawTableFromCSV'to_sql_iris(curs, df, iris_table, iris_schema, drop_table=True)   # save it into a new IRIS table of specified name
    #to_sql_iris(curs, df, iris_table)  # append dataframe to an exsiting IRIS table

    Out[4]: True

    import pandas as pd
    from IPython.display import displaydf2 = pd.read_sql("SELECT COUNT(*) from %s.%s" %(iris_schema, iris_table),conn)
    display(df2)   
    <th>
      Aggregate_1
    </th>
    
    <td>
      1925
    </td>
    
     
    0

    したがって、全データが「Covid19RawTableFromCSV」というIRISテーブルに挿入されました。IRIS管理ポータルにログインすると、レコードが含まれるそのテーブルも表示されます。

    5. テスト - 簡単なベンチマークを実行する

    このデータフレームをたとえば10回挿入して、1つのJDBCセッションでこの基本的なCE dockerに掛かった時間を確認しましょう。

    from tqdm import tqdm
    import pandas as pd
    import time
    from IPython.display import displaystart = time.clock() 
    for i in tqdm(range(0, 10)):
        to_sql_iris(curs, df, iris_table)
        
    print("Total time elasped: ", time.clock()-start, " for importing total records:")
    df2 = pd.read_sql("SELECT COUNT(*) from %s.%s" %(iris_schema, iris_table),conn)
    display(df2)
    100%|██████████| 10/10 [00:14<00:00,  1.42s/it]
    Total time elasped:  12.612431999999998  for importing total records:
    <th>
      Aggregate_1
    </th>
    
    <td>
      19250
    </td>
    
     
    0

     

    以上です。非常に基本的ではありますが、少なくともデータ分析パイプラインに沿って操作されたデータフレームを保存し、多少本格的なMLを試すために、SQLインターフェースを介してIntegratedMLを呼び出すことができるようになりました。  

    言及すべき警告: データフレームの文字列は、「オブジェクト」として解釈されることがあるため、df['column'].astype(str)などを使用して、IRISテーブルに挿入される前に文字列に変換する必要があります。  「DROP TABLE」は前のテーブルを上書きするために使用されます。 「DROP VIEW」は前のビューを削除するために使用できます。 

    0
    0 349
    記事 Toshihiko Minamoto · 1月 25, 2022 9m read

    キーワード: PyODBC、unixODBC、IRIS、IntegratedML、Jupyterノートブック、Python 3

    目的

    数か月前、私は「IRISデータベースへのPython JDBC接続」という簡易メモを書きました。以来、PCの奥深くに埋められたスクラッチパッドよりも、その記事を頻繁に参照しています。 そこで今回は、もう一つの簡易メモで「IRISデータベースへのPython ODBC接続」を作成する方法を説明します。

    ODBCとPyODCBをWindowsクライアントでセットアップするのは非常に簡単なようですが、Linux/Unix系サーバーでunixODBCとPyODBCクライアントをセットアップする際には毎回、どこかで躓いてしまいます。

    バニラLinuxクライアントで、IRISをインストールせずに、リモートIRISサーバーに対してPyODBC/unixODBCの配管をうまく行うための単純で一貫したアプローチがあるのでしょうか。

    範囲

    最近、Linux Docker環境のJupyterノートブック内でゼロからPyODBCデモを機能させるようにすることに少しばかり奮闘したことがありました。 そこで、少し冗長的ではありますが、後で簡単に参照できるように、これをメモに残しておくことにしました。  

    範囲内 

    このメモでは、以下のコンポーネントに触れます。

  • PyODBC over unixODBC
  • TensorFlow 2.2とPython 3を使ったJupyter Notebookサーバー
  • サンプルテストデータを含むIntegratedMLを使ったIRIS2020.3 CEサーバー
  • この環境内で:

  • AWS Ubuntu 16.04におけるdocker-composeによるDockerエンジン 
  • Docker Desktop for MacOS、およびDocker Toolbox for Windows 10もテストされます。
  • 範囲外:

    繰り返しになりますが、このデモ環境で機能しない部分は評価されません。 それらは重要なことであり、以下のようにサイト固有の機能である可能性があります。

  • エンドツーエンドのセキュリティと監査
  • パフォーマンスとスケーラビリティ
  • ライセンスとサポート可能性など
  • 環境

    以下の構成とテスト手順では、任意のバニラLinux Dockerイメージを使用できますが、以下のようにすると、そのような環境を5分で簡単にセットアップできます。

    1.  このデモテンプレートをGit cloneします。
    2.  クローンされた、docker-compose.ymlファイルを含むディレクトリで"docker-compose up -d"を実行します。

    以下のトポロジーのように、2つのコンテナーのデモ環境が作成されます。 1つはPyODBCクライアントとしてのJupyter Notebookサーバー用で、もう1つはIRIS2020.3 CEサーバー用です。

    上記の環境では、tf2jupyterには"Python over JDBC"クライアント構成しか含まれておらず、ODBCまたはPyODBCクライアント構成はまだ含まれていません。

    そこで、わかりやすくするために、以下の手順を実行して、Jupyter Notebook内から直接それらをセットアップしましょう。  

    手順

    AWS Ubuntu 16.04サーバーで、以下の構成とテストを実行しました。 私の同僚の@Thomas.Dyarは、MacOSで実行しました。 また、Docker Toolbox for Windowsでも簡単にテストされていますが、 何らかの問題に遭遇した場合は、お知らせください。

    以下の手順は、Dockerfileに簡単に自動化できます。 ここでは、どのように行われたかを数か月後に忘れてしまった場合に備えて、手動で記録しました。

    1. 公式ドキュメント

  • IRISのODBCサポート
  • UnixにおけるODBCデータソースの定義 
  • IRISのPyODBCサポート 
  • 2. Jupyterサーバーに接続する

    私はローカルのPuttyのSSHトンネリングを使用してリモートのAWS Ubuntuポート22に接続し、上記のトポロジーのようにポート8896にマッピングしました。

    (ローカルのdocker環境では、たとえば、直接dockerマシンのIP:8896にHTTP接続することもできます。)

    3. Jupyterノートブック内からODBCインストールを実行する

    Jupyterのセル内から直接以下を実行します。 

    !apt-get update&lt;br>!apt-get install gcc&lt;br>!apt-get install -y tdsodbc unixodbc-dev&lt;br>!apt install unixodbc-bin -y&lt;br>!apt-get clean -y

    上記は、次の手順でPyODBCドライバーをリコンパイルするために必要なgcc(g++を含む)、FreeTDS、unixODBC、およびunixodbc-devをインストールします。

    この手順はネイティブWindowsサーバーまたはPCでのPyODBCインストールには必要ありません。 

    4. Jupyter内からPyODBCインストールを実行する

    !pip install pyodbc
    Collecting pyodbc
      Downloading pyodbc-4.0.30.tar.gz (266 kB)
         |████████████████████████████████| 266 kB 11.3 MB/s eta 0:00:01
    Building wheels for collected packages: pyodbc
      Building wheel for pyodbc (setup.py) ... done
      Created wheel for pyodbc: filename=pyodbc-4.0.30-cp36-cp36m-linux_x86_64.whl size=273453 sha256=b794c35f41e440441f2e79a95fead36d3aebfa74c0832a92647bb90c934688b3
      Stored in directory: /root/.cache/pip/wheels/e3/3f/16/e11367542166d4f8a252c031ac3a4163d3b901b251ec71e905
    Successfully built pyodbc
    Installing collected packages: pyodbc
    Successfully installed pyodbc-4.0.30

    上記は、このDockerデモ用に最小化されたpip installです。 公式ドキュメントには、「MacOS Xインストール」用のより詳細なpip installが提供されています。

    5. LinuxでODBC INIファイルとリンクを再構成する

    以下を実行して、odbcinst.iniodbc.iniリンクを再作成します。

    !rm /etc/odbcinst.ini
    !rm /etc/odbc.ini
    !ln -s /tf/odbcinst.ini /etc/odbcinst.ini
    !ln -s /tf/odbc.ini /etc/odbc.ini

    注意: 上記を行う理由は、手順3と4では通常2つの空の(したがって無効な)ODBCファイルが\etc\ディレクトリに作成されるためです。Windowsインストールとは異なりこれらの空のiniファイルは問題を生じるため、まずそれらを削除してから、マッピングされたDockerボリュームに提供されている実際のiniファイル(/tf/odbcinst.ini, and /tf/odbc.ini)へのリンクを再作成してください。

    これらの2つのiniファイルをチェックしましょう。この場合、Linux ODBC構成の最も単純な形式です。

    !cat /tf/odbcinst.ini
    [InterSystems ODBC35]
    UsageCount=1
    Driver=/tf/libirisodbcu35.so
    Setup=/tf/libirisodbcu35.so
    SQLLevel=1
    FileUsage=0
    DriverODBCVer=02.10
    ConnectFunctions=YYN
    APILevel=1
    DEBUG=1
    CPTimeout=&lt;not pooled>
    !cat /tf/odbc.ini
    [IRIS PyODBC Demo]
    Driver=InterSystems ODBC35
    Protocol=TCP
    Host=irisimlsvr
    Port=51773
    Namespace=USER
    UID=SUPERUSER
    Password=SYS
    Description=Sample namespace
    Query Timeout=0
    Static Cursors=0

    上記のファイルは事前構成済みであり、マッピングされたドライブで提供されています。 IRISサーバーのコンテナーインスタンスからも取得できるドライバーファイルlibirisodbcu35.soを参照しています。

    したがって、上記のODBCインストールを機能させるには、これらの3つのファイルがマッピングされたドライブ(または任意のLinuxドライブ)に存在し、適切なファイルアクセス権が適用されていることが必要です。

  • libirisodbcu35.so
  • odbcinst.ini
  • odbc.ini
  • **6. PyODBCのインストールを検証する **

    !odbcinst -j
    unixODBC 2.3.4
    DRIVERS............: /etc/odbcinst.ini
    SYSTEM DATA SOURCES: /etc/odbc.ini
    FILE DATA SOURCES..: /etc/ODBCDataSources
    USER DATA SOURCES..: /root/.odbc.ini
    SQLULEN Size.......: 8
    SQLLEN Size........: 8
    SQLSETPOSIROW Size.: 8
    import pyodbc
    print(pyodbc.drivers())
    ['InterSystems ODBC35']

    上記の出力では、現在ODBCドライバーに有効なリンクがあることが示されています。

    Jupyter NotebookでPython ODBCテストを実行できるはずです。

    7. IRISサンプルへのPython ODBC接続を実行する

    import pyodbc 
    import time
    ### 1. Get an ODBC connection 
    #input("Hit any key to start")
    dsn = 'IRIS PyODBC Demo'
    server = 'irisimlsvr'   # IRIS server container or the docker machine's IP 
    port = '51773'   # or 8091 if docker machine IP is used
    database = 'USER' 
    username = 'SUPERUSER' 
    password = 'SYS' 
    #cnxn = pyodbc.connect('DSN='+dsn+';')   # use the user DSN defined in odbc.ini, or use the connection string below
    cnxn = pyodbc.connect('DRIVER={InterSystems ODBC35};SERVER='+server+';PORT='+port+';DATABASE='+database+';UID='+username+';PWD='+ password)
    ###ensure it reads strings correctly.
    cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='utf8')
    cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf8')
    cnxn.setencoding(encoding='utf8')
    ### 2. Get a cursor; start the timer
    cursor = cnxn.cursor()
    start= time.clock()
    ### 3. specify the training data, and give a model name
    dataTable = 'DataMining.IrisDataset'
    dataTablePredict = 'Result12'
    dataColumn =  'Species'
    dataColumnPredict = "PredictedSpecies"
    modelName = "Flower12" #chose a name - must be unique in server end
    ### 4. Train and predict
    #cursor.execute("CREATE MODEL %s PREDICTING (%s)  FROM %s" % (modelName, dataColumn, dataTable))
    #cursor.execute("TRAIN MODEL %s FROM %s" % (modelName, dataTable))
    #cursor.execute("Create Table %s (%s VARCHAR(100), %s VARCHAR(100))" % (dataTablePredict, dataColumnPredict, dataColumn))
    #cursor.execute("INSERT INTO %s  SELECT TOP 20 PREDICT(%s) AS %s, %s FROM %s" % (dataTablePredict, modelName, dataColumnPredict, dataColumn, dataTable)) 
    #cnxn.commit()
    ### 5. show the predict result
    cursor.execute("SELECT * from %s ORDER BY ID" % dataTable)   #or use dataTablePredict result by IntegratedML if you run step 4 above
    row = cursor.fetchone() 
    while row: 
        print(row) 
        row = cursor.fetchone()
    ### 6. CLose and clean     
    cnxn.close()
    end= time.clock()
    print ("Total elapsed time: ")
    print (end-start)
    (1, 1.4, 0.2, 5.1, 3.5, 'Iris-setosa')
    (2, 1.4, 0.2, 4.9, 3.0, 'Iris-setosa')
    (3, 1.3, 0.2, 4.7, 3.2, 'Iris-setosa')
    (4, 1.5, 0.2, 4.6, 3.1, 'Iris-setosa')
    (5, 1.4, 0.2, 5.0, 3.6, 'Iris-setosa')
    ... ...
    ... ...
    ... ...
    (146, 5.2, 2.3, 6.7, 3.0, 'Iris-virginica')
    (147, 5.0, 1.9, 6.3, 2.5, 'Iris-virginica')
    (148, 5.2, 2.0, 6.5, 3.0, 'Iris-virginica')
    (149, 5.4, 2.3, 6.2, 3.4, 'Iris-virginica')
    (150, 5.1, 1.8, 5.9, 3.0, 'Iris-virginica')
    Total elapsed time: 
    0.023873000000000033

    ここにはいくつかの落とし穴があります。

    1. **cnxn = pyodbc.connect() ** - Linux環境では、この呼び出しに渡される接続文字列は、スペースなしで文字通り正しい必要があります。  
    2. 接続エンコーディングをたとえばuft8などで適切に設定してください。  この場合は、文字列のデフォルトエンコーディングは機能しません。
    3. libirisodbcu35.so - 理想的には、このドライバーファイルはリモートIRISサーバーのバージョンと緊密に連携する必要があります。  

    **今後の内容 **

    これで、リモートIRISサーバーへのPyODBC(およびJDBC)接続による、Python 3とTensorFlow 2.2(GPUなし)を含むJupyterノートブックのDocker環境を得られました。 IRIS IntegratedML固有のSQL構文など、特別に設計されたすべてのSQL構文で機能するはずです。そこで、IntegratedMLの機能をもう少し探り、MLライフサイクルを駆動するSQL手法を工夫してみてはどうでしょうか。 

    また、次回は、Python環境でIRISネイティブSQLまたはマジックSQLを使用してIRISサーバーに接続する上で、最も単純なアプローチに触れられればと思います。 また、今では優れたPython Gatewayを使用できるため、外部のPython MLアプリケーションとサービスをIRISサーバー内から直接呼び出してみることも可能です。これについてもさらに詳しく試せればいいなと思っています。

    付録

    上記のノートブックファイルは、こちらのGitHubリポジトリとOpen Exchangeにチェックインされます。

    0
    0 1188
    記事 Toshihiko Minamoto · 1月 6, 2022 9m read

    キーワード: Python、JDBC、SQL、IRIS、Jupyterノートブック、Pandas、Numpy、および機械学習 

    1. 目的

    これは、デモの目的で、Jupyterノートブック内でPython 3によってIRIS JDBCドライバーを呼び出し、SQL構文でIRISデータベースインスタンスにデータを読み書きする、5分程度の簡単なメモです。 

    昨年、私はCacheデータベースへのPythonバインディング(セクション4.7)について簡単に触れました。 そこで、Pythonを使ってIRISデータベースに接続し、そのデータをPandasデータフレームとNumPy配列に読み込んで通常の分析を行ってから、事前処理済みまたは正規化されたデータをML/DLパイプラインに通すためにIRISに書き込む作業においてのオプションと議論について要約しましょう。

    すぐに思い浮かぶ簡単なオプションがいくつかあります。

    1.    ODBC: Python 3とネイティブSQLを使ったPyODBCを使ってはどうでしょうか?
    2.    JDBC: Python 3とネイティブSQLを使ったJayDeBeApiはどうでしょうか?
    3.    Spark: PySparkとSQLを使ったら?
    4.    IRIS用PythonネイティブAPI: 前に使用したCache用Pythonバイディングを拡張してみたらどうでしょうか?
    5.   IPtyhon Magic SQL %%sqlとした場合、 それはまだIRISで動作するでしょうか?

     ここで見逃されたオプションがほかにありますか?  それらも試してみたいですね。 

    2. 範囲 

    通常のJDBCアプローチからはじめましょう。 ODBC、Spark、PythonネイティブAPIについては、次回の簡易メモで要約することにします。 

    範囲内:

    このクイックデモでは、以下の一般的なコンポーネントについて触れています。

  • Anaconda
  • Jupyterノートブック 
  • Python 3
  • JayDeBeApi
  • JPyPe
  • Pandas
  • NumPy
  • IRIS 2019.xのインスタンス
  •  範囲外:

    この簡易メモでは、以下の項目には触れていません。重要な項目であり、具体的なサイトソリューション、デプロイ、およびサービスで個別に対処される可能性があります。 

  • エンドツーエンドのセキュリティ
  • 機能しないパフォーマンスなど
  • トラブルシューティングとサポート
  • ライセンス 
  • 3. デモ

    3.1 IRISインスタンスを実行する

    私は単にIRIS 2019.4コンテナーを「リモート」データベースサーバーとして実行しましたが、 適切な承認済みのアクセス権を持つIRISインスタンスであれば、どれでも使用できます。

    zhongli@UKM5530ZHONGLI MINGW64 /c/Program Files/Docker Toolbox
    $ docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                PORTS                                              NAMES
    d86be69a03ab        quickml-demo        "/iris-main"        3 days ago          Up 3 days (healthy)   0.0.0.0:9091->51773/tcp, 0.0.0.0:9092->52773/tcp   quickml

    3.2 AnacondaとJupyterノートブック

     Anacondaについてはこちらのセクション4.1に説明されたセットアップアプローチ、Jupyterノートブックについてはこちらに説明されたセットアップアプローチをノートパソコンで再利用します。  Python 3.xはこのステップでインストールされます。

    3.3 JayDeBeApiとJPyPeをインストールする

    私は自分のJupyterノートブックを起動してから、そのセルで以下を実行し、Python-to-JDBC/Javaブリッジをセットアップしました。
     
      !conda install --yes -c conda-forge jaydebeapi

    この記事の執筆時点(2020年1月)では、JeDeBeApiはJPype 0.7を使用していますが、既知のバグによって機能しないため、0.6.3にダウングレードする必要がありました。

    !conda install --yes -c conda-forge JPype1=0.6.3 --force-reinstall

    3.4 JDBC経由でIRISデータベースに接続する 

    公式のJDBCからIRISへの接続に関するドキュメントはこちらにあります。 

    JDBCでPyshon SQLを実行するには、以下のコードを例として使用しました。 このIRISインスタンスの「USER」ネームスペース内にある「DataMining.IrisDataset」というデータテーブルに接続します。 

    ### 1. Set environment variables, if necessary
    #import os
    #os.environ['JAVA_HOME']='C:\Progra~1\Java\jdk1.8.0_241'
    #os.environ['CLASSPATH'] = 'C:\interSystems\IRIS20194\dev\java\lib\JDK18\intersystems-jdbc-3.0.0.jar'
    #os.environ['HADOOP_HOME']='C:\hadoop\bin'  #winutil binary must be in Hadoop's Home
    ### 2. Get jdbc connection and cursor
    import jaydebeapi
    url = "jdbc:IRIS://192.168.99.101:9091/USER"
    driver = 'com.intersystems.jdbc.IRISDriver'
    user = "SUPERUSER"
    password = "SYS"

    #libx = "C:/InterSystems/IRIS20194/dev/java/lib/JDK18"
    jarfile = "C:/InterSystems/IRIS20194/dev/java/lib/JDK18/intersystems-jdbc-3.0.0.jar"
    conn = jaydebeapi.connect(driver, url, [user, password], jarfile)
    curs = conn.cursor()
    ### 3. specify the source data table
    dataTable = 'DataMining.IrisDataset'

     
    ### 4. Get the result and display
    curs.execute("select TOP 20 * from %s" % dataTable)
    result = curs.fetchall()
    print("Total records: " + str(len(result)))
    for i in range(len(result)):
        print(result[i])
    ### 5. CLose and clean - I keep them open for next accesses.
    #curs.close()
    #conn.close()
    Total records: 150
    (1, 1.4, 0.2, 5.1, 3.5, 'Iris-setosa')
    (2, 1.4, 0.2, 4.9, 3.0, 'Iris-setosa')
    (3, 1.3, 0.2, 4.7, 3.2, 'Iris-setosa')
    ... ...
    (49, 1.5, 0.2, 5.3, 3.7, 'Iris-setosa')
    (50, 1.4, 0.2, 5.0, 3.3, 'Iris-setosa')
    (51, 4.7, 1.4, 7.0, 3.2, 'Iris-versicolor')
    ... ... 
    (145, 5.7, 2.5, 6.7, 3.3, 'Iris-virginica')
    ... ... 
    (148, 5.2, 2.0, 6.5, 3.0, 'Iris-virginica')
    (149, 5.4, 2.3, 6.2, 3.4, 'Iris-virginica')
    (150, 5.1, 1.8, 5.9, 3.0, 'Iris-virginica')

     

    ここで、JDBCでPythonが機能していることをテストしました。 以下はちょっとした日常業務的なデータ分析と通常のMLパイプラインのプリプロセッシングであり、後のデモと比較で何度も触れる内容です。ここでは、利便的に添付しています。 

    3.5 SQL結果をPandasデータフレーム、そしてNumPy配列に変換する

    PandasとNumPyパッケージがインストールされていない場合は、上記のセクション3.3と同様に、Condaを使ってインストールします。

    次に、以下のコードを例として実行しました。

    ### transform SQL results "sqlData"to Pandas dataframe "df", then further to NumPy array "arrayN" for further ML pipelines 
    import pandas as pd
    sqlData = "SELECT * from DataMining.IrisDataset"
    df= pd.io.sql.read_sql(sqlData, conn)
    df = df.drop('ID', 1)
    df = df[['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth', 'Species']]
    # set the labels to 0, 1, 2, for NumPy matrix
    df.replace('Iris-setosa', 0, inplace=True)
    df.replace('Iris-versicolor', 1, inplace=True)
    df.replace('Iris-virginica', 2, inplace=True)
    # turn dataframe into Numpy array
    arrayN = df.to_numpy()
    ### 6. CLose and clean - if connection is not needed anymore?
    #curs.close()
    #conn.close()

    いつものように現在のデータを覗いてみましょう。

    df.head(5)

    df.describe()

    データフレームと、ソースデータテーブルから正規化されたNumPy配列を取得して、使用できるようになりました。  

    もちろん、こちらのリンクのように、MLユーザーが以下のようにPython で行うような様々なルーチン分析を試して、Rを置き換えることができます。

    データソースはこちらから引用されています。

    3.6 SQLでデータを分割してIRISデータベースに書き込む

    確かに、以降でIRISの刺激的なML機能で使用できるように、データを通常どおりトレーニングセットと検証またはテストセットに分割し、一時データベーステーブルに書き込むことができます。

    import numpy as np 
    from matplotlib import pyplot
    from sklearn.model_selection import train_test_split
    # keep e.g. 20% = 30 rows as test data; trained on another e.g. 80% = 120 rows
    X = arrayN[:,0:4]
    y = arrayN[:,4]
    X_train, X_validation, Y_train, Y_validation = train_test_split(X, y, test_size=0.20, random_state=1, shuffle=True)
    # make 80% of random rows into a Train set
    labels1 = np.reshape(Y_train,(120,1))
    train = np.concatenate([X_train, labels1],axis=-1)
    # make 20% of left rows into Test set
    lTest1 = np.reshape(Y_validation,(30,1))
    test = np.concatenate([X_validation, lTest1],axis=-1)
    # write the train data set into a Pandas frame
    dfTrain = pd.DataFrame({'SepalLength':train[:, 0], 'SepalWidth':train[:, 1], 'PetalLength':train[:, 2], 'PetalWidth':train[:, 3], 'Species':train[:, 4]})
    dfTrain['Species'].replace(0, 'Iris-setosa', inplace=True)
    dfTrain['Species'].replace(1, 'Iris-versicolor', inplace=True)
    dfTrain['Species'].replace(2, 'Iris-virginica', inplace=True)
    # write the test data into another Pandas frame
    dfTest = pd.DataFrame({'SepalLength':test[:, 0], 'SepalWidth':test[:, 1], 'PetalLength':test[:, 2], 'PetalWidth':test[:, 3], 'Species':test[:, 4]})
    dfTest['Species'].replace(0, 'Iris-setosa', inplace=True)
    dfTest['Species'].replace(1, 'Iris-versicolor', inplace=True)
    dfTest['Species'].replace(2, 'Iris-virginica', inplace=True)
    ### 3. specify temp table names
    #dataTable = 'DataMining.IrisDataset'
    dtTrain = 'TRAIN02'
    dtTest = "TEST02"
    ### 4. Create 2 temporary tables - you can try drop tables then re-create them every time
    curs.execute("Create Table %s (%s DOUBLE, %s DOUBLE, %s DOUBLE, %s DOUBLE, %s VARCHAR(100))" % (dtTrain, dfTrain.columns[0], dfTrain.columns[1], dfTrain.columns[2], dfTrain.columns[3], dfTrain.columns[4]))
    curs.execute("Create Table %s (%s DOUBLE, %s DOUBLE, %s DOUBLE, %s DOUBLE, %s VARCHAR(100))" % (dtTest, dfTest.columns[0], dfTest.columns[1], dfTest.columns[2], dfTest.columns[3], dfTest.columns[4]))
    ### 5. write Train set and Test set into the tales. You can try to delete old record then insert everytime. 
    curs.fast_executemany = True
    curs.executemany( "INSERT INTO %s (SepalLength, SepalWidth, PetalLength, PetalWidth, Species) VALUES (?, ?, ?, ? ,?)" % dtTrain,
         list(dfTrain.itertuples(index=False, name=None)) )
    curs.executemany( "INSERT INTO %s (SepalLength, SepalWidth, PetalLength, PetalWidth, Species) VALUES (?, ?, ?, ? ,?)" % dtTest,
         list(dfTest.itertuples(index=False, name=None)) )
    ### 6. CLose and clean - if connection is not needed anymore?
    #curs.close()
    #conn.close()

    ここで、IRIS管理コンソールまたはターミナルSQLコンソールに切り替えると、120行のTRAIN02と30行のTEST02という2つの一次テーブルが作成されているのがわかります。

    この記事は非常に短い簡易メモを目的としているため、本内容はここまでとします。

    4. 警告

    • 上記のコンテンツは変更または改善される場合があります。 

    5. 今後の内容

    簡易メモを貢献していただける方がいらっしゃらなければ、セクション3.3と3.4をPyODBC、PySPark、およびIRIS用PythonネイティブAPIに置き換えることにします。貢献していただけるのであれば、大感謝です。

    0
    0 1014
    記事 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
    記事 Toshihiko Minamoto · 11月 30, 2021 16m read

    キーワード: COVID-19、医用画像、ディープラーニング、PACSビューア、HealthShare。

    目的

    私たちは皆、この前例のないCovid-19パンデミックに悩まされています。 現場のお客様をあらゆる手段でサポートする一方で、今日のAI技術を活用して、Covid-19に立ち向かうさまざまな前線も見てきました。 

    昨年、私はディープラーニングのデモ環境について少し触れたことがあります。 この長いイースターの週末中に、実際の画像を扱ってみてはどうでしょうか。Covid-19に感染した胸部X線画像データセットに対して簡単な分類を行うディープラーニングモデルをテスト実行し、迅速な「AIトリアージ」や「放射線科医の支援」の目的で、X線画像やCT用のツールがdockerなどを介してクラウドにどれほど素早くデプロイされるのかを確認してみましょう。     

    これは、10分程度の簡易メモです。学習過程において、最も単純なアプローチでハンズオン経験を得られることを願っています。   

    範囲

    このデモ環境では、次のコンポーネントが使用されます。 これまで見てきた中で最も単純な形式です。

    • 3タイプの小さな匿名加工オープンデータセット: Covid-19感染胸部、細菌性肺炎胸部、正常な胸部。
    • 1セットのディープラーニングモデル(X線胸部画像分類用のInception V3モデル)
    • JupyterノートブックによるTensorFlow 1.13.2コンテナ
    • GPU用のNvidia-Docker2コンテナ
    • Nvidia T4 GPU搭載AWS Ubuntu 16.04 VM(事前トレーニング済みモデルの再トレーニングを行わない場合はノートパソコンのGPUで十分です)

    および

    • 「AI支援CT検出」のデモコンテナ
    • サードパーティのOpen PACS Viewerのデモコンテナ
    • HealthShare Clinical Viewerのデモインスタンス

    以下は、このデモの範囲では説明されていません。

    • PyTorchの人気が高まっています(次の機会に利用します)
    • デモ環境では、TensorFlow 2.0の実行速度がはるかに低下します(そのためバージョン1.13に戻します) 
    • AutoMLなどのマルチモデルアンサンブル(実際に人気が高まっていますが、この小さなデータセットでは昔ながらのシングルモデルで十分です)
    • 実際のサイトから得るX線およびCTデータ。 

    免責事項

    このデモは、この特定の分野における臨床試験についてではなく、技術的なアプローチに関するものです。 CTおよびX線などの証拠に基づくCovid-19診断は現在ではオンラインで広く入手可能であり、肯定的なレビューもあれば、否定的なレビューもあります。また、このパンデミックにおいて、国や文化における役割が実際に異なります。 また、この記事のコンテンツとレイアウトは、必要に応じて変更される場合があります。   このコンテンツは「開発者」としての純粋な個人的見解です。

    データ

    このテストの元の画像は、Joseph Paul Cohenによって一般公開されているCovid-19 Lung X-Ray setに含まれるものと、オープン形式のKaggle Chest X-Ray setsからAdrian YuがGradientCrescentリポジトリの小さなテストセットに集めたの正常な胸部画像です。 また、皆さんが使用できるように、簡単なテスト用のテストデータをこちらにアップロードしました。 これまでのところ、以下の小さなトレーニングセットが含まれます。 

    • Covid-19に感染した胸部画像 60点 
    • 正常な胸部画像 70点
    • 細菌性肺炎に感染した胸部画像 70点

    テスト

    以下のテストでは、独自のフレーバーに合わせてわずかに変更したものを実行しました。

    • ベースのInception V3モデルとその上の2つのCNNレイヤー
    • 再トレーニング用に基盤のInceptionレイヤーの非凍結重みを使った転移学習(ノートパソコンのGPUでは、事前トレーニング済みのInceptionレイヤーを凍結するだけです)
    • これまでに収集した小さなデータセットを補うためのわずかなデータ拡張
    • バイナリの代わりに3つのカテゴリを使用: Covid-19、正常、細菌性(またはウイルス性)肺炎(これらの3つのクラスを使用した理由は後で説明します)
    • 後のステップで使えるテンプレートとして、基本的な3クラス混同行列を計算  

    注意: ほかの一般的なCNNベースのモデル(VGG16やResNet50など)ではなく、Inception V3を選択した理由は特にありません。 他にもモデルがありますが、最近、骨折データセットのデモ実行に使用したため、ここではそれを再利用しているだけです。  以下のJupyterノートブックスクリプトを実行し直す際には、お好きなモデルを使用してください。

    この記事には、Jupyterノートブックも添付しました。 以下に簡単な説明も示しています。

    1. 必要なライブラリをインポートする

    # import the necessary packages
    from tensorflow.keras.layers import AveragePooling2D, Dropout, Flatten, Dense, Input
    from tensorflow.keras.models import Model
    from tensorflow.keras.optimizers import Adam
    from tensorflow.keras.utils import to_categorical
    from tensorflow.keras import optimizers, models, layers
    from tensorflow.keras.applications.inception_v3 import InceptionV3
    from tensorflow.keras.applications.resnet50 import ResNet50
    
    from tensorflow.keras.preprocessing.image import ImageDataGenerator
    from sklearn.preprocessing import LabelEncoder, OneHotEncoder
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import classification_report, confusion_matrix
    from imutils import paths
    import matplotlib.pyplot as plt
    import numpy as np
    import cv2
    import os

    2. ここに提供されているサンプルの画像ファイルを読み込む

    # set learning rate, epochs and batch size
    INIT_LR = 1e-5    # この値は選択したモデルに固有の値です: Inception、VGG、ResNetなど。
    EPOCHS = 50 
    BS = 8
    
    print("Loading images...")
    imagePath = "./Covid_M/all/train"  # 同じ画像のローカルパスに変更してください
    imagePaths = list(paths.list_images(imagePath))
    
    data = []
    labels = []
    
    # 指定されたパスにあるすべてのX線画像を読み取り、サイズを256x256に変更します
    for imagePath in imagePaths:
        label = imagePath.split(os.path.sep)[-2]
        image = cv2.imread(imagePath)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        image = cv2.resize(image, (256, 256))
        data.append(image)
        labels.append(label)
        
    #ピクセル値を0.0~1.0の実数に正規化します
    data = np.array(data) / 255.0
    labels = np.array(labels)
    
    # マルチクラスのラベル付けを行うためにワンホットエンコーディングを実行します
    label_encoder = LabelEncoder()
    integer_encoded = label_encoder.fit_transform(labels)
    labels = to_categorical(integer_encoded)
    
    print("... ... ", len(data), "images loaded in multiple classes:")
    print(label_encoder.classes_)
    Loading images...
    ... ...  200 images loaded in 3x classes:
    ['covid' 'normal' 'pneumonia_bac']

    3. 基本的なデータ拡張を追加し、モデルを再構成してトレーニングする 

    # データとトレーニング用と検証用に分割します。
    (trainX, testX, trainY, testY) = train_test_split(data, labels, test_size=0.20, stratify=labels, random_state=42)
    
    # 単純な拡張を追加します。 注意: このケースでは、拡張が多すぎるとうまく行きません。テストの過程でわかりました。 
    trainAug = ImageDataGenerator(rotation_range=15, fill_mode="nearest")
    
    #事前トレーニング済み「ImageNet」の重みの転移学習でInceptionV3モデルを使用します。
    #注意: VGG16またはResNetを選択した場合は、最上部で初期の学習率をリセットする必要がある場合があります。
    baseModel = InceptionV3(weights="imagenet", include_top=False, input_tensor=Input(shape=(256, 256, 3)))
    #baseModel = VGG16(weights="imagenet", include_top=False, input_tensor=Input(shape=(256, 256, 3)))
    #baseModel = ResNet50(weights="imagenet", include_top=False, input_tensor=Input(shape=(256, 256, 3)))
    #Inception V3モデルの上にカスタムCNNレイヤーを2つ追加します。 
    headModel = baseModel.output
    headModel = AveragePooling2D(pool_size=(4, 4))(headModel)
    headModel = Flatten(name="flatten")(headModel)
    headModel = Dense(64, activation="relu")(headModel)
    headModel = Dropout(0.5)(headModel)
    headModel = Dense(3, activation="softmax")(headModel)
    
    # 最終モデルを構成します
    model = Model(inputs=baseModel.input, outputs=headModel)
    
    # Navidia T4 GPUを使用しているので、再トレーニングを行うために、事前トレーニング済みのInception「ImageNet」重みの凍結を解除します
    #baseModel.layersのレイヤーの場合:
    #    layer.trainable = False
    
    print("Compiling model...")
    opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS)
    model.compile(loss="categorical_crossentropy", optimizer=opt, metrics=["accuracy"])
    
    # 上記で事前トレーニング済みの重みの凍結を解除したため、全モデルをトレーニングします。
    print("Training the full stack model...")
    H = model.fit_generator( trainAug.flow(trainX, trainY, batch_size=BS), steps_per_epoch=len(trainX) // BS,
                             validation_data=(testX, testY), validation_steps=len(testX) // BS, epochs=EPOCHS)
    ... ... 
    Compiling model...
    Training the full stack model...
    ... ...
    Use tf.cast instead.
    Epoch 1/50
    40/40 [==============================] - 1s 33ms/sample - loss: 1.1898 - acc: 0.3000
    20/20 [==============================] - 16s 800ms/step - loss: 1.1971 - acc: 0.3812 - val_loss: 1.1898 - val_acc: 0.3000
    Epoch 2/50
    40/40 [==============================] - 0s 6ms/sample - loss: 1.1483 - acc: 0.3750
    20/20 [==============================] - 3s 143ms/step - loss: 1.0693 - acc: 0.4688 - val_loss: 1.1483 - val_acc: 0.3750
    Epoch 3/50
    ... ...
    ... ...
    Epoch 49/50
    40/40 [==============================] - 0s 5ms/sample - loss: 0.1020 - acc: 0.9500
    20/20 [==============================] - 3s 148ms/step - loss: 0.0680 - acc: 0.9875 - val_loss: 0.1020 - val_acc: 0.9500
    Epoch 50/50
    40/40 [==============================] - 0s 6ms/sample - loss: 0.0892 - acc: 0.9750
    20/20 [==============================] - 3s 148ms/step - loss: 0.0751 - acc: 0.9812 - val_loss: 0.0892 - val_acc: 0.9750

     

    4. 検証結果用に混同行列をプロットする

    print("Evaluating the trained model ...")
    predIdxs = model.predict(testX, batch_size=BS)
    
    predIdxs = np.argmax(predIdxs, axis=1)
    
    print(classification_report(testY.argmax(axis=1), predIdxs, target_names=label_encoder.classes_))
    
    # 基本的な混同行列を計算します
    cm = confusion_matrix(testY.argmax(axis=1), predIdxs)
    total = sum(sum(cm))
    acc = (cm[0, 0] + cm[1, 1] + cm[2, 2]) / total
    sensitivity = cm[0, 0] / (cm[0, 0] + cm[0, 1] + cm[0, 2])
    specificity = (cm[1, 1] + cm[1, 2] + cm[2, 1] + cm[2, 2]) / (cm[1, 0] + cm[1, 1] + cm[1, 2] + cm[2, 0] + cm[2, 1] + cm[2, 2])
    
    # 混同行列、精度、感度、特異度を示します
    print(cm)
    print("acc: {:.4f}".format(acc))
    print("sensitivity: {:.4f}".format(sensitivity))
    print("specificity: {:.4f}".format(specificity))
    
    # トレーニング損失と精度をプロットします
    N = EPOCHS 
    plt.style.use("ggplot")
    plt.figure()
    plt.plot(np.arange(0, N), H.history["loss"], label="train_loss")
    plt.plot(np.arange(0, N), H.history["val_loss"], label="val_loss")
    plt.plot(np.arange(0, N), H.history["acc"], label="train_acc")
    plt.plot(np.arange(0, N), H.history["val_acc"], label="val_acc")
    plt.title("Training Loss and Accuracy on COVID-19 Dataset")
    plt.xlabel("Epoch #")
    plt.ylabel("Loss/Accuracy")
    plt.legend(loc="lower left")
    plt.savefig("./Covid19/s-class-plot.png")

    上の図から、小さなデータセットと5分未満の簡易トレーニングでも「転移学習」のメリットにより、結果はそれほど悪くないことがわかります。12点すべてのCovid-19に感染した胸部画像は正しく分類されており、誤って「細菌性肺炎」の胸部画像として分類された正常な胸部画像は、合計40点のうち1点のみです。 

     

    5. 実際のX線画像をテストするための混同行列をプロットする

    では、さらにもう一歩飛躍してみましょう。簡単にトレーニングされたこの分類器がどれほど効果的であるかをテストするために、実際のX線画像を送信してみます。 

    上記のトレーニングや検証セットで使用していない27点のX線画像をモデルにアップロードしました。

    Covid-19に感染した胸部画像 9点と正常な胸部画像 9点と細菌性肺炎に感染した胸部画像 9点です。  (これらの画像は、この記事にも添付されています。)

    ステップ2のコードを1行だけ変更し、テスト画像が確実に異なるパスから読み込まれるようにしました。

    ...
    imagePathTest = "./Covid_M/all/test"
    ...

    次に上記のトレーニング済みのモデルを使用して予測します。 

    predTest = model.predict(dataTest, batch_size=BS)
    print(predTest)
    predClasses = predTest.argmax(axis=-1)
    print(predClasses)
    ...

    最後に、ステップ5のようにして、混同行列を再計算します。

    testX = dataTest
    testY = labelsTest
    ... ...

    実際のテスト結果が得られました。

     またしても、トレーニング済みモデルは、すべてのCovid-19に感染した胸部画像を正しく分類できるようです。 こんなに小さなデータセットにしては、それほど悪くない出来です。 

    6. さらなる監察結果

    このイースターの週末に、さまざまなデータセットを試し、Covid-19に感染した胸部画像には明確な特徴があるように見えました。AI分類器の観点では、通常の細菌性またはウイルス性(インフルエンザ)感染症の影響を受けた胸部画像と区別することは比較的簡単です。

    また、いくつかの簡単なテストから、細菌性とウイルス性(一般的なインフルエンザ)の胸部画像を区別するのは非常に困難であることに気づきました。  時間があれば、ほかのKaggle挑戦者がおそらくあの状況で行うように、クラスタアンサンブルを使用して、その違いを追跡しなければならないでしょう。  

    では、臨床の観点では、上記の結果は本当に正しいのでしょうか? Covid-19に感染した胸部にはX線で本当に明確な特徴が見られるのでしょうか? あまり確信が持てません。 実際の胸部放射線科医に意見を聞かなくてはいけないでしょう。 今のところは、現在のデータセットは結論を出すには小さすぎると思います。  

    : 実際のサイトのX線画像をもっと集めて、xgsboot、AutoML、または新しいIRIS IntegratedMLワークベンチを使って、深く調べたいと思います。  さらに、医師やA&Eトリアージ向けに、Covid-19に感染した胸部画像を、その深刻度に応じてレベル1、レベル2、およびレベル3のようにさらに分類できるはずです。

    とにかく話を戻すと、データセットと上記のJupyterノートブックを添付しました

    デプロイメント

    上記では、この「医用画像」分野における簡単なセットアップについて、わりと単純な出発点に触れました。 このCovid-19フロントは、実際には、過去1年の週末や長期休暇中に調べたもののうち、3つ目の試行となります。 他には、「AI支援骨折検出」システムや「AI支援眼科網膜診断」システムなどを調べました。 

    上記のモデルは、今のところは単純すぎて試すほどでもないかもしれませんが、一般的な疑問はすぐにでも避けて通れないでしょう。ある種の「AIサービス」はどのようにデプロイすればよいのでしょうか? 

    テクノロジースタックとサービスのライフサイクルに関わることですが、どのような問題を解決しようとしているのか、どういった実際の価値が得られるのかといった実際の「ユースケース」によっても異なります。  答えはテクノロジーほど明確ではないこともあります。

    イギリスのRCR(王立放射線学者会)の原案では、「放射線技師のAI支援」と「A&EまたはプライマリケアにおけるAIトリアージ」という2つの単純なユースケースが提案されました。 正直なところ現時点では2つ目の「AIトリアージ」に同意しており、個人的には、この方がより高い価値をもたらすのではないかと思っています。  また、幸いにも、今日の開発者はクラウド、Docker、AI、そしてもちろんInterSystemsのHealthShareにより、これまで以上の力を使ってこの種のケースを解決することができます。 

    たとえば、以下のスクリーンキャプチャは実際にAWSにホストされたエンタープライズ級の「AI支援によるCovid-19感染胸部のCT検出」サービスを示しており、デモの目的で、いかにしてこのサービスを直接HealthShare Clinical Viewerに組み込むかを説明しています。 X線撮影と同様に、DICOMに設定されたCTも迅速な「AIトリアージ」のユースケース用に毎日24時間稼働しながら、このオープンPACS Viewerに直接アップロードまたは送信し、「AI診断」をクリックするだけで、トレーニング済みモデルに基づいて定量化されたCovid-19感染確率の判定を提供することができます。 X線画像分類などのモデルは、最前線に立つ医師を支援できるよう、同一患者のコンテキストで既存のPACSビューアの上にデプロイし、同じ方法で呼び出すことができます。  

    謝辞  

    繰り返しますが、このテスト画像は、Joseph Paul Cohenによる Covid-19 Lung X-Ray setから得たもので、正常な胸部画像はAndrian YuがGradientCrescentリポジトリに収集しているオープンのKaggle Chest X-Ray setsに含まれるものです。 また、「テスト」セクションにリストされたとおり、独自に改善したトレーニングを使ってPyImageSearchのAdrianの構造を再利用しています。 また、テストデータベースを確認するために、X線画像とCT画像用のAIモジュール付きAWSクラウドベースOpen PACS Viewerを提供していただいたHYMにも感謝しています。

    次の内容

    今日、AIは、人間の健康と日常生活のほぼすべての側面を「浸食」しています。 単純化し過ぎた私の見解では、ヘルスケア分野におけるAI技術の応用には、以下のようないくつかの方向性があると考えられます。

    • 医用画像: 胸部、心臓、目、脳などのX線、CT、またはMRIなどの診断画像。
    • NLPによる読解: 膨大な量のテキスト資産とナレッジベースのマイニング、理解、学習。
    • 公衆衛生: 疫学などの傾向予測、分析、モデリングなど。 
    • パーソナル化AI: 個人専用の健康アシスタントとして、ともに成長して老化するように特別にトレーニングされたAI/ML/DLモデル。
    • その他のAI: AlphaGoや、Covid-19への対抗に活用できる3次元タンパク質構造予測向けのAlphaFoldなど。このような最先端の画期的な技術に非常に感激しています。 

    学習の過程で、焦点を当てられるものを検討していきたいと思います。 いずれにしても、在宅が長く続かない限りは、取り上げたいリストにしかすぎないかもしれません。 

    付録 - ファイルアップロードはこちらです。 上記で使用した画像と上記のJupyterノートブックファイルが含まれています。 週末に新規でセットアップして実行するには、数時間かかるかもしれません。

    0
    0 548
    記事 Toshihiko Minamoto · 11月 25, 2021 17m read

    キーワード:   Jupyterノートブック、TensorFlow GPU、Keras、ディープラーニング、MLP、HealthShare    

    1. 目的

    前回の「パート1」では、ディープラーニングデモ環境をセットアップしました。今回「パート2」では、それを使ってできることをテストします。

    私と同年代の人の中には、古典的なMLP(多層パーセプトロン)モデルから始めた人がたくさんいます。 直感的であるため、概念的に取り組みやすいからです。

    それでは、AI/NNコミュニティの誰もが使用してきた標準的なデモデータを使って、Kerasの「ディープラーニングMLP」を試してみましょう。 いわゆる「教師あり学習」の一種です。 これを実行するのがどんなに簡単かをKerasレベルで見ることにします。

    後で、その歴史と、なぜ「ディープラーニング」と呼ばれているのかについて触れることができます。流行語ともいえるこの分野は、実際に最近20年間で進化してきたものです。 

    HealthShareにも関連しているため、最終的には、少々実現的なユースケースを想像または予測できるようになることを願っています。

    2. 範囲と免責事項

    次のことを行います。 

    • tensorflow-gpu環境用に新しいJupyterカーネルをセットアップします。
    • ANNコミュニティで一般的な標準のMNISTサンプルを使って、Keras MLPモデルを定義、トレーニング、および検証(テスト)します。
    • 重要なパラメーターのほんの一部の非常に単純なものを簡単に説明します。
    • デモデータを簡単に調べます。データを理解することは、あらゆる実験において常に重要なことです。 
    • データサンプルをCache/HealthShareに保存し、予測(分類)と推論を行うために読み取り直す作業がどれほど簡単であるかを実演します。

    その後で、テストサンプルを少し回転させ、トレーニング済みのモデルをどれくらい混乱させられるかを確認し、それによって明確な制限を理解します。

    学術的・数学的な部分は省略しますが、仕組みについて簡単に説明するところもあります。

    免責事項: MNISTデータサンプルは、このデモの目的で公開されています。 ほとんどのデモコードは最小限に縮減されており、エラー処理の含まれないベアなコードでした。 Kerasコードのソースは「謝辞」に記載されています。  この内容は、必要に応じていつでも変更されます。

    3. 前提条件

    前の「パート1」の記事に記載されているとおりにデモ環境をセットアップする以外で、以下の実験のための前提条件はありません。 

    4. Jupyterノートブックのセットアップ

    前回インストールした「tensorflow-gpu」環境で次のコマンドを実行しました。 

    (tensorflow-gpu) C:\>conda install ipykernel
    Solving environment: done

    ... ...

    (tensorflow-gpu) C:\>python -m ipykernel install --user --name tensorflow-gpu --display-name "Tensorflow-GPU"
    Installed kernelspec tensorflow-gpu in C:\Users\zhongli\AppData\Roaming\jupyter\kernels\tensorflow-gpu

    こうすることで、「Tensorflow-GPU」などと呼ばれる新しいJupyterカーネルを作成しました。

    これで、Anaconda Promptから次のようにしてJupyterノートブックを起動できるようになりました。

    (tensorflow-gpu) C:\anaconda3\keras\Zhong>jupyter notebook
    [... ... 
    [I 10:58:12.728 NotebookApp] The Jupyter Notebook is running at:
    [I 10:58:12.729 NotebookApp] http://localhost:8889/?token=6b40f6e6749e88b80a338eec3330d06c181ead9b644cffe1
    [I 10:58:12.734 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
    [C 10:58:12.835 NotebookApp] ... ... 

    ブラウザのUIが以下のように起動していることを確認できます。 [New]をクリックすると、新しい「Tensorflow_GPU」タブが開きます。

    5. ディープラーニングMLPモデルのトレーニング

    標準のディープラーニングMLPモデルデモを試してみましょう。

     5.1 環境のテスト

    Jupyterタブを「MLP_Demo_ HS」のような名前に変更し、そのセル [1] で以下の行を実行して「Run」をクリックします。

    print('Hello World!')

    Hello World!

     

    5.2 PythonからHealthShareへの接続のテスト 

    セル[2]でPythonサンプルを実行し、まだ「パート1」の記事に記載されたとおりにHealthShareデータベースインスタンスに接続できるかをテストします。

    import codecs, sys
    import intersys.pythonbind3

    try:
        print ("Simple Python binding sample")

        port = input("Cache server port (default 56778)? ")
        port = port.rstrip()
        if (port == ""):
            port = "56778"

        url = "localhost["+port+"]:SAMPLES"
        print ("Connection string: " + url)

        print ("Connecting to Cache server")
        conn = intersys.pythonbind3.connection( )
        conn.connect_now(url, "_SYSTEM", "SYS", None)
        print ("Connected successfully")

        print ("Creating database")
        database = intersys.pythonbind3.database( conn)

        print ("Opening Sample.Person instance with ID 1 with default concurrency and timeout")
        person = database.openid( "Sample.Person", "1", -1, -1)

        print ("Getting the value of the Name property")
        name = person.get("Name")
        print ("Value: " + name)

        print ("Test completed successfully")
    except intersys.pythonbind3.cache_exception( err):
        print ("InterSystems Cache' exception")
        print (sys.exc_type)
        print (sys.exc_value)
        print (sys.exc_traceback)
        print (str(err))

    Simple Python binding sample
    Cache server port (default 56778)?
    Connection string: localhost[56778]:SAMPLES
    Connecting to Cache server
    Connected successfully
    Creating database
    Opening Sample.Person instance with ID 1 with default concurrency and timeout
    Getting the value of the Name property
    Value: Zevon,Mary M.
    Test completed successfully

     

    5.3 説明 - MLPモデルのトポロジーとMNISTデータセット

    MLPネットワークのトポロジーは、以下に示すとおり単純です。 通常、1つの入力と1つの出力のレイヤーがあり、多数の非表示レイヤーがあります。 

    各レイヤーには多数のニューロン(ノード)があります。 各ニューロンには活性化関数があります。 以下のように、2つの異なるレイヤーのニューロン間に完全にメッシュ化された接続(「密度」モデル)が存在することになります。 

    関連画像

    これに対応し、以下でテストしているKeras MLPモデルには次のものが含まれます。

    • 28 x 28ノードの計784ノードの入力レイヤー(ようするに28x28ピクセルの小さな画像であり、それぞれは「0」から「9」の手書きの数字です。MNISTデータセットにはこのような画像がトレーニング用に60,000個、テスト用に10,000個含まれています
    • 10ノードの出力レイヤー(0から9の間の入力画像の分類結果を表します)
    • 2つの非表示レイヤー(各レイヤーには512個のノードがあります)

    これが、このデモモデルの主要トポロジーです。 他の詳細については今のところは省略して、実際に実行することにしましょう。 

    関連画像  

    5.4. GoogleパブリッククラウドからMNISTサンプルデータを読み込む    

    では、上記のモデルをまったく最初から作成し始めることにしましょう。KerasパッケージとMNISTデータをJupyter Cellにロードして、  メニューの[Run]ボタンをクリックします。

    ### Import Keras modules 
    import keras
    from keras.datasets import mnist
    from keras.models import Sequential
    from keras.layers import Dense, Dropout
    from keras.optimizers import RMSprop

    ### Define key training parameter
    batch_size = 128  # weights adjusted in 128 steps
    num_classes = 10  # 10 classification results on the output layer
    epochs = 20       # run the set of samples 20 times.

    ###load the data from Google public cloud 
    # load the MNIST sample image  data, split between train and test sets
    (x_train, y_train), (x_test, y_test) = mnist.load_data()

    注意: 問題がある場合は、例外の内容に従うか(ほとんどの場合が、パッケージが見つからないといった例外です)、Googleで答えを探すか(99%の確率で回答を得られます)、以下に質問を投稿してください。

    コードの最後の行で、60,000個と10,000個の全データセットが3次元整数のPython配列にロードされました。  トレーニングサンプルの1つをHealthShareデータベースに読み込んでみてみましょう。

    5.5 データサンプルをHealthShareのグローバルに読み込む

    HealthShare -> SAMPLESネームスペース - > Sample.Person.clsで、この最も単純なクラスメソッドをスクラッチします。

    ClassMethod SetTrainGlobals(d1 As %Integer = , d2 As %Integer = , value As %String = "", target As %String = "") As %BigInt [ SqlProc ]
    {
    Set ^XTrainInput(d1, d2) = value
    Set ^YTrainTarget(d1) = target
    return $$$OK
    }

    1つの入力トレーニングサンプルを文字列としてグローバル^XTrainInputに取り込み、入力トレーニングターゲットを^YTrainTargetに保存します。

    リコンパイルし、セクション5.2に従って接続を更新してから、以下のようにPythonのセルから呼び出しを実行します。

    result1 = person.run_obj_method("SetTrainGlobals", [0, 2, str(x_train[0]), str(y_train[0])])

    HealthShare -> Samplesで、^XTrainGlobal(0, 2) というグローバルが2次元整数の文字列で作成されたことがわかります。

    後で、別の単純なメソッドを実行し、データをサンプルとしてPython変数に読み戻すことができます。  

    5.6 モデルを実行してトレーニング実行する

    JupyterでのMLPモデルの定義とトレーニングを完了しましょう。

    基本的に以下のコードの「reshape」は、それぞれの28 x 28のサンプルを0から255の値の1x 784個の値に変換し、その後で0から1.0の浮動小数点型に正規化します。

    Model.SequentialからModel.Summaryまでのコードは、784 x 512 x 512 x 10ノードのMLPを、「relu」活性化関数を使って定義するするものです。 

    最後に、 model.fitでトレーニングし、model.evaluteでテスト結果を評価します。   

    x_train = x_train.reshape(60000, 784)
    x_test = x_test.reshape(10000, 784)
    x_train = x_train.astype('float32')
    x_test = x_test.astype('float32')
    x_train /= 255
    x_test /= 255

    print(x_train.shape[0], 'train samples')
    print(x_test.shape[0], 'test samples')

    # convert class vectors to binary class matrices
    y_train = keras.utils.to_categorical(y_train, num_classes)
    y_test = keras.utils.to_categorical(y_test, num_classes)

    model = Sequential()
    model.add(Dense(512, activation='relu', input_shape=(784,)))
    model.add(Dropout(0.2))
    model.add(Dense(512, activation='relu'))
    model.add(Dropout(0.2))
    model.add(Dense(num_classes, activation='softmax'))

    model.summary()

    model.compile(loss='categorical_crossentropy',
                  optimizer=RMSprop(),
                  metrics=['accuracy'])

    history = model.fit(x_train, y_train,
                        batch_size=batch_size,
                        epochs=epochs,
                        verbose=1,
                        validation_data=(x_test, y_test))

    score = model.evaluate(x_test, y_test, verbose=1)

    print('Test loss:', score[0])
    print('Test accuracy:', score[1])

    Using TensorFlow backend.
    60000 train samples
    10000 test samples
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #
    =================================================================
    dense_1 (Dense)              (None, 512)               401920
    _________________________________________________________________
    dropout_1 (Dropout)          (None, 512)               0
    _________________________________________________________________
    dense_2 (Dense)              (None, 512)               262656
    _________________________________________________________________
    dropout_2 (Dropout)          (None, 512)               0
    _________________________________________________________________
    dense_3 (Dense)              (None, 10)                5130
    =================================================================
    Total params: 669,706
    Trainable params: 669,706
    Non-trainable params: 0
    _________________________________________________________________
    Train on 60000 samples, validate on 10000 samples
    Epoch 1/20
    60000/60000 [==============================] - 11s 178us/step - loss: 0.2476 - acc: 0.9243 - val_loss: 0.1057 - val_acc: 0.9672
    Epoch 2/20
    60000/60000 [==============================] - 6s 101us/step - loss: 0.1023 - acc: 0.9685 - val_loss: 0.0900 - val_acc: 0.9730
    Epoch 3/20
    60000/60000 [==============================] - 6s 101us/step - loss: 0.0751 - acc: 0.9780 - val_loss: 0.0756 - val_acc: 0.9783
    Epoch 4/20
    60000/60000 [==============================] - 6s 100us/step - loss: 0.0607 - acc: 0.9816 - val_loss: 0.0771 - val_acc: 0.9801
    Epoch 5/20
    60000/60000 [==============================] - 6s 101us/step - loss: 0.0512 - acc: 0.9844 - val_loss: 0.0761 - val_acc: 0.9810
    Epoch 6/20
    60000/60000 [==============================] - 6s 102us/step - loss: 0.0449 - acc: 0.9866 - val_loss: 0.0747 - val_acc: 0.9809
    Epoch 7/20
    60000/60000 [==============================] - 6s 101us/step - loss: 0.0377 - acc: 0.9885 - val_loss: 0.0765 - val_acc: 0.9811
    Epoch 8/20
    60000/60000 [==============================] - 6s 101us/step - loss: 0.0334 - acc: 0.9898 - val_loss: 0.0774 - val_acc: 0.9840
    Epoch 9/20
    60000/60000 [==============================] - 6s 101us/step - loss: 0.0307 - acc: 0.9911 - val_loss: 0.0771 - val_acc: 0.9842
    Epoch 10/20
    60000/60000 [==============================] - 6s 105us/step - loss: 0.0298 - acc: 0.9911 - val_loss: 0.1015 - val_acc: 0.9813
    Epoch 11/20
    60000/60000 [==============================] - 6s 102us/step - loss: 0.0273 - acc: 0.9922 - val_loss: 0.0869 - val_acc: 0.9833
    Epoch 12/20
    60000/60000 [==============================] - 6s 99us/step - loss: 0.0247 - acc: 0.9926 - val_loss: 0.0945 - val_acc: 0.9824
    Epoch 13/20
    60000/60000 [==============================] - 6s 101us/step - loss: 0.0224 - acc: 0.9935 - val_loss: 0.1040 - val_acc: 0.9823
    Epoch 14/20
    60000/60000 [==============================] - 6s 100us/step - loss: 0.0219 - acc: 0.9939 - val_loss: 0.1038 - val_acc: 0.9835
    Epoch 15/20
    60000/60000 [==============================] - 6s 104us/step - loss: 0.0227 - acc: 0.9936 - val_loss: 0.0909 - val_acc: 0.9849
    Epoch 16/20
    60000/60000 [==============================] - 6s 100us/step - loss: 0.0198 - acc: 0.9944 - val_loss: 0.0998 - val_acc: 0.9826
    Epoch 17/20
    60000/60000 [==============================] - 6s 101us/step - loss: 0.0182 - acc: 0.9951 - val_loss: 0.0984 - val_acc: 0.9832
    Epoch 18/20
    60000/60000 [==============================] - 6s 102us/step - loss: 0.0178 - acc: 0.9955 - val_loss: 0.1150 - val_acc: 0.9839
    Epoch 19/20
    60000/60000 [==============================] - 6s 100us/step - loss: 0.0167 - acc: 0.9954 - val_loss: 0.0975 - val_acc: 0.9847
    Epoch 20/20
    60000/60000 [==============================] - 6s 102us/step - loss: 0.0169 - acc: 0.9956 - val_loss: 0.1132 - val_acc: 0.9832
    10000/10000 [==============================] - 1s 71us/step
    Test loss: 0.11318948425535869
    Test accuracy: 0.9832 

     

    以上で、「トレーニング済み」となりました。 ほんの数行のコードで、このKerasディープラーニングMLPは、「tensorflow-gpu」環境でかなり効率的に実行します。 これまでのすべてのキットインストールを検証します。 

    6 サンプルを使用してモデルをテストする

    以下の指定されたサンプルを使用してトレーニング済みのモデルをテストしましょう。

    10,000個のx_testセットから特定のサンプルをランダムに選択し、別のHealthShareグローバルに保存してから、そのグローバルからPython配列にデモサンプルとして読み戻します。 それを使用してトレーニング済みのモデルをテストします。

    次に、この入力サンプルを90度、180度、および270度に回転させてモデルを再テストし、混乱が生じないかを確認します。 

    6.1 サンプルをHealthShareに保存する - デモ 

    サンプルをランダムに選択しましょう。たとえば、10,000個のテストサンプルから12番目のサンプルを選択し、HSグローバルに保存します。

    HealthShare -> SAMPLE -> Sample.Personクラスに新しいクラスメソッドを追加します。

    ClassMethod SetT2Globals(d1 As %Integer = 0, d2 As %Integer = 0, d3 As %Integer = 0, value As %String = "", target As %String = "") As %BigInt [ SqlProc ]
    {
             Set ^XTestInput(d1, d2, d3) = value
             Set ^YTestTarget(d1, d2) = target
             return $$$OK
    }

    Sample.Person.cls をリコンパイルします。  Jupyterノートブックで、セクション5.2のコードを再実行し、データベースのバインディングを更新します。次に、この行を実行して、28 x 28 個の数字サンプルをグローバル^XTestInputに保存します。

    import re
    n = 12  # randomly choose a sample 
    for i in range(0, len(x_train[n])):
         r1 = person.run_obj_method("SetT2Globals", [1, n, i, re.sub('0\s0', '  0   0', str(x_test[n][i])), str(y_test[n])])

    これで、2次元配列のサンプルがHS SAMPLEグローバル^XTestInputに保存されていることがわかりました。 それぞれの数字は、0~255のピクセルグレースケールです。 以下のHS管理ポータルから、それが「9」であることが簡単にわかります。

       

    6.2 HealthShareグローバルからサンプルを読み取る - デモ

    HSデータベースグローバルからサンプルを確実に読み取ることができます。  

    別のクラスメソッドをSample.Person.clsに追加して、それをリコンパイルします。

    ClassMethod GetT2Globals(d1 As %Integer = 0, d2 As %Integer = 0, d3 As %Integer = 0) As %String [ SqlProc ]
    {
         Set value = ^XTestInput(d1, d2, d3)
         return value
    }

    Jupyterで、前述のようにDBバインディングを更新してから、このPythonコードを実行してHealthShareから文字列としてグローバルを読み取り、1 x 2次元数値配列に変換します。

    import re, ast
    sample = ""
    for i in range(0, len(x_train[n])):
       sample += person.run_obj_method("GetT2Globals", [1, n, i])
    #convert it to numpy ndarray
    as1  = np.array(ast.literal_eval(re.sub('\s+', ',', re.sub('0\]', '0', re.sub('\[  ', '', re.sub('\]\[', ' ', sample))))))   
    Sample12 = as1.reshape(1, 28, 28)
    print(Sample12)

    6.3 トレーニング済みモデルをテストする 

    これで、Jupyterで、この配列「Sample12」をトレーニング済みのモデルに送信できるようになりました。  model.predictmodel.predict_classesがこの作業を行います。

    Sample12  = Sample12.reshape(1, 784)
    Sample12f = Sample12.astype('float32')/255  # normalise it to float between [0, 1]
    Result12f = model.predict(Sample12f)   #test the 1x784 sample, the result is a 1d matrix
    print(Result12f)

    Result12 = model.predict_classes(Sample12f)  #test the sample, the result is a clasified lable.
    print(Result12)

    [[2.5672970e-27 1.1168821e-25 1.3736557e-20 6.2964843e-17 7.0107062e-09 6.2905544e-17 1.5294099e-28 7.8019199e-17 3.5748028e-16 1.0000000e+00]]
    [9]

    結果には出力レイヤーのニューロン#9に最大値「1.0」があることが示されているため、分類結果は「9」となります。  これは正しい結果です。

    確かに、人工的な28 x 28整数のサンプルをモデルに送信して試してみることができます。

    6.4 サンプルを回転させてモデルを再テストする

    このサンプルを反時計回りに90度回転させて、もう一度試してみることはできるでしょうか? 

    Sample12 = Sample12.reshape(28, 28)  #reshape to 2D array values
    Sample1290 = np.rot90(Sample12)  #rotate in 90 degree
    print(Sample1290)

    次に、モデルを再テストします。

    Sample12901  = Sample1290.reshape(1, 784)
    Sample1290f = Sample12901.astype('float32')/255  
    Result1290f = model.predict(Sample1290f)   
    print(Result1290f)

    Result1290 = model.predict_classes(Sample1290f)  
    print(Result1290)

    [[2.9022769e-05 1.2192334e-20 1.7143857e-07 3.0004558e-11 2.4583075e-11 6.2443775e-01 2.5749558e-05 3.7550735e-01 2.0722151e-08 5.5368415e-10]]
    [5]

    さて、モデルは「5」と認識しました。ニューロン#5が最大出力値でトリガーされています。  どうやら少し混乱しているようです! (確かに縦向きのものが「5」のように見えるので仕方ありませんね)。

    では今度はサンプルを180度回転させましょう。モデルはどのように認識するでしょうか?  

    [[3.3131425e-11 3.0135434e-27 8.7524540e-23 7.1371946e-24 2.4029167e-13 4.2327470e-09 1.0000000e+00 1.7086377e-18 1.3129146e-18 2.8595145e-22]]
    [6]

    もちろん、間違いなく「6」と認識しました!  人間も「9」ではなく「6」と認識するでしょう。 

    では、最後に270度回転させてみましょう。 

    どうやら、また混乱しているようです。今度は「4」と認識しました。

    [[1.6130849e-06 3.0311636e-14 2.1490927e-03 2.7108688e-03 9.9499077e-01 1.4130991e-04 6.2298268e-06 8.6649310e-09 2.9320630e-12 1.5710594e-07]]
    [4]

     

    6.5 パブリッククラウドツールとの比較

    上記の配列をPythonコードの行を介してPNGにエクスポートし、回転して、反転して、画像上にまとめました。 次のようになっています。

     

    次に、それぞれ「Google Vision API」、「Amazon Rekognition」、および「Microsoft Computer Vision API」にアップロードすると、結果はどうなるでしょうか。

    この場合、AWSの「数字」のスコアが95%とわずかに最高となっています(これは絶対に代表的な結果ではありません)。 

    1. Google Vision APIの結果:

     

    2. AWS Rekognitionの結果:

    3. Microsoft Computer Visionの結果: 

     

    7. 次の内容

    次は、以下のような他のいくつかの簡単なポイントについてフォローアップします。 

    • 一言で、MLPはどのように機能するのか?
    • 制限と考えられるユースケースは?
    • 現在のスタックで実行可能な最も一般的なML/DL/ANNモデルの簡単なウォークスルー  
    • 謝辞 
    0
    0 181
    記事 Toshihiko Minamoto · 11月 18, 2021 13m read

    Python 3をHealthShareにバインディングした深層学習デモキット(パート1) キーワード:  Anaconda、Jupyterノートブック、TensorFlow GPU、ディープラーニング、Python 3、HealthShare    

    1. 目的

    この「パート1」では、Python 3をHealthShare 2017.2.1インスタンスにバインドして、「単純」かつ一般的なディープラーニングデモ環境をセットアップする方法を段階的に簡単に説明します。  私は手元にあるWin10ノートパソコンを使用しましたが、このアプローチはMacOSとLinuxでも同じように実装できます。

    先週、PYPL Indexにおいて、Pythonが最も人気のある言語としてJavaを超えたことが示されました。  TensorFlowも研究や学術の分野において非常に人気のある強力な計算エンジンです。 HealthShareは、ケア提供者に患者の統一介護記録を提供するデータプラットフォームです。

    これらを1つのキットにまとめることはできるでしょうか。また、これを実現する上での最も単純なアプローチは何でしょうか。  ここでは、このトピックの最初のステップを一緒に試してから、次に試すことのできるデモについて検討しましょう。  

    2. 範囲と免責事項

    ここで構築しようとしているデモキットには、次のコンポーネントが含まれます。

    •  Anaconda - 十分に構造化されたパッケージ管理で人気のあるデータサイエンスプラットフォーム。 
    • TensorFlow - 強力な計算エンジンを備えた機械学習プラットフォーム。
    • Theano - ML用計算エンジンのPythonライブラリ。 オプションで、TensorFlowの代替として利用できます。
    • Keras - TensorFlowまたはTheanoエンジン上に配備されるPython Deep Learningライブラリ。 
    • Jupyterノートブック - Anacondaパッケージに含まれます。
    • Python 3 - Anacondaパッケージに含まれます。
    • HealthShare - HealthShare 2017.2.1インスタンスを使用します。

    ... ... そして、Win10ノートパソコンです。   

    私のDellノートパソコンにはたまたまローエンドのGPU GeForce 840Mが搭載されています。強力ではありませんが、それでもデモのトレーニング速度は3倍高められます。

    それ以外は、以下のすべてのステップはMacOS(私のはMac Miniです)かLinux環境(たとえばAWSでUbuntuも試しました)で十分に機能します。  

    HealthShare 2017インスタンスは、便宜上、デモDBとして使用されていますが、ここで始めようとしている基本的な実験は、CacheまたはEnsembleのインスタンスにおいても機能し、最終的にはIRISにおいても機能すると思っています。  

    免責事項: これは、PoCデモキットを一緒に使用することで、コミュニティの関心を引くことを狙いとした記事です。 何らかの手段または合法的なブランドによる公式リリースまたは正式発表では決してありません。 内容や範囲は、いずれ空きのある時間に、必要に応じて変更されることがあります。 

    3. 前提条件

    ここでは、ANN、AI、ディープラーニング、またはTensorFlowなどの知識や使用経験は必要ありません。 Python初心者でも十分に使用できます。

    ノートパソコンやサーバーにGPUは必要ありません。 ただし、搭載されているのであれば、そのドライブを更新する必要があるかもしれません。 私の場合はここからドライバーをダウンロードしました。

    ちょっとした注意: 最後の警告7.1を参照してください。

    4. デモ環境のセットアップ - 手順

    4.1 Anaconda環境のインストール

    4.1.1 ダウンロードとインストール 

    次のリンクからAnacondaリリースをダウンロードします。この記事を書いた2019年3月時点でのダウンロード最新バージョンは、Anaconda 2018.12(Python 3.7)です。

    このリンクにある簡単な画面ごとの段階的な指示に従って、Anacondaベース環境をインストールします。 

    _注意: 同じリンクから、MacOSまたはLinuxホスト用のリリースをダウンロードできます。 _

    4.1.2 Anacondaインストールのテスト

    このリンクに従ってインストールを段階的にテストし、PythonとJupyterノートブックが正しく動作することを確認します。ただし、Spyder IDEは必要ありません。 

    リンク先の指示にあるように、WindowsスタートまたはWindowsコマンドラインからJupyterノートブックを起動できることを確認します。

    4.2 TensorFlow環境のインストール 

    Anaconda PromptウィンドウでCondaコマンドを使用して、TensorFlowエンジンをAnacondaパッケージとしてインストールします。

    手順は次のとおりです。

                1. Anaconda Promptウィンドウを起動します。CondaバージョンとPythonバージョンを確認してください。

    (base) C:\>conda -V

    conda 4.5.12

    (base) C:\>python -V
    Python 3.7.1

               2. 「tensorflow」という新しい環境を作成して、アクティブ化します。

    (base) C:\>conda create -n tensorflow
    Solving environment: done

    .... ... ... ...
    (base) C:\>conda activate tensorflow

    (tensorflow) C:\>

               3. 指定されたCondaチャンネルを介して、TensorFlowパッケージをインストールします。

    (tensorflow) C:\>conda install -c conda-forge tensorflow

    このステップでは、非常に大量の具体的なパッケージをダウンロード、解決、アップグレード/ダウングレードするため、かなりの時間が掛かります。

              4. TensorFlowが正常にインストールされたことをテストします。

     tensorflow) C:\>python
    Python 3.6.7 (default, Feb 28 2019, 07:28:18) ... .... ... ... 
    >>> import tensorflow as tf
    >>> se=tf.Session()
    >>> print(se.run(tf.constant('Hello Tensorflow')))
    b'hello TensorFlow!'

    >>> print(tf.__version__)
    1.10.0

    >>> quit()

    (tensorflow) C:\>

     

    4.3 GPU環境のインストール

    TensorFlow GPU環境と同様の手順でインストールします。

    1. 「Tensorflow」という新しい環境を作成して、アクティブ化します。

    (base) C:\>conda create -n tensorflow-gpu
    Solving environment: done

    ... ... 
    (base) C:\>conda activate tensorflow-gpu

    (tensorflow-gpu) C:\>

    2. チャンネルを指定せずに(「tensorflow」ではなく)「tensorflow-gpu」パッケージをインストールします。 

    (tensorflow-gpu) C:\>conda install tensorflow-gpu 

    この手順では、すべてのパッケージのダウンロード、解決、インストールに時間が掛かります。

    3. インストールを検証します。 

    >>> import tensorflow as tf
    >>> se = tf.Session()
    2019-03-14 14:02:52.423895: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX AVX2
    2019-03-14 14:02:53.081332: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1433] Found device 0 with properties:
    name: GeForce 840M major: 5 minor: 0 memoryClockRate(GHz): 1.124
    pciBusID: 0000:03:00.0
    totalMemory: 2.00GiB freeMemory: 1.65GiB
    2019-03-14 14:02:53.087514: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1512] Adding visible gpu devices: 0
    2019-03-14 14:08:18.789761: I tensorflow/core/common_runtime/gpu/gpu_device.cc:984] Device interconnect StreamExecutor with strength 1 edge matrix:
    2019-03-14 14:08:18.794278: I tensorflow/core/common_runtime/gpu/gpu_device.cc:990]      0
    2019-03-14 14:08:18.796348: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1003] 0:   N
    2019-03-14 14:08:18.804907: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 1395 MB memory) -> physical GPU (device: 0, name: GeForce 840M, pci bus id: 0000:03:00.0, compute capability: 5.0)

    注意: この手順ではCUDA gpuライブラリが再構築されているため、かなりの時間が掛かることがあります。 問題がある場合は、Anaconda Promptを「管理者として実行」で再起動し、この手順を再試行してください。 私の問題は、2回ほど再起動して解決されました。 

    >>> print(se.run(tf.constant('Hello')))
    b'Hello'
    >>> print(tf.__version__)
    1.13.1

    では、このAnacondaの環境をリスト表示しましょう。 

    (base) c:\>conda env list
    # conda environments:
    #
    base                  *  C:\ProgramData\Anaconda3
    tensorflow               C:\Users\zhongli\AppData\Local\conda\conda\envs\tensorflow
    tensorflow-gpu           C:\Users\zhongli\AppData\Local\conda\conda\envs\tensorflow-gpu

     

    4.4 Theano環境のインストール(オプション)

    Keras構成を試す予定がなく、常にTensorFlowを基盤のエンジンとして使用するのであれば、この手順を省略できます。

    そうでない場合は、新しい環境を作成してアクティブ化し、次のコマンドを実行してください: conda install -c conda-forge theano

    4.5 Kerasのインストール

    Kerasは、このディープラーニングデモスタックの最上位のレイヤーモジュールです。 

    今作成した「tensorflow-gpu」環境にインストールしましょう。  注意: ここでは「keras」ではなく「keras-gpu」をインストールしています。

    (tensorflow-gpu) c:\>conda install -c anaconda keras-gpu

    関連するパッケージがインストールされます。 では、簡単な検証を行いましょう。

    (tensorflow-gpu) c:\>python
    Python 3.6.8 |Anaconda, Inc.| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import keras as k
    Using TensorFlow backend.

    「パート2」では、ディープラーニングモデルの実行にJupyterノートブックを使用して、上記でインストールしたすべてのコンポーネントを検証しますが、 その前に、HealthShareインスタンスのインストールとPython 3バインディングを完了しましょう。

    4.6. HealthShareインスタンスのインストール

    私はIntersystems WRCのダウンロードページから標準のHealthShareインストールファイルをダウンロードしました。   

    hscore15.032_hsaa15.032_hspi15.032_hsviewer15.032_linkage15.032  Windows 64 Bit EXE

    また、いつものように一時ライセンスが必要となりますが、これはInterSystemsの営業部またはサポートに連絡すると取得できます。

    インストールが完了すると、バージョン文字列は次のようになります: Cache for Windows (x86-64) 2017.2.1 (Build 801_3_18095U) Mon May 7 2018 14:28:58 EDT [HealthShare Modules:Core:16.0.7669 + Linkage Engine:16.0.7669 + Patient Index:16.0.7669 + Clinical Viewer:16.0.7669 + Active Analytics:16.0.7669]

    4.7 HealthShareへのPythonバインディングをTensorFlow環境にインストール  

    4.7.1 HealthShareインスタンスパスの特定

    製品の公式ドキュメント『Python Binding to Intersystems Cache』はこちらにあります。

    たとえば、私のHSインスタンスは次のローカルの場所にインストールされています: C:\InterSystems\HS20181

    そのため、まず、このISC Python DLLパスをWindowsの「環境パス」に追加しました: C:\InterSystems\HS20181\bin

    4.7.2 VC++コンパイラのセットアップ 

    次に、「vcvarsall.bat」コマンドを実行して、パスがMS VC++コンパイラ用にセットアップされていることを確認しました。 

    私の場合は、**[Visual Studio 2017]->[Tools]->[Get Tools and Features]**メニューに移動し、以下のように「Desktop Development with C++」がインストールされている(選択済み)ことを再確認しています。この選択済みのチェックがない場合は、インストールする必要があります。  すると、デフォルトのディレクトリ(例: **C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build **)に「vcvarsall.bat」が表示されるようになります。

    4.7.3 HealthShareインスタンスへのPython 3バインディングのインストール

    次に、前のセクションでインストールした「tensorflow-gpu」環境に直接「HealthShareへのPython 3バインディング」をセットアップします。

    注意: 私は「...setup.py ...」の代わりに「python setup3.py install」を実行しました。

    (tensorflow-gpu) c:\>cd c:\InterSystems\HS20181\dev\python

    (tensorflow-gpu) c:\InterSystems\HS20181\dev\python>python setup3.py install
    enter directory where you installed Cache'c:\InterSystems\HS20181
    libdir=c:\InterSystems\HS20181/dev/cpp/lib
    include dir=c:\InterSystems\HS20181/dev/cpp/include
    libs=['cbind']
    running install
    running bdist_egg
    running egg_info
    ... ...
    installing library code to build\bdist.win-amd64\egg
    running install_lib
    running build_py
    running build_ext
    creating build\bdist.win-amd64\egg
    creating build\bdist.win-amd64\egg\intersys
    copying build\lib.win-amd64-3.6\intersys\pythonbind.py -> build\bdist.win-amd64\egg\intersys
    ... ...

    creating stub loader for intersys\pythonbind31.cp36-win_amd64.pyd
    byte-compiling build\bdist.win-amd64\egg\intersys\pythonbind31.py to pythonbind31.cpython-36.pyc
    creating build\bdist.win-amd64\egg\EGG-INFO
    ... ...

    Processing pythonbind3-1.0-py3.6-win-amd64.egg
    creating c:\users\zhongli\appdata\local\conda\conda\envs\tensorflow-gpu\lib\site-packages\pythonbind3-1.0-py3.6-win-amd64.egg
    Extracting pythonbind3-1.0-py3.6-win-amd64.egg to c:\users\zhongli\appdata\local\conda\conda\envs\tensorflow-gpu\lib\site-packages
    Adding pythonbind3 1.0 to easy-install.pth file

    Installed c:\users\zhongli\appdata\local\conda\conda\envs\tensorflow-gpu\lib\site-packages\pythonbind3-1.0-py3.6-win-amd64.egg
    Processing dependencies for pythonbind3==1.0
    Finished processing dependencies for pythonbind3==1.0

    4.7.4 バインディングがHealthShareデータベースインスタンスで機能していることを確認

    では、「samples3」パス内の「test.py」を実行しましょう。

    (tensorflow-gpu) c:\InterSystems\HS20181\dev\python\samples3>python test.py
    Simple Python binding sample
    Cache server port (default 1972)? 56778
    Connection string: localhost[56778]:SAMPLES
    Connecting to Cache server
    Connected successfully
    Creating database
    Opening Sample.Person instance with ID 1 with default concurrency and timeout
    Getting the value of the Name property
    Value: Zevon,Mary M.
    Test completed successfully

    上記により、特定のHealthShareデータベース(SAMPLESネームスペース: Sample.Person テーブル)へのPython 3バインディングがtensorflow-gpu環境内で機能していることが確認されました。 

    5. 次の内容

    これで、実際のディープラーニングデモを試すための一般的なツールを使用した基本環境を用意できました。

    次の「パート2」では、Jupyterノートブックを使用してサンプルコードを実行し、ほとんどの人が最初に使用する最も古典的なモデルを手始めに、さまざまなモデルや機能の重要な概念を探っていきましょう。 最終的に実際のケースを想像したり収集したりする前に、一般的なサンプルデータをトレーニングまたは予測する上で、最も単純なアプローチや近道を探ります。  

    6. 謝辞  

    ここに記載したほとんどの作業は、静かなクリスマスと年末年始の休暇中にやり直されたものです。 ここに記載されているデモキットについては、HealthShareインスタンスへのPythonバインディングを実行することだけが追加作業として必要でした。

    7. 警告

    7.1 GPU ドライバーの更新: GPUドライバーを直接更新すると、Matlabや一般的なゲーミングプラットフォームなどのほかのアプリケーションに問題が発生することがあると言われました。そこで、修正をいじることに慣れている必要があります。

    7.2 簡単なショートカット: 可能な限り、単純なコードやショートカットを使用しようとしています。  考えられる実際のケースや問題については、モデルパラメーターの最適化やデータ正規化に関する正式な方法は常に大変なタスクであるため、ここでのデモデータセットにおいて考慮する必要はありません。 

    0
    0 284
    記事 Toshihiko Minamoto · 8月 3, 2021 6m read

    画像

    IRIS と Python でチャットボットを作成する

    この記事では、InterSystems IRIS データベースを Python と統合して自然言語処理(NLP)の機械学習モデルを提供する方法を説明します。

    Python を使用する理由

    世界的に広く採用され使用されている Python には素晴らしいコミュニティがあり、様々なアプリケーションをデプロイするためのアクセラレータ/ライブラリが豊富に提供されています。 関心のある方は https://www.python.org/about/apps/ をご覧ください。

    IRIS のグローバル

    ^globals について学び始めると、型にはまらないデータモデルに素早くデータを取り込む手法として使用することに慣れてきました。 そのため、最初は ^globals を使用してトレーニングデータと会話を保存し、チャットボットの動作をログに記録することにします。

    自然言語処理

    自然言語処理(NLP)は、人間の言語から意味を読み取って理解する能力を機械に与える AI のテーマです。 ご想像のとおりあまり単純ではありませんが、この広大で魅力的な分野で最初の一歩を踏み出す方法を説明します。

    デモ - 試してみましょう

    チャットボットアプリケーションをデモとしてデプロイしています: http://iris-python-suite.eastus.cloudapp.azure.com:8080

    どのように動作しますか?

    機械学習

    まず、機械学習には、一般的なソフトウェア開発とは異なるパラダイムがあることを知っておきましょう。 分かりにくい要点は、機械学習モデルの開発サイクルです。

    完全な説明ではありません

    標準的なアプリケーション開発サイクルは次のようになっています。

    コードの開発 -> テスト(開発データを使用)-> デプロイ(実際のデータを使用)

    そして、機械学習では、コード自体に同じ価値がありません。 責任はデータと共有されています! つまり、データがなければ、実際のデータもないということです。 これは、実行される最終的なコードは、開発コンセプトと使用されるデータのマージによって生成されるためです。 したがって、機械学習アプリケーションのサイクルは次のようになっています。

    モデルの開発(トレーニング)と実データ -> 検証 -> この結果(モデル)をデプロイ

    モデルをトレーニングするには

    モデルをトレーニングするにはたくさんの手法があり、それぞれのケースと目的には大きな学習曲線が伴います。 ここでは、いくつかの手法をカプセル化して、トレーニング方法と事前処理済みのトレーニングデータを提供する ChatterBot ライブラリを使用し、結果に焦点を当てやすくしています。

    事前学習のモデル言語とカスタムモデル

    基本的な会話型チャットボットを作成するにはこれを使用することができます。 チャットボットをトレーニングするためのすべてのデータがニーズを完全に満たすように作成することもできますが、短時間で作成するのは困難です。 このプロジェクトでは、会話のベースとして en_core_web_sm を使用し、フォームを使って作成できるカスタムトレーニングデータとマージします。

    基本アーキテクチャ

    画像

    Python で使用したもの

    このアプリケーション環境では、Python 3.7 と以下のモジュールを使用します。

    • PyYAML<=5.0.0
    • dash==1.12.0
    • dash-bootstrap-components==0.10.1
    • dash-core-components==1.10.0
    • dash-html-components==1.0.3
    • dash-renderer==1.4.1
    • dash-table==4.7.0
    • plotly==4.7.1
    • numpy==1.18.4
    • networkx==2.4
    • Flask>=1.0.0
    • chatterbot>=1.0.0
    • chatterbot-corpus>=1.2.0
    • SQLAlchemy>=1.2
    • ./nativeAPI_wheel/irisnative-1.0.0-cp34-abi3-linux_x86_64.whl

    プロジェクト構造

    このプロジェクトは理解しやすい単純な構造になっています。 メインのフォルダには、最も重要な 3 つのサブフォルダがあります。

    • ./app: すべてのアプリケーションコードとインストール構成が含まれます。
    • ./iris: アプリケーションをサービングする InterSystems IRIS dockerfile が含まれます。
    • ./data: ボリュームによってホストをコンテナー環境にリンクします。

    アプリケーション構造

    ./app ディレクトリには、以下のファイルが含まれます。

    • chatbot.py: Web アプリケーションの実装が含まれます。
    • iris_python_suite.py: IRIS Native API によって IRIS データベースや Python と使用する、アクセラレータを持つクラスです。

    データベース構造

    このアプリケーションでは、InterSystems IRIS をリポジトリとして使用します。使用されるグローバルは以下のとおりです。

    • ^chatbot.training.data: 質疑応答の形式で、すべてのカスタムトレーニングデータを保存します。
    • ^chatbot.conversation: すべての会話ペイロードを保存します。
    • ^chatbot.training.isupdated: トレーニングパイプラインを制御します。

    ほかのソリューションの製品

    全会話のレポートは作成しませんでしたが、私のグローバルグラフビューアを使用すれば、問題なく会話を追跡することができます。

    画像

    自分でアプリケーションを実行する

    前提条件

    • git
    • docker と docker-compose(docker のメモリ設定を 4 GB 以上に増加してください)
    • 環境のターミナルへのアクセス

    手順

    docker-compose を使って、すべてのピースと構成を備えた 1 つの環境を簡単に起動できます。iris-python-covid19 フォルダに移動し、次のように入力します。

    $ docker compose build
    $ docker compose up
    

    コンテナの推定起動時間

    初回実行時は、画像や依存関係をダウンロードするためのインターネット接続に依存します。 15 分以上かかる場合は、おそらく何らかの問題が発生しているので、こちらにご連絡ください。 2 回目以降はパフォーマンスが向上し、2 分もかかりません。

    すべてが万全である場合

    しばらくしたら、ブラウザを開いて次のアドレスに移動します。

    トレーニングデータのフォーム

    http://localhost:8050/chatbot-training-data
    

    チャットボット

    http://localhost:8080
    

    IRIS 管理ポータルの確認

    この時点では、USER ネームスペースを使用しています。

    http://localhost:9092
    user: _SYSTEM
    pass: theansweris42
    

    この記事が役に立った場合、またはコンテンツを気に入った場合は、投票してください。

    このアプリケーションは、Open Exchange コンテストに現在参加中です。こちら(https://openexchange.intersystems.com/contest/current)から私のアプリケーション「iris-python-suite」に投票してください。

    0
    0 638
    お知らせ Mihoko Iijima · 7月 26, 2021

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

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

    今回のお知らせでは、見事受賞されたアプリケーションと開発者の方々を発表します!


    0
    0 101
    お知らせ Mihoko Iijima · 7月 19, 2021

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

    今日から、第13回 InterSystems IRIS プログラミングコンテスト(AI) の投票が始まりました!

    これだ 🔥 と思う作品への投票、よろしくお願いします!

    🔥 投票はこちらから! 🔥

    投票方法については、以下の通りです。

    0
    0 123
    お知らせ Mihoko Iijima · 7月 7, 2021

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

    第 13 回 InterSystems IRIS プログラミングコンテスト(AI編)のテクノロジーボーナス🍆が発表されました!

    ボーナスポイントを獲得して 💰賞金💰 をゲットしてください!

    IntegratedML の利用 - 4 ポイント

    AI/ML ソリューションに InterSystems IntegratedML を利用すると4ポイント獲得できます。

    ご利用いただくときは、IRISのバージョンが2021.1以上であることをご確認ください。ZPMパッケージマネージャを含めた最新のMLイメージは以下イメージ名です。

    intersystemsdc/iris-ml-community:2021.1.0.215.0-zpm
    intersystemsdc/irishealth-ml-community:2021.1.0.215.0-zpm

     

    R Gateway and Python gateway の利用 - 4 ポイント

    InterSystems IRIS 2021リリースには、R ゲートウェイと Python ゲートウェイの 2 つの新機能が含まれています。

    Rゲートウェイの使用方法に関するテンプレートを公開しています。使い方の簡単なデモはこちらのビデオをご覧ください。

    Embedded Python の利用 - 4 ポイント

    0
    0 101
    お知らせ Mihoko Iijima · 6月 20, 2021

    開発者の皆さん、こんにちは!次のコンテストのテーマが発表されました!

    🏆 InterSystems AI Programming Contest 🏆

    応募期間は 2021年6月28日~7月18日 です!

    💰 賞金総額: $8,750 💰

    (投票期間は 2021年7月19日~7月25日、勝者発表は 7月26日を予定しています)

    優勝特典

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

    🥇 1位 - $4,000 

    🥈 2位 - $2,000 

    🥉 3位 - $1,000

    2、開発者コミュニティで多く票を集めたソリューションには、以下の賞金が贈られます。

    🥇 1位 - $1000 

    🥈 2位 - $500 

    🥉 3位 - $250

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

    参加資格

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

    👥 開発者がチームを組んで共同でアプリケーションを作成し、応募することもできます! 1チーム 2~5名 までご参加いただけます。

    チームでご応募いただく場合は、アプリケーションの README にチームメンバー名の記載をお忘れなく!!(開発者コミュニティのプロファイルのリンクもお願いします)

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

    0
    0 217
    記事 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 · 12月 28, 2020

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

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

    今回のお知らせでは、見事受賞されたアプリケーションと開発者の方々を発表します!

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

    🥇 1位 - $2,000 は iris-analytics-notebook を開発された @José Roberto Pereira さんに贈られました!

    🥈 2位 - $1,000 は website-analyzer を開発された @YURI MARX GOMES さんに贈られました!

    🥉 3位 - $500 は iris-analytics-package を開発された @Henrique Dias Gonçalves Dias さんに贈られました!

    🏆 Community Nomination - 最も多くの票を獲得したアプリケーションに贈られます。

    🥇 1位 - $1,000 は iris-analytics-package を開発された @Henrique Dias Gonçalves Dias さんに贈られました!

    0
    0 101
    お知らせ Mihoko Iijima · 12月 21, 2020

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

    2020年最後の IRIS プログラミングコンテストの投票が始まりました!
    🔥 これだ!と思う一押し作品に投票お願いします! 🔥

    投票方法は?

    今回から投票方法が新しくなりました!
    Expert Nomination または Community Nomination を選択いただき、どの作品がどの順位になるかを指定しながら投票します。

    Community Leaderboard:

    順位 ポイト
    1位 3点
    2位 2点
    3位 1点

    そして、エキスパートノミネーションからの投票は以下の通りとなりました。

    Experts Leaderboard:

    エキスパートレベル

    順位
    1位 2位 3位
    GM、モデレーター、プロダクトマネージャーのVIPレベル 9点 6点 3点
    グローバルマスターズのエキスパートレベル 6点 4点 2点
    グローバルマスターズのスペシャリストレベル 3点 2点 1点

    エキスパートリーダーボードの投票はコミュニティリーダーボードにもポイント(1位3点、2位2点、3位1点)が加算されます。

    投票方法について

    投票は Open Exchange コンテストページで行われ、Open Exchange にサインインする必要があります。

    0
    0 107
    記事 Mihoko Iijima · 12月 17, 2020 4m read

    みなさん、こんにちは。 昨日、Apache Spark、Apache Zeppelin、そして InterSystems IRIS を接続しようとしたときに問題が発生したのですが、有用なガイドが見つからなかったので、自分で書くことにしました。

    はじめに

    Apache Spark と Apache Zeppelin とは何か、そしてどのように連携するのかを理解しましょう。

    Apache Spark はオープンソースのクラスタコンピューティングフレームワークです。暗黙的なデータ並列化と耐障害性を備えるようにクラスタ全体をプログラミングするためのインターフェースを提供しています。そのため、ビッグデータを扱う必要のある場合に非常に役立ちます。 一方の Apache Zeppelin はノートブックです。分析や機械学習に役立つ UI を提供しています。組み合わせて使う場合、IRIS がデータを提供し、提供されたデータを Spark が読み取って、ノートブックでデータを処理する、というように機能します。

    注意: 以下の内容は、Windows 10 で行っています。

    Apache Zeppelin

    では、必要なすべてのプログラムをインストールしましょう。

    まず、Apache Zeppelin の公式サイトから Apache Zeppelin をダウンロードします。私は zeppelin-0.8.0-bin-all.tgz を使用しました。このファイルには、ApacheSparkScala、および Python が含まれます。

    ダウンロードファイルを任意のフォルダに解凍します。解凍後、Zeppelin フォルダのルートから \bin\zeppelin.cmd を呼び出して、Zeppelin を起動します。 「Done, zeppelin server started」が表示されたら、ブラウザでhttp://localhost:8080 を開きます。 すべてうまくいった場合、「Welcome to Zeppelin!」メッセージが表示されます。

    注意: InterSystems IRIS がインストール済みであることを前提としています。まだインストールしていない場合は、次のステップに進む前に IRIS をダウンロードしてインストールしてください。

    Apache Spark

    ブラウザウィンドウに Zeppelin ノートブックが開いている状態です。右上の「anonymous」をクリックし、「Interpreter」をクリックします。下にスクロールして「spark」を見つけてください。

    「spark」の横に「 edit 」ボタンがあるので、それをクリックしましょう。 下にスクロールして、intersystems-spark-1.0.0.jarintersystems-jdbc-3.0.0.jar に依存関係を追加します。 私の環境は InterSystems IRIS を C:\InterSystems\IRIS\ ディレクトリにインストールしているため、追加しなければならないものは以下の場所にあります。

    私の環境でのファイルは以下の通りです。

    そして保存します。

    動作確認

    動作確認してみましょう。 新しいノートを作成し、段落に次のコードを貼り付けます。

    var dataFrame=spark.read.format("com.intersystems.spark").option("url", "IRIS://localhost:51773/NAMESPACE").option("user", "UserLogin").option("password", "UserPassword").option("dbtable", "Sample.Person").load()
    
    // dbtable - name of your table
    

    URL - IRIS アドレスを 次の書式で指定します。IRIS://ipAddress:superserverPort/namespace

  • **プロトコル「IRIS」** は、Java 共有メモリ接続を提供する TCP/IP 経由の JDBC 接続です。
  • **ipAddress** - InterSystems IRIS インスタンスの IP アドレス。 ローカルで接続している場合は、localhost の代わりに 127.0.0.1 を使用してください。
  • **superserverPort** - IRIS インスタンスのスーパーサーバーのポート番号。Web サーバーのポート番号とは異なります。 スーパーサーバーのポート番号を見つけるには、管理ポータルを開き、画面上部にある「概要」のリンクをクリックして表示される画面の「Superserver Port」を確認してください。
  • **namespace** - InterSystems IRIS インスタンスの既存のネームスペースを指定します。 このデモでは、USER ネームスペースに接続しています。
  • この段落を実行しましょう。 うまくいけば、「FINISHED」が表示されます。

    私のノートブックでの実行例です。

    まとめ

    この記事の内容をまとめると、Apache Spark、Apache Zeppelin、および InterSystems IRIS がどのように連携できるかがわかりました。 次の記事では、データ分析についてお話しします。

    リンク

    0
    0 332
    記事 Minoru Horita · 11月 30, 2020 6m read

    みなさん、こんにちは。 今回は ML モデルを IRIS Manager にアップロードしてテストしようと思います。

    注意: Ubuntu 18.04、Apache Zeppelin 0.8.0、Python 3.6.5 で以下を実行しました。

    はじめに

    最近では実にさまざまなデータマイニングツールを使用して予測モデルを開発し、これまでにないほど簡単にデータを分析できるようになっています。 InterSystems IRIS Data Platform はビッグデータおよび高速データアプリケーション向けに安定した基盤を提供し、最新のデータマイニングツールとの相互運用性を実現します。

    この連載記事では、InterSystems IRIS で利用できるデータマイニング機能について説明します。最初の記事ではインフラストラクチャを構成し、作業を開始する準備をしました。2 番目の記事では、Apache Spark と Apache Zeppelin を使用して花の種を予測する最初の予測モデルを構築しました。 この記事では KMeans PMML モデルを構築し、InterSystems IRIS でテストします。

    Intersystems IRIS は PMML の実行機能を提供しています。 そのため、モデルをアップロードし、SQLクエリを使用して任意のデータに対してそのモデルをテストできます。 正解率、適合率、F スコアなどが表示されます。

    要件の確認

    まず、jpmml をダウンロードし(表を確認して適切なバージョンを選択してください)、それを任意のディレクトリに移動します。 Scala を使用しているのであれば、それで十分でしょう。

    Python を使用している場合は、ターミナルで次のコマンドを実行してください。

    pip3 install --user --upgrade git+https://github.com/jpmml/pyspark2pmml.git

    正常にインストールされたことを確認したら Spark Dependencies に異動し、ダウンロードした jpmml に次のように依存関係を追加してください。

    KMeans モデルの作成

    PMML ビルダーはパイプラインを使用しますので、ここでは以前の記事で書いたコードに若干の変更を加えました。 次のコードを Zeppelin で実行します。

    %pyspark
    from pyspark.ml.linalg import Vectors
    from pyspark.ml.feature import VectorAssembler
    from pyspark.ml.clustering import KMeans
    from pyspark.ml import Pipeline
    from pyspark.ml.feature import RFormula
    from pyspark2pmml import PMMLBuilder

    dataFrame=spark.read.format("com.intersystems.spark").\
    option("url", "IRIS://localhost:51773/NEWSAMPLE").option("user", "dev").\
    option("password", "123").\
    option("dbtable", "DataMining.IrisDataset").load() # iris データセットをロード

    (trainingData, testData) = dataFrame.randomSplit([0.7, 0.3]) # データを 2 セットに分割
    assembler = VectorAssembler(inputCols = ["PetalLength", "PetalWidth", "SepalLength", "SepalWidth"], outputCol="features") # features を含む新しいカラムを追加

    kmeans = KMeans().setK(3).setSeed(2000) # 使用するクラスタリングアルゴリズム

    pipeline = Pipeline(stages=[assembler, kmeans]) # 渡されたデータはまず assembler に対して実行され、その後に kmeans に対して実行されます。
    modelKMeans = pipeline.fit(trainingData) # トレーニングデータを渡す

    pmmlBuilder = PMMLBuilder(sc, dataFrame, modelKMeans)
    pmmlBuilder.buildFile("KMeans.pmml") # pmml モデルを作成

    上記により、PetalLength / PetalWidth / SepalLength / SepalWidth を特徴として使用して Species を予測するモデルが作成されます。 このモデルは PMML フォーマットを使用します。

    PMML は XML ベースの予測モデル交換フォーマットであり、分析アプリケーションがデータマイニングおよび機械学習アルゴリズムによって生成された予測モデルを記述し、交換する方法を提供します。 これにより、モデルの構築とモデルの実行を切り離すことができます。

    出力には PMML モデルへのパスが表示されます。

    PMML モデルのアップロードとテスト

    IRIS Manager から [Menu] -> [Manage Web Applications] を開き、目的のネームスペースをクリックしてから [Analytics] を有効にしてから [Save] をクリックします。

    次に、[Analytics] -> [**Tools **] -> [PMML Model Tester] に移動します。

    次の画像のように表示されるはずです。

    [New] をクリックしてクラス名を書き、PMML ファイル(パスは出力に表示されていました)をアップロードし、[Import] をクリックします。その後、次の SQL クエリを [Custom data source] に貼り付けます。

    SELECT PetalLength, PetalWidth, SepalLength, SepalWidth, Species,
     CASE Species
      WHEN 'Iris-setosa' THEN 0
      WHEN 'Iris-versicolor' THEN 2
      ELSE 1
     END
    As prediction
    FROM DataMining.IrisDataset

    KMeans クラスタリングではクラスタが数値(0、1、2)として返されるため、ここでは CASE を使用しています。また、種を数値に置換しなかった場合は誤ってカウントされてしまいます。クラスタの番号を種の名前に置換する方法をご存じの方はコメントをお願いします。

    結果は以下のとおりです。

    結果には詳細な分析データが表示されています。

    真陽性偽陰性などの知識を深めたい方は、「適合率と再現率」を参照してください。

    まとめ

    PMML Model Tester がデータに対してモデルをテストできる非常に便利なツールであることが分かりました。 このツールは詳細な分析データ、グラフ、SQL 実行機能を提供しますので、 別途ツールを用意しなくてもモデルをテストすることができます。

    リンク

    前の記事

    PySpark2PMML

    JPMML

    機械学習パイプライン

    Apache Spark のドキュメント

    0
    0 224
    記事 Minoru Horita · 8月 6, 2020 2m read

    この連載記事では、InterSystemsデータプラットフォーム用のPython Gatewayについて説明します。 また、InterSystems IRISからPythonコードなどを実行します。 このプロジェクトは、InterSystems IRIS環境にPythonの力を与えます。

    • 任意のPythonコードを実行する
    • InterSystems IRISからPythonへのシームレスなデータ転送
    • Python相互運用アダプタでインテリジェントな相互運用ビジネスプロセスを構築する
    • InterSystems IRISからのPythonコンテキストの保存、調査、変更、復元

    その他の記事

    現時点での連載計画です(変更される可能性があります)。

    はじめに

    Jupyter Notebookは実コード、数式、図、説明文を含むドキュメントを作成および共有できるオープンソースのWebアプリケーションです。

    この拡張機能を使用すると、InterSystems IRIS BPLのプロセスをJupyterノートブックとして参照および編集できます。

    現在、デフォルトのPython 3のexecutorが使用されています。

    この拡張機能はアノテーションにPythonコードが含まれていることを前提としており、アクティビティ名を先行する読み取り専用の見出しとして使用します。

    最近、私はJupyterのサポートを拡張しました。 これで、JupyterからPythonGatewayのビジネスプロセスを開発できるようになりました。 以下のように何でも対応できます。

    • 新しいビジネスプロセスを作成する
    • ビジネスプロセスを削除する
    • 新しいアクティビティを作成する
    • アクティビティを変更する
    • アクティビティを削除する

    デモ動画をご覧ください。 次のように表示されます。

    プロセスエクスプローラー

    プロセスエディタ

    インストール

    1. InterSystems IRIS 2019.2以降が必要です。
    2. PythonGateway バージョン0.8以降をインストールします(isc.py.util.Jupyterisc.py.ens.ProcessUtils のみが必要です)。
    3. リポジトリからObjectScriptのコードベースを更新します。
    4. do ##class(isc.py.util.Jupyter).Install() を実行し、プロンプトに従います。

    Readmeと詳細なインストール手順.

    要約

    Python Gatewayを使用すると、InterSytems IRISとPythonをシームレスに統合できます。 これを使用し、Pythonの機能をInterSystems IRISアプリケーションに追加してください。 ビジネスプロセスを編集するには、Jupyter Notebookを使用してください。 いつものように、テストとバグ報告は大歓迎です。

    リンク

    0
    0 194
    お知らせ 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
    記事 Minoru Horita · 7月 6, 2020 7m read

    この連載記事では、InterSystemsデータプラットフォーム用のPython Gatewayについて説明します。 また、InterSystems IRISからPythonコードなどを実行します。 このプロジェクトは、InterSystems IRIS環境にPythonの力を与えます。 

    • 任意のPythonコードを実行する 
    • InterSystems IRISからPythonへのシームレスなデータ転送 
    • Python相互運用アダプタでインテリジェントな相互運用ビジネスプロセスを構築する 
    • InterSystems IRISからのPythonコンテキストの保存、調査、変更、復元 

    その他の記事 

    現時点での連載計画です(変更される可能性があります)。 

    • パート I:概要、展望、紹介 
    • パート II:インストールとトラブルシューティング <-- 現在、この記事を参照しています 
    • パート III:基本機能 
    • パート IV:相互運用アダプタ 
    • パート V:Execute関数 
    • パート VI:動的ゲートウェイ 
    • パート VII:プロキシゲートウェイ 
    • パート VIII:使用事例とML Toolkit 

    インストール 

    この記事はPython Gatewayをインストールするのに役立ちます。Python Gatewayをインストールして使用する方法はいくつか存在します。 

    0
    1 320