【놀이】신카리온의 톤 데모 메일을 구문 분석
말했는지 말하지 않았는지 어느 쪽인지 제대로 기억하고 있지 않지만, 확실히 그동안 손으로 감아 파티를 했을 때에 조금 말한 생각이 들지 않아도 없어도 아마 말했잖아, 라고 여기까지 생각 했지만, 뭐라고 말하는 듯이 말하고 있어도 거기까지 문제 없지요, 라고 생각하게 된 나름입니다.
이 메일은 애니메이션으로 1 초 정도밖에 나오지 않고 제작 스탭의 장난기가 가득한 문장입니다.
이번에는 그 문장을 Cabocha를 사용해 구문 분석해 pydot로 표시했습니다.
하고 있는 것은 기사 「타키자와 카렌의 이해할 수 없는 문장을 언어 해석해 보았다.」 의 2번 달입니다.
구문 분석 결과
긴 문장만 있어 큰・・・ 생각보다 잘 해석할 수 있습니다. 보면 볼수록 끔찍한 글입니다.
출처
파이썬으로 쓰고 있습니다. 언어 처리 100개 노크 사이에 약간의 숨결으로 만들었습니다. 그 프로그램의 유용하기 때문에 조금 쓸데없는 부분이 있습니다. 기사 「아마추어의 언어 처리 100개 노크:44」 를 참고로 하겠습니다.
import re, CaboCha, pydot
class Morph:
def __init__(self, surface, pos):
self.surface = surface # 表層形(surface)
self.pos = pos # 品詞(pos)
class Chunk:
def __init__(self):
self.morphs = []
self.srcs = [] # 係り元文節インデックス番号のリスト
self.dst = -1 # 係り先文節インデックス番号(初期値:-1, 係り先がない場合は-1のまま)
def output_surface(self):
surface = ''
for morph in self.morphs:
# 記号を除外
if morph.pos != '記号':
surface += morph.surface
return surface
def parse_lines(tree_list):
chunks = dict() # idxをkeyにChunkを格納
for line in tree_list:
if line[:3] == 'EOS':
# Chunkのリストを返す
if len(chunks) > 0:
# chunksをkeyでソートし、valueのみ取り出し
sorted_tuple = sorted(chunks.items(), key=lambda x: x[0])
return list(zip(*sorted_tuple))[1] #[1]がリストのvalue部分
chunks.clear()
else:
return []
# 先頭が*の行は係り受け解析結果なので、Chunkを作成
elif line[0] == '*':
# Chunkのインデックス番号と係り先のインデックス番号取得
cols = re.split('\s|D', line)
idx = int(cols[1]) # Chunkのインデックス番号
dst = int(cols[2]) # 係り先文節インデックス番号
# Chunkを生成(なければ)し、係り先のインデックス番号セット
if idx not in chunks:
chunks[idx] = Chunk()
chunks[idx].dst = dst
# 係り先のChunkを生成(なければ)し、係り元インデックス番号追加
if dst != -1:
if dst not in chunks:
chunks[dst] = Chunk()
chunks[dst].srcs.append(idx) # 係り元は複数あるのでappend
else:
#タブとカンマで分割
cols = re.split('\t|,', line)
chunks[idx].morphs.append(Morph(
cols[0], # 表層形(surface)
cols[1] # 品詞(pos)
))
# 構文解析
parser = CaboCha.Parser()
tree = parser.parse('言ってあったか言ってなかったかどっちだったかちゃんと覚えていないけど、確かこの間手巻きパーティをやった時にちょこっと言った気がしなくもなきにしもあらずで多分言ったんじゃないかな、とココまで考えてみたけど、まあ言ってようが言っていまいがそこまで問題ないよね、と思うに至った次第です。')
#tree = parser.parse('今日の天気は晴れでしたが、明日の天気は悪くなるそうです。')
# Stringのlistに分解
tree_string = tree.toString(CaboCha.FORMAT_LATTICE)
tree_list = tree_string.splitlines()
# 係り受けを整理
chunks = parse_lines(tree_list)
# 係り先があるものをpydotに渡す形式に変更
edges = []
for i, chunk in enumerate(chunks):
if chunk.dst != -1:
# 記号を除いた表層形をチェック、空なら除外
src = chunk.output_surface()
dst = chunks[chunk.dst].output_surface()
if src != '' and dst != '':
edges.append(((i, src), (chunk.dst, dst)))
# pydotで有向グラフとして画像保存
if len(edges) > 0:
graph = pydot.graph_from_edges(edges, directed=True)
graph.write_png('result.png')
Reference
이 문제에 관하여(【놀이】신카리온의 톤 데모 메일을 구문 분석), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/FukuharaYohei/items/a781b0573d8fdf78b6b6
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
파이썬으로 쓰고 있습니다. 언어 처리 100개 노크 사이에 약간의 숨결으로 만들었습니다. 그 프로그램의 유용하기 때문에 조금 쓸데없는 부분이 있습니다. 기사 「아마추어의 언어 처리 100개 노크:44」 를 참고로 하겠습니다.
import re, CaboCha, pydot
class Morph:
def __init__(self, surface, pos):
self.surface = surface # 表層形(surface)
self.pos = pos # 品詞(pos)
class Chunk:
def __init__(self):
self.morphs = []
self.srcs = [] # 係り元文節インデックス番号のリスト
self.dst = -1 # 係り先文節インデックス番号(初期値:-1, 係り先がない場合は-1のまま)
def output_surface(self):
surface = ''
for morph in self.morphs:
# 記号を除外
if morph.pos != '記号':
surface += morph.surface
return surface
def parse_lines(tree_list):
chunks = dict() # idxをkeyにChunkを格納
for line in tree_list:
if line[:3] == 'EOS':
# Chunkのリストを返す
if len(chunks) > 0:
# chunksをkeyでソートし、valueのみ取り出し
sorted_tuple = sorted(chunks.items(), key=lambda x: x[0])
return list(zip(*sorted_tuple))[1] #[1]がリストのvalue部分
chunks.clear()
else:
return []
# 先頭が*の行は係り受け解析結果なので、Chunkを作成
elif line[0] == '*':
# Chunkのインデックス番号と係り先のインデックス番号取得
cols = re.split('\s|D', line)
idx = int(cols[1]) # Chunkのインデックス番号
dst = int(cols[2]) # 係り先文節インデックス番号
# Chunkを生成(なければ)し、係り先のインデックス番号セット
if idx not in chunks:
chunks[idx] = Chunk()
chunks[idx].dst = dst
# 係り先のChunkを生成(なければ)し、係り元インデックス番号追加
if dst != -1:
if dst not in chunks:
chunks[dst] = Chunk()
chunks[dst].srcs.append(idx) # 係り元は複数あるのでappend
else:
#タブとカンマで分割
cols = re.split('\t|,', line)
chunks[idx].morphs.append(Morph(
cols[0], # 表層形(surface)
cols[1] # 品詞(pos)
))
# 構文解析
parser = CaboCha.Parser()
tree = parser.parse('言ってあったか言ってなかったかどっちだったかちゃんと覚えていないけど、確かこの間手巻きパーティをやった時にちょこっと言った気がしなくもなきにしもあらずで多分言ったんじゃないかな、とココまで考えてみたけど、まあ言ってようが言っていまいがそこまで問題ないよね、と思うに至った次第です。')
#tree = parser.parse('今日の天気は晴れでしたが、明日の天気は悪くなるそうです。')
# Stringのlistに分解
tree_string = tree.toString(CaboCha.FORMAT_LATTICE)
tree_list = tree_string.splitlines()
# 係り受けを整理
chunks = parse_lines(tree_list)
# 係り先があるものをpydotに渡す形式に変更
edges = []
for i, chunk in enumerate(chunks):
if chunk.dst != -1:
# 記号を除いた表層形をチェック、空なら除外
src = chunk.output_surface()
dst = chunks[chunk.dst].output_surface()
if src != '' and dst != '':
edges.append(((i, src), (chunk.dst, dst)))
# pydotで有向グラフとして画像保存
if len(edges) > 0:
graph = pydot.graph_from_edges(edges, directed=True)
graph.write_png('result.png')
Reference
이 문제에 관하여(【놀이】신카리온의 톤 데모 메일을 구문 분석), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/FukuharaYohei/items/a781b0573d8fdf78b6b6텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)