皆様、遅くなりましたが明けましておめでとうございます。本年も宜しくお願い申し上げます。
今回は前回に引き続き、ユーザシーケンスからコサイン関数の計算に必要な値(図1のa1:b1、a1、およびb1)を取り出す方法を紹介します。
おさらい
Hadoopはデータをクラスタ内のローカルディスクに分散し、そのデータがあるノード上で処理を実行するというデータローカリティを実現しているため、コサイン関数をMapReduceのフレームワークに変換して処理することを紹介しました。
その設計方法として、処理結果の形式から逆に考える方法を紹介しました。
ユーザシーケンスからアクセスユーザ数のカウントまで
第二段階の処理フローは次の通りです。ここでもアイテムIDを具体的なアイテム名で示しています。
- ①では、各ユーザシーケンスからシーケンス内に含まれるアイテムをkey、同一ユーザシーケンス内に含まれていた他アイテムをvalueとするペアのリストを作成します。
- ②では、keyであるアイテムでソートしてReducerに渡しています。
- ③では、keyであるアイテムをアクセスしたユーザ数、およびそのアイテムと同一ユーザシーケンス内に出現したアイテムの両方をアクセスしたユーザ数を算出しています。
HDFSには、同一ユーザにアクセスされたアイテムの組み合わせをkey、各アイテムをアクセスしたユーザ数、および両アイテムをアクセスしたユーザ数をvalueとするペアが入ります。
この例ではザスーラ、ジュマンジ、両方をアクセスしたユーザ数はそれぞれ3人、2人、2人なので、keyをザスーラとジュマンジ(順序に注意してください)、valueをザスーラをアクセスしたユーザ数、ザスーラとジュマンジをアクセスしたユーザ数、ジュマンジをアクセスしたユーザ数の並びで構成しています(色の違いを参考にしてください)。さらにこれらの順序を入れ替えたkeyとvalueのペアも出力します。
バトルランナーにアクセスしたユーザは他の映画をアクセスしていないので、コサイン関数を計算できないため、以降の処理で使わないため出力しません。
これをMapperおよびReducerで実装します。
Mapperは図2内の①に相当します。主な処理はユーザシーケンスからのアイテムリストの作成です。アイテムリストをユーザシーケンスごとに作成し、アイテムリスト内のアイテムの個数により、処理を分岐します。
複数のアイテムが存在する場合は、各リスト内のアイテムの組み合わせを出力します。この場合は、アイテムリスト内の任意のアイテムをkey、それ以外のアイテムをリスト化したをvalueとしたペアを出力します。リストはアイテムを``:''でネストして生成します。
もちろん、アイテムリスト内の全てのアイテムのペアを取り出して、そのアイテムペアをkey、ユーザidをvalueとして出力する方法もありますが、アイテムをリスト化した場合に比較してkeyとvalueのペアを大量に生成することになり、ソート処理に時間がかかり、処理全体の効率が悪くなります。
Reduceは図2内の③に相当します。主な処理はMapperの出力をマージして、各アイテムをアクセスしたユーザ数、および両アイテムをアクセスしたユーザ数の算出です。「同じkeyに関連付けられた全データ(keyが同じkeyとvalueのペア)は同じReducerに送られる」という特徴を生かし、Reducer側ではkeyのカウントをするだけで、keyとなっているアイテムをアクセスしたユーザ数を取得します。これはReducerの$countの変数に入ります。
出力は$key_currentとペアを作るアイテムidについて、$key_currentをアクセスしたユーザ数と、$key_currentおよびアイテムidの両方をアクセスしたユーザ数を出力します。この段階ではペアとなるアイテムidをアクセスしたユーザ数が分からないので、コサイン関数は計算できません(Reducerの数を1に設定し、全てのkeyとvalueのペアを読み込むまで出力しないように設計すれば可能ですが、データサイズが大きければメモリの限界を超えるでしょう)。次の処理で計算できるように、出力は$key_currentとペアを作るアイテムidを入れ替えた結果をも出力します。
次回は最後の第三段階の処理を紹介し、協調フィルタリング編のまとめとします。実はこの第二段階の処理で、協調フィルタリングに必要なアイテム間相関の値が得られていることも、そこで紹介します。