2012-07-16 12 views
12

これはコーディング固有の問題ではありませんが、これはそのような質問をするのに最適な場所だと私は知っています。ユーザーベースのフィルタリング:推奨システム

私は10をリストアップし、以下のような辞書を与えていると仮定し、私は同様のlikes.Orを持っている人は多分二人はそれが可能になるmost.Also似ている者を決定するにはどうすればよい

likes={ 
    "rajat":{"music","x-men","programming","hindi","english","himesh","lil wayne","rap","travelling","coding"}, 
    "steve":{"travelling","pop","hanging out","friends","facebook","tv","skating","religion","english","chocolate"}, 
    "toby":{"programming","pop","rap","gardens","flowers","birthday","tv","summer","youtube","eminem"}, 
    "ravi":{"skating","opera","sony","apple","iphone","music","winter","mango shake","heart","microsoft"}, 
    "katy":{"music","pics","guitar","glamour","paris","fun","lip sticks","cute guys","rap","winter"}, 
    "paul":{"office","women","dress","casuals","action movies","fun","public speaking","microsoft","developer"}, 
    "sheila":{"heart","beach","summer","laptops","youtube","movies","hindi","english","cute guys","love"}, 
    "saif":{"women","beach","laptops","movies","himesh","world","earth","rap","fun","eminem"} 
    "mark":{"pilgrimage","programming","house","world","books","country music","bob","tom hanks","beauty","tigers"}, 
    "stuart":{"rap","smart girls","music","wrestling","brock lesnar","country music","public speaking","women","coding","iphone"}, 
    "grover":{"skating","mountaineering","racing","athletics","sports","adidas","nike","women","apple","pop"}, 
    "anita":{"heart","sunidhi","hindi","love","love songs","cooking","adidas","beach","travelling","flowers"}, 
    "kelly":{"travelling","comedy","tv","facebook","youtube","cooking","horror","movies","dublin","animals"}, 
    "dino":{"women","games","xbox","x-men","assassin's creed","pop","rap","opera","need for speed","jeans"}, 
    "priya":{"heart","mountaineering","sky diving","sony","apple","pop","perfumes","luxury","eminem","lil wayne"}, 
    "brenda":{"cute guys","xbox","shower","beach","summer","english","french","country music","office","birds"} 
} 

人それぞれの項目を気に入ってユーザーベースまたはアイテムベースのフィルタリングに関する適切なサンプルまたはチュートリアルを参照できる場合に役立ちます。

+1

これは、Programming Collective Intelligenceの[Chapter 2](http://books.google.co.uk/books?id=fEsZ3Ey-Hq4C&lpg=PP1&pg=PA7#v=onepage&q=false)によってかなり包括的に網羅されています。コード例はPythonであり、もう一つのプラスです。 –

+0

私はこの本を知っていますが、それは非常に古く(2007年に公開されています)、Webは大きく変化しています。この本の例のほとんどが今日はうまくいくとは思いません。 –

+4

基本的なテクニックはまだありません。あなたがもっと複​​雑でスケーラブルなものを探しているなら、あなたの質問に言及したいかもしれません。また、あなたが試したことや考えたことに言及する価値があるかもしれません。 –

答えて

10

を行うには良い方法があるに違いありません(免責事項が、私はこの分野で熟達していないですし、唯一の集団フィルタリングの通過の知識を持っている。以下は、単に私が有用であることが判明しているリソースの集合です)

Chapter 2 of the "Programming Collective Intelligence" bookには、これの基本が完全に網羅されています。コード例はPythonであり、もう一つのプラスです。

また、このサイトは便利かもしれない - A Programmer's Guide to Data Mining、特定のChapter 2Chapter 3に推薦システムとアイテムベースのフィルタリングを説明しています。つまり、Pearson Correlation Coefficient,Cosine Similarity,k-nearest neighboursなどを計算するなどの技術を使用して、好き/購入/投票したアイテムに基づいてユーザー間の類似性を判断することができます。

この目的のために書かれたさまざまなPythonライブラリがあります。 pysuggest,Crab,python-recsysおよびSciPy.stats.stats.pearsonr

ユーザー数がアイテム数を超えている大規模なデータセットの場合、データを逆転させてアイテム間の相関関係を計算する(アイテムベースのフィルタリングなど)ことでソリューションを拡張し、類似ユーザーを推測する。当然のことながら、これをリアルタイムで実行するのではなく、定期的な再計算をバックエンドタスクとしてスケジュールします。いくつかのアプローチを並列化/分散して、計算時間を大幅に短縮することができます(リソースを持っていると仮定して)。

1

私が考えることができる最も基本的なアプローチは、各人の好きな人のリストの間の交差点を見つけることです。最も好きなものに一致する2人は交差点の数が最も多くなります。

list(set(list1).intersection(list2))のようなものを使用できます。これは、交差点を定義する項目を含むリストを返します。

このアプローチでは、各ユーザーの好きなものを他のものと比較する必要があるため、その数が多くなるとうまく調整できないことに注意してください。約O(n^2)ユーザー数です。あなたのコメントの一部で

あなたは協調フィルタリングに言及し、それは通常、異なるユーザーによってランク付け同じのアイテムを持って、その後、順位との類似点を見つけるに適用されるので、あなたがにランクいくつかのアイテムを持っているユーザーのために外挿することができます同様の方法ですが、他の方法はありません(ここでは、他の項目と同様のランクを与えたユーザーのランクを使用します)。私はそれがまったく同じ問題だとは思わない。

3

SequenceMatcherdifflibは、この種のものに役立ちます。もしratio()を使用する場合には、ドキュメントから、2つの配列間の類似性に対応する0と1の間の値を返す:

戻り範囲のfloatとして配列類似性の尺度[0,1] 。 ここで、Tは両方のシーケンスの要素の合計数であり、Mは の一致数であり、これは2.0 * M/Tです。 のシーケンスが同一の場合は1.0で、何も共通しない場合は0.0です。 、唯一'rajat'みんなに対しての比較、([]ための内部{}を切り替えることにより、辞書に修正)あなたの例から

import difflib 
for key in likes: 
    print 'rajat', key, difflib.SequenceMatcher(None,likes['rajat'],likes[key]).ratio() 
#Output: 
rajat sheila 0.2 
rajat katy 0.2 
rajat brenda 0.1 
rajat saif 0.2 
rajat dino 0.2 
rajat toby 0.2 
rajat mark 0.1 
rajat steve 0.1 
rajat priya 0.1 
rajat grover 0.0 
rajat ravi 0.1 
rajat rajat 1.0 
rajat stuart 0.2 
rajat kelly 0.1 
rajat paul 0.0 
rajat anita 0.2 
+0

ありがとうございましたが、私は "共同フィルタリング"のようなものを探しています。 –

0
for k in likes: 
    if likes["rajat"] & likes[k]: 
     print k, likes["rajat"] & likes[k] 
    else: 
     print k, " No Like with rajat" 

Output 

sheila set(['hindi', 'english']) 
katy set(['music', 'rap']) 
brenda set(['english']) 
saif set(['himesh', 'rap']) 
dino set(['x-men', 'rap']) 
toby set(['programming', 'rap']) 
mark set(['programming']) 
steve set(['travelling', 'english']) 
priya set(['lil wayne']) 
grover No Likes with rajat 
ravi set(['music']) 
rajat set(['lil wayne', 'x-men', 'himesh', 'coding', 'programming', 'music', 'hindi', 'rap', 'english', 'travelling']) 
stuart set(['music', 'coding', 'rap']) 
kelly set(['travelling']) 
paul No Likes with rajat 
anita set(['travelling', 'hindi']) 

これは "rajat" のように共通の比較ですdictの他のメンバーと一緒に。この

7

のpython recsysライブラリ[http://ocelma.net/software/python-recsys/build/html/quickstart.html]

from recsys.algorithm.factorize import SVD 
from recsys.datamodel.data import Data 

likes={ 
    "rajat":{"music","x-men","programming","hindi","english","himesh","lil wayne","rap","travelling","coding"}, 
    "steve":{"travelling","pop","hanging out","friends","facebook","tv","skating","religion","english","chocolate"}, 
    "toby":{"programming","pop","rap","gardens","flowers","birthday","tv","summer","youtube","eminem"}, 
    "ravi":{"skating","opera","sony","apple","iphone","music","winter","mango shake","heart","microsoft"}, 
    "katy":{"music","pics","guitar","glamour","paris","fun","lip sticks","cute guys","rap","winter"}, 
    "paul":{"office","women","dress","casuals","action movies","fun","public speaking","microsoft","developer"}, 
    "sheila":{"heart","beach","summer","laptops","youtube","movies","hindi","english","cute guys","love"}, 
    "saif":{"women","beach","laptops","movies","himesh","world","earth","rap","fun","eminem"}, 
    "mark":{"pilgrimage","programming","house","world","books","country music","bob","tom hanks","beauty","tigers"}, 
    "stuart":{"rap","smart girls","music","wrestling","brock lesnar","country music","public speaking","women","coding","iphone"}, 
    "grover":{"skating","mountaineering","racing","athletics","sports","adidas","nike","women","apple","pop"}, 
    "anita":{"heart","sunidhi","hindi","love","love songs","cooking","adidas","beach","travelling","flowers"}, 
    "kelly":{"travelling","comedy","tv","facebook","youtube","cooking","horror","movies","dublin","animals"}, 
    "dino":{"women","games","xbox","x-men","assassin's creed","pop","rap","opera","need for speed","jeans"}, 
    "priya":{"heart","mountaineering","sky diving","sony","apple","pop","perfumes","luxury","eminem","lil wayne"}, 
    "brenda":{"cute guys","xbox","shower","beach","summer","english","french","country music","office","birds"} 
} 

data = Data() 
VALUE = 1.0 
for username in likes: 
    for user_likes in likes[username]: 
     data.add_tuple((VALUE, username, user_likes)) # Tuple format is: <value, row, column> 

svd = SVD() 
svd.set_data(data) 
k = 5 # Usually, in a real dataset, you should set a higher number, e.g. 100 
svd.compute(k=k, min_values=3, pre_normalize=None, mean_center=False, post_normalize=True) 

svd.similar('sheila') 
svd.similar('rajat') 

結果を用いて、溶液:

In [11]: svd.similar('sheila') 
Out[11]: 
[('sheila', 0.99999999999999978), 
('brenda', 0.94929845546505753), 
('anita', 0.85943494201162518), 
('kelly', 0.53385495931440263), 
('saif', 0.39985366653259058), 
('rajat', 0.30757664244952165), 
('toby', 0.28541364367155014), 
('priya', 0.26184289111194581), 
('steve', 0.25043700194182622), 
('katy', 0.21812807229358305)] 

In [12]: svd.similar('rajat') 
Out[12]: 
[('rajat', 1.0000000000000004), 
('mark', 0.89164019482177692), 
('katy', 0.65207273451425907), 
('stuart', 0.61675507205285718), 
('steve', 0.55730648750670264), 
('anita', 0.49836982296014803), 
('brenda', 0.42759524471725929), 
('kelly', 0.40436047539358799), 
('toby', 0.35972227835054826), 
('ravi', 0.31113813325818901)] 
+0

ありがとう!私はこれのようなものをしばらく探していた – nickromano

+0

すばらしい図書館! (私はあなたが作者であることに気付きます)。しかし、Python 3との互換性はありません。 – Siddhartha

0

一つも使用することができ、ユーザベースのフィルタリングを行うにscikitを学習:

単純撮影をたとえば、次のような場合:

以下のようなあなたの余弦行列を与える

"toby:{"hip-hop","pop","rap"}

あなたがsklearnのペアごとのコサイン類似の機能を使用することができ、

from sklearn.feature_extraction.text import CountVectorizer 
from sklearn.metrics.pairwise import cosine_similarity 

vec = CountVectorizer(analyzer='char') 
vec.fit(stuart_list) 

x = cosine_similarity(vec.transform(toby_list), 
       vec.transform(stuart_list)) 

とあなたが彼の音楽の好みの類似性を検討したいです。

[[ 0.166 0.327 1] 
[ 0.123 0.267 0.230]] 

最初の行はtobyの選択のすべて3つとrapのコサイン類似性を表します。適切な三角法の意味での完全な類似性を表す1に注目すると、2つのオプションが0度の角度を持つ(すなわち同一である)ことを意味するので、1のコサインを有する。

第2列は同様にrockのコサイントビーの選択肢の3つすべてと類似点。

sklearnの2つのリスト間の全体的な類似性を見つける方法が見つかりませんでしたが、コサイン行列を仮定すると、1の数を数えて類似点の数にすることができます。または、「ヒップホップ」や「ヒップホップ」のようなほぼ同じ言葉を扱うために、0.9秒以上をカウントすることができます。

(Sklearnはまた、コサイン類似性の代替物として使用することができるユークリッド類似性を有する。)