はじめに
今や世の中にごまんとあるCHATGPTの活用事例、今更もう一つ増やしてもほとんど意味がないのですが、先ほどちょっとした調べ物をした際、たった10分ですべて解決してしまい感動したので、その記録を残しておくことします。
問題設定
英文テキストに対して、単語分割を行い、同時に単語の品詞と、活用形のある単語は原形も知りたいというのがやりたいことです。対象が日本語であればjanmeで一発OKであり、私自身qiitaにその記事を書いたことがあるくらい知っているのですが、対象が英語の場合は知識も経験もないので、その点を調べたいという話になります。
実は、過去にこの質問自体は CHATGPTにしたことがあり、ライブラリとしてspacyを使うのが適切であるということまでは事前に知っていました。今日、試したのは、その先の、本当に動く実装コードを作ることになります。
環境
自分のPC内のminiconda + jupyter lab (MAC)です。
実況中継
ここからは、実際のQAの過程を実況中継します。
第1ラウンド(初期コード)
Q
spacyを用いた英文の単語抽出サンプルコードを教えて下さい。
A
以下は、Spacyを使用して英文のテキストから単語を抽出するサンプルコードです。
import spacy
# spacyモデルを読み込む
nlp = spacy.load("en_core_web_sm")
# 解析対象のテキスト
text = "This is a sample sentence."
# テキストを解析する
doc = nlp(text)
# 単語を抽出する
for token in doc:
print(token.text)
上記のコードでは、まずSpacyの英語モデルを読み込み、テキストを解析しています。
そして、docオブジェクトには、解析結果が格納されています。
単語を抽出するために、docオブジェクトをループ処理し、各トークンのテキストを出力しています。
この例では、This、is、a、sample、sentenceが出力されます。
(心の声)
なるほど。一瞬でできてしまいそうだな。自分の環境にまだ、spacyは入っていないはずなので、冒頭のセルで
!pip install spacy
とやって、次のセルにこのコードをはりつければおしまいか?
(しかし、実際にはspacy.load関数呼び出しでエラーになる)
第2ラウンド (問題判別)
Q
こういうエラーになりました。
OSError: [E050] Can't find model 'en_core_web_sm'. It doesn't seem to be a Python package or a valid path to a data directory.
A
このエラーは、Spacyが英語モデルを見つけられなかったことを示しています。一般的に、このエラーは次のような理由で発生します。
- 英語モデルがインストールされていない
- 英語モデルが間違った名前でインストールされている
- 英語モデルが正しい場所にインストールされていない
解決策としては、以下の手順を試すことができます。
- Spacyの英語モデルをインストールする。以下のコマンドを実行してください。
python -m spacy download en_core_web_sm
もし、英語モデルがすでにインストールされている場合は、モデル名が間違っている可能性があります。次のコマンドで利用可能なモデルのリストを確認できます。
python -m spacy info
- そして、利用可能な英語モデルを指定してください。
nlp = spacy.load("en_core_web_sm")
nlp = spacy.load("/path/to/en_core_web_sm")
もし英語モデルが正しい場所にインストールされていない場合は、次のように指定することもできます。
- ここで、/path/to/en_core_web_smは英語モデルがインストールされているパスに置き換えてください。
(心の声)
なるほど、pip installでなく、downloadというコマンドにすべきだったのかな。いったんjupyter labを止めてコマンドラインでこれを実行し、notebookを再起動してみよう
→結果、先ほどのコードが正しく動くようになる
しかし、これだと肝心の品詞がわからないな。どうするるのだろうか?
第3ラウンド(品詞も調べる)
Q
各単語の品詞も調べたいです。
A
Spacyを使って各単語の品詞を調べるには、pos_属性を使います。以下は、先ほどのサンプルコードに品詞の情報を追加したものです。
import spacy
# spacyモデルを読み込む
nlp = spacy.load("en_core_web_sm")
# 解析対象のテキスト
text = "This is a sample sentence."
# テキストを解析する
doc = nlp(text)
# 単語と品詞を抽出する
for token in doc:
print(token.text, token.pos_)
上記のコードでは、forループ内で、各トークンのtext属性とpos_属性を出力しています。pos_属性には、各単語の品詞が格納されています。出力結果は以下のようになります。
This DET
is VERB
a DET
sample NOUN
sentence NOUN
それぞれの品詞には、Spacyの品詞タグが割り当てられています。例えば、"DET"は定冠詞または不定冠詞を表し、"VERB"は動詞を表します。Spacyの品詞タグの一覧は、公式ドキュメントで確認できます。
(心の声)
完璧な回答で素晴らしいです。ここで私は寄り道とわかっていつつ、どんな品詞があるか知りたいと思ってしまったのです。
過去の記録を遡ってみて笑ってしまったのが、その説明はCHATGPTが先回りしてして参照先として示しているのですね。
そこに気付かずに次の質問をしてしまった私はダメな人間なのですが、次のやりとりでのCHATGPTの振る舞いがさすがです。
第4ラウンド 品詞一覧を調べる
Q
品詞にはどんなものがあるか教えていただけますか?
A
Spacyの品詞タグには、以下のようなものがあります。
品詞タグ | 説明 |
---|---|
ADJ | 形容詞 |
ADP | 接置詞 |
ADV | 副詞 |
AUX | 助動詞 |
CONJ | 接続詞 |
DET | 限定詞、冠詞 |
INTJ | 間投詞 |
NOUN | 名詞 |
NUM | 数詞 |
PART | 助詞 |
PRON | 代名詞 |
PROPN | 固有名詞 |
PUNCT | 句読点 |
SCONJ | 従属接続詞 |
SYM | 記号 |
VERB | 動詞 |
X | その他 |
これらの品詞タグを利用して、Spacyは文の構造を解析し、テキスト内の単語をタグ付けすることができます。各品詞には、さらに詳細なサブタグが存在する場合もあります。例えば、VERBには、動詞の種類を示すサブタグがあります(例:VBZは現在形3人称単数の動詞を表します)。詳細については、Spacyの公式ドキュメントを参照してください。
(心の声)
先生が人間だと、さっき説明したばかりのことを聞かれるとイラッときて、そこからトラブルがはじまるわけです。
「さっき言ったばじゃりじゃない」という気持ちはみじんもださずに冷静に質問されたことに答え、さらには聞いてもいない関連情報まで追加で教えてくれるCHAPGPTは、あまりに大人で私も見習わないとと思いました。
さて、今回の調査でもう一つ確認しないといけないことがあります。それは動詞など活用形のある品詞については、その原形を調べるということです。しめくくりに、この質問をしてみましょう。
第5ラウンド 原形を調べる
Q
動詞など活用のある品詞は、原型も同時に知りたいのですが方法はありますか?
A
Spacyを使用して、単語の原型を取得するには、lemma_属性を使用します。以下は、動詞の原型を取得するサンプルコードです。
import spacy
# spacyモデルを読み込む
nlp = spacy.load("en_core_web_sm")
# 解析対象のテキスト
text = "He walked to the store."
# テキストを解析する
doc = nlp(text)
# 動詞とその原型を抽出する
for token in doc:
if token.pos_ == "VERB":
print(token.text, token.lemma_)
上記のコードでは、forループ内で、各動詞のtext属性とlemma_属性を出力しています。lemma_属性には、各動詞の原型が格納されています。出力結果は以下のようになります。
walked walk
同様に、名詞の原型を取得する場合には、pos_属性に "NOUN" を指定して、各名詞のtext属性とlemma_属性を出力します。他の品詞に対しても同様の方法で原型を取得することができます。
(心の声)
今回の目的の場合、下記の実装をひな形にすればいいことがわかりました。
import spacy
# spacyモデルを読み込む
nlp = spacy.load("en_core_web_sm")
# 解析対象のテキスト
text = "This is a sample sentence."
# テキストを解析する
doc = nlp(text)
# 単語と品詞と原形を抽出する
for token in doc:
print(token.text, token.pos_, token.lemma_)
結果
This PRON this
is AUX be
a DET a
sample NOUN sample
sentence NOUN sentence
. PUNCT .
ストップウォッチで計ったわけではないですが、この結論にたどり着くまでの時間は実質10分強だったと思います。
いつものように、ググって APIリファレンス見たり、解説記事見たししてやると、軽く1時間はかかるのではないでしょうか?
特に問題判別でピンポイントのヒントをもらえるのは本当に助かります。
相手が機械であっても、ありがたいと思ったら感謝しないとと思い、最後に次のやりとりで締めくくっています。
最終ラウンド(お礼)
Q
これで知りたいことは完璧にわかりました。
効率よく調べられて大変感謝しております。
どうもありがとうございました。
A
どういたしまして!お役に立てて嬉しいです。何か他にもお困りのことがありましたら、いつでもお気軽にお問い合わせください。
おまけ(後日談)
今回のこの調査、業務での必要があってのことでした。
その業務では、品詞、原形がわかった上で、それぞれの件数をカウントします。
その際には、別記事執筆の際にCHATGPTに教えてもらった、defaultdictを早速活用しました。大変感謝です。
今や、CHATGPTなしには、やっていけない身になりつつあるのかもです、