こんにちは、開発エンジニアの amdaba_sk(ペンネーム未定)です。
ラクスの開発部ではこれまで社内で利用していなかった技術要素を自社の開発に適合するか検証し、ビジネス要求に対して迅速に応えられるようにそなえる 「
この記事はかみせんプロジェクト2019年度下期成果報告ブログの一つです。
前回の成果報告では「機械学習プロジェクトの進め方」について検証した結果のまとめをしました。今回は「じゃあ実際に機械学習をやることになったら、どんなライブラリ、サービスを使えばいいの?」といったところの検証結果をまとめようと思います。
対象読者は前回と違って、機械学習に興味のあるエンジニアの方です。
なお今までの記事はかみせんカテゴリからどうぞ。
概要
非常に単純な機械学習タスクを実施するプログラムをいくつかのライブラリ、サービスを用いて実装することで、それぞれのライブラリ、サービスの使いやすさを評価しました。
やはり Python の scikit-learn はデファクトスタンダードであり、ライブラリの備える API の充実ぶり、Web や書籍の情報量は他を圧倒するものがあります。ただ学習データの量や、連携するシステムの開発言語によっては Apache Spark も有用です。
クラウドのマネージドサービスは、単なる Notebook の実行環境としての使い方をしている限りにおいては結局のところ scikit-learn を用いることになりがちでありその利点を引き出すことはできないということが分かりました。マネージドサービスは付属する学習済みモデルを利用するサービス、AutoML による自動学習、アプリケーションへのデプロイの容易さといったところに利点があるのだと推測されます。
今回の目標
実際に機械学習を利用した機能を作ることになった場合にまずやることになるであろうライブラリ、サービスの選定フェーズに対して参考になりそうな情報をまとめたいと思い調査を行いました。
とはいえライブラリやサービスを選ぶうえでの条件、観点はさまざまであり案件ごとに重視するポイントも固有のものがあるはずです。さらに調査メンバーがそもそも機械学習に関してそこまで詳しくはないということを考えると、実務上そのまま使えそうなレベルの資料を作るのは難しすぎます。
そこでさしあたり単純なサンプルプロジェクトを設定して機械学習モデルの作成スクリプトをいくつかのライブラリ、サービスを使って実装し、それぞれの使用感をまとめました。
対象ライブラリ・サービスの選定
- Python + scikit-learn
- Python + H2O
- JVM系 + Smile
- Apache Spark
- Amazon SageMaker
- AI Platform
- Azure Machine Learning
JVM系の言語としてはメンバーのモチベーション的な理由からScalaを採用しました。
また事前の調査から「Python 3 + scikit-learn」がディープラーニングを行わない場合のデファクトスタンダードのような存在であることが分かっていますので、他のライブラリはそれとの比較という観点で調査をすることにしました。
サンプルプロジェクトについて
サンプルは弊社の事業を考えると日本語テキストを扱うものの方がよいだろうと思われました。その上で単純なものであればなんでもよかったので、思い付きのままにAIチャットサービスっぽいものを作ることにしました。
ここに一人のゲーマーが居る。彼または彼女を A としよう。
A は最近ハマっているとあるゲームについて、公式サポートに問合せをするべく Web サイトに訪問した。
サイトにはありがちなよくある質問一覧の他に、「チャットで問い合わせる」というリンクが設置されていた。リンクをクリックするとページ内にチャットウィンドウが立ち上がり「気軽にご質問ください!」という定型的なメッセージが表示された。ウィンドウの下部にはメッセージ入力欄があり、カーソルが誘うように明滅している。
A はしばしの黙考ののち、質問を入力し始めた――
ここで自然な会話のできるAIチャットボットを作れればすごいですが、難易度激ムズな気がするので以下のような動きをするものとしましょう。
- 訪問者のメッセージを受け付ける
- メッセージが既存の「よくある質問」のどれに相当するかを分類する
- 質問の候補をいくつか選択肢として表示する
- 選ばれた質問に対して事前に設定された回答を表示する
(どことなく弊社のとあるサービスに激似ですが、気にしないことにします)
機械学習が関わってくるのは上の 2 のステップです。比較的短文な日本語文章の多クラス分類問題であると定式化できます。
前回の記事でまとめた内容によれば、ここで機械学習を使わない MVP を検討するところではありますが、今回はその辺をすっ飛ばします。また上のイメージのような組み込み先システムの設計も先に考えておくべきところではありますが、これも簡単のためにすっ飛ばして前処理とモデル学習のステップを考えていくことにします。
学習データについて
この分類問題では生のデータとしては例えば以下のようなものが得られると想像できます。
メッセージ | よくある質問ID |
---|---|
ログインできなくなりました。どうしたらいいですか? | 1 |
ログインができず、ゲームがプレイできません。 | 1 |
ゲームを始めようとするとエラーが出てログアウトしてしまいます。 | 1 |
: | : |
機種変更しても同じセーブデータで遊べますか? | 4 |
引き継ぎナンバーは一度発行すれば繰り返し使えますか? | 4 |
動作が重いです。 | 5 |
ゲーム内で購入したアイテムの情報が反映されません。 | 6 |
: | : |
ここで「メッセージ」が推測の入力となるデータ、「よくある質問ID」が推測したいクラスのラベルです。
会員制サイトなどで質問者の属性情報や前後の文脈など追加の情報が得られることもあるかと思いますが、ここでは匿名のユーザーによる単発の質問への対応という想定で上のようなデータをサンプルとして使うとしましょう。
とはいえそう都合よくチャットログデータは持ち合わせていませんでしたので、社内のいろいろな方に協力をお願いして自前で作りました。
- クラス数: 96
- データ
- 総数: 6051
- クラスごとのデータ数:
- 平均: 63.0
- 最大: 199
- 最小: 16
(改めて統計情報を見てみると、クラス数めっちゃ多いしクラスごとの分布もめっちゃ偏っていてあまりいいデータセットとは言えない気が…)
具体的なデータの中身は社外秘ということになったので公開できませんが、ゲームのサポートチャットではないということだけ言い添えておきます。
前処理について
元のデータは日本語テキストデータなので、何とかして数値データとして表現しなければなりません。
自然言語処理における前処理の種類とその威力によれば、テキストデータの前処理は以下のものを行うようです。
- テキストのクリーニング
- 単語の分割
- 単語の正規化
- ストップワードの除去
- 単語のベクトル表現
- 文書のベクトル表現
それぞれについて具体的な方法など検討すべき点はあるものの、大まかには上の工程を行えば良さそうです。
テキストのクリーニング
テキストのクリーニングは、テキスト内のノイズを除去する工程です。Web ページをスクレイピングして得たデータなどは HTML タグが含まれていたりしますが、これらは推測したいラベルと意味的な関わりの無いノイズとなります。ノイズを除去することでタスクの結果に及ぼす悪影響を抑えることができます。
今回はチャットメッセージの形で蓄積されたデータであり、ほぼ不要と思われるので特に何もしないことにしました。
単語の分割
テキストを機械学習の入力とする場合は、数値のベクトルに変換することがよく行われます。その際テキストを何らかの「最小単位」へと分割し、その最小単位が対応する数値ベクトルを使ってテキスト全体を数値ベクトルにするという方法を取ります。
この「最小単位」として何を使うかによって大きく二つの方法があるようです。
- 形態素に分ける方法 MeCab や Janome、Kuromoji といった形態素解析器で文を形態素に分解します。
- N-gram法を使って分ける方法 テキストを文字ごとに分け、各文字の後ろN文字目までの組によって作られる「N-gram」を最小単位とする方法です。
今回の実装では形態素に分ける方式を取りました。理由としては
- 参考記事が形態素にしか触れていない
- 文法的に意味のある単位の方がそれっぽい
- 実装も容易
という点が挙げられます。
使用した形態素解析器は以下の通りです。
どちらもそれぞれの環境で導入が容易であり、使用方法も簡単であったためこれらを選びました。辞書は何を使うかも検討しなければいけないところですが、今回は簡便にどちらもIPA辞書を使っています。
単語の正規化
単語の正規化では全角半角などの文字種の統一、表記揺れの吸収といった処理をすることで、意味的に同じ単語を同じものとして扱えるようにします。
- 文字種の統一
- 日本語文字は全角に
- 英数字記号は半角に
- 数字の置き換え
- 数字はすべて 0 に置き換え
- 単語の統一
- 形態素解析から原形を使う
ストップワードの除去
ストップワードは自然言語処理の際に一般的で役に立たない等の理由で処理対象外とする単語のことです。「てにをは」のような助詞や助動詞、「あれ、それ」などの代名詞といった単語はどのような意味のメッセージにも登場し、内容の推測には役に立たないため除去します。
ストップワードの除去には様々な方式があるようですが、ここでは日本語のストップワード辞書の一つである Slothlib を使い、これに含まれる語は除去することにしました。
単語のベクトル表現
これまでの工程できれいになった単語を、数値ベクトルに対応させます。ベクトル化するのにも様々な手法が存在するようですが、主なものは以下の2つのようです。
- one-hot表現
- 分散表現
one-hot表現は各単語を単位ベクトルに対応させます。シンプルで分かりやすい方法です。
分散表現は Word2Vec みたいなやつですね。one-hot 表現からさらに加工して得るもののようです。
どちらを使うかはこの後の文書のベクトル表現の種類によって決まってきます。
文書のベクトル表現
前工程で決めた単語ごとの数値ベクトルを用いてテキスト全体の数値ベクトルへの対応を作ります。単語ベクトルと同じく主な手法は2種類に大別できます。
one-hot 表現からは文書に含まれる単語のベクトルを足し合わせた Bag of Words となります。さらに単語の出現頻度と逆文書頻度の積で単語を重みづけすれば TfIdfベクトルです。
分散表現での文書ベクトル表現は Word2Vec で得た単語ベクトルを足し合わせたり、doc2vecを使ったりで得ることが出来ます。
今回のサンプル実装に先立っての事前調査で、scikit-learn に TfIdf ベクトルを計算するための API が用意されており、また仮に自前で実装したとしても何とかなりそうということで、Tfidf ベクトルを使うことにしました。
モデル学習について
分類アルゴリズムは各ライブラリ、サービスごとに用意されたものを使うことになると想定されました。それぞれのライブラリ、サービスによっては実装されていないアルゴリズムもあるかもしれず、ここはあえて統一せずに使えるものを使うという方針にしました。
ただし選定の際のガイドとして scikit-learn のアルゴリズム選定チートシート を使用しました。 これによれば、今回のサンプルプロジェクトにおけるデータセット規模やタスクの性質から、線形 SVM 分類器、あるいは単純 Bayes 分類器が良いとのことです。そのため単純 Bayes 分類器が使える場合はこれを使うようにしています。
学習のそのあと
学習されたモデルはシステムへ組み込まれサービスとして運用されるのがまっとうなプロジェクトの進み先ですが、今回はサンプルプロジェクトなので評価指標の算出までで実装完了とします。
算出した評価指標は以下の通りです。
- 混同行列
- 正解率
- 適合率、再現率、F 値
- 加重平均
- マクロ平均
実装を終えての所感
Python + scikit-learn
scikit-learn は Python の代表的な機械学習のオープンソースライブラリです。 改めて調べてみても、やはりデファクトスタンダードとなっていると納得せざるを得ませんでした。
- API が非常に充実している
- インターフェースの統一された API
- データ分割、ハイパーパラメータチューニング、性能評価、可視化もできる
- ドキュメントも充実している
- ググればサンプルがたくさん出てくる
特にインターフェースが統一され、かつ充実した API は非常に便利であり、機械学習を試したいならまずこれ触れば間違いはなさそうです。
Python + H2O
H2O is an open source, in-memory, distributed, fast, and scalable machine learning and predictive analytics platform that allows you to build machine learning models on big data and provides easy productionalization of those models in an enterprise environment.
H2O ドキュメントトップページより引用
とあるように、H2O はライブラリというよりかはプラットフォームのようです。Python からその機能を使うこともできるし、アーキテクチャを見れば Java や Scala, R などからも使うことが出来るとわかります。また scikit-learn のパイプラインに組み込むことが可能だったりと他ライブラリ、プラットフォームとの連携にも考慮されている点もいいですね。
また AutoML という機能もあり、自分でコードを書かずともデータを与えれば自動でいい感じに学習してくれるようです。
ただ今回は AutoML は使わず、自分で Python のコードを書いて実装しました。
scikit-learnと比較して
分類アルゴリズムには単純 Bayes 分類器を選びました。出来上がったコードは自体は scikit-learn のものと比べ記述量や難易度は変わらない印象を受けました。
ただ H2O を使って実装してみた系の日本語記事が少なく、参考にできるのは公式ドキュメントのサンプルコードのみというのがつらいところ。
公式チュートリアルもありますが、中途半端なコードだったりで情報量が少なく、事前に scikit-learn などで実装した経験がないとなかなかしんどいかと。
また H2O はモデルの学習部分にフォーカスしているためか、テキストのベクトル化といった前処理に関して特に組み込みの API があるというわけではなさそうでした。そのため Tf-Idf ベクトル化は scikit-learn の API を使うなどする必要があります。
JVM系 + Smile
Smile is a fast and comprehensive machine learning engine.
Smileは JVM 上で利用できる機械学習エンジンで、Java や Scala など好きな JVM 言語で使うことが出来ます。組み込む先のシステムが JVM 言語で作られているのであれば、機械学習関連のコードとアプリケーションのコードで言語を揃えられるのが良いですね。
実行速度に優れ、自然言語処理、統計処理、データ可視化も Smile の API でできると謳われています。
scikit-learnと比較して
ライブラリの特徴というよりかは言語的な特徴になりますが、Scala での実装は説明的で分かりやすくなるように感じました。ただ Java で実装した場合、型表記が面倒か抽象的過ぎるかになりそうという印象でもあります。
Smile そのものに言及すると、インターフェイスが独特で scikit-learn などとは差が大きく、結構慣れるのに時間がかかりそうです。使ってみた系の情報が少ない点もネックになるかなと思われます。
また分類アルゴリズムは豊富に用意されているもののハイパーパラメータチューニングなどの便利 API などはなさそうで、そのあたりを自前で実装しなければならないあたり不便という印象がぬぐえません。
Apache Spark
Apache Spark は巨大なデータに対して高速に分散処理を行うためのフレームワークです。Java や Scala、Python などいろいろな言語での API が用意されています。
分散処理のためのフレームワークなので汎用的に使えるのですが、機械学習のためのコンポーネントが組み込まれていることから機械学習ライブラリとしても使用することが出来ます。
先にも触れたようにいろいろな言語で使用することが出来ますが、今回は Scala から使ってみました。
scikit-learnと比較して
Spark の機械学習コンポーネントが提供する API のインターフェースは scikit-learn のように統一されており、Smile より使いやすい印象です。 組み込みで前処理やハイパーパラメータチューニングができたりと機能も充実しており、使い勝手だけを見れば scikit-learn とも遜色ないように思えます。
今回 Windows 上での環境構築をしてみましたが、インストーラを起動しなければならないあたり面倒でした。Linux や Mac であればコマンドでインストールできるのでその点は問題にはならないと思われます。 マネージドサービスで Spark を使えるものが多いため、そういったサービスで使う場合もよさそうです。
Amazon SageMaker
Amazon SageMaker は AWS 上で提供されている完全マネージド型の機械学習サービスです。Amazon SageMaker というサービスの下に
- Amazon SageMaker Studio
- Amazon SageMaker Ground Truth
- Amazon Augmented AI
- Amazon SageMaker Studio Notebooks
- ...
といった機能が用意されています。
今回は自前で前処理等の部分を実装する想定だったため、Amazon SageMaker Studio Notebooks を使って自分で実装した Python コードを実行しました。
scikit-learnと比較して
- 組み込みアルゴリズムについて
sagemaker
というパッケージを読み込むことで組み込みアルゴリズムや Amazon SageMaker 独自のアルゴリズムやモデルを使用することが出来ます。
ただ提供されているアルゴリズムも限られていること、ドキュメントやサンプル実装の情報は存在するものの少ないことから、あえて組み込みアルゴリズムを利用するメリットは感じられませんでした。
Amazon SageMaker 上で scikit-learn コードを使用する方法もドキュメントに記載があることから、Notebook 上で自分でコードを書くのであれば scikit-learn を利用しておけばよいのではないかという印象です。
- 活用について
学習したモデルと AWS Lambda、Amazon API Gateway を組み合わせることで、HTTPS エンドポイントを作成することができます。 作成したモデルを用いて手早くアプリケーションを作成したい場合には有用そうです。
AI Platform
AI Platform は Google Cloud 上の AI 関連サービスのブランドです。 2020/3/10時点でまだベータ版。そのためメニュー上でもかなり下の方に配置されています。
AI Platformというブランドの下に
- AI Platform Notebooks
- AI Platform Training
- AI Platform Prediction
- Data Labeling Service(ベータ版)
- Deep Learning VM Image
- Deep Learning Containers(ベータ版)
- ...
とたくさんのサービスがぶら下がっています。
AI Platform Training ではトレーニングデータ、検証データ、テストデータと分けて GCS( S3 の GCP 版)に格納することで組み込みアルゴリズムによる学習も行える様子。 ただ今回は自前で前処理等の部分を実装する想定だったため、AI Platform Notebooks を使って実装したコードを実行しました。
scikit-learnと比較して
- 組み込みのアルゴリズムについて
AI Platform では独自のアルゴリズムなどを提供する Python パッケージが用意されているわけではないようです。 そのため今回の実装では結局のところ scikit-learn での実装を AI Platform Notebook 上で実行できるようにしたものとなりました。
その際 GCP で用意されている scikit-learn は 2020/3/10 現在で 0.19.2 だったことでハマりました。最新の 0.22.x 系とは API の非互換の部分が多いので注意が必要です1。
- 環境について
Notebooks 環境が用意されているので開発環境構築の手間はかからないのが良いです。クラウドサービスらしくスペックの変更もすぐに実施できます。 ただデフォルトのスペックが n1-standard-4(4 vCPU / メモリ15GB) + ストレージ 100GB と少し強めなので、軽い処理の実験用につどスペック変更するのが手間でした。
- 活用について
まだベータ版なので正式サービスに導入するには抵抗がありますが、サービスに組み込むための学習モデルの作成プラットフォームといった利用方法であれば問題なさそうです。 またハイスペックなインスタンスを利用することで短期間でのモデル作成が実現できそうとも感じました。
ただし、前処理やモデル生成の処理時間に困っていないのであれば、ローカルで scikit-learn を使うことに対するアドバンテージがないかもしれないというのも正直な感想です。
Azure Machine Learning
Azure Machine Learning は Microsoft Azure 上で提供される機械学習サービスで、機械学習を含む DevOps、MLOps を実現するクラウド環境です。 機械学習モデルのトレーニング、デプロイ、自動化、管理、追跡というワークフローすべてにおいて使用できるツールが提供されています。
Azure Machine Learning デザイナー や 自動 ML という、コードを書かずにモデルの作成ができるツールもあります。
ただ今回は Azure Machine Learning 上の Notebook で自分で実装したコードを実行しました。
scikit-learnと比較して
- 組み込みのアルゴリズムについて
Azure Machine Learning ではazureml
という Python パッケージが用意されているものの、これは学習アルゴリズムなどを提供するものではないようです。
公式のチュートリアルを見ても、Python でのサンプルは scikit-learn を使って線形回帰を行っています。
そのため今回の実装では結局のところ scikit-learn での実装を Azure Machine Learning の Notebook 上で実行できるようにしたものとなりました。
- 活用について
AI Platform と同じくサービスに組み込むための学習モデルの作成プラットフォームといった利用方法ができそうです。
ただ Notebook の実行環境としてしか使わないのであれば、ローカルで scikit-learn を使うことに対するアドバンテージがないかもしれないというのも AI Platform と同様です。
まとめ
今回は機械学習のライブラリ、サービスの使用感を、単純なモデル学習スクリプトを実装することで調べました。
単純な学習スクリプトを自分で実装する限りにおいて、ライブラリやサービスの機能的な面で決定的な違いは無いように思えました。
ただし、普及具合を考えると scikit-learn がやはりおすすめということになります。
scikit-learn は機械学習ライブラリのデファクトスタンダードです。それ自体の充実した API、ドキュメントもさることながら、日本語の解説記事も Web 上にあふれています。 Python の環境さえ作ればライブラリのインストールも容易であり、学習時やさくっと試したい時に最適でしょう。
今後の展望
今回は非常に単純な機械学習タスクに対し、自分で実装するという縛りの下でライブラリやサービスの使用感を調べました。
ですが、Amazon SageMaker や AI Platform、Azure Machine Learning などを見ていると、Notebook 以外にもいろいろな機械学習関連機能、サービスがあります。 プロジェクトの要件にもよるかと思いますが、マネージドサービスを使う利点はそういったサービス群にこそあるのではないかと感じています。
今後機会があればそれらのサービスも触ってみたいものです。
参考
- scikit-learn Machine Learning in Python
- H2O.ai Documentation
- h2oai/h2o-tutorials
- Smile - Statistical Machine Intelligence and Learning Engine
- Apache Spark
- Amazon SageMaker(機械学習モデルを大規模に構築、トレーニング、デプロイ)| AWS
- Amazon SageMaker Python SDK — sagemaker 1.51.0 documentation
- Google Cloud - AI & Machine Learning Products
- Google Cloud - AI Platform Notebooksベータ版
- Azure Machine Learning
-
最新版を入れ直すことも可能かもしれないが未調査。↩