Jaccard指数を使ったリコメンドシステムをPythonで書いてみた
Posted on Mon, 05 May 2014 12:55:10 +0900
Hacker Newsあたりに流れてておもしろそうだったので、Pythonで書いてみました。 元の記事は以下です。
Simple recommendation system written in Ruby
Jaccard(ジャッカード)指数は サンプル群間の類似度を比較するためのものとのこと 。 A集合とB集合で、AとBの両方に出現ものを分子、AとBのどちらかに出現するものを分母として算出します。 Pythonを使うと set.intersection と set.union で表現できます。
日本語の単語抽出には mecab を使いました。
# coding: utf-8 import re import MeCab class Book(object): def __init__(self, title): self.title = title # original #self.words = [t.lower() for t in set(title.split()) if re.match("[a-zA-Z]{3,}", t)] # use mecab tagger = MeCab.Tagger('-Owakati') node = tagger.parseToNode(self.title) nodes = set() while node: if len(node.surface) < 3: node = node.next continue nodes.update(node.surface) node = node.next self.words = nodes class BookRecommender(object): def __init__(self, book, books): self.book = book self.books = books def recommendations(self): for book in self.books: intersection = len(set(self.book.words).intersection(book.words)) union = len(set(self.book.words).union(book.words)) try: book.jaccard_index = float(intersection) / union except ZeroDivisionError: book.jaccard_index = 0.0 self.books.sort(key=lambda b: 1 - b.jaccard_index) return self.books DATA = """\ Go言語入門 初めてのPython 継続的デリバリー 「レベルアップ」のゲームデザイン プログラミングRuby パーフェクトPython Finding the best language for the job Could Ruby save the day Python will rock your world Is Ruby better than Python Programming in Ruby is fun Python to the moon Programming languages of the future """ target_book = Book("Pythonチュートリアル") books = [Book(t) for t in DATA.splitlines()] br = BookRecommender(target_book, books) for b in br.recommendations(): print("%s: %.2f" % (b.title, b.jaccard_index))
以下実行結果
0.55 パーフェクトPython 0.50 初めてのPython 0.33 Python to the moon 0.27 Is Ruby better than Python 0.25 Python will rock your world 0.24 「レベルアップ」のゲームデザイン 0.19 Programming languages of the future 0.17 継続的デリバリー 0.16 プログラミングRuby 0.16 Programming in Ruby is fun 0.15 Could Ruby save the day 0.14 Finding the best language for the job 0.08 Go言語入門
シンプルですが結構強力ですね。