networkX を使用した問題の解決策を次に示します。
このコードは、有向グラフ dG を生成します。dG は単語ごとに 1 つのノードを持ち、単語が何回見られたかを示す「count」属性を持ちます。バイグラムごとに 1 つの有向エッジがあり、バイグラムが発生した回数を示す「重み」属性があります。
import networkx as nx
import string
from sys import maxint
str1 = """Man who run in front of car, get tired.
Man who run behind car, get exhausted."""
wordList1 = str1.split(None)
wordList2 = [string.rstrip(x.lower(), ',.!?;') for x in wordList1]
dG = nx.DiGraph()
for i, word in enumerate(wordList2):
try:
next_word = wordList2[i + 1]
if not dG.has_node(word):
dG.add_node(word)
dG.node[word]['count'] = 1
else:
dG.node[word]['count'] += 1
if not dG.has_node(next_word):
dG.add_node(next_word)
dG.node[next_word]['count'] = 0
if not dG.has_edge(word, next_word):
dG.add_edge(word, next_word, weight=maxint - 1)
else:
dG.edge[word][next_word]['weight'] -= 1
except IndexError:
if not dG.has_node(word):
dG.add_node(word)
dG.node[word]['count'] = 1
else:
dG.node[word]['count'] += 1
except:
raise
グラフの内容を確認するには、ノードとエッジを印刷します。
for node in dG.nodes():
print '%s:%d\n' % (node, dG.node[node]['count'])
for edge in dG.edges():
print '%s:%d\n' % (edge, maxint - dG.edge[edge[0]][edge[1]]['weight'])
バイグラム エッジの重みは、ゼロからカウントアップするのではなく、maxint からカウントダウンすることに注意してください。これは、networkX の最短パス ユーティリティが重み値をエッジあたりのコストとして使用するためです。最大のカウントを最小の重みにすることで、これらのユーティリティを使用して、最大のエッジ カウントを持つパスを見つけることができます。
たとえば、「man」という単語と「exhausted」という単語の間のカウントが最大のパスを取得できます。
>>>shortest_path = nx.shortest_path(dG, source='man', target='exhausted', weight='weight')
>>>print shortest_path
['man', 'who', 'run', 'behind', 'car', 'get', 'exhausted']
または、「man」という単語と他のすべての単語の間のカウントが最も高いパスを取得できます。
>>>shortest_paths = nx.shortest_path(dG, source='man', weight='weight')
>>>print shortest_paths
{'run': ['man', 'who', 'run'],
'get': ['man', 'who', 'run', 'behind', 'car', 'get'],
'exhausted': ['man', 'who', 'run', 'behind', 'car', 'get', 'exhausted'],
'car': ['man', 'who', 'run', 'behind', 'car'],
'who': ['man', 'who'],
'behind': ['man', 'who', 'run', 'behind'],
'of': ['man', 'who', 'run', 'in', 'front', 'of'],
'in': ['man', 'who', 'run', 'in'],
'front': ['man', 'who', 'run', 'in', 'front'],
'tired': ['man', 'who', 'run', 'behind', 'car', 'get', 'tired'],
'man': ['man']}
上で述べたように、このようなグラフではサイクルが発生する可能性があり、networkx 最短パス アルゴリズムがそのケースをどの程度うまく処理できるかはわかりません。
幸運を!