🐍
GiNZAを利用して、主語・述語・目的語、修飾被修飾関係などを抽出する
環境
WSL 2
Python 3.10.12
pip 23.3.1
GiNZA インストール(コマンド)
以下でspacyも入ります。
pip install -U ginza
私の場合、spacy 3.6.1、ginza 5.1.3でした。
主語・述語を出す
以下のコードで、主語・述語を出すことができます。
引用したコード
import spacy def parse_document(sentence, nlp): doc = nlp(sentence) tokens = [] for sent in doc.sents: for token in sent: tokens.append(token) subject_list = [] for token in tokens: ## 依存関係ラベルがnsubj=>「<見出し語>:<係り先の見出し語>」をリストに追加する。 if token.dep_ in ["nsubj", "iobj"]: subject_list.append(f"{token.lemma_}:{tokens[token.head.i].lemma_}") return subject_list ## ここからメイン nlp = spacy.load('ja_ginza') print(parse_document("昨日から胃がキリキリと痛い。ただ、熱は無い。", nlp))
Output
['胃:痛い', '熱:無い']
参考
修飾・被修飾関係を出す
以下のコードで、係り受け解析できます。
dep = DependencyAnalysis() res = dep.analyze('チーム開発を通して生徒同士の交流を図っています。') for r in res: print(f'{r[0]} → {r[1]}')
引用したコード(DependencyAnalysis())
import spacy import ginza import codecs class DependencyAnalysis: def __init__(self): """ コンストラクタ """ self.nlp = spacy.load("ja_ginza_electra") self.document = None def read_file(self,filename,encoding='utf-8'): ''' ファイルの読み込み Parameters: -------- filename : str 分析対象のファイル名 ''' with codecs.open(filename,'r',encoding,'ignore') as f: self.read_text(f.read()) def read_text(self,text): ''' テキストの読み込み Parameters: -------- text : str 分析対象のテキスト ''' self.document = text def analyze(self,text = None,mode = 0): ''' 係り受け結果を主辞(文節で一番重要な単語)で出力 Parameters: -------- mode : int 0=通常の係り受け 1:係り受けされる側(左)のみに主辞を適用 2: 両方に主辞を適用 ''' ret = [] # mode が 1以下の場合、通常の係り受け関数、2の場合は主辞の関数を使用する func = ginza.bunsetu_spans if mode <= 1 else ginza.bunsetu_phrase_spans # 引数があればそれを、Noneの場合はインスタンス変数の self.textを使う doc = self.nlp(self.document if text == None else text) # 文書から一文を取り出す for sentence in doc.sents: # 係り受けの関数を適用 for span in func(sentence): # 係り受け解析結果を取り出す for token in span.lefts: # modeが 1 の場合のみ、係り受け元を文節として取り出す。(例 mode=0 or 2:交流を mode=1:交流) key = token if mode >= 1 else ginza.bunsetu_span(token) # 結果を辞書に登録 ret.append((str(key),str(span))) return ret
参考
目的語を出す
import spacy from spacy.symbols import obj nlp = spacy.load('ja_ginza') # モデルをロード doc = nlp('私は猫を撫でた') # 文章を解析 for tok in doc: if tok.dep == obj: # トークンが目的語なら print(tok.text) # テキストを表示
Output
猫
参考
まとめ
今回は、GiNZAを用いて、係り受け解析などをしたので、それを備忘録としてまとめました。
obj以外のパラメータについて、以下のノートに詳しく載っていたので、参考にどうぞ。
Discussion