TensorFlow Extended (TFX) の紹介と導入, そして使ってみた感想

概要
====

2017年の KDD で, Google の著者チームから [TensorFlow Extended (TFX)](https://www.tensorflow.org/tfx/) というものが発表されていました[1]. あまり日本語圏では話題になっていないので[^outofdate]、ここで論文の要約と、TFX の導入方法、そして使ってみた感想などを書いてみます。

論文のレビュー
==============

まずは、 TFX の紹介論文[1]に何が書かれているか要約します。以前に私が読んだ時に印象に残った部分をメモしたものから書き起こしているため、もしかしたら内容が偏ってるかもしれませんが、TFX をどういう思想で設計したかがうかがい知れます。

論文の概要
----------

-   TFX の使い方の解説と実際のデプロイまでの流れを説明しています。

-   著者らは Google Play ストアの担当チームであり、その業務経験から機械学習運用の経験則からの知見も示しています。

-   TFX を構成する各モジュールは、機械学習活用のステージ順に data analysis, data transformation,
    data validation, trainer, model analysis, serving で、それぞれどのような役割があるかを紹介しています。

<div align="center">
<img width="895" alt="fig1.png" src="https://qiita-image-store.s3.amazonaws.com/0/236849/da7ec433-f41b-6a88-ecbd-8a4ca24d22ea.png">

<p>[1] より、言及する範囲</p>
</div>


機械学習の運用フレームワークに必要なもの
----------------------------------------

著者らは機械学習の運用フレームワークとして、以下のような要件があるとよいと考えています。

1.  **多くの学習タスクを単一プラットフォームで** (One ML platform for many learning tasks): 多くの異なるタスクを規格化できるように。Tensorflow は、線形学習、 DL, それらの混合、決定木ベースのアルゴリズム、系列学習、など多くのアルゴリズムをカバーしている。

2.  **継続的な学習とリリース** (Continuous training and serving): One-shot ではなく日々反復して訓練できるような機械学習プラットフォームであること。共通の1つの設定で全てのコンポネントを記述し、必要ならば共有もできる。コンポネントを規格化しているのでデバッグや状態管理もまとめて行える。

3.  **人間参加型** (Human-in-the-loop): エンジニアが簡単にデプロイできるようなインターフェイス、ユーザーの理解を助けデータとモデルを分析する助けになること。機械学習のデプロイの複雑なところを取り扱えカプセル化できればエンジニアもデータサイエンティストもより実用的なモデルを作成するタスクに専念できる。

4.  **プロダクトレベルの信頼性とスケーラビリティ** (Production-level reliability and scalability):
    入力データ、ソフトウェア、ユーザー設定などの変化に柔軟であること、稼働システムの大量データやトラフィックの増加に対してもスケールすること。

Data Analysis
-------------

データを取り込んで各変数の記述統計(平均や分散、頻出ラベル上位K個、など)を計算したり度数表やヒストグラムを描画したりするほか、2変数間の関係、相関係数を計算したり散布図を描画したりするコンポネントです。データの概形を捉える、品質管理、などの用途があります。データが膨大になると、このような処理は難しくなりますが、TFX では近似計算アルゴリズムを提供します。
(訳注: TF Data Analysis という名称のモジュールはありません。TF Data Validation が対応しています。)

Data Transformation
-------------------

この工程ではとてもエラーが出やすいです。単なるエラーではなく、エラーとして検出しにくい品質の悪化も存在するので厄介です。データの品質チェックは重要です。 TFX のこのコンポネントは、押し付けがましくない程度のアラートや、どう対応すべきかのヒントを与えてくれるといいます。 例えば,

-   feature-to-integer mapping (単語と整数の一対一変換)

-   整数ID値の sparse categorical featuring. sparse化はユニーク値が1\~100B
    くらいあるような特徴量に対して時間・空間計算量の節約になります。 (訳注: feature hasher のことか)

などです. (訳注: 主に自然言語処理での前処理がフィーチャーされています.)

特に重大な問題は、訓練データと本番データとで変換ロジックを一致させる必要があることです。訓練データとは違うやり方で入力を変換させたような特徴量はモデルの性能を損ねます。TFX はこのような問題にも対処できます。

(訳注: 特徴量のカテゴリカル変数の新しいラベルや、欠損値など、訓練データには存在しなかったのに本番データになって発生するような状況のことを言ってるのだと思います。)

Data Validation
---------------

DA の後で[^dv]、どのようにデータをテストすべきか、データは健全か、それとも問題があるか、それはユーザーに通知すべきか、ということを記述したスキーマを用意し動作させるコンポネントです。例えば以下のような項目をチェックできます。

-   データに存在することが期待されている特徴量

-   期待されている各特徴量の型

-   期待されている各特徴量の性質、最小カウント、例数の比率、などなど

-   期待される観測ごとの特徴の性質。最大値、最小値など

Model Training
--------------

すでに書いたように TF には多彩な学習アルゴリズムの訓練機能があり、アルゴリズムの変更も簡単にできます。継続的に訓練をやり直すような運用は、典型的な機械学習の事例ですが、実際に膨大なデータで性能を維持しつつ続けるのは時間・リソースともに要求され難しいです。著者らの所属する Google でもそのような課題に直面することが何度かありました。たとえば Google Play ストアには毎日数千もの新たなアプリが導入されています。

性能が要求水準になるように訓練するには、膨大なデータセットで数時間、ときには数日かけて計算する必要があり、モデルの性能と、「モデルの鮮度」はトレードオフの関係にあったそうです。 TFX では、*warm-starting* というテクニックでこの問題に対処しました。warm-starting は**転移学習** (transfer learning) に着想を得たものです。転移学習の一般的なアプローチでは、基本データセットで基本となるニューラルネットワークを学習します。次に、基本ネットワークから「汎化パラメータ」を得て予測対象のデータに使うネットワークの初期化に使い、最後に対象データセットに対するネットワークを学習させます。TFX ではこのような機能も単一の高級APIを介して容易に活用できます。

### 高級APIについて

TFX を高級APIたらしめている概念に `FeatureColumns` と `Estimator`
があります。前者はどの特徴量を入力に使っているのか一望してわかるようにしてくれます。後者はモデルの訓練と評価を行うクラスです。
(訳注: 本文に掲載されているサンプルコードを見ればわかりますが、これは tensorflow のPython の構文の話をしています。特徴量の設定を [`FeatureColumns`](https://www.tensorflow.org/guide/feature_columns) クラスインスタンスとして記述し、 `Estimator` に与えています. さらに `Estimator` は `train` メソッドと `evaluate` メソッドを持ち、それぞれに学習データ、テストデータを与えます。)

モデルの評価と検証 (Model Analysis)
------------------

### 「良い」モデルとは何か定義する

機械学習のモデルは複雑な処理をし、入力データも膨大だったり予期しないものだったりします。 よって、モデルの**精度の質**
(prediction quality) と**リリース安全性** (safe to serve) の両方で評価する必要があります。

リリース安全性とは問題のある or 予期しない入力を受け取ったり出力したりしたときにエラーを出したりクラッシュしたり大量のリソースを要したりしないことです。具体例として、リリースしたもので使っている機械学習ライブラリより新しいバージョンのものを開発時に使っており、新しく開発したモデルをリリースしたらエラーが発生した、とかです。

精度の質の評価では、入力から予測までのプロセスを1つの系として見たとき、精度がしきい値を超えているかで評価します。このしきい値は、たとえば現行モデルの予測精度などです。

常にモデルを学習し変更し続けるやり方で問題となるのは、全ての潜在的エラーを把握できないことと、「期待どおりの変化」と「期待していない変化」を切り分けることが難しいことです。訓練データが毎回かわるので、当てはまりの指標も変わります。つまり、保守的になりすぎて細かな変化のたびにアラートを出した結果、めんどくさくなってアラートを完全に無視するようになるか、逆に緩くしすぎて多くの期待していない変化を見落とすか、という葛藤のことです。
著者らの経験から言うと、多くのバグは指標に劇的な変化をもたらすので、ゆるい基準でも検知できます。しかし、これは無数の微小なバグが問題にされなかっただけ、という選択バイアスでしかないともいえます。

### スライシング

著者らのチームでは、訓練データから一部を抜き出したものを**スライス** (slice) と読んでいます。著者らは特に米国内のデータを対象としたモデルの精度を気にしているので、しばしば米国のスライスデータだけでモデルの性能を評価することがあります。データセット全体となると膨大であり、全体で計算した指標では局所的なあてはまりを反映しない可能性があるためです。そのため、TFMA のスライシングは、プロダクトチームがモデルの精度を向上させるのに役立ったり、全体の精度改善のために重要なスライスでの精度を犠牲にするようなことを回避できます。

モデルのデプロイ
----------------

TensorFlow Serving (TFS) を使います。完全に、かつカスタマイズ可能なようにデプロイできるようにするため、プロダクトレベルの機械学習モデルをサーバーシステムにデプロイできるようなフレームワークです。通常のデプロイに必要な**お決まりのコード**
(boilerplate code) を書く手間を削減してくれるとのこと。

TF Serving の文脈では、 マルチテナント性 (Multitenancy) とは、1つのサーバーインスタンスで複数の機械学習モデルを同時に動かすことを意味します。毎秒膨大な数のリクエストさばくと同時に、モデルを読み込むプロセスも処理しなければなりません。両者の干渉をなくし、独立性を向上するため、モデル読み込み処理を独立した専用スレッドプールとして設定できる機能を追加しました。

TF は共通のデータ形式を使用するという特徴があります。このおかげで、組織内でデータ、モデル、ツール、視覚化、最適化その他のテクニックを共有しやすくしています。一方で、形式を共通化することは、特定の目的に最適化したものに対してデータサイズや読み込み速度についてトレードオフの関係が発生します。ニューラルネットワーク以外のモデルは、CPU集約的というよりデータ集約的で、データのI/Oがボトルネックになりやすいです。この問題を解決するため、複数のパーサー設定で目的特化されたプロトコルバッファーパーサを用意できるようにしました。

ケーススタディ
--------------

Google Play ストアにデプロイした推薦システムの例を紹介します。ユーザが役に立つアプリを発見できるようにするというのが目的で、ストアのアプリページにアクセスしたとき、関連するアプリを表示させる。ユーザーがアクセスしたときにそのユーザーの情報とアプリの情報を送り
(クエリ)、推薦システムはいくつかのアプリのリストを返し、ランキングシステムがアプリごとにスコアを計算します。

典型的な場合では訓練データは数千億件のデータで、1件1件にユーザーの情報やアプリの評価レートなどの特徴量が含まれます。これを学習し厳密なモデルの評価をパスすると、モデルは TFS でデータセンターにデプロイされます。ここでは毎秒数千件のクエリが送られ、数百ミリ秒単位でのレイテンシが要求されます。プロダクトレベルのモデルも実験段階のモデルも、鮮度の維持のため日々学習が行われます。これをレイテンシの低下なく行う必要があります。従来のフレームワークから TFX に移行したことで、学習に必要な計算量の削減を始め多くの恩恵がありました。

(訳注: このあたりは、FaceBookの研究チームによる機械学習運用基盤の論文[2]と読み比べると面白いかもしれません。FBはOSSプラットフォームこそ提供していませんが、パフォーマンス向上のためのハードウェア選定についても考察しており面白いです。)

TFX を使う
==========

インストール手順
----------------

2018年12月28日現在では、対応しているOSは Mac または Ubuntu です。また、**Python3.x には対応していない**[^soon]ので、Python2.7をインストールする必要があります。。

たぶん Python 2.7版TFを使ってる人は少ないと思うので、[公式インストールガイド](https://www.tensorflow.org/install/pip%3Flang%3Dpython2%26hl%3Dja)をもとに python2.7で TF をインストールし直します。例えば ubuntu の場合、デフォルトが python3 なので、以下のように `virtualenv` 環境に切り替えるまでは `pip2` を使います。公式の例にならって `virtualenv` を使いましたが、`pyenv/pyenv-virtualenv` で Python2.7.9の環境を作っても同様にインストールできると思います。また、環境構築するだけなら、最初から TF を使える Google Colaboratory のほうが簡単かもしれません(参考: [Google ColaboratoryでGPUを使った機械学習](http://tfujiwar.hatenablog.com/entry/2018/06/03/090000)。 しかし、 Google Colab はデータのインポートが少し面倒だということに注意してください)。

```bash
    # python2.7 のインストール
    sudo apt update sudo apt install python-dev python-pip
    pip2 install -U virtualenv
    # ./venv に TF環境を作る
    virtualenv --system-site-packages -p python2.7 ./venv
    source ./venv/bin/activate
    pip install -U pip
    pip install -U ipykernel
    pip install -U jupyter
    ipython kernel install --user --name=tfx # 仮想環境を kernel として追加。 --name= で付ける名前は自由
    # TF インストール
    pip install tensorflow # GPU版なら代わりに tensorflow-gpu
    # 動作確認
    python -c "import tensorflow as tf; tf.enable_eager_execution(); print(tf.reduce_sum(tf.random_normal([1000, 1000])))"
    # TFX 各モジュールインストール
    # https://www.tensorflow.org/tfx/
    pip install tensorflow-data-validation
    pip install tensorflow-transform
    pip install tensorflow-model-analysis
    bin/jupyter nbextension enable --py widgetsnbextension
    bin/jupyter nbextension install --user --sys-prefix --py --symlink tensorflow_model_analysis
    bin/jupyter nbextension enable --py tensorflow_model_analysis
```

おそらくハマりやすいのが、TFMA の jupyter notebook 拡張機能をインストールする箇所です。私の環境 (Ubuntu OS) では公式の通りにやるとPython3 のパスを参照してインストールしようとしてエラーになります。公式には仮想環境の場合 `-–sys-prefix` を付けるといいと書かれていますが、それでもダメです。私の場合は、仮想環境のディレクトリ直下で、 `jupyter` ではなく、 `bin/jupyter` とするとなぜか Python3 のリンクが外れて上手く行きました (これはなぜでしょう?)。

実際の使い方
------------

もう既に書かれているので 『[あなたの機械学習システム構築を手助けする、TensorFlow Extended](https://qiita.com/kamujun/items/59de48efffe103632c3f)』 や、公式の例を参考にしてください。

1. [TFDV の公式 Example](https://github.com/tensorflow/data-validation/blob/master/examples/chicago_taxi/chicago_taxi_tfdv.ipynb)
2. [TFT の公式 Example](https://www.tensorflow.org/tfx/transform/tutorials/TFT_simple_example)
3. [Get Started With TensorFlow Model Analysis](https://www.tensorflow.org/tfx/model_analysis/get_started)

インターフェイスや構文はこれらをみればだいたい雰囲気をつかめると思います。

使った感想
==========

実際に使ってみると、TFXだけで完全に自己完結な運用プラットフォームとして**使うのは難しい**とわかります。主な理由は、以下の2つです。

1.  TFX が python 2.x にしか対応していない
2.  まだ機能が足りないところもある。
3.  まだドキュメントが充実していない

TF 自体は Python3.xにも対応していますが、TFX は Python3.x にはまだ対応していません。そのうち対応するというアナウンスはありますが。

たとえば、TFDV は読み込めるデータが csv か TFRecord 形式しかない、記述統計を表示するインターフェイスの機能が貧弱 (私が[以前紹介](https://qiita.com/s_katagiri/items/26763fd39f3dd9756809)したような可視化パッケージに遠く及ばない!)、など枚挙に暇がありません。

公式ドキュメントも、まだ簡単なチュートリアル程度のものが多いです。とはいえ、私が以前 (今年の夏頃?) 見た頃はほとんどインストール手順しか書いてなかったため、だいぶましになったとも言えます。

ただし、使えないと言うのはあくまで、「TFXエコシステムが自己完結なシステムとして使えるか」という回答に対してです。TF 本体はすでに実績がありますし、 TFT ではすでに前処理用APIが豊富にあります。

個人的には、 TFX によってモデルの訓練からデプロイのプロセスだけでなく、それ以前の前処理も含めてサポートするようになったというのが魅力的だと思います。よく知られているように、一番簡単な構造のニューラルネットの1つはロジスティック回帰です。TFX では複雑なディープラーニングのモデルだけでなく、そういったものを使うまでもない単純なタスクに対しても、すべて同じプラットフォームで簡単に取り扱えることになります。定義済みのモデルが充実すれば、毎回各レイヤーの設定を書くことも減るでしょう。この点で、TFX は例えば scikit-learn のような既存のものとは違います。

とはいえ、現状はまだまだ開発途上のようで、TFX だけで機械学習タスクを完結させるのは難しいです。しかし、Googleらしい (?) 野心的な取り組みだと思うので、今後注視していきたいところです。

参考文献
========
[1] D. Baylor et al., _“TFX : A TensorFlow-Based Production-Scale Machine Learning Platform,”_ in Proceedings of the 23rd ACM SIGKDD International Conference on Knowledge Discovery and Data Mining, Halifax, NS, Canada, 2017, pp. 1387–1395. DOI: [10.1145/3097983.3098021](https://doi.org/10.1145/3097983.3098021).
[2] K. Hazelwood et al., _“Applied Machine Learning at Facebook: A Datacenter Infrastructure Perspective,”_ in 2018 IEEE International Symposium on High Performance Computer Architecture (HPCA), Vienna, 2018, vol. 2018-Febru, pp. 620–629. available at [here](https://research.fb.com/publications/applied-machine-learning-at-facebook-a-datacenter-infrastructure-perspective/).



[^outofdate]: TFXの論文を読んでこの記事の元となるメモを書いた時点ではそうでしたが、つい最近[qiitaの記事](https://qiita.com/kamujun/items/59de48efffe103632c3f) が書かれています。
[^dv]: Data Analysis の後でとありますが、Data Validation はよみこんだ 直後と Data Trasnsform 後という複数のタイミングで使うことを想定しているようです。
[^soon]: ただし、「すぐにでも」 Python3 にも対応する、とのことです(~~このアナウンスは数ヶ月前から変わってませんが~~)。参考: [GitHub の issue](https://github.com/tensorflow/data-validation/issues/10)