機械学習
記事内に商品プロモーションを含む場合があります

Item2Vec: Word2Vecを使って商品レコメンドを実装する

tadanori

この記事では、単語をベクトル化するword2vecを応用して商品リコメンドを実装する方法を解説します。word2vecは、単語間のベクトル化して、似た意味の単語を調べることができますが、うまく活用するといろいろな使い方が可能です。

Word2Vecとは

Word2Vecとは

Word2Vecは、単語をベクトルとして表現するもので、ベクトル空間上位の距離により、単語の意味や関係性を捉えることが可能な手法です。

Word2Vecでは、文章(連続した単語列)を使って、単語の周辺に出現する単語の確率分布を予測することができます。これにより、意味的に似た単語はベクトル空間上で近くに配置されるようになります。

Word2Vecには、CBOW(Continuous Bag of Words)とSkip-gramという2つの主要なモデルがあります。CBOWは、周囲の単語のコンテキストから中央の単語を予測するタスクを行うモデルであり、Skip-gramは中央の単語から周囲の単語を予測するモデルです(この記事ではWord2Vecの技術的な仕組みは省略します)。

Word2Vecを使えば単語の類似性や意味的な関係性を調べることができるので、自然言語処理のさまざまなタスクで利用されています。

文章のベクトル表現はsentence transformerを使って生成することもできます。sentence transformerについては以下の記事も参考にしてください。

Sentence Transformersで文章の類似度を調べる方法
Sentence Transformersで文章の類似度を調べる方法

Item2Vec

Item2Vecは、Word2Vecを使ってアイテム間の類似性や関連性を学習する手法です。

Item2Vecでは、ユーザーがアイテムを購入したり評価したりした情報を利用して、アイテムの類似性を見つけていきます。具体的には、ユーザーが選択したアイテム群からアイテム間の関連性を学習します。

この手法を使うことで、Word2Vecを使って、レコメンデーションなどを行うことが可能です。例えば、ユーザーが購入した商品に基づいて、関連商品を推薦するシステムなどが可能になります。

この記事では、実際にWord2Vecを使って学習させ、リコメンドを行ってみます

おすすめの商品(商品レコメンド)を実装する

利用するデータセット

ここで利用するデータセットは、「オンラインストア購買データ」です。このデータには、以下のデータが含まれています。今回は、このデータのStockCode(商品コード)と、CustomerID(顧客ID)を利用します。

項目名内容
InvoiceNo基本は6桁の整数で、”c”から始まるコードはキャンセルを表す。
StockCode基本は5桁の整数だが、末尾にアルファベットが付くものもある。
Description商品の名称(商品コードと1:1に対応していないものもある)
Quantity購入数量
InvoiceDateトランザクションが生成された日時
UnitPrice一商品あたりの英貨
CustomerID5桁の整数で顧客の識別コード
Country顧客が居住する国

データセットはいくつかの場所からダウンロードできますが、今回は、以下からダウンロードしました。

Online Retail Data Set
https://www.kaggle.com/datasets/vijayuv/onlineretail

なお、以下の説明では、データセットはカレントディレクトリにOnlineRetail.csvという名前で格納されているとします。

ライブラリのインポート

利用するライブラリをインポートしておきます。メインで利用するのはpandasgensimword2vecです。

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を利用すると簡単です。

あわせて読みたい
Pandasのshift, groupby活用してテーブルを変形する方法【Python】
Pandasのshift, groupby活用してテーブルを変形する方法【Python】
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

まとめ

Word2Vecを使って、レコメンドを行う方法を解説しました。

Word2Vecを単語のベクトル以外で使うというのはkaggleなどでも結構利用することがある手法です。

Woed2Vecを使った、類似ベクトル検索は、比較的簡単に利用できるので、やり方を覚えておけば、いろいろな場面で利用できるので便利です。

おすすめ書籍

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

記事URLをコピーしました