Jaccard指数を使ったリコメンドシステムをPythonで書いてみた

Hacker Newsあたりに流れてておもしろそうだったので、Pythonで書いてみました。 元の記事は以下です。

Simple recommendation system written in Ruby

Jaccard(ジャッカード)指数は サンプル群間の類似度を比較するためのものとのこと 。 A集合とB集合で、AとBの両方に出現ものを分子、AとBのどちらかに出現するものを分母として算出します。 Pythonを使うと set.intersectionset.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言語入門

シンプルですが結構強力ですね。