Screaming Loud

日々是精進

Pythonで実装する類似度計算

A = {"みかん":5,"りんご":8,"ぶどう":2}
B = {"みかん":5,"なし":8,"ぶどう":2,"もも":1}
辞書の要素は{単語:その出現頻度}という構成です.

この2つのベクトルの類似度を計算する尺度を紹介する.
PMIなど共起についての尺度は使わず,単純なベクトルの比較を行うものです.

コサイン類似度 (cosine similarity)

頻度を考慮した類似度計算.
よく使われる.

import math

def dotProduct(dicX,dicY):
    '''return a dot product.'''
    sum = 0
    for key in dicX:
        if key in dicY:
            sum += float(dicX[key])*float(dicY[key])
    return sum

def root_squareSum(vector):
    """the root of the sum of squares"""
    return math.sqrt(sum([int(x)**2 for x in vector]))

def cosineSim(dicX,dicY):
    """this is a main"""
    if dicX=={} or dicY=={}:
        return 0
    upper = dotProduct(dicX,dicY)
    bottom = root_powerSum(dicX.values()) * root_powerSum(dicY.values())
    return float(upper)/bottom

print cosineSim(A, B)

ジャカード係数 (Jaccard similarity Coefficient)

言語処理ではよく使われる.
コサイン類似度と違い,集合を計算する

def jaccardSim(dicX,dicY):
    if dicX=={} or dicY=={}:
        return 0
    setX = set(dicX.keys())
    setY = set(dicY.keys())
    upper = len(setX&setY)
    bottom = len(setX|setY)
    if bottom!=0:
        return float(upper)/bottom
    else:
        return 0

print jaccardSim(A, B)

シンプソン係数 (Simpson similarity coefficient)

ジャカード係数と同じく集合から計算.

def simpsonSim(dicX,dicY):
    if dicX=={} or dicY=={}:
        return 0
    setX = set(dicX.keys())
    setY = set(dicY.keys())
    upper = len(setX&setY)
    bottom = min(len(setX),len(setY))
    return float(upper)/bottom

Match coefficient

日本語読みがあるかわかりません.
これは単純に共通部分をとっているだけです.

def matchCoeff(dicX,dicY):
    setX = set(dicX.keys())
    setY = set(dicY.keys())
    return len(setX&setY)

更に詳しい共起に関する論文はこちら
CiNii 論文 -  共起に基づく類似性尺度(<特集>自然言語とコンピュータ)