0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Flairで文章中のバイオメディカル関連語を抽出する

Last updated at Posted at 2021-05-09

1. はじめに

機械学習初心者の化学屋が自分用のメモとして書いた記事です。
自然言語処理のためのライブラリFlairで提供されている学習済みモデル”HunFlair”を利用して、文章中の化合物病気微生物遺伝子タンパク質生物種といったバイオメディカル関連の単語を抽出します。

実行環境
・python 3.7.1
・flair 0.8.1
・pytorch 1.5.0(flairの動作に torch<1.8.0, >=1.5.0 が必要)
・torchvision 0.6.0

2. FlairによるNER(固有表現抽出)

Flairとは自然言語処理用のライブラリで、最新の言語モデルなどを簡単に試すことができます。
Flairは公式チュートリアルが充実しています。文章中の単語へのタグ付け(Tagging)、単語へのベクトル埋め込み(Word Embedding)、オリジナルモデルのトレーニングまでカバーされており、読めば一通りのことが試せるようになっています。

Flairでは様々なNERのためのtaggerが提供されています。
以下のチュートリアルを見ればそれぞれのtaggerでどのようなタグ付けができるのかわかります。
各モデルのIDの部分をクリックすると各taggerで付与できるタグの一覧とサンプルコードが載っているページに飛びます。
Tutorial 2: Tagging your Text --- List of Pre-Trained Sequence Tagger Models

"ner"のページを見てみると、以下のタグ付けができることが分かります。

tag meaning
PER person name
LOC location name
ORG organization name
MISC other name

サンプルコードを参考に動かしてみると以下のような感じです。

from flair.data import Sentence
from flair.models import SequenceTagger

# load "ner" tagger
tagger = SequenceTagger.load("ner")

# make example sentence
sentence = Sentence("George Washington went to Washington .")

# predict NER tags
tagger.predict(sentence)

# print sentence
print(sentence)

# print predicted NER spans
print('The following NER tags are found:')
# iterate over entities and print
for entity in sentence.get_spans('ner'):
    print(entity)

出力結果

George <B-PER> Washington <E-PER> went to Washington <S-LOC> . 
The following NER tags are found:
Span [1,2]: "George Washington"   [− Labels: PER (0.9968)]
Span [5]: "Washington"   [− Labels: LOC (0.9994)]

この例では人名のワシントンと地名のワシントンを区別できており、"George Washington"を1つの意味のまとまり(chunk)として抽出できていることが分かります。
また、各タグの接頭語(B-, E-, S-)はBIOESフォーマットに従って付与されているようです。
B, I, O, E, SはそれぞれchunkのBeggining, Inside, Outside, Ending, Singleを意味しています。

上の例では"George Washington"の2語で人名<PER>に対応するchunkを構成しており、Georgeは人名のBegginingなので<B-PER>、Washingtonは人名のEndingなので<E-PER>となっています。
地名<LOC>の"Wahington"は単独Singleでchunkを構成しているので、<S-LOC>となっています。
chunkが3単語以上からなる場合は、内部の単語のタグに"I-"が付与されます。

Span[*] は文章中での位置を表しています。

このような感じで簡潔なコードで固有表現抽出が可能となっています。

3. HunFlairによるバイオメディカル関連語の抽出

Flairではバイオメディカル分野におけるNER用にHunFlairというtaggerが提供されており、今回はその中のhunflair-chemicalを使用して化合物の抽出を行ってみます。
hunflairは以下の5種類のtaggerから構成されており、HunFlair-DataSets に各taggerが学習に用いたデータセットなどが示されています。
・hunflair-celline
・hunflair-chemical
・hunflair-disease
・hunflair-gene
・hunflair-species

3.1 hunflair-chemical を使った化合物の抽出

SequenceTagger.load()hunflair-chemicalを指定することで化合物の抽出ができます。

from flair.data import Sentence
from flair.models import SequenceTagger

# load "hunflair-chemical" tagger
tagger = SequenceTagger.load("hunflair-chemical")

# make example sentence
sentence = Sentence("[Co(NH3)6]Cl3 is prepared by treating CoCl2 with ammonia and ammonium chloride followed by oxidation.")

# predict hunflair-chemical tags
tagger.predict(sentence)

# print sentence
print(sentence.to_tagged_string())

# print predicted NER spans
print('The following hunflair-chemical tags are found:')
# iterate over entities and print
for entity in sentence.get_spans():
    print(entity)

出力結果

[ <B-Chemical> Co <I-Chemical> ( <I-Chemical> NH3 <I-Chemical> ) <I-Chemical> 6 <I-Chemical> ] <I-Chemical> Cl3 <E-Chemical> is prepared by treating CoCl2 <S-Chemical> with ammonia <S-Chemical> and ammonium <B-Chemical> chloride <E-Chemical> followed by oxidation .
The following hunflair-chemical tags are found:
Span [1,2,3,4,5,6,7,8]: "[ Co ( NH3 ) 6 ] Cl3"   [− Labels: Chemical (0.8793)]
Span [13]: "CoCl2"   [− Labels: Chemical (0.9527)]
Span [15]: "ammonia"   [− Labels: Chemical (0.9331)]
Span [17,18]: "ammonium chloride"   [− Labels: Chemical (0.9692)]

このようにテキスト中の化合物を抽出できます。
[Co(NH3)6]Cl3 のような単語中に ( ) [ ] ・ を含むものについては、

[Co(NH3)6]Cl3 [ Co ( NH3 ) 6 ] Cl3

のように分けられていますが、1つのchunkとして認識されています。
(Flairの内部処理で、( ) [ ] ・などによって単語が区切られるようです。)

3.2 MultiTaggerを使ったバイオメディカル関連語の抽出

先程は、SequenceTagger.load("hunflair-chemical")として化合物の検出のみを行いました。
病名、化合物、遺伝子など複数のタイプのタグ付けを行う際には、公式チュートリアルのようにMultiTagger.load("hunflair")とすれば5種類全てのtaggerが読み込まれて、5つのタイプのタグを付与することができます。

例えば以下のコードでは、病名、タンパク質、化合物、生物種の抽出ができます。

from flair.data import Sentence
from flair.models import MultiTagger # SequenceTaggerではなくMultiTaggerをimportする

# load tagger
tagger = MultiTagger.load("hunflair")

# make example sentence
sentence = Sentence("Amyloid beta (Aβ or Abeta) denotes peptides of 36–43 amino acids that are the main component of the amyloid plaques found in the brains of people with Alzheimer's disease.")

# predict hunflair-chemical tags
tagger.predict(sentence)

# print sentence
print(sentence.to_tagged_string())

# print predicted NER spans
print('The following hunflair tags are found:')
# iterate over entities and print
for entity in sentence.get_spans():
    print(entity)

出力結果

Amyloid <B-Gene> beta <E-Gene> ( Aβ <S-Gene> or Abeta <S-Gene> ) denotes peptides of 36 – 43 amino <B-Chemical> acids <E-Chemical> that are the main component of the amyloid plaques found in the brains of people <S-Species> with Alzheimer <B-Disease> 's <I-Disease> disease <E-Disease> .
The following hunflair tags are found:
Span [14,15]: "amino acids"   [− Labels: Chemical (0.8314)]
Span [32,33,34]: "Alzheimer 's disease"   [− Labels: Disease (0.9604)]
Span [1,2]: "Amyloid beta"   [− Labels: Gene (0.5752)]
Span [4]: "Aβ"   [− Labels: Gene (0.8071)]
Span [6]: "Abeta"   [− Labels: Gene (0.9552)]
Span [30]: "people"   [− Labels: Species (0.7343)]

5種類のtaggerを読み込むので少し時間がかかります。
"hunflair-chemical"タイプの"Chemical"タグ
"hunflair-disease"タイプの"Disease"タグ
"hunflair-gene"タイプの"Gene"タグ(GeneとProteinの両方にGeneタグが付与される)
"hunflair-species"タイプの"Species"タグ
が付与されています。
"hunflair-cellline"タイプの"CellLine"タグに該当するものは無いようです。

ここから、"hunflair-gene"タイプのタグだけを取り出したいときは、以下のように記述します。

for disease in sentence.get_spans("hunflair-gene"):
    print(disease)

出力結果

Span [1,2]: "Amyloid beta"   [− Labels: Gene (0.5752)]
Span [4]: "Aβ"   [− Labels: Gene (0.8071)]
Span [6]: "Abeta"   [− Labels: Gene (0.9552)]

任意のタイプのタグから、"Disease"タグだけを取り出したいときは、以下のように記述します。
for entity in sentence.get_spans():
    if entity.tag=="Disease" :
        print(entity)

出力結果

Span [27,28,29]: "Alzheimer 's disease"   [− Labels: Disease (0.9609)]

参考サイト

FLAIR TUTORIAL
NLP state of the artをお手軽に使えるflair(fukuの犬小屋)

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?