2

音楽ライブラリの各アーティストの加重タグを含む辞書がたくさんあります。加重タグの辞書を指定して、より類似したアーティストを検索したいと思います (おそらく類似性評価もありますか?)。

例えば:

tags = {
    'grails': {
        'post-rock': 100,
        'instrumental': 53,
        'experimental': 38,
        'ambient': 30,
        'post rock': 14,
        'psychedelic': 11,
        'Psychedelic Rock': 6,
        'Progressive rock': 6,
        'rock': 4,
        'instrumental rock': 3,
        'atmospheric': 3,
        'american': 3,
        'space rock': 1
    },
    'camel': {
        'Progressive rock': 100,
        'classic rock': 28,
        'art rock': 24,
        'Progressive': 18,
        'rock': 17,
        'symphonic prog': 7,
        'british': 6,
        'Symphonic Rock': 4,
        'Canterbury Scene': 3,
        'prog rock': 3,
        'prog': 3,
        'Psychedelic Rock': 2,
        'space rock': 1
    },
    'mozart': {
        'Classical': 100,
        'mozart': 30,
        'instrumental': 21,
        'composers': 16,
        'opera': 13,
        'piano': 11,
        'Wolfgang Amadeus Mozart': 9,
        'symphonic': 9,
        'orchestral': 8,
        'austrian': 5
    }
    # etc.
}


best_matches({
            'Progressive rock': 100,
            'experimental': 33,
            'classic rock': 26,
            'Progressive': 23,
            'rock': 23,
            'art rock': 12,
            'psychedelic': 5,
            'prog rock': 5,
            'british': 5,
            'prog': 4,
            'Experimental Rock': 3,
            'Avant-Garde': 3,
            'Psychedelic Rock': 3,
            'Jazz Rock': 2
        }, tags)

# should output camel, then grails, then mozart

Slope One などのいくつかの推奨アルゴリズムについて聞いたことがありますが、Python でこの種の計算を行うためのより簡単な方法があるかどうか、また、これらすべての辞書を「比較」するための最速のアルゴリズムは何かと考えていました。

4

2 に答える 2

1

各タグをベクトル空間の次元として扱い、コサイン類似度を適用する必要があります。

例えば:

import numpy as np

def cosine_similarity(dict1, dict2):
    sim = float(sum([dict1[k] * dict2[k] for k in intersect(dict1,dict2)]))
    return sim / (norm_values(dict1) * norm_values(dict2))

def norm_values(dict):
    v = np.array(dict.values())
    return np.sqrt(np.sum(np.square(v)))

def intersect(dict1,dict2):
    return list(set(dict1.keys()) & set(dict2.keys()))

tags = {
    'grails': {
        'post-rock': 100,
        'instrumental': 53,
        'experimental': 38,
        'ambient': 30,
        'post rock': 14,
        'psychedelic': 11,
        'Psychedelic Rock': 6,
        'Progressive rock': 6,
        'rock': 4,
        'instrumental rock': 3,
        'atmospheric': 3,
        'american': 3,
        'space rock': 1
    },
    'camel': {
        'Progressive rock': 100,
        'classic rock': 28,
        'art rock': 24,
        'Progressive': 18,
        'rock': 17,
        'symphonic prog': 7,
        'british': 6,
        'Symphonic Rock': 4,
        'Canterbury Scene': 3,
        'prog rock': 3,
        'prog': 3,
        'Psychedelic Rock': 2,
        'space rock': 1
    },
    'mozart': {
        'Classical': 100,
        'mozart': 30,
        'instrumental': 21,
        'composers': 16,
        'opera': 13,
        'piano': 11,
        'Wolfgang Amadeus Mozart': 9,
        'symphonic': 9,
        'orchestral': 8,
        'austrian': 5
    }
}
query = {
    'Progressive rock': 100,
    'experimental': 33,
    'classic rock': 26,
    'Progressive': 23,
    'rock': 23,
    'art rock': 12,
    'psychedelic': 5,
    'prog rock': 5,
    'british': 5,
    'prog': 4,
    'Experimental Rock': 3,
    'Avant-Garde': 3,
    'Psychedelic Rock': 3,
    'Jazz Rock': 2
}

for t in tags:
    print "{}: {}".format(t, cosine_similarity(tags[t], query))

これにより、次が生成されます。

mozart: 0.0
grails: 0.141356488829
camel: 0.944080602442
于 2012-11-28T11:56:35.860 に答える