##内容
これまでの流れで、入力のテキストデータを分割したものをノードに、分割したもの同士の母音の一致をエッジの重みにしてネットワーク分析を行ってみる。グラフの描写、中心性を見るところまでが目標。
##データを分割し、辞書を作る
from pykakasi import kakasi
import re
from collections import defaultdict
from janome.tokenizer import Tokenizer
with open("./gennama.txt","r") as f:
data = f.read()
tokenizer = Tokenizer()
tokens = tokenizer.tokenize(data)
surface_list = []
part_of_speech_list = []
for token in tokens:
surface_list.append(token.surface)
part_of_speech_list.append(token.part_of_speech.split(",")[0])
segment_text = []
for i in range(len(surface_list)):
if part_of_speech_list[i] == "記号":
continue
elif part_of_speech_list[i] == "助詞" or part_of_speech_list[i] == "助動詞":
row = segment_text.pop(-1) + surface_list[i]
else:
row = surface_list[i]
segment_text.append(row)
kakasi = kakasi()
kakasi.setMode('H', 'a')
kakasi.setMode('K', 'a')
kakasi.setMode('J', 'a')
conv = kakasi.getConverter()
text_data = [conv.do(text) for text in segment_text]
vowel_data = [re.sub(r"[^aeiou]+","",text) for text in text_data]
#{0:"oea"}
dic_vo = {k:v for k,v in enumerate(vowel_data)}
#voel_dataのインデックスで母音変換前のdataが分かるように辞書作成。{0:"俺は"}
dic = {k:v for k,v in enumerate(segment_text)}
part3でやったことを活用。今回はN-gramは向いていないと判断。この、dic_voのキーの数だけノードがあり、ノード間は母音の一致があるかどうかで繋がりを見る。母音が一致する長さが長いほど重みを付けるようにしておく。part1で作っていたような方法を使用するが、自身への繋がりと2文字以上の一致からエッジが出来るようにする。
##グラフを作る
#dic_voを渡し、インデックスがnode,値がedge,重みがscoreの(node,node,score)を作る。
def create_edge(dic_vo):
node_len = len(dic_vo)
edge_list = []
for i in range(node_len):
for j in range(node_len):
score = create_weight(dic_vo[i],dic_vo[j])
if score != 0:
edge_list.append((i,j,score))
return edge_list
def create_weight(word_a, word_b):
weight = 0
if len(word_a) > len(word_b):
max_len = len(word_b)
for i in range(max_len):
for j in range(max_len + 1):
if word_b[i:j] in word_a:
if word_b == word_a:
continue
elif len(word_b[i:j]) < 2:
continue
else:
weight += len(word_b[i:j])
else:
max_len = len(word_a)
for i in range(max_len):
for j in range(max_len + 1):
if word_a[i:j] in word_b:
if word_a == word_b:
continue
elif len(word_b[i:j]) < 2:
continue
else:
weight += len(word_a[i:j])
return weight
edge_list = create_edge(dic_vo)
あとはこのedge_listをもとにグラフを描写する。ついでに、固有ベクトル中心性と媒介中心性が高いノードを取得し、元のデータを表示してみる。
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
G.add_weighted_edges_from(edge_list)
pos = nx.spring_layout(G)
nx.draw_networkx_edges(G, pos)
plt.show()
#固有ベクトル中心性
cent = nx.eigenvector_centrality_numpy(G)
max_cent_node = max(list(cent.keys()), key=lambda val: cent[val])
#媒介中心性
between_cent = nx.communicability_betweenness_centrality(G, weight="weight)
max_betw_node = max(list(between_cent.keys()), key=lambda val: between_cent[val])
print("固有ベクトル中心性が高いのは:" + dic[max_cent_node])
print("媒介中心性が高いのは:" + dic[max_betw_node])
結果は予想通り、part2で行った「target_wordを絞れるのでは」と同じだ。まあ同じことをしているので当たり前だが、networkx
ではこのグラフを元にまだ出来ることがありそうなので追及してみる。
##今後の方針
スコアの付け方で、「い」と「う」に注目し、前の音が「e」と「o」ならば、つまり「eい」「oう」ならば「ee」「oo」と変換して母音の一致を見るというものを考えている。(外来語の発音を参考にした)日本語でもそれは聞き分けにくく、響きは同じだと言えるはずだ。ラップ界での押韻の扱いではNGだと思われるがやってみる。ちなみに皆さんは本場の「ABCの歌」を聞いたことがあるだろうか?「LMNOP」を「エレネノピー」と一気にいくあれだ。子供の頃から「韻」が身近にあるようだ。日本語ラップへのリスペクトは忘れないが、韻を少し拡張して捉えることを試みる