Apache Hivemall next release

この記事は[Machine Learning Advent Calendar](http://qiita.com/advent-calendar/2016/machine-learning)19日目の記事です。

HivemallがApache Incubation入りした話と、来年リリース予定の新機能に関して書きたいと思います。

# 祝 Apache Incubator!

<img width="734" alt="Screen Shot 2016-12-18 at 16.43.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/7129/ed96c6c1-dcb3-f7ba-9159-0aadfe6b7a09.png">


まず今年はHivemallがApache Incubation projectに選ばれました。:congratulations:

[機械学習ライブラリHivemallが米国Apacheソフトウェア財団の育成プロジェクトに認定](https://www.treasuredata.com/press_release_jp/20161208_apache_hivemall/)

日本発のOSSとしては初めてのことらしいです。HivemallはHadoopやSpark上で動作するUDFのコレクションとして実装されていて、機械学習のアルゴリズムだけでなくfeature engineeringや自然言語処理、更にはパラメータサーバ(mix server)の実装なども含まれています。機能も豊富なHivemallですが、他の機械学習ライブラリと比較して特徴づけられるものとして以下の２点があげられます。

* SQLクエリで実行できるため新しいsyntaxやインタフェースを覚える必要がない
* HadoopやSparkなど既存のスケーラブルなプラットフォームの上で動作する

こういった点も評価されてIncubation入りを果たしました。Apache Incubatorはトッププロジェクトへの昇格のための登竜門という位置づけなので、これからコミュニティを拡大させたり、開発を加速させることでトッププロジェクト入りを目指していきたいと思います。

そんなHivemallですが、来年の早い時期にIncubator後最初のリリースを予定しています。この記事では、次のリリースで予定されている機能のいくつかを紹介したいと思います。まだunder reviewなものも含まれますので、詳細はリリース時と異なる可能性があります。雰囲気だけ読んでいただければと思います。

# Docs & Resources

まず[Hivemallのサイト](http://hivemall.incubator.apache.org/), [GitHubリポジトリ](https://github.com/apache/incubator-hivemall)が新しくなりました。これはIncubationに伴ったものですが、[ドキュメント](http://hivemall.incubator.apache.org/userguide/index.html)も見やすくなりましたので、今後はこちらを参照ください。

[使い方](http://hivemall.incubator.apache.org/userguide/getting_started/installation.html)は今まで変わっていません。今までのリリースは[GitHub releases](https://github.com/myui/hivemall/releases)にあり、これをダウンロードしてHive consoleで下記のようにjarをインストールします。

```
add jar /home/myui/tmp/hivemall-core-xxx-with-dependencies.jar;
source /home/myui/tmp/define-all.hive;
```

もし自前でビルドしたものを使いたい場合、[ビルド手順](http://hivemall.incubator.apache.org/contributing.html)は以下のようになります。．

```bash
# This is a workaround for resolving xgboost dependencies.
$ mvn validate -Pxgboost
 
$ mvn clean package
```

サイトのリソースは[リポジトリのsrc/site](https://github.com/apache/incubator-hivemall/tree/master/src/site)にありますので、加筆修正必要な箇所見つけましたらPull Requestお願いします。

# Kernelized Passive Aggressive

Treasure Data春のインターンで来てくれた　[L3Sota](https://github.com/L3Sota)さんが開発してくれました。
Passive Aggressiveを使ったregressor, classifierは既にHivemallにはあったのですが、Kernelized Passive Aggressiveは予測スコアを計算するときにモデルパラメタとの積ではなく、各サポートベクトルとの距離をカーネル関数を使って計算します。

Passive Aggressiveは下記のモデルで表現される$\bf{w}$を最適化するようなアルゴリズムですが

```math
\phi_{PA}(\bf{x}) = \bf{w} \dot \bf{x} - \bf{b}
```

Kernelized PAではモデルは下記で表されます。

```math
\phi_{KPA} ( \bf{x} ) = \sum_{i} \alpha_{i} K(\bf{x}, \bf{x_i})
```

$\bf{x_i}$はサポートベクトル。$K$はカーネル関数。$\alpha$が学習すべきパラメータになります。Kernel SVMと同じようにサンプルをより高次元へのマッピングして暗に計算してくれるので線形モデルよりも表現力の高いモデルになります。

Hivemallの実装ではこのカーネル関数は多項式カーネルのみが実装されています。

```math
K(\bf{x}, \bf{x_i}) = (\bf{x} \dot \bf{x_i} + c)^d
```

ほぼKernel SVMと同じようなアルゴリズムなのですが、

* 分類に失敗したサンプルのみパラメタ$\alpha$を更新

```java
    protected void updateKernel(final float label, 
      final float loss, final PredictionResult margin,
            FeatureValue[] features) {
        if (loss > 0.f) { // y * p < 1
            float eta = pa1 ? eta1(loss, margin) : pa2 ? eta2(loss, margin) : eta(loss, margin);
            float diff = eta * label;
            alpha.add(diff);
        } else {
           // 予測には使わない
            alpha.add(0.f);
        }
    }
```

という点が特徴となっています。この実装は[PR 13](https://github.com/apache/incubator-hivemall/pull/13)でunder reviewです。

ref: [Spring 2016 Intern at Treasure Data](http://www.slideshare.net/SotaroSugimoto/spring-2016-intern-at-treasure-data)

# New Optimizer system

今までのHivemallでは分類のためのUDFとパラメタの最適化アルゴリズムが密結合していて、最適化アルゴリズムを柔軟に変更したり、あるいは複数のUDFで共有したりというのが難しくなっていました。そこでこれを分離して使いやすくしようとしているのが下記のPRになります。

[PR 14](https://github.com/apache/incubator-hivemall/pull/14)

`Optimizer`クラスは下記のAPIを持ちます。

```java
 public interface Optimizer {

    /**
     * Update the weights of models thru this interface.
     */
    float computeUpdatedValue(@Nonnull Object feature, float weight, float gradient);

    // Count up #step to tune learning rate
    void proceedStep();

}
```

`computeUpdatedValue`では`feature`とそれに対応するモデルの重みパラメタ、そしてその勾配を受取り、更新後の値を返します。Hivemallでは特徴は`FeatureValue`というクラスで表現されており、特徴からその値へのKey-Valueペアになっています。`feature`はこのキーの方に対応します。`proceedStep`は学習率の調整を行うためイテレーションをひとつ進めます。

このクラスは分類問題、回帰問題用の各抽象クラス(`GeneralClassifierUDTF`, `GeneralRegressionUDTF`)の中で使われています。

```java
// 特徴を取得
Object feature = f.getFeature();
// その特徴の値を取得
float xi = f.getValueAsFloat();
// その特徴に対応するモデルパラメタの現在地を取得
float weight = model.getWeight(feature);
// 次の値を計算。ここで`Optimizer`を使う
float new_weight = optimizerImpl.computeUpdatedValue(feature, weight, -label * xi);
model.setWeight(feature, new_weight);
```

この`Optimizer`は現在

* Stochastic Gradient Descent
* AdaDelta
* AdaGrad
* Adam

の4種類が実装されていますがUDFとしてユーザからデフォルト利用できるのはAdaGradになっています。今後増やして行きたいと思います。

# System Test Framework

Hive UDFのテストはきちんとやろうとするとHadoopの環境が必要になるので、ユニットテストを走らせようと思うと結構たいへんでした。より簡単に実環境に近い形でテストを可能にしたのがSystem Test Frameworkです。このSystem Test Frameworkでは下記のようにRunnerとTeamというものを定義します。Runnerはテストを走らせる環境、Teamがその上で走るテストスイートを管理します。Runnerとして現在実装されているのは下記の2つです。

* HiveSystemTestRunner: Hive UDF用のテストフレームワーク [HiveRunner](https://github.com/klarna/HiveRunner)上で動作します。
* TDSystemTestRunner: Treasure Data Serviceの上で動作します。

HiveSystemTestRunnerが主にローカルでのテスト用、TDSystemTestRunnerがクラウドサービスであるTreasure Data上での確認用に使われます。

使い方として例えば下記のようにRunnerを用意します。この場合はHiveSystemTestRunnerです。

```
    @ClassRule
    public static HiveSystemTestRunner hRunner = new HiveSystemTestRunner(ci) {
        {
            // データをロードし、テーブルを作成します。
            initBy(HQ.uploadByResourcePathAsNewTable("color", ci.initDir + "color.tsv",
                    new LinkedHashMap<String, String>() {
                        {
                            put("name", "string");
                            put("red", "int");
                            put("green", "int");
                            put("blue", "int");
                        }
                    })); // create table `color`, which is marked as immutable, for this test class
                    
            // テストに必要なUDF、関数をここで登録します。
            initBy(HQ.fromStatement("CREATE TEMPORARY FUNCTION hivemall_version as 'hivemall.HivemallVersionUDF'"));
        }
    };
```

次にこのRunnerをteamに追加して、テストを実行します。

```java
// デフォルトのRunnerとして先程のHiveSystemTestRunnerを追加
@Rule
public SystemTestTeam team = new SystemTestTeam(hRunner); 

@Test
public void test0() throws Exception {
    team.add(otherRunner); // 必要であれば他のRunnerを追加することも可能
    // テストクエリとexpectationをセット
    team.set(HQ.fromStatement("SELECT name FROM color WHERE blue = 255 ORDER BY name"), "azure\tblue\tmagenta", true);
    // クエリを実行して検証する
    team.run(); 
}
```

これだけでHivemall UDFのテストができるようになったので開発がより簡単になるはずです。この機能はTreasure Data夏のインターン来てくれていた[amaya382さん](https://github.com/amaya382)が開発してくれました。

see: [PR 12](https://github.com/apache/incubator-hivemall/pull/12)

# その他

この他の新機能も紹介したいと思います。

## SST based Change finder

Singular Spectrum Transformationを使ったChange finderです。Anomaly Detectionなどに用いることができます。この機能もTreasure Data夏のインターンに来てくれていた[takuti](https://github.com/takuti)さんが開発してくれました。

see: [PR 11](https://github.com/apache/incubator-hivemall/pull/11)

## Feature binning, Onehot encoding

Feature TransformationのひとつとしてFeature BinningとOnehot Encodingが実装されました。

Feature Binningは連続的な特徴を予め定義された範囲の下でラベル値に変換するUDFです。
Onehot Encodingはラベル特徴量をone-of-k符号化で2値ベクトルに変換するUDFです。

see: [Implement feature binning (#322)](https://github.com/apache/incubator-hivemall/commit/07729e17e6aafa1f5bc3ee23fd43fd61ef53fced)
see: [Onehot encoding (#357)](https://github.com/apache/incubator-hivemall/commit/ebdbb004b7e9fa1dadd6620a3483784d0b4edbcb)

## Binary responses measures for item recommendation

主にレコメンデーションアルゴリズムを評価するためのmetricsが幾つか追加されました。

* Precision
* Recall
* MRR(Mean Reciprocal Rank)
* MAP(Mean Average Precision)
* AUC(Area under the ROC curve)

see: [Implemented UDAFs of the additional binary responses measures](https://github.com/apache/incubator-hivemall/commit/8b199f4b2c38af6d9bf3d14f3ddeb610c2883239)

# まとめ

大事なことですが、ここで紹介した機能はリリース時には**実装、使い方含めて変更されているかもしれません。**利用される場合は改めて[User Guide](http://hivemall.incubator.apache.org/userguide/index.html)を参照ください。またHivemallはApache Incubatorになり一層User, Developerからのfeedback, contributionを歓迎していますので、興味のある方は是非[Mailing List](http://hivemall.incubator.apache.org/mail-lists.html), [JIRA](https://issues.apache.org/jira/browse/HIVEMALL/?selectedTab=com.atlassian.jira.jira-projects-plugin:summary-panel)をチェックしてみてください。

# 参照

* [Apache Hivemall site](http://hivemall.incubator.apache.org/)
* [Apache Hivemall JIRA](https://issues.apache.org/jira/browse/HIVEMALL)
* [Apache Hivemall Mailing List](http://hivemall.incubator.apache.org/mail-lists.html)
* [Apache Hivemall User Guide](http://hivemall.incubator.apache.org/userguide/index.html)
* ["Real-world Machine Learning" by takuti](https://speakerdeck.com/takuti/treasure-data-summer-internship-2016)
* ["Internship final report" by amaya382](http://www.slideshare.net/amaya_382/internship-final-reporttreasure-data-inc)