FiNCでの機械学習の使われ方 ~ 数学からUI、そしてインフラまで

はじめに

FiNCでエンジニアインターンをしております、栗栖です。

現在AIチームに所属しており、画像認識の調査や、機械学習を使ったモデルのアプリケーションへの応用を担当しています。

今回は、アプリ上の課題を機械学習を使って解決した実例を、ご紹介したいと思います。

それでは、本記事のアジェンダです。

  1. 生活習慣アンケートとその課題
  2. 生活習慣の予測モデルとそのUI
  3. Rails + Pythonによるアプリケーションの運用
  4. まとめ

1. 生活習慣アンケートとその課題

FiNCのアプリでは、お客様の健康増進のソリューションを提供するために、生活習慣アンケートがあります。

このような生活習慣アンケートは、ベストなソリューション提供のためには必要不可欠なのですが、一定量の質問を答えなければならないため、ユーザーの負担がやや大きいということが課題でした。

そこで、設問数を減らせないのか?という問題に取り組むことになりました。

2. 生活習慣の予測モデルとそのUI

機械学習による解決策の考案

この課題(生活習慣アンケートの設問数の削減)をどのように解決するかなのですが、結論から言うと、

  1. 情報量の多い質問を抽出する
  2. 他の質問は機械学習によって回答結果を予測する
  3. 予測が間違っている場合は、ユーザーがフィードバックして簡単に修正できるようにする

という方向性で検討しました。

なぜこの考えに行き着いたのかというと、

  1. 多くの生活習慣の中には、他の生活習慣に影響を与えるような、情報量の大きな生活習慣があるはず
  2. 例えば4択の質問を5問聞くだけでも、1024通りの回答パターンがあり、十分な情報量を得られるはず

といった仮説があったからです。

仮説1に関しては、一例として、20代の女性で「間食をよくする」という情報があれば、自ずと「お菓子をよく食べる」という可能性が高いことは容易に想像できます。

仮説2には書いたそのままですが、実際、人の生活習慣は多様であるとは言え、ある程度パターンがあるため、1024通りは十分な情報量であるとも考えました。

主成分分析による、重要な質問の抽出

主成分分析は簡単に言うと「複数のベクトルから、分散が最大化されるようなベクトルを作成する」 手法です。

以下はwikipediaから拝借した図です。

この図のデータセットの場合、右斜め上の矢印方向に沿ってデータが集中していることが見て取れます。

そうすると、x方向の(1, 0)ベクトルと、y方向の(0, 1)ベクトルの2つによって各座標を表すのではなく、図中の2本の矢印方向の単位ベクトルを使ったほうが、データを効率的に表現できます。

今回であれば、複数の質問の回答結果を多次元空間の座標として表せるため、そこで主成分分析を行い、抽出されたベクトルに対して寄与度の高い質問を順に選びました。

サポートベクターマシンによる回答結果の予測

サポートベクターマシン(SVM)は、特徴量を入力し、カテゴリ等の分類を行うアルゴリズムです。

今回のケースは、

  • 年齢、性別、BMIのようなユーザーの基本情報
  • いくつかの質問の回答結果

を入力して、他のある質問について、回答結果をアウトプットとしました。 質問は基本的に択一式なので、分類問題に帰着されます。

SVM以外のアルゴリズム、例えばランダムフォレストなども試しましたが、今回はSVMの精度が最も高かったため、採用しました。

3. Rails + Pythonによるアプリケーションの運用

運用上の課題とシステム全体像

企画が出来たところで、最後は実装についてですが、大きく分けて2つの課題がありました。

ひとつは、FiNCのアプリケーションの大半はRailsにより実装されていますが、数理統計・機械学習のライブラリはPythonを利用したかったため、これらを共存させなければいけない、ということです。

もうひとつは、機械学習の場合、Trainingという過去のデータからモデルを作成するプロセスと、Testという実際にそのモデルで予測等を行うプロセスとの2つがあり、これらのサーバー間の連携です。

結果的に、システムの全体像は以下のようになりました。

以下の点がポイントに絞ってご紹介したいと思います。

  • 定期的に立ち上げるTrainingサーバ
  • S3を介したスクリプトの配布
  • Railsからpythonのプロセスを作動

定期的に立ち上げるTrainingサーバ

予測モデルを生成するには、過去のデータを使ってTrainingを行う必要があります。

理論上、データが増えれば増えるほど、モデルの精度は良くなるので、定期的にTrainingを行う必要があります。 とはいえ、データがあまり増えていなければそれほどモデルに変化が無いため、実際にはTrainingは週に1回や月に数回程度行います。 ですので、Trainingサーバーは定期的に立ち上げて運用するようにしています。

執筆時点ではモデルの頻繁な改良もあるため、手動での作業がメインですが、運用が安定化してくれば、cronサーバから自動で立ち上げ・シャットダウンに完全に移行予定です。 また、コスト削減のためにスポットインスタンスの利用も検討しています。

S3を介したスクリプトの配付

Training用のサーバーで出来たモデルのスクリプトを、実際に動かすTestサーバーに転送しなければいけないのですが、このファイルのやり取りにはS3を経由させています。

S3を経由させる以外にも、

  • scp、rsyncコマンドによるスクリプトの転送
  • 自動でGithubにforce push & CI経由によるデプロイ

などの手段が考えましたが、最終的にS3に一旦アップロードする運用が安全であると結論付けました。 Testサーバーのスクリプトはデプロイ時に自動でS3からダウンロードするようにしています。

Railsからpythonのプロセスを作動

Trainingによって生成されたモデルスクリプトを実際にどのように動かすのかが問題です。やり方として、

  1. Python専用のサーバーを作成しAPIで連携する
  2. Rubyを運用しているサーバーでPythonも動かす

の2通りの方法が考えられますが、結果的に2を採用しました。

1の方法の場合、サーバー構成管理は楽になのですが、サーバーを増やしたりPythonのアプリケーションを作成しなければいけないので、手間はかかります。

一方2の方法の場合、Rubyを動かしているサーバーにPythonのモジュール等もインストールしなければならず、Ansibleによるサーバー構成管理は多少、煩雑になります。 しかし、シェルスクリプト経由でPythonを動作させるだけなので、アプリケーションレイヤーの開発は非常に楽になります。

この両者を比較した時、今回の場合、スクリプトを動かすためだけに別のサービスを立ち上げることの手間の方が大きいと考えました。 また、FiNCはマイクロサービスを採用しているため、このような特殊なサーバー構成も気軽に行える状況にありました。 こうして、方法2のRubyのサーバーでPythonを動かす方法を採用するに至りました。

4. まとめ

ご紹介したように、FiNCのAIチームは、サービス上の課題発見から、機械学習による解決策の提示、UIまで含めた企画、実装・運用までを広く担っています。

今回行った改善では、必須質問数は従来の6分の1程度になり、回答率も15%程度向上しました。

この他にも、

  • ソリューションのパーソナライズ
  • 食事画像の認識
  • SNSでのユーザー推薦
  • タイムラインの最適化

など、様々なプロジェクトが動いております。ご興味ある方は是非、気軽にFiNCに遊びに来ていただければと思います

AIエンジニア募集中です