bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

コサイン類似度の計算

これをGoで書いてみたテスト。
【レコメンド】内容ベースと協調フィルタリングの長所と短所・実装方法まとめ - Qiita

ベクトルにできれば内積でどのくらい類似しているか分かるのは便利。

package main

import (
	"fmt"
	"math"
)

type Comedian struct {
	Name   string
	Values map[string]float64
}

//デバッグ用.
func (comedian Comedian) Dump() {
	fmt.Println(comedian.Name)
	fmt.Println(comedian.Values)
}

func Dot(m, n map[string]float64) (ret float64) {
	for mkey, mvalue := range m {
		nvalue, ok := n[mkey]
		if ok {
			ret += mvalue * nvalue
		}
	}
	return
}

func Length(m map[string]float64) (ret float64) {
	for _, mvalue := range m {
		ret += mvalue * mvalue
	}
	ret = math.Sqrt(ret)
	return
}

func CosineSimilarity(values1, values2 map[string]float64) (ret float64) {
	dot := Dot(values1, values2)
	length := Length(values1) * Length(values2)
	ret = dot / length
	return
}

func main() {
	m := map[string]float64{
		"京都":   0.131578947369,
		"漫才":   0.122807017544,
		"お笑い":  0.122807017544,
		"ラジオ":  0.105263157894,
		"吉本興業": 0.09649122807,
		"芸人":   0.09649122807,
		"いくよ":  0.0701754385966,
		"コンビ":  0.0701754385966,
		"大阪":   0.0526315789474,
		"名人":   0.0438596491229,
		"上方":   0.0438596491229,
		"花王":   0.0438596491229,
	}
	var ikuyo_kuruyo Comedian = Comedian{Name: "今いくよ・くるよ", Values: m}

	m = map[string]float64{
		"お笑い": 0.169014084507,
		"西野":  0.12676056338,
		"大阪":  0.112676056338,
		"ナダル": 0.0845070422536,
		"コンビ": 0.0845070422536,
		"優勝":  0.0704225352114,
		"コロコロチキチキペッパーズ": 0.0704225352114,
		"ネタ":       0.0704225352114,
		"芸人":       0.056338028169,
		"吉本興業":     0.056338028169,
		"漫才":       0.056338028169,
		"キングオブコント": 0.0422535211267,
	}
	var korochiki Comedian = Comedian{Name: "コロコロチキチキペッパーズ", Values: m}

	var similarity = CosineSimilarity(ikuyo_kuruyo.Values, korochiki.Values)
	fmt.Println(similarity)
}