📚

レコメンドシステム—— Item2Vec (GensimでEmbeddingをトレーニング)

2023/09/26に公開

はじめに

Item2Vecとは、文章から単語の分散表現を獲得するWord2Vecを推薦システムに適用した技術です。具体的にECサイトでの推薦を考えたときに、Word2Vecの単語を商品に、文章をユーザが評価したアイテム集合として、アイテムの分散表現を獲得し、アイテム間の類似度などをもとに推薦していく感じです。

Item2Vecに関する詳細な紹介は下記のリンクで読んでください。
https://qiita.com/dcm_kkubota/items/4c0a87e3a947c2f3e14b

本記事はGensimというPython Libを使ってアイテムのEmbeddingを作成することに紹介したいと思います。

コード実例

インストール

pip install gensim

gensimにはword2vec、doc2vecなどのモデルが実装されていますが、word2vecにはCBOW(Continuous bag-of-words)とskip-gramの2つのモデルがあります。

データ前処理

Libの導入

import logging
import os
import gensim
from gensim.models import word2vec

# All the data could be downloaded from: https://1drv.ms/f/s!Ao2ItRTtXaxehiA2DdroBpFMIqL_

from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
import nltk
## Need to download packages in advance.
# nltk.download('all')

article = open("/Users/hayden/Documents/data/1984.txt","r").read()

token_list = []
sentence = nltk.sent_tokenize(article)

for s in sentence:
    words = nltk.word_tokenize(s)
    token_list.append(words)

## Split with blank simplely.
# sentences = word2vec.LineSentence('data/1984.txt') 

len(token_list)
token_list[100]

6702
['This', 'was', 'not', 'illegal', '(', 'nothing', 'was', 'illegal', ',' , 'since', 'there', 'were', 'no','longer', 'any','laws',')', ',', 'but', 'if', 'detected', 'it', 'was', 'reasonably', 'certain', 'that', 'it', 'would', 'be', 'punished', 'by', 'death', ',', 'or', 'at', 'least', 'by', 'twenty-five', 'years', 'in', 'a', 'forced-labour', 'camp', '.']

token_listは二次元のリストになり、sentencesとwordsということです。

モデルのトレーニング

model = word2vec.Word2Vec(token_list, sg=0,hs=1,min_count=4,window=10,vector_size=50,workers=4)

gensimパラメーター解釈:

  • sentencesの1つ目のパラメータは前処理されたトレーニングコーパスです反復可能なリストですが、より大きなコーパスの場合、ディスク/ネットワークから直接文を送る反復が考えられます。
  • sg=1はskip-gramであり;デフォルトはsg=0、CBOWであり。
  • size(int)は出力語ベクトルの次元で、デフォルトは100です。この次元の取り方はテキストの大きさに関係していて、例えばテキストテキストの100M未満の場合はデフォルト値を使えばいいのが普通です。大きな語句の場合は次元を大きくすることをお勧めします。値が小さすぎるとワードマップが衝突して結果に影響を与え、大きすぎるとメモリが消耗してアルゴリズムの計算が遅くなります。一般的な値は100から200の間ですが、300次元のものも多く見られます。
  • window (int)は文の中の現在の単語と予測される単語の間の最大距離で、windowが大きければ大きいほど、ある単語から遠い単語にも文脈関係が生じます。デフォルトは5です。windowsが大きくなればなるほどエニュメレートの予測が多くなり、計算に時間がかかります。
  • min countはそれ以下の頻度の単語をすべて無視します。デフォルトは5です。
  • workersはワードベクトルをトレーニングする際に使用するスレッド数を表し、デフォルトは現在実行しているマシンのプロセッサコア数です。
  • サンプリングと学習率についても、一般的にはあまり設定されていないnegativeとsampleは、トレーニングの結果に応じて微調整することができます。sampleは、より高い頻度の単語がランダムに設定されたしきい値にサンプリングされることを表します。hs=1はsoftmaxレベルが使用されることを意味し、デフォルトhs=0でnegativeがゼロでない場合、負のサンプルが選択されて使用されます。

詳細の説明は下記のオフィシャルサイトに見てください。
https://radimrehurek.com/gensim/models/word2vec.html

Embeddingの扱い

アイテムのEmbedding

model.wv['you']

array([-0.5462636 , 1.4320626 , -0.4568431 , 0.8021699 , -0.5455619 ,
-0.05609033, -0.7483306 , -0.00387839, -1.1634578 , 0.49402925,
1.451362 , -1.026659 , 1.5925962 , 0.50039256, -0.68487597,
-0.5655675 , 0.04943949, 1.0824729 , -0.9539901 , 0.93983656,
0.92929626, 0.34397632, 1.6380502 , 1.0974818 , 0.8904612 ,
0.5492748 , -0.1004713 , -1.436136 , 1.1982089 , 2.9891722 ,
-1.6135296 , -1.8696574 , -0.02344712, -1.6066076 , -1.219439 ,
1.5865974 , 0.97423553, 0.0551686 , 0.33960804, -0.22320561,
3.0165079 , -0.49505797, -0.22032976, 0.91331065, 1.4776955 ,
-0.7764727 , 1.0840627 , -0.6499999 , 0.98748434, -0.6491677 ],
dtype=float32)

Top Nのアイテム

model.wv.most_similar('you', topn =10)

[('want', 0.9507809281349182),
('You', 0.9488500952720642),
('we', 0.945176899433136),
('say', 0.9215162992477417),
('think', 0.9140624403953552),
('tell', 0.9118809700012207),
('suppose', 0.9098665118217468),
('I', 0.9038820862770081),
('?', 0.9027588367462158),
('do', 0.9024166464805603)]

類似度の計算

model.wv.similarity('country', 'you')

0.5865977

異なる種類のアイテムを選び出す

model.wv.doesnt_match("country political private you".split())

'you'

おわりに

Embeddingでリコール

Item2Vecは一般的にリコールの流れで使われています。特定のアイテムにTopNの候補者をEmbeddingの類似度で選択します。

リアルタイムではなるべく速くTopNを探します。そんな時はFaissというエンジンを使って、もしくはベクターデータベースを使います。

Item2Vecは複雑なアルゴリズムですが、今にもレコメンドシステムに幅広く使われています。

Discussion