Item2Vec: 商品レコメンドの実装(関連性の学習とお勧め商品予測)
この記事では、単語をベクトル表現して類似性を捉えることができるWord2Vecの技術を応用し、商品レコメンドシステムを実装する方法について詳しく解説します。この技術を応用することで、ユーザーが購入した商品をベクトル化し、購入履歴に応じて商品をレコメンドするシステムを実装することが可能です。この記事では、Item2Vecの学習手順から、レコメンドする商品の予測する方法を解説します。
Word2Vecとは
Word2Vecとは
Word2Vecは、単語をベクトルとして表現するもので、ベクトル空間上位の距離により、単語の意味や関係性を捉えることが可能な手法です。
Word2Vecでは、単語(連続した単語列)を使って、単語の周辺に出現する単語の確率分布を予測することができます。つまり、意味的に似た単語はベクトル空間上で近くに配置されます。
Word2Vecには、CBOW(Continuous Bag of Words)とSkip-gramという2つの主要なモデルがあります。CBOWは、周囲の単語のコンテキストから中央の単語を予測するタスクを行うモデルであり、Skip-gramは中央の単語から周囲の単語を予測するモデルです(この記事ではWord2Vecの技術的な仕組みは省略します)。
Word2Vecを使えば、単語の類似性や、意味的な距離を簡単に調べることが可能で、自然言語処理分野で広く利用されています。
文章のベクトル表現は、sentence transformerを使って生成することもできます。sentence transformerについては以下の記事も参考にしてください。
Item2Vec
Item2Vecは、Word2Vecを使ってアイテム間(商品間)の類似性や関連性を学習する手法です。
Item2Vecでは、ユーザーの購買情報やアイテムレビューの情報を利用して、アイテム同士の類似性を見つけていきます。具体的には、例えば、ユーザーのアイテム購入履歴から、アイテムの関連性を学習させます。
この手法を使えば、Word2Vecのシステムを使って、商品レコメンデーションを行うことが可能となります。具体的には、「ユーザーの購入履歴に基づいて、関連商品を推薦するシステム」などを実装することが可能になります。
この記事では、実際にWord2Vecを使って学習させ、リコメンドを行ってみます。
おすすめの商品(商品レコメンド)を実装する
利用するデータセット
ここで利用するデータセットは、「オンラインストア購買データ」です。このデータには、以下のデータが含まれています。今回は、このデータのStockCode(商品コード)と、CustomerID(顧客ID)を利用します。
項目名 | 内容 |
---|---|
InvoiceNo | 基本は6桁の整数で、”c”から始まるコードはキャンセルを表す。 |
StockCode | 基本は5桁の整数だが、末尾にアルファベットが付くものもある。 |
Description | 商品の名称(商品コードと1:1に対応していないものもある) |
Quantity | 購入数量 |
InvoiceDate | トランザクションが生成された日時 |
UnitPrice | 一商品あたりの英貨 |
CustomerID | 5桁の整数で顧客の識別コード |
Country | 顧客が居住する国 |
データセットはいくつかの場所からダウンロードできますが、今回は、以下からダウンロードしました(kaggleのアカウントが必要となります)
Online Retail Data Set
https://www.kaggle.com/datasets/vijayuv/onlineretail
なお、以下の説明では、データセットはカレントディレクトリにOnlineRetail.csv
という名前で保存しているとします。
ライブラリのインポート
利用するライブラリをインポートしておきます。メインで利用するのはpandas
とgensim
のword2vec
です。
import pandas as pd
from gensim.models import word2vec
from tqdm import tqdm
import multiprocessing
顧客毎の購入リストを作成し、ファイルに保存する
顧客リストを読み込みます。
csv
ファイルのエンコーディングでエラーが出たのでencoding ="ISO-8859-1"
を指定しています。
また、CustomerID
に未定義(nan
)があるので、nan
の行を削除し、CustomerID
の型を整数型に変換しておきます。
df = pd.read_csv("OnlineRetail.csv", encoding ="ISO-8859-1")
df = df.dropna()
df['CustomerID'] = df['CustomerID'].astype('int')
読み込んだデータセットから、顧客(CustomerID
)ごとの購入商品リスト(StockCode
)を作成します。これには、groupby
を利用すると簡単です。
custdf = df.groupby('CustomerID').agg({"StockCode": list}).reset_index()
実行するとcustdf
は、以下のようなデータフレームになります。
Word2Vecに読み込ませるために、これをテキストファイルとして保存します。
# テキスト形式にして保存
with open('items.txt', 'w') as f:
for i in tqdm(range(len(custdf))) :
_, e = custdf.iloc[i]
l = " ".join(e)
f.write(l + '\n')
保存は、顧客IDを除いた商品リストになります。
Word2Vecで学習させるのは、ある顧客が購入した商品IDのリストです。ある顧客の購入した商品IDのリストをWord2Vecに渡すと、Word2Vecではこれを1つの文章として、単語(商品ID)間の距離を学習することができます。
つまり「ある顧客の購入した商品のリスト」を「1つの文章」としてWord2Vecに与えることで、ある商品に近い商品の確率分布を計算することができるようになるわけです(=類似商品を計算)
Word2Vecで学習する
Word2Vecで学習をさせるのは簡単です。num_of_cpus
は、実行環境のプロセッサ数です。これをworkers
に渡すことで、CPUのコアを全て使ったトレーニング可能になります(高速に処理できます)。もちろん、workers=1
として、1つのCPUコアで学習させることも可能です。
vector_size
は256次元に、window=1000
に設定しています。window
は周辺語として何単語まで考えるかという値ですが、今回はかなり大きく設定しています(商品列の並びについて関係がほとんどないため)。
num_of_cpus = multiprocessing.cpu_count()
sentences = word2vec.LineSentence('items.txt')
model = word2vec.Word2Vec(sentences,
vector_size=256,
window=1000,
seed=42,
min_count=1,
workers=num_of_cpus)
学習には少し時間がかかります(上記のコード実行には少し時間がかかります)。
以下は、学習したモデルの保存と読み込み方法です。保存はsave
、読み込みはload
で行うことが可能です。
model.save("word2vec.model")
model = word2vec.Word2Vec.load("word2vec.model")
選択された商品に対して、おすすめ商品を推測する
ある商品(商品ID=22356)を選んだ場合に、おすすめな商品を推測するコードです。
おすすめ商品というより、「この商品を購入した方は、こちらの商品も購入しています」という商品を推測するといった方がわかりやすいかもしれません。
これには、wv.most_similar
関数を使います。topn
は、上位何個まで出力するかです。
ret = ret = model.wv.most_similar('22356', topn=10)
for id, prob in ret :
print("StockCode=", id, " prob=",prob)
上記のコードを実行すると、商品ID(StockCode)と、おすすめ度(類似度, prob)が出力されます。
StockCode= 20723 prob= 0.8651097416877747
StockCode= 20724 prob= 0.8459421396255493
StockCode= 22355 prob= 0.8320007920265198
StockCode= 22661 prob= 0.766094446182251
StockCode= 85065 prob= 0.725541353225708
StockCode= 20719 prob= 0.7169413566589355
StockCode= 84839 prob= 0.7046974897384644
StockCode= 21641 prob= 0.6310057640075684
StockCode= 84750B prob= 0.6128920912742615
StockCode= 82581 prob= 0.5844061970710754
商品IDを羅列しても、正しく動作しているかはわかりづらいです。
テストデータセットにkaggleのH&M Personalized Fashion Recommendationsなどを利用すると、こちらは商品画像があるので妥当性を主観的に評価可能です。
ちなみに、H&Mのコンペには参加していました。Word2Vecは、他の手法で選択した商品のスクリーニングに活躍しました。
顧客に対して、おすすめ商品を推測する
以下は、顧客に対しておすすめ商品を推測する例です。
例では、顧客(ID=18280)に対しておすすめ商品を推測する例になります。
この場合は、顧客がこれまで購入したリストをmost_similar
関数に渡します。これで、購入りストに類似した商品が検索できます。
items = custdf[custdf['CustomerID'] == 18280].StockCode
print(list(items))
ret = model.wv.most_similar(list(items)[0], topn=10)
for id, prob in ret :
print("StockCode=", id, " prob=",prob)
顧客(ID=18280)がこれまで購入した商品は、'82484', '22180', '22467', '22725', '22727', '22495', '22358', '22499', '22611', '22084'
です。
これから推測されるおすすめ商品は以下のようになりました。
[['82484', '22180', '22467', '22725', '22727', '22495', '22358', '22499', '22611', '22084']]
StockCode= 85086A prob= 0.8375034928321838
StockCode= 85170A prob= 0.7887055277824402
StockCode= 21895 prob= 0.7870038151741028
StockCode= 21658 prob= 0.7827568650245667
StockCode= 22760 prob= 0.7729128003120422
StockCode= 22880 prob= 0.7673733830451965
StockCode= 21910 prob= 0.7586606740951538
StockCode= 84597B prob= 0.7456515431404114
StockCode= 21911 prob= 0.7415158152580261
StockCode= 22194 prob= 0.732184112071991
Item2Vecは強力はツールですが、これだけでレコメンドを作成するより他の手法をと組み合わせることをお勧めします。
例えば、週間の売れ筋商品や売りたい商品をリスト化しておき、これらのアイテムと、お客様の購入履歴との距離をItem2Vecで計算し、近い順にソートします。
上位のいくつかをピックしてお勧めとすれば、「売れ筋商品のうち、お客様の購入履歴に近いもの」をお勧めすることが可能です。
このように、他の手法を簡単に組み合わせることができるのもItem2Veの強みです。
まとめ
この記事では、Word2Vecを応用して、商品レコメンドを行うItem2Vecという手法について解説しました。Word2Vecを単語の距離を測る目的以外で使うというのは、いろいろな場面で利用することが可能な手法です。
Woed2Vecを応用した類似ベクトル検索は、比較的簡単に利用できるので、とりあえず、やり方を覚えておけばいろいろな場面で利用できます。