こんにちは!
テービーテックの村松です。
「言語処理100本ノック2020]」
nlp100.github.io
に挑戦中!
途中でくじけないか見守ってください・・・。
そして、皆さんも一緒に挑戦してみましょう!
本日は第5章: 係り受け解析 47~49です!
間違い・コード改善点などありましたら教えていただけると嬉しいです。
第5章: 係り受け解析
日本語Wikipediaの「人工知能」に関する記事からテキスト部分を抜き出したファイル(https://nlp100.github.io/data/ai.ja.zip)を使用して問題に取り組みます。
※6月に5章で使用するデータが変更となりました。更新内容はこちら
下準備はこちら↓↓で行いました。
ds-blog.tbtech.co.jp
47.機能動詞構文のマイニング
「動詞のヲ格にサ変接続名詞が入っている場合のみに着目したい.46のプログラムを以下の仕様を満たすように改変せよ.
〇「サ変接続名詞+を(助詞)」で構成される文節が動詞に係る場合のみを対象とする
〇述語は「サ変接続名詞+を+動詞の基本形」とし,文節中に複数の動詞があるときは,最左の動詞を用いる
〇述語に係る助詞(文節)が複数あるときは,すべての助詞をスペース区切りで辞書順に並べる
〇述語に係る文節が複数ある場合は,すべての項をスペース区切りで並べる(助詞の並び順と揃えよ)」
path = '出力保存先/47.txt' with open(path, mode='w')as f: for s in s_list: for chunk in s: for m in chunk.morphs: if m.pos == '動詞': for i, src in enumerate(chunk.srcs): if len(s[src].morphs) == 2 and s[src].morphs[0].pos1 == 'サ変接続' and s[src].morphs[1].surface == 'を': predicate = ''.join([s[src].morphs[0].surface, s[src].morphs[1].surface, m.surface]) c = [] cases = [] chu = [] for sr in chunk.srcs[:i] + chunk.srcs[i + 1:]: for mo in s[sr].morphs: if mo.pos == '助詞': c.append(mo.surface) if len(c) > 0: cases = cases + c chu.append(' '.join(m.surface for m in s[sr].morphs if m.pos != '記号')) if len(cases) > 0: cases = sorted(list(set(cases))) output = predicate + '\t' + ' '.join(cases) + '\t' + ' '.join(chu) + '\n' print(output) f.write(output)
##結果(一部抜粋)
記述をする と 主体 と
注目を集め が サポートベクターマシン が
経験を行う に を 元 に 学習 を
学習を行う に を 経験 を 元 に
進化を見せ て において は 活躍 し て いる 特に 敵対 的 生成 ネットワーク は 加え て 生成 技術 において
進化をいる て において は 活躍 し て いる 特に 敵対 的 生成 ネットワーク は 加え て 生成 技術 において
開発を行っ は エイダ・ラブレス は
意味をし に データ に
研究を進める て 費やし て
命令をし で 機構 で
48.名詞から根へのパスの抽出
「文中のすべての名詞を含む文節に対し,その文節から構文木の根に至るパスを抽出せよ. ただし,構文木上のパスは以下の仕様を満たすものとする。
〇各文節は(表層形の)形態素列で表現する
〇パスの開始文節から終了文節に至るまで,各文節の表現を” -> “で連結する」
s = s_list[5] for chunk in s: n = [m.pos for m in chunk.morphs] if '名詞' in n: path = [''.join(mo.surface for mo in chunk.morphs if mo.pos != '記号')] while chunk.dst != -1: path.append(''.join(mo.surface for mo in s[chunk.dst].morphs if mo.pos != '記号')) chunk = s[chunk.dst] print('->'.join(path))
##結果(一部抜粋) 2006年の->ディープラーニング->登場と->登場により->行った->なった ディープラーニング->登場と->登場により->行った->なった 深層学習の->登場と->登場により->行った->なった 登場と->登場により->行った->なった 2010年代->以降の->ビッグデータの->登場により->行った->なった 以降の->ビッグデータの->登場により->行った->なった ビッグデータの->登場により->行った->なった
49.名詞間の係り受けパスの抽出
「文中のすべての名詞句のペアを結ぶ最短係り受けパスを抽出せよ.ただし,名詞句ペアの文節番号がiとj(i
〇文節iとjに含まれる名詞句はそれぞれ,XとYに置換する
〇文節iから構文木の根に至る経路上に文節jが存在する場合: 文節iから文節jのパスを表示
〇上記以外で,文節iと文節jから構文木の根に至る経路上で共通の文節kで交わる場合: 文節iから文節kに至る直前のパスと文節jから文節kに至る直前までのパス,文節kの内容を” | “で連結して表示」
from itertools import combinations import re s = s_list[5] nouns = [] for i, chunk in enumerate(s): if '名詞' in [morph.pos for morph in chunk.morphs]: nouns.append(i) for i, j in combinations(nouns, 2): path_i = [] path_j = [] while i != j: if i < j: path_i.append(i) i = s[i].dst else: path_j.append(j) j = s[j].dst if len(path_j) == 0: chunk_X = ''.join([morph.surface if morph.pos != '名詞' else 'X' for morph in s[path_i[0]].morphs]) chunk_Y = ''.join([morph.surface if morph.pos != '名詞' else 'Y' for morph in s[i].morphs]) chunk_X = re.sub('X+', 'X', chunk_X) chunk_Y = re.sub('Y+', 'Y', chunk_Y) path_XtoY = [chunk_X] + [''.join(morph.surface for morph in s[n].morphs) for n in path_i[1:]] + [chunk_Y] print(' -> '.join(path_XtoY)) else: # 2つ目のケース chunk_X = ''.join([morph.surface if morph.pos != '名詞' else 'X' for morph in s[path_i[0]].morphs]) chunk_Y = ''.join([morph.surface if morph.pos != '名詞' else 'Y' for morph in s[path_j[0]].morphs]) chunk_k = ''.join([morph.surface for morph in s[i].morphs]) chunk_X = re.sub('X+', 'X', chunk_X) chunk_Y = re.sub('Y+', 'Y', chunk_Y) path_X = [chunk_X] + [''.join(morph.surface for morph in s[n].morphs) for n in path_i[1:]] path_Y = [chunk_Y] + [''.join(morph.surface for morph in s[n].morphs) for n in path_j[1:]] print(' | '.join([' -> '.join(path_X), ' -> '.join(path_Y), chunk_k]))
##結果(一部抜粋)
Xの -> Y
Xの -> ディープラーニング | (Y)の | 登場と
Xの -> ディープラーニング -> Yと
Xの -> ディープラーニング -> 登場と | Y -> 以降の -> ビッグデータの | 登場により、
Xの -> ディープラーニング -> 登場と | Yの -> ビッグデータの | 登場により、
Xの -> ディープラーニング -> 登場と | Yの | 登場により、
Xの -> ディープラーニング -> 登場と -> Yにより、
Xの -> ディープラーニング -> 登場と -> 登場により、 | Yの -> 流行を -> 超えて -> 浸透して | 行った。
Xの -> ディープラーニング -> 登場と -> 登場により、 | Yを -> 超えて -> 浸透して | 行った。
Xの -> ディープラーニング -> 登場と -> 登場により、 | Yに -> 浸透して | 行った。
Xの -> ディープラーニング -> 登場と -> 登場により、 | Yして | 行った。
ここまでご覧いただきありがとうございます。
以上、第5章終了です!