パスワードを忘れた? アカウント作成
14173916 journal
人工知能

yasuokaの日記: 『言語処理100本ノック 2020』「48. 名詞から根へのパスの抽出」をGiNZAで解いてみる

日記 by yasuoka

昨日の日記で指摘した『言語処理100本ノック 2020』の「48. 名詞から根へのパスの抽出」を、GiNZAで解いてみることにした。まずは問題文。

48. 名詞から根へのパスの抽出
文中のすべての名詞を含む文節に対し,その文節から構文木の根に至るパスを抽出せよ. ただし,構文木上のパスは以下の仕様を満たすものとする.

  • 各文節は(表層形の)形態素列で表現する
  • パスの開始文節から終了文節に至るまで,各文節の表現を” -> “で連結する

「吾輩はここで始めて人間というものを見た」という文(neko.txt.cabochaの8文目)から,次のような出力が得られるはずである.

吾輩は -> 見た
ここで -> 始めて -> 人間という -> ものを -> 見た
人間という -> ものを -> 見た
ものを -> 見た

この問題に対し、私(安岡孝一)なりに知恵を絞って、Google Colaboratory上で解いてみた。ただし、クラスMorphChunkの代わりに、それぞれTokenSpanを拡張する形にした。

!pip install ginza

from spacy.tokens import Token,Span,Doc
Token.set_extension("surface",getter=lambda token:token.orth_,force=True)
Token.set_extension("base",getter=lambda token:token.lemma_,force=True)
Token.set_extension("pos",getter=lambda token:token.pos_,force=True)
Token.set_extension("pos1",getter=lambda token:token.tag_,force=True)
Span.set_extension("morphs",getter=lambda span:span,force=True)
Span.set_extension("dst",getter=lambda span:max(t.head._.bunsetu_index for t in span),force=True)
Span.set_extension("srcs",getter=lambda span:{s[0]._.bunsetu_index for s in span.doc._.chunks if s._.dst==span[0]._.bunsetu_index},force=True)
def _make_chunks(doc):
  b=[i for i,t in enumerate(doc) if t._.bunsetu_bi_label=="B"]
  return [Span(doc,s,e) for s,e in zip(b,b[1:]+[len(doc)])]
Doc.set_extension("chunks",getter=_make_chunks,force=True)

import ja_ginza
nlp=ja_ginza.load()
doc=nlp("吾輩はここで始めて人間というものを見た")
chunks=doc._.chunks
for c in chunks:
  if [t for t in c._.morphs if t._.pos in {"NOUN","PRON","PROPN"}]!=[]:
    s=str(c)
    d=chunks[c._.dst]
    while d!=c:
      s+=" -> "+str(d)
      c=d
      d=chunks[c._.dst]
    print(s)

この結果、私の手元では、以下の出力が得られた。

吾輩は -> 見た
ここで -> 始めて -> 見た
人間という -> ものを -> 見た
ものを -> 見た

プログラム自体は、間違ってないはずなんだけどなぁ。困ったなぁ。

この議論は、yasuoka (21275)によって ログインユーザだけとして作成されたが、今となっては 新たにコメントを付けることはできません。
typodupeerror

ナニゲにアレゲなのは、ナニゲなアレゲ -- アレゲ研究家

読み込み中...