このドキュメントでは、改良された SWING 類似度計算アルゴリズムの原理を紹介します。また、アルゴリズムパッケージのダウンロード方法、パラメータ、よくある質問 (FAQ) についても説明します。
改良された SWING アルゴリズム
改善点 1:共通の隣人の制限
元の SWING アルゴリズムは、アイテムペアとインタラクションしたユーザーが少数しかいない場合、信頼性が低くなります。データが不十分な場合、算出される類似度スコアに大きな誤差が生じる可能性があります。
次の極端な例を考えてみましょう。
次の図に示すように、A、B、C の 3 つのビデオがあります。10 人の熱心なレアル・マドリードファン (X1 から X10) と、音楽しか聴かない 1 人の音楽愛好家 (Y) がいます。レアル・マドリードファンは、人気のビデオ C とあまり視聴されないビデオ A の両方を含む、チーム関連のコンテンツを視聴します。彼らは皆、レアル・マドリードに関するビデオを 200 本視聴したと仮定します。ファンの 1 人である X1 は、ニッチな音楽ビデオ B を推奨されましたが、そのダークなクラシックスタイルが気に入らず、やはり高揚感のあるレアル・マドリードのアンセム A を好みます。音楽愛好家の Y は、A と B の両方を含むさまざまな種類の音楽を聴きます。このシナリオでは、ビデオ A と B の両方を視聴したユーザーは 2 人だけなので、SWING アルゴリズムは s(A,B)=0.33 > s(A,C)=0.22 というスコアを算出します。しかし、ユーザーがビデオ A を視聴している場合、ビデオ B を推奨するよりもビデオ C を推奨する方が適切であることは明らかです。
解決策:この問題は、両方のアイテムに共通するユーザー数が少ないことに起因します。この問題に対処するため、共通ユーザー数に基づいて結果を処理します。ノイズを低減するため、指示関数 Id(.) を追加して SWING の式を強化します。さらに、行動の重みを導入して、過度に人気のあるユーザーやアイテムをダウンウェイトします。改良された式は次のとおりです。

改善点 2:シーン固有の i2i のサポート
シーン固有のアイテム間 (i2i) は、SWING アルゴリズムを使用して、グローバルなクリックとシーン固有のクリックの両方の共起から学習します。このアプローチは、特定のシーン内でのユーザーのクリックを予測することに焦点を当てています。

次の図は、グローバルな i2i とシーン固有の i2i を示しています。グローバルな i2i とは異なり、シーン固有の i2i は、ターゲットシーン内でインタラクションのないユーザーを無視し、シーン内のユーザークリックのみを考慮します。
改良された SWING のデプロイ
-
アルゴリズムパッケージをダウンロードします:swing-1.0.jar。
ダウンロードに失敗した場合は、リンクをコピーしてブラウザのアドレスバーに貼り付けてください。
-
MaxCompute プロジェクトで、JAR リソースを追加します。
[Create Resource] ダイアログボックスで、[Resource Type] に [JAR] を選択し、[Upload as ODPS Resource] を選択して、ローカルファイルの
swing-1.0.jarをアップロードし、[Create] をクリックします。注:パッケージのデプロイは、プロジェクトごとに 1 回だけ必要です。
入出力形式
入力テーブル (パーティションテーブルも可) には、少なくとも次の 2 つの列が含まれている必要があります。
-
user_id:ユーザー ID またはセッション ID (推奨)。型は BIGINT または STRING です。コードは特定のデータ型をチェックしません。
-
item_list:クリックされたアイテムをセミコロン (;) で区切ったリストを含む STRING 型の文字列です。リスト内の各アイテムは、複数のフィールドを含むカンマ区切りの文字列です。
リスト内の各アイテムは、item_id,norm,timestamp,scene のように、カンマで区切られた複数のフィールドから構成されます。ここで、item_id は最初のフィールドである必要があります。
norm フィールドは、アイテムの最近の人気度を表します。この値はアイテムの影響度を示し、非常に人気のあるアイテムにペナルティを課し、「ハリー・ポッター効果」を軽減します。norm の計算方法がわからない場合や、データにおいて「ハリー・ポッター効果」が重要でない場合は、このフィールドを空のままにすることができます。
「ハリー・ポッター効果」とは、ハリー・ポッターの書籍シリーズのように、非常に人気があり広く知られているアイテムが推薦リストを独占し、他のアイテムが同様の注目を集めることが困難になる現象です。
注:norm の値は現在のアイテムにのみ関連し、現在のユーザーとは無関係に、そのグローバルな人気度を表します。同じアイテムの場合、norm の値はトレーニングデータセット内のすべてのレコードで一貫している必要があります。
タイムスタンプは %Y%m%d%H%M%S 形式 (例:20190805223205) に従う必要があります。タイムスタンプが不要な場合は、すべてのアイテムに同じタイムスタンプを使用できます。item_list は、クリック時間の昇順に並べる必要があります。
scene フィールドはオプションです。ユーザーのアクションが発生したシーンを指定し、シーン固有の i2i をサポートします。
|
user_id |
item_list |
|
12031602 |
558448406561,137,20190805223205;585456515773,39397,20190806170331;10200442969,81,20190807223820 |
|
3954442742 |
658448406561,137,20190805223206;485456515773,39397,20190806170335 |
注:1 つのレコードの item_list に重複した item_id 値を含めないでください。1 日あたり 1 つの <user, item> ペアのみを保持することが推奨されます。例えば、concat(user_id, date) を使用するなど、入力テーブルの user_id を処理して仮想セッション ID を作成できます。
出力テーブル (パーティション列をサポート) は、次の形式になります:
-
item_id:トリガーアイテムの ID (BIGINT)。
-
similar_items:類似アイテムのリスト。
similar_items は item_id1,score1,coccur1,ori_score1;item_id2,score2,coccur2,ori_score2;... という形式です。ここで、ori_score1 は元の類似度スコア、score1 は最大値正規化後のスコア、coccur1 は共起回数です。
注:出力テーブルは事前に作成しておく必要があります。列の型が正しいことを確認してください。列名はカスタマイズできます。
結果の例:
|
item_id |
similar_items |
|
1084315 |
7876717,0.000047,2,0.003601;6929557,0.000250,2,0.019373;1084342,0.000780,4,0.060325;1089552,0.000963,4,0.074516;1083467,0.008233,5,0.637016;66042,0.012925,6,1.000000 |
|
1090195 |
1090172,0.015136,1,1.000000 |
参照コマンド
DataWorks で、新しい ODPS MR ノードを作成し、次のコマンドを使用してジョブを送信します。ODPS SQL ノードを使用するとエラーが発生する可能性があります。
jar [<GENERIC_OPTIONS>] <MAIN_CLASS> [ARGS];
-conf <configuration_file> # アプリケーション設定ファイルを指定します
-resources <resource_name_list> # マッパーまたはリデューサーで使用されるファイル/テーブルリソース (カンマ区切り)
-classpath <local_file_list> # mainClass の実行に使用されるクラスパス
-D<name>=<value> # mainClass の実行に使用されるプロパティ値のペア
ARGS: <in_table/input_partition> <out_table/output_partition>
例:
パブリッククラウド (アウトオブバンド) ユーザー向けのコマンド:
##@resource_reference{"swing-1.0.jar"}
jar -resources swing-1.0.jar
-classpath swing-1.0.jar
-DtopN=150
-Dmax.user.behavior.count=500
-Dcommon.user.number.threshold=0
-Dmax.user.per.item=600
-Ddebug.info.print.number=10
-Dalpha1=5
-Dalpha2=1
-Dbeta=0.3
-Dodps.stage.mapper.split.size=1
com.alibaba.algo.PaiSwing
swing_click_input_table/ds=${bizdate}
swing_output/ds=${bizdate}
;
注:完全なコードには 1 行目のコメントが含まれます。パラメータ値を指定するには、-D
インバンドユーザー向けのコマンド:
jar -resources swing-1.0.jar
-classpath http://schedule@{env}inside.cheetah.alibaba-inc.com/scheduler/res?id=XXXXX
-DtopN=150
-Dmax.user.behavior.count=500
-Dcommon.user.number.threshold=0
-Dmax.user.per.item=600
-Ddebug.info.print.number=10
-Dalpha1=5
-Dalpha2=1
-Dbeta=0.3
-Dodps.stage.mapper.split.size=1
com.alibaba.algo.PaiSwing
swing_click_input_table/ds=${bizdate}
swing_output/ds=${bizdate}
;
インバンドのクラスパスを取得するには:
DataWorks で、SWING リソースパッケージを右クリックし、[Historical Versions] をクリックして、http で始まるファイルパスを取得します。
パラメータ
|
パラメータ |
説明 |
型とデフォルト |
|
common.user.number.threshold |
両方のアイテムとインタラクションしたユーザー数のしきい値。これはフィルターとして機能します。この値を高く設定しすぎると、返される結果が少なくなりすぎる可能性があります。ユースケースに基づいてこのパラメータを調整する必要があります。 |
整数。デフォルト:0。 |
|
max.user.per.item |
各アイテムの k-最近傍を計算するために使用するユーザーのクリックシーケンスの最大数。 |
整数。デフォルト:700。 |
|
max.user.behavior.count |
ユーザーの行動シーケンスの最大長。シーケンスがこの長さを超える場合、最新のインタラクションのみを保持するように切り捨てられます。 |
整数。デフォルト:600。 |
|
debug.info.print.number |
デバッグ情報を出力するレコード数。 |
整数。デフォルト:10。 |
|
alpha1 |
SWING アルゴリズムのパラメータ。 |
整数。デフォルト:5。 |
|
beta |
SWING アルゴリズムのパラメータ。 |
実数。デフォルト:0.3。 |
|
alpha2 |
SWING アルゴリズムのパラメータ。 |
整数。デフォルト:1。 |
|
user.column.name |
ユーザー ID またはセッション ID を含む列の名前。 |
文字列。デフォルト:"user_id"。 |
|
item.list.column.name |
{item_id, norm, ...} のリストを格納する列の名前。 |
文字列。デフォルト:"item_list"。 |
|
topN |
各トリガーアイテムに対して保持する k-最近傍の数。 |
整数。デフォルト:200。 |
|
odps.stage.mapper.split.size |
各マッパーが処理するデータ量。 |
整数。単位:MB。デフォルト:256。 |
|
odps.stage.reducer.num |
アイテムペアの類似度を計算するために使用されるリデューサーの数。 |
整数。デフォルト:200。 |
|
item.delimiter |
入力テーブルのアイテムリストのデリミタ。 |
文字列。デフォルト:セミコロン (;)。 |
|
item.field.delimiter |
入力テーブルのアイテムのフィールドのデリミタ。 |
文字列。デフォルト:カンマ (,)。 |
|
pos_norm |
アイテムの人気度 (norm) に対応するフィールドのゼロベースのインデックス。この例では 1 です。 |
整数。デフォルト:1。 |
|
pos_time |
タイムスタンプに対応するフィールドのゼロベースのインデックス。この例では 2 です。 |
整数。デフォルト:2。 |
|
pos_scene |
シーン名に対応するフィールドのゼロベースのインデックス。 |
整数。デフォルト:3。 |
|
target.scene.name |
シーン固有の i2i モデリングのためのターゲットシーンの名前。 |
指定しない場合、デフォルトでグローバル i2i が使用されます。 |
|
max.time.span |
アイテムが近傍と見なされるための 2 つのクリック間の最大時間間隔 (日数)。 |
整数。デフォルト:1。 |
|
do_supplement_by_adamic_adar |
見つかった類似アイテムの数が |
ブール型。デフォルト:true。 |
よくある質問
1. java.lang.ClassCastException: com.aliyun.odps.io.LongWritable cannot be cast to com.aliyun.odps.io.Text
FAILED: ODPS-0123131:User defined function exception - Traceback:
java.lang.ClassCastException: com.aliyun.odps.io.LongWritable cannot be cast to com.aliyun.odps.io.Text
at com.aliyun.odps.udf.impl.batch.TextBinary.put(TextBinary.java:55)
at com.aliyun.odps.udf.impl.batch.BaseWritableSerde.put(BaseWritableSerde.java:20)
at com.aliyun.odps.udf.impl.batch.BatchUDTFCollector.collect(BatchUDTFCollector.java:54)
at com.aliyun.odps.udf.UDTF.forward(UDTF.java:164)
at com.aliyun.odps.mapred.bridge.LotTaskUDTF.collect(LotTaskUDTF.java:62)
at com.aliyun.odps.mapred.bridge.LotReducerUDTF$ReduceContextImpl.write(LotReducerUDTF.java:167)
at com.aliyun.odps.mapred.bridge.LotReducerUDTF$ReduceContextImpl.write(LotReducerUDTF.java:162)
at com.aliyun.odps.mapred.bridge.LotReducerUDTF$ReduceContextImpl.write(LotReducerUDTF.java:151)
at com.alibaba.algo.Paiswing$swingI2IReducer.reduce(Paiswing.java:346)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.aliyun.odps.mapred.bridge.utils.MapReduceUtils.runReducer(MapReduceUtils.java:160)
at com.aliyun.odps.mapred.bridge.LotReducerUDTF.run(LotReducerUDTF.java:330)
at com.aliyun.odps.udf.impl.batch.BatchStandaloneUDTFEvaluator.run(BatchStandaloneUDTFEvaluator.java:53)
出力テーブルの item_id カラムは、STRING 型ではなく BIGINT 型にする必要があります。お使いの CREATE TABLE ステートメントでスキーマ情報を確認してください。
関連ドキュメント
基本的な SWING アルゴリズムについては、「SWING アルゴリズムツール」をご参照ください。