Amazon Web Services ブログ

AWS COVID-19 ナレッジグラフの作成とクエリ

このブログ記事では、AWS CloudFormation および Amazon Neptune を使用して AWS COVID-19 ナレッジグラフ (CKG) を再作成し、お客様の AWS アカウントの Amazon SageMaker でホストされている Jupyter ノートブックを使用してグラフをクエリする方法について詳しく説明します。CKG は、AWS COVID-19 データレイクでホストされる COVID-19 Open Research Dataset (CORD-19) の探索と分析を支援します。グラフの強みは、学術論文、著者、科学的概念、機関の間のつながりにあります。CKG は、CORD-19 検索ページの強化にも役立ちます。

AWS COVID-19 データレイクは、新型コロナウイルス (SARS-CoV-2) とこれに関連する病気である COVID-19 の広がりおよび特性についての、またはそれに関する最新のデータセットが収集され、一元化されたリポジトリで、一般公開されています。詳細については、「COVID-19 データの分析用のパブリックデータレイク」と「AWS COVID-19 パブリックデータレイクの探索」を参照してください。

CKG は、Neptune、CORD-19 データセット、および Amazon Comprehend Medical のアノテーションを使用して構築されています。2020 年 4 月 17 日の時点で、CORD-19 データセットは 52,000 件を超える学術論文で構成され、そのうち 41,000 件は全文掲載されています。データは、PubMed、bioArxiv、medRxiv などのいくつかのチャネルから取り込んでいます。データセットは拡大し続けており、アレン人工知能研究所が、幅広い研究コミュニティと協力して、データの品質を標準化および改善しています。データセットは学際的で、ウイルス学、展開医療、疫学などのトピックが含まれています。

グラフの構造

CKG は有向グラフです。次の表は、ノードとエッジの関係をまとめたものです。有向エッジは、指定されたエッジの重みを使用して、ソースノードから宛先ノードに移動します。

エッジ名 ソースノード 宛先ノード エッジの重み
affiliated_with 著者 機関
associated_concept 論文 概念 Amazon Comprehend Medical 信頼スコア
authored_by 論文 著者
引用 論文 論文
associated_topic 論文 トピック 潜在的ディリクレ分析スコア

以下は、CKG のグラフの例です。Paper ノードから Author ノードと Concept ノードへ、そして Author ノードから Institution ノードへの発信接続に注意してください。

論文 (青色のノード) は、特定の機関 (緑色のノード) に所属する著者 (黄色のノード) によって書かれています。論文は複数の著者を持つことができ、著者は複数の機関に所属することができます。

概念ノード (赤いノード) は、Amazon Comprehend Medical Detect Entities V2 を使用して生成され、病状、投薬量、解剖学的情報、治療手順、薬物などの医学情報を抽出します。

トピックノード (前の図には表示されていません) は、潜在的ディリクレ配分モデルの拡張機能を使用して生成されます。この生成モデルは、観測されたコンテンツによってドキュメントをグループ化し、各ドキュメントにトピックベクトルのミックスを付与します。論文ごとに、モデルはプレーンテキストのタイトル、要約、本文を使用し、表、図、参考文献は無視されます。

このようなノードは、著者と機関を介した論文間、および論文自体のテーマとの間でつながりができるようにすることで、グラフを強化しています。

ソリューションの概要

AWS データレイクでは、提供されている CloudFormation テンプレートを使用して CloudFormation スタックを作成できます。CloudFormation スタックは、1 つのユニットとして管理される AWS リソースのコレクションです。詳細については、「スタックの操作」を参照してください。

CKG を構築するには、提供されたテンプレートから CloudFormation スタックを作成する必要があります。テンプレートは必要な AWS リソースを作成し、データをグラフに取り込みます。

AWS アカウントで CKG を構築した後、Gremlin-Python を使用して基本的なクエリと高度なクエリを実行できます。

基本的なクエリは、グラフの探索と検索を実行します。目的はグラフの直感を構築し、Gremlin-Python を使用したグラフのクエリに精通することにあります。

この記事では、高度なクエリを実行して次のことを行います。

  • CKG をクエリして、特定の概念に関連する論文を取得する
  • 著者の専門性によって論文をランク付けして、最初に読む論文を決定する
  • グラフクエリを使用して関連する論文レコメンデーションエンジンを作成することで、次に読むべき論文を決定する

前提条件

始める前に、次のものがあることを確認してください。

  • AWS アカウントへのアクセス
  • CloudFormation スタックを作成する権限

CloudFormation テンプレートを使用する

AWS アカウントでグラフとサンプルクエリノートブックを設定するには、CloudFormation テンプレートを使用して CloudFormation スタックを作成します。

次のワンクリックテンプレートを起動し、スタック作成プロセス中にプロンプトが表示されたら次のパラメータを使用します (他のパラメータはすべてデフォルトのままにします)。

AutoIngestData: True

テンプレートは次のことを行います。

  • Neptune データベースクラスターを作成します。
  • Virtual Private Cloud (VPC) を作成します。
  • Amazon SageMaker ノートブックインスタンスを作成し、VPC 内の Neptune クラスターにアクセスする権限を付与します。
    • スタックは、ノートブックインスタンスに多数の Python ライブラリもロードします。これにより、グラフとやり取りできるようになります。
    • ノートブックインスタンスには、グラフのクエリ方法を示すデモ用の Jupyter ノートブックも含まれています。
  • データをグラフに取り込みます。このグラフのすべてのデータは、AWS COVID-19 パブリックデータレイクに保存されています。

テンプレートが完成したら、Amazon SageMaker ノートブックインスタンスとサンプルの Jupyter ノートブックにアクセスできます。手順については、「ノートブックインスタンスへのアクセス」を参照してください。

Neptune と Gremlin

Neptune は Apache TinkerPop3 および Gremlin 3.4.1 と互換性があります。つまり、Gremlin グラフ走査言語を使用して Neptune データベースインスタンスにクエリを実行できます。Gremlin-Python は、Python 言語内に Gremlin を実装します。Gremlin の詳細については、「PRACTICAL GREMLIN: An Apache TinkerPop Tutorial」を参照してください。

Neptune のクエリは、Gremlin-Python を通じて可能です。詳細については、「Gremlin を使用して Neptune グラフへアクセスする」を参照してください。

基本的なクエリ

このようなクエリは、Amazon SageMaker Jupyter ノートブックで Gremlin-Python を使用して基本的なグラフの探索と検索を行う方法を示しています。これらのクエリなどを備えた Jupyter ノートブックは、以前に作成した Amazon SageMaker ノートブックインスタンスで利用できます。データセットは常に進化しているため、出力はこの記事の出力と異なる場合があります。

グラフ探索

次のクエリは、ノード数と各タイプのノード数を取得します。グラフのすべての頂点を抽出するには、g.V() および hasLabel (NODE_NAME) を使用して、特定のノードのグラフをフィルタリングし、count() を使用してノード数を取得します。最後のステップ next() は結果を返します。

nodes = g.V().count().next()
papers = g.V().hasLabel('Paper').count().next()
authors = g.V().hasLabel('Author').count().next()
institutions = g.V().hasLabel('Institution').count().next()
topics = g.V().hasLabel('Topic').count().next()
concepts = g.V().hasLabel('Concept').count().

print(f"papers: {papers}, authors: {authors}, institutions: {institutions}")
print(f"topics: {topics}, concepts: {concepts}")
print(f"Total number of nodes: {nodes}")

次のコードが、その出力です。

papers: 42220, authors: 162928, institutions: 21979
topics: 10, concepts: 109750
Total number of nodes: 336887

次のクエリは、エッジ数と各タイプのエッジ数を返します。グラフのすべてのエッジを抽出するには、g.E()hasLabel(EDGE_NAME) を使用して特定のエッジのグラフをフィルタリングし、count() を使用してエッジ数を取得します。最後のステップ next() は結果を返します。

paper_author = g.E().hasLabel('authored_by').count().next()
author_institution = g.E().hasLabel('affiliated_with').count().next()
paper_concept = g.E().hasLabel('associated_concept').count().next()
paper_topic = g.E().hasLabel('associated_topic').count().next()
paper_reference = g.E().hasLabel('cites').count().next()
edges = g.E().count().next()

print(f"paper-author: {paper_author}, author-institution: {author_institution}, paper-concept: {paper_concept}")
print(f"paper-topic: {paper_topic}, paper-reference: {paper_reference}")
print(f"Total number of edges: {edges}")

次のコードが、その出力です。

paper-author: 240624, author-institution: 121257, paper-concept: 2739666
paper-topic: 95659, paper-reference: 134945
Total number of edges: 3332151

グラフ検索

次のクエリは、すべての作成者ノードのグラフをフィルタリングし、valueMap()limit()、および toList() を使用して、CKG から 5 人の著者をサンプリングし、辞書を返します。

g.V().hasLabel('Author').valueMap('full_name').limit(5).toList()

次のコードが、その出力です。

[{'full_name': ['· J Wallinga']},
 {'full_name': ['· W Van Der Hoek']},
 {'full_name': ['· M Van Der Lubben']},
 {'full_name': ['Jeffrey Shantz']},
 {'full_name': ['Zhi-Bang Zhang']}]

次のクエリは、トピックノードのグラフをフィルタリングします。クエリは、hasLabel()has() を使用して特定のトピックをフィルタリングし、次に both() を使用して、このトピックノードの入力エッジと出力エッジの両方から論文ノードを取得します。さらに limit() を使用して結果を制限し、values() を使用してトピックノードから特定のプロパティを取得します。最後のステップ toList() は結果をリストとして返します。

g.V().hasLabel('Topic').has('topic', 'virology').both()\
.limit(3).values('title').toList()

次のコードが、その出力です。

['Safety and Immunogenicity of Recombinant Rift Valley Fever MP-12 Vaccine Candidates in Sheep',
 'Ebola Virus Neutralizing Antibodies Detectable in Survivors of theYambuku, Zaire Outbreak 40 Years after Infection',
 'Respiratory Viruses and Mycoplasma Pneumoniae Infections at the Time of the Acute Exacerbation of Chronic Otitis Media']

高度なクエリ

次の図は、CKG から取得できる情報のタイプを示しています。CKG を使用して、論文のリストをランク付けし、1 つの論文に関する情報を取得できます (詳細については、以下のセクションをご覧ください)。

概念に関連する論文をランク付けする

このユースケースでは、ウイルス耐性に関連する論文を取得するために CKG にクエリを実行し、主要な著者ごとに論文をランク付けします。このトピックに関するすべての論文を見つけるには、次のコードを入力します。

concept = 'viral resistance'
papers = g.V().has('Concept', 'concept', concept).both().values('SHA_code').toList()

print(f"Number of papers related to {concept}: {len(papers)}")

次のコードが、その出力です。

ウイルス耐性に関する論文の数: 74

論文をランク付けするには、次のコードを入力します。

def author_prolific_rank(graph_results, groupby='SHA_code'):
    P = g.V()\
        .has('Paper', 'SHA_code', within(*graph_results))\
        .group().by(__.values(groupby))\
        .by(
            __.out('authored_by').local(__.in_('authored_by').simplePath().count()).mean()
        ).order(local).by(values, desc).toList()[0]
    
    return P
    
def sha_to_title(sha):
    title_list = g.V().has('Paper', 'SHA_code', sha)\
    .values('title').toList()
    
    return ''.join(title_list)
author_ranked = author_prolific_rank(papers)author_ranked_df = pd.DataFrame(
    [author_ranked], index=['Score']
).T.sort_values('Score', ascending=False).head()
author_ranked_df['title'] = author_ranked_df.index.map(sha_to_title)

for row in author_ranked_df.drop_duplicates(subset='title').reset_index().iterrows():
    print(f"Score: {round(row[1]['Score'], 2)}\tTitle: {row[1]['title']}")

次のコードが、その出力です。

Score: 27.5    Title: Surveillance for emerging respiratory viruses
Score: 11.45    Title: Third Tofo Advanced Study Week on Emerging and Re-emerging Viruses, 2018
Score: 10.5    Title: The Collaborative Cross Resource for Systems Genetics Research of Infectious Diseases
Score: 10.0    Title: RNA interference against viruses: strike and counterstrike
Score: 9.0    Title: Emerging Antiviral Strategies to Interfere with Influenza Virus Entry

関連論文のレコメンデーション

これは、読んだばかりの論文に基づいて、次にどのような関連論文を読むべきかを知りたい場合のユースケースです。レコメンデーションエンジンを開発するには、グラフクエリが使えます。論文と概念は、エッジを介して接続されたグラフのノードです。概念は、Amazon Comprehend Medical によって導出された機械学習 (ML) で信頼性スコア conf が含まれ、概念 c が論文 p にあることについてML システムがどれほど自信があるかを示します。

2 つの論文が互いに関連しているかどうかを判断するには、最初に類似性スコア S を定義します。論文ノードは、CKG で中間概念ノードに接続されます。

特定の論文 P に関連する論文のリストを生成するには、P と CKG 内の他のすべての論文との類似性スコアを生成し、結果をランク付けします。類似性スコアが高い論文ほど、論文 P に関連しています。

2 つの論文間の類似性スコアは、2 つの論文間のすべてのパスの重み付き合計です。行列の観点からは、候補論文のスコア P c は、ベクトル P TP c のドット積で、ベクトル P と候補論文 P c はそれぞれサイズ [N_ {concepts}, 1] になります。各要素 e i は、論文から概念 i までのエッジの重みであり、エッジがない場合は 0 です。

次の図は、推奨フレームワークの例を示しています。

この図では、2 つの論文間のパスは、rhinovirus という用語を経由しています。各論文の概念エッジには信頼スコア conf があります。

2 つの論文間のすべてのパスについて、信頼スコアを乗算します。2 つの論文間の類似性スコアを計算するには、すべての信頼スコアの積を合計します。

まず、次の論文の関連論文を入手しましょう。次のコードを参照してください。

sha = "f1716a3e74e4e8139588b134b737a7e573406b32"
title = "Title: Comparison of Hospitalized Patients With ARDS Caused by COVID-19 and H1N1"
print(f"Title: {title}")
print(f"Unique ID: {sha}") 

次のコードが、その出力です。

Title: Comparison of Hospitalized Patients With ARDS Caused by COVID-19 and H1N1
Unique ID: f1716a3e74e4e8139588b134b737a7e573406b32

前に定義したアルゴリズムを使用してグラフをクエリします。次のコードを参照してください。

rankings = g.withSack(1).V().has('Paper', 'SHA_code', sha)\
.outE('associated_concept').sack(mult).by('score').inV().simplePath()\
.inE('associated_concept').sack(mult).by('score')\
.group().by(__.outV().values('title')).by(__.sack().sum()).toList()
pd.DataFrame(rankings, index=['Score']).T.sort_values('Score', ascending=False).head()

次の表は、出力をまとめたものです。

スコア
感染症 160.095712
要約 (続) 144.739026
口頭発表 93.617558
呼吸器系ウイルス 75.077273
SIOP の要約 72.091667

クリーンアップ

AWS COVID-19 データレイクは Amazon Simple Storage Service (Amazon S3) で無料でホストされており、Amazon S3 のデータをリクエストする標準料金はパブリックデータレイクバケットでは無効になっているため、料金は発生しません。ただし、提供された CloudFormation スタックを使用して AWS アカウントで CKG を構築する場合、Amazon SageMaker でホストされている Neptune および Jupyter ノートブックを使用するため、料金が発生する場合があります。詳細については、Amazon Neptune 料金表Amazon SageMaker 料金表をご覧ください。

繰り返し発生するコストを回避するには、終了時に CloudFormation スタックを削除します。手順については、「AWS CloudFormation コンソールでのスタックの削除」を参照してください。ルートスタック (前に作成したスタック) を必ず削除してください。ルートスタックを削除すると、ネストされたスタックがすべて削除されます。

まとめ

CloudFormation テンプレートを使用してナレッジグラフを作成し、サードパーティのグラフ視覚化ツール Tom Sawyer Graph データベースブラウザを使用してグラフを視覚化することもできます。詳細については、「Amazon Neptune、Amazon Comprehend Medical、および Tom Sawyer Graph データベースブラウザを使用して COVID-19 の科学的研究を探索する」を参照してください。

組織や科学分野での垣根を超え、私たちの総力をもってすれば、COVID-19 のパンデミックとの戦いに打ち勝つことができます。CKG では、COVID-19 に関する科学文献に関する質問と回答を行うことができます。データ、テクノロジー、科学を組み合わせたオープンで協力的な取り組みを通じて、COVID-19 を封じ込め、感染規模を縮小し、最終的には完治させるために必要な洞察を引き出し、飛躍的な進歩を実現できると信じています。

 


著者について

 

Ninad Kulkarni は、Amazon Machine Learning Solutions Lab のデータサイエンティストです。ビジネス問題に対処するためのソリューションを構築することにより、お客様が機械学習および AI ソリューションを採用するのを支援しています。最近では、ファンのエンゲージメントを向上させるために、画面上の使用量に関してスポーツ業界のお客様向けの予測モデルを構築しました。

 

 

Miguel Romero は、Amazon Machine Learning Lab のデータサイエンティストで、AWS のお客様が AI とクラウド機能を使用してビジネス上の問題に対処するのを支援しています。最近では、スポーツとヘルスケア業界向けの CV と NLP ソリューションを構築しました。

 

 

 

Colby Wise は、Amazon Machine Learning Solutions Lab のデータサイエンティスト兼マネージャーで、さまざまな業界の AWS のお客様が AI とクラウドの導入を加速するのを支援しています。

 

 

 

George Price は、Amazon Machine Learning Solutions Lab の深層学習アーキテクトで、AWS のお客様のためにモデルとアーキテクチャの構築を支援しています。以前は、Amazon Alexa のソフトウェアエンジニアでした。