ホーム  >   ブログ  >   MacのローカルにHivemallを導入してアイテム推薦をするまで

2017-02-11

MacのローカルにHivemallを導入してアイテム推薦をするまで

昨年、Hive向けの機械学習ライブラリ HivemallApache Software FoundationのincubatorプロジェクトになったTreasure Dataがオフィシャルでサポートしているということもあり、名前くらいは聞いたことがあるという人も多いと思う。

とはいえ、やれHadoopだHiveだとスケールの大きな話をされると、手元でちょっと試すなんて気分にはならないものである。というわけで、実際にMacのローカルでHadoop, Hiveの導入からHivemallを動かすまでをやってみた。

Hadoopのインストール

$ brew install hadoop

(今回のバージョンは 2.7.3)

/usr/local/Cellar/hadoop/{バージョン} 以下を直接漁ることになるのでエイリアスを設定しておく。

export HADOOP_DIR=/usr/local/Cellar/hadoop/{バージョン}

${HADOOP_DIR}/libexec/etc/hadoop/core-site.xml<configuration> を編集:

<configuration>
    <property>
    <name>fs.defaultFS</name>
    <value>hdfs://localhost:9000</value>
  </property>
</configuration>

${HADOOP_DIR}/libexec/etc/hadoop/hdfs-site.xml<configuration> を編集:

<configuration>
  <property>
    <name>dfs.replication</name>
    <value>1</value>
  </property>
</configuration>

HDFSをフォーマット:

$ hdfs namenode -format

localhostへのSSH接続を許可する必要があるので、Macの システム環境設定 > 共有 からリモートログインを有効にする。さらに、SSH公開鍵を自身のauthorized_keysに追加する。

$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

これで $ ssh localhost ができる。

Hadoopの設定おわり。

起動・終了はエイリアスを設定しておくと便利:

alias hstart=${HADOOP_DIR}/sbin/start-all.sh
alias hstop=${HADOOP_DIR}/sbin/stop-all.sh
$ hstart

うごく。

$ hstop

とまる。

Hiveのインストール

$ brew install hive

(今回のバージョンは 2.1.0)

適当に作業用ディレクトリ(今回は ~/hive )を掘って、そこでスキーマを初期化する:

$ mkdir ~/hive
$ cd ~/hive
$ schematool -initSchema -dbType derby

HadoopとHiveを起動する:

$ hstart
$ hive
hive>

Hivemallのインストール

基本はここにある通り。

まずビルド済みのHivemall hivemall-core-xxx-with-dependencies.jarGitHubリポジトリからダウンロードする。

そしてHiveの起動時スクリプトとして以下を ~/.hiverc に書いてあげる:

add jar /path/to/hivemall-core-xxx-with-dependencies.jar;

これだけ。

Hivemallは機械学習に特化したHiveの関数セットなので、なにか仰々しいインストールスクリプトが走るというものではない。

Hivemallでアイテム推薦

ここまででMacのローカルにHadoop、Hive、そしてHivemallが導入できた。最後に一例として、アイテム推薦をHivemall上でやってみよう。

使うアルゴリズムは Matrix Factorization で、これや推薦手法全般の概略は「Courseraの推薦システムのコースを修了した」を読んでほしい。

Hivemall公式のチュートリアルはここにある。

Step 1: MovieLens 1MデータセットでHiveテーブルを作る

MovieLens 1Mは推薦の分野では定番のデータセット。これを使って Matrix Factorizationでアイテム(映画)の推薦 を成し遂げるべく、Hiveテーブルを作成していく。

まずHiveでのDB、テーブル作成用スクリプトを create_db.hive のような名前で以下の中身で作って、Hiveの作業用ディレクトリで走らせる:

create database movielens;
use movielens;

CREATE EXTERNAL TABLE ratings (
  userid INT,
  movieid INT,
  rating INT,
  tstamp STRING
) ROW FORMAT DELIMITED
FIELDS TERMINATED BY '#' -- 適当な1文字のセパレータ
STORED AS TEXTFILE
LOCATION '/dataset/movielens/ratings';
$ hive < create_db.hive

そしてデータをダウンロード:

$ curl -o ml-1m.zip -L http://files.grouplens.org/datasets/movielens/ml-1m.zip
$ unzip ml-1m.zip
$ cd ml-1m

使うのは ratings.dat で、ユーザごとのアイテム(映画)に対する評価値が入っている。このセパレータをテーブル作成時の適当な1文字にしておく(今回は # ):

$ sed 's/::/#/g' ratings.dat > ratings.t

そしてこのデータをHDFSにコピーする:

$ hadoop fs -put ratings.t /dataset/movielens/ratings

Hiveに入ってデータを確認する:

$ hive
hive> use movielens;
hive> select * from ratings limit 5;
OK
1       1193    5       978300760
1       661     3       978302109
1       914     3       978301968
1       3408    4       978300275
1       2355    5       978824291
Time taken: 1.36 seconds, Fetched: 5 row(s)

よさそう。

(以下、すべてHiveのインタラクティブシェル hive> 上での入力)

Step 2: Hivemallから使う関数を呼び出す

Matrix Factorizationでアイテム推薦 のために使う関数たちを読み込んであげる。Matrix Factorizationで2つ ( mf_predict , train_mf_sgd ) 、推薦リストの生成に1つ ( each_top_k )、そしてユーティリティ関数を2つ ( array_avg , to_ordered_map ) 読んでいる。

create temporary function mf_predict as 'hivemall.mf.MFPredictionUDF';
create temporary function train_mf_sgd as 'hivemall.mf.MatrixFactorizationSGDUDTF';
create temporary function each_top_k as 'hivemall.tools.EachTopKUDTF';
create temporary function array_avg as 'hivemall.tools.array.ArrayAvgGenericUDAF';
create temporary function to_ordered_map as 'hivemall.tools.map.UDAFToOrderedMap';

ちなみに、これらを ~/.hivercadd jar ... の後に直接書いておけば、起動時に毎回関数を自動で読み込んでくれる。

Step 3: クエリで「おすすめ映画リスト」をつくる

あとは中間テーブルを作成しつつクエリを実行していけば「おすすめ映画リスト」が得られる。

まず train_mf_sgd にユーザIDと映画ID、評価値を渡せば、Matrix Factorizationが走ってモデルが返ってくる:

CREATE TABLE mf_model AS
SELECT
  idx,
  array_avg(u_rank) as Pu,
  array_avg(i_rank) as Qi,
  avg(u_bias) as Bu,
  avg(i_bias) as Bi
FROM (
  SELECT
    train_mf_sgd(userid, movieid, rating) AS (idx, u_rank, i_rank, u_bias, i_bias)
  FROM ratings
) t
GROUP BY idx
;

そして推薦対象のユーザID userid と、推薦リストのサイズ k を変数として設定して、

set hivevar:userid=1;
set hivevar:k=10;

対象ユーザに対して各映画の評価値を予測して、その上位k件の「おすすめ映画リスト」を返すクエリが以下:

WITH top_k AS (
  SELECT
    each_top_k(
          ${k}, u.userid, mf_predict(u.pu, i.qi, u.bu, i.bi),
      u.userid, movieid
        ) AS (rank, score, userid, movieid)
  FROM (
      SELECT idx AS userid, pu, bu
      FROM mf_model m
      WHERE m.idx = ${userid}
    ) u
  CROSS JOIN (
      SELECT idx AS movieid, qi, bi
      FROM mf_model m
    ) i
)
SELECT
  userid,
  map_values(to_ordered_map(rank, movieid)) AS recommended_items
FROM
  top_k
GROUP BY
  userid
;

結果はこんな感じで、ID=1のユーザはID=926とか905とかの映画が好きなんだなぁという気持ちになって無事目標達成。

userid recommended_items
1 [926,905,922,3030,928,910,3022,904,909,916]

まとめ

MacのローカルにHadoop, Hiveをインストールして、機械学習ライブラリHivemallを使ったアイテム推薦までやってみた。

Hadoop, Hiveに必要な設定は思っていたよりも少なかった。

アイテム推薦に関しては、「とりあえず動かす」ことに専念したので、

  • 精度の評価はどうするのか
  • Matrix Factorizationのパラメータはどうするのか
  • ユーザがすでに評価した、既知の映画まで推薦してしまって良いのか

といった問題が残っている。このあたりはまたの機会に書こうと思う。

参考

  シェアする

このエントリーをはてなブックマークに追加

  カテゴリ

機械学習 情報推薦

  あわせて読みたい

2017-08-20
HiveでテキストのFuzzy Search
2017-05-14
推薦システムのためのOSSたち
2017-05-07
Hivemall on Dockerを試すぜ

  もっと見る

最終更新日: 2022-01-18

  書いた人: たくち

Takuya Kitazawaたくち)です。長野県出身、カナダ・バンクーバー在住のソフトウェアエンジニア。これまでB2B/B2Cの各領域で、Web技術・データサイエンス・機械学習のプロダクト化および顧客への導入支援・コンサルティング、そして関連分野の啓蒙活動に携わってきました。現在は主に北米(カナダ)、アジア(日本)、アフリカ(マラウイ)の個人および企業を対象にフリーランスとして活動中。詳しい経歴はレジュメ を参照ください。いろいろなまちを走って、時に自然と戯れながら、その時間その場所の「日常」を生きています。ご意見・ご感想およびお仕事のご相談は [email protected] まで。

  近況   一杯のコーヒーを贈る

  免責事項

  • Amazonのアソシエイトとして、当サイトは amazon.co.jp 上の適格販売により収入を得ています。
  • 当サイトおよび関連するメディア上での発言はすべて私個人の見解であり、所属する(あるいは過去に所属した)組織のいかなる見解を代表するものでもありません。
  • 当サイトのコンテンツ・情報につきまして、可能な限り正確な情報を掲載するよう努めておりますが、個人ブログという性質上、誤情報や客観性を欠いた意見が入り込んでいることもございます。いかなる場合でも、当サイトおよびリンク先に掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。
  • その他、記事の内容や掲載画像などに問題がございましたら、直接メールでご連絡ください。確認の後、対応させていただきます。