じぶんメモ

プログラミングのメモ、日常のメモとか。

n-gramによる文章の類似率を求める

N-gramとは、テキストで隣り合ったN文字のことを示す。
以下では2つ文章を指定された文字数で分割し、2つの文章間で分割した文字がどれだけマッチするかの頻度から、2つの文章の類似率を求める。

def ngram(str, num):
    res  = []
    slen = len(str) - num + 1
    for i in range(slen):
        extract_str = str[i:i+num]
        res.append(extract_str)
    return res

# 2つの文章の類似率を調べる
def diff_ngram(str1, str2, num):
    str1_ngram   = ngram(str1, num)
    str2_ngram   = ngram(str2, num)
    match_result = []
    count        = 0
    for str1_unit in str1_ngram:
        for str2_unit in str2_ngram:
            if str1_unit == str2_unit:
                count += 1
                match_result.append(str1_unit)
    return count / len(str1_ngram), match_result

# 2つの文章がどれだけ似ているかテストする
# 文字の分割を2文字ごと3文字ごとにして調べる。
a = '今日、渋谷で美味しいトンカツを食べた。'
b = '渋谷で食べた今日のトンカツは美味しかった。'

result2, word_list2 = diff_ngram(a, b, 2)
result3, word_list3 = diff_ngram(a, b, 3)

print('2-gram:', result2, word_list2)
print('3-gram:', result3, word_list3)

# 2-gram: 0.6111111111111112 ['今日', '渋谷', '谷で', '美味', '味し', 'トン', 'ンカ', 'カツ', '食べ', 'べた', 'た。']
# 3-gram: 0.29411764705882354 ['渋谷で', '美味し', 'トンカ', 'ンカツ', '食べた']

これだと単純な接続詞とかでもヒットしてしまうのであまり精度は高く無い気がする。 もっと本格的に文章解析するならば、RNNやLSTMに手をつかけるのがいいのかな。。。