こちらのgoogle colabで試すことができます

https://colab.research.google.com/github/yuta-vet/NLP-health-consultation-system/blob/main/veterinary_medicine_NLP.ipynb

動機

飼い主の入力したテキストから、病気の可能性をあぶり出すというAI・機械学習があったらいいなと思います。自動診断の試みだと、質問を次々にしていき、病気の選択肢を狭めていくという作戦がメジャーだと思います。

オランダでは、医師の電子カルテ入力内容のテキストデータから、NLPによって処方内容を提案するという試みが運用されていることを知りました。

この取り組みに着想を得て、飼い主の自由入力のテキストデータから、病気の可能性を計算するというのができるか、検討したいと思います。

Hugging Face

Hugging face🤗というサービスに世界中の学習済み機械学習モデルが集まっていて、そのモデルを利用しやすい形で提供されているようです。モデルのターゲットタスクは、NLPと画像認識がメインのようです。画像認識を勉強しているときは、tensorflowのAPIからpretrainedモデルが入手できたので、こういったサービスを知りませんでした。NLPを勉強してhugging faceを知りました。

使ってみると、すごいモデルは多いもののエラーも多く、なかなか使うのが大変といった印象です。いやそれにしても、すごいモデルが多いです。translationタスクだったり、文書分類タスクだったり、文章推測タスクだったり、自分では到底到達できないレベルのモデルが使えるのはありがたいです。

その中で、今回使えそうだなと思ったのはZero-Shot Classificationというモデルの種類です。

Zero-Shot Classification

zero-shot classificationというモデルの種類は、テキストの分類問題を解くためのモデルの種類です。通常、分類問題は学習済みのclassにしか分類ができません。しかし、zero-shot classificationは、学習してきたclassでなくても、既存の学習データの解析から、新たなclassに分類をトライすることが可能なモデルです。なんでそんなことができるのか、私には詳細はわかりません。

が、Hugging faceのAPIを使えば簡単にzero-shot classificationを使うことができます。このzero-shot classificationを使って、新たな学習なしで、自動診断装置の可能性を検討したいと思います。

コード

google colabで実行します。学習済みモデルを読み込みます。日本語を含んだ多数の言語を学習しているjoeddav/xlm-roberta-large-xnliというモデルを指定します。このモデルは、RoBERTa(Robustly optimized BERT approach)です。

!pip install -q transformers==3.1.0
from transformers import pipeline
classifier = pipeline("zero-shot-classification", model='joeddav/xlm-roberta-large-xnli')

この段階で、エラーが出ることがありました。なぜか一貫性・再現性がないんですけどね。この場合には、ランタイムの再起動を実行して、再度上記コードを実行してください。治りました。

 ValueError                                Traceback (most recent call last)
  in ()
       1 from transformers import pipeline
 ----> 2 classifier = pipeline("zero-shot-classification", model='joeddav/xlm-roberta-large-xnli')
       3 """
       4 ValueError: Couldn't instantiate the backend tokenizer from one of:
       5 (1) a tokenizers library serialization file,
 5 frames
 /usr/local/lib/python3.7/dist-packages/transformers/tokenization_utils_fast.py in init(self, *args, **kwargs)
     104         else:
     105             raise ValueError(
 --> 106                 "Couldn't instantiate the backend tokenizer from one of: \n"
     107                 "(1) a tokenizers library serialization file, \n"
     108                 "(2) a slow tokenizer instance to convert or \n"
 ValueError: Couldn't instantiate the backend tokenizer from one of: 
 (1) a tokenizers library serialization file, 
 (2) a slow tokenizer instance to convert or 
 (3) an equivalent slow tokenizer class to instantiate and convert. 
 You need to have sentencepiece installed to convert a slow tokenizer to a fast one.

分類タスクを実行します。まずは、比較的わかりやすそうな分類問題から実行してみたいと思います。学習させてないのに、分類なんてできるのでしょうか。

sequence = "犬の名前はジョンです" 
candidate_labels = ["動物", "医療", "教育"]
classifier(sequence, candidate_labels)

{‘labels’: [‘動物’, ‘教育’, ‘医療’],
‘scores’: [0.9933984279632568, 0.0038738290313631296, 0.0027276789769530296],
‘sequence’: ‘犬の名前はジョンです’}

凄すぎる。なんで、適当にラベルを作ったのに正確に分類できるんだ。驚く。

まずは、医療と獣医療に分けれるか実験してみます。

sequence = "クッシング症候群" 
candidate_labels = ["獣医", "医療"]
classifier(sequence, candidate_labels)

{‘labels’: [‘医療’, ‘獣医’],
‘scores’: [0.7189062833786011, 0.28109368681907654],
‘sequence’: ‘クッシング症候群’}

ほうほう。クッシングは人医療でもあるからね。

sequence = "フィラリア" 
candidate_labels = ["獣医", "医療"]
classifier(sequence, candidate_labels)

{‘labels’: [‘獣医’, ‘医療’],
‘scores’: [0.526101291179657, 0.473898708820343],
‘sequence’: ‘フィラリア’}

フィラリアは獣医療の方でよく聞くからね。

sequence = "ノミ" 
candidate_labels = ["獣医", "医療"]
classifier(sequence, candidate_labels)

{‘labels’: [‘獣医’, ‘医療’],
‘scores’: [0.7690937519073486, 0.23090624809265137],
‘sequence’: ‘ノミ’}

ノミ駆除は動物でよく行うからね。

sequence = "ジステンパー" 
candidate_labels = ["獣医", "医療"]
classifier(sequence, candidate_labels)

{‘labels’: [‘獣医’, ‘医療’],
‘scores’: [0.5298661589622498, 0.47013387084007263],
‘sequence’: ‘ジステンパー’}

いやこれもう、一般人の能力を超えていますね。ジステンパーが獣医よりのワードなんてわかるのは、獣医しかいないんじゃないでしょうか。

病気診断をトライ

最近、背中を痛がるようになった。足に麻痺を起こしていて歩き方が変。

という相談があったと仮定する。以下の疾患リストの中からどれが可能性が高いかを推測する。椎間板ヘルニアの症状を想定している。

“消化器系疾患”,
“免疫性疾患”,
“整形学的疾患”,
“泌尿器疾患”,
“呼吸器疾患”,
“神経疾患”,
“循環器疾患”,
“腫瘍”,
“感染症”,
“皮膚疾患”

sequence = "最近、背中を痛がるようになった。\
足に麻痺を起こしていて歩き方が変" 
candidate_labels = ["消化器系疾患",
                    "免疫性疾患",
                    "整形学的疾患",
                    "泌尿器疾患",
                    "呼吸器疾患",
                    "神経疾患",
                    "循環器疾患",
                    "腫瘍",
                    "感染症",
                    "皮膚疾患"]
classifier(sequence, candidate_labels)

{‘labels’: [‘神経疾患’, ‘整形学的疾患’, ‘呼吸器疾患’, ‘皮膚疾患’, ‘循環器疾患’, ‘消化器系疾患’, ‘免疫性疾患’, ‘泌尿器疾患’, ‘腫瘍’, ‘感染症’], ‘scores’: [0.42440810799598694, 0.36921027302742004, 0.11229202896356583, 0.04532711207866669, 0.020979465916752815, 0.010208426043391228, 0.00604222621768713, 0.005001042503863573, 0.0035264447797089815, 0.0030048873741179705], ‘sequence’: ‘最近、背中を痛がるようになった。足に麻痺を起こしていて歩き方が変’}

神経疾患、整形学的疾患と、椎間板ヘルニアのジャンルを正確に予想することができた。

つぎは乳腺腫瘍を想定する。

最近、乳腺にところにしこりを見つけた

{‘labels’: [‘腫瘍’, ‘整形学的疾患’, ‘泌尿器疾患’, ‘呼吸器疾患’, ‘循環器疾患’, ‘消化器系疾患’, ‘皮膚疾患’, ‘神経疾患’, ‘感染症’, ‘免疫性疾患’], ‘scores’: [0.4470369517803192, 0.22556471824645996, 0.22521758079528809, 0.0527813546359539, 0.01576724275946617, 0.01235829945653677, 0.011494344100356102, 0.00416777515783906, 0.00358038698323071, 0.00203126622363925], ‘sequence’: ‘最近、乳腺にところにしこりを見つけた’}

腫瘍がトップ。しこりがヒントになったのかな。正しい。

次は、特徴がない症状。感染症を想定する。

くしゃみと下痢と嘔吐がひどい

{‘labels’: [‘泌尿器疾患’, ‘消化器系疾患’, ‘呼吸器疾患’, ‘皮膚疾患’, ‘循環器疾患’, ‘免疫性疾患’, ‘感染症’, ‘整形学的疾患’, ‘神経疾患’, ‘腫瘍’], ‘scores’: [0.36231371760368347, 0.3388262987136841, 0.21967527270317078, 0.050441768020391464, 0.024436933919787407, 0.0016003451310098171, 0.0015975534915924072, 0.0005487559246830642, 0.00040926571818999946, 0.00015007593901827931], ‘sequence’: ‘くしゃみと下痢と嘔吐がひどい’}

泌尿器??やはり万能ではないのか。

次はアレルギーを想定する。

ドッグフードを変えてから下痢が続く

{‘labels’: [‘泌尿器疾患’, ‘消化器系疾患’, ‘呼吸器疾患’, ‘循環器疾患’, ‘感染症’, ‘皮膚疾患’, ‘免疫性疾患’, ‘整形学的疾患’, ‘神経疾患’, ‘腫瘍’], ‘scores’: [0.46187543869018555, 0.4438173472881317, 0.062411967664957047, 0.01475661899894476, 0.004942263010889292, 0.004458988085389137, 0.004000507295131683, 0.0023850607685744762, 0.0008319323533214629, 0.0005199371371418238], ‘sequence’: ‘ドッグフードを変えてから下痢が続く’}

泌尿器か。それはないと思う。消化器とほぼ同確率だから、いいのか。

体がかゆい

{‘labels’: [‘皮膚疾患’, ‘整形学的疾患’, ‘呼吸器疾患’, ‘消化器系疾患’, ‘神経疾患’, ‘泌尿器疾患’, ‘免疫性疾患’, ‘循環器疾患’, ‘腫瘍’, ‘感染症’], ‘scores’: [0.6490961313247681, 0.09349663555622101, 0.04980313405394554, 0.037822406738996506, 0.03260861709713936, 0.03230635076761246, 0.03046264685690403, 0.027696704491972923, 0.025622649118304253, 0.021084683015942574], ‘sequence’: ‘体がかゆい’}

皮膚疾患は間違いないが、免疫性疾患も上位に来てほしかった。

飲水量が増えて尿の量も増えた

labelsに内分泌疾患を追加してみる。

{‘labels’: [‘消化器系疾患’, ‘泌尿器疾患’, ‘呼吸器疾患’, ‘内分泌疾患’, ‘循環器疾患’, ‘皮膚疾患’, ‘感染症’, ‘整形学的疾患’, ‘免疫性疾患’, ‘神経疾患’, ‘腫瘍’], ‘scores’: [0.21576860547065735, 0.21105551719665527, 0.1298489272594452, 0.10295474529266357, 0.0976296216249466, 0.06423339992761612, 0.049677446484565735, 0.04158603399991989, 0.035675279796123505, 0.027343878522515297, 0.024226509034633636], ‘sequence’: ‘飲水量が増えて尿の量も増えた’}

消化器がトップに来た。そうかなあ、泌尿器、内分泌、感染症といったところではないかと思う。

結論

結論は、微妙といったところか。予想がいいのかどうなのか、なかなか判断がつかない。

Categories:

category