dely Tech Blog

クラシル・TRILLを運営するdely株式会社の開発ブログです

データサイエンスチームでの1ヶ月インターンの記録

こんにちは。delyインターンのしょーといいます。 データサイエンスチームで1ヶ月間インターンさせていただきました。
本記事では、インターンで行なってきた事柄を紹介していきます。

目次

1. コホート分析

レシピ詳細画面のUIが変わったことによるリテンションの変化を分析しました。

分析手法

コホート分析を用いました。なぜコホート分析を用いたかというと、リテンションの変化が一目で分かりやすいからです。

roboma.io

今回はGoogleアナリティクスではなく、Pythonを用いてコホート分析を行いました。

まず、以下のデータをSQLで取り出して分析に使用します。

date: 最初にレシピ詳細画面を開いた日
past_days: dateから何日後にアプリを起動したか
user_count: dateの日にアプリを起動した人の中で、さらにpast_days後にアプリを起動した人数
total_count: dateの日にアプリを起動した人数

user_countをtotal_countで割ると、それぞれのリテンションを算出することができます。この値と、date、past_daysを用いてピボットテーブルを作成し、seabornで図を作成しました。

結果

完成した図がこちらです。
(イメージ図となっています、ご了承ください。) f:id:syou818:20190822184050p:plain

こちらを用いてUI変更前との比較を行なった結果、新しいUIの方がリテンションが改善されていることが分かりました。

2. アプリダウンロード数の推移

データレイクごとのアプリダウンロード数のデータを抽出し、それぞれのデータレイクにおいてデータが欠損してないかを調べました。
クラシルのデータレイクは以下を参照ください。

logmi.jp

今回はeternalpose、logpose、firebaseの3つのデータレイクを用いました。

分析手法

それぞれのデータレイクからアプリダウンロード数を、SQLを書いてデータを取り出し、seabornを用いて可視化しました。
日毎に5ヶ月の期間で推移を見ていきました。

結果

可視化したグラフは非公開とさせていただきます、申し訳ございません。

それぞれのデータレイクのアプリダウンロード数を確認したところ、firebaseにおいて、他の2つのデータレイクに比べて所々極端に少なくなっているところがあり、データの欠損が確認できました。このデータの欠損は今後のクラシルのデータ分析にも影響を与えると考えたので、開発チームに伝えてデータの修正をしていただきました。

また、logposeに格納されているアプリダウンロード数が、序盤から中盤まで他の2つのデータベースより少なかったことが分かりました。更に詳細に調査を行った結果、iOSのダウンロード数は正常でしたが、androidのダウンロード数が序盤から中盤まで少なかったため、androidのデータに何か異常が起きていたのだと考えられます。

3. 動画視聴予測モデル作成

ユーザが任意のレシピ動画を見るか見ないかを予測するモデルを作りました。   目標は実際のサービスに組み込めるようなモデルです。

以下用いるデータは、Athenaのeternalposeより取り出しています。

基礎となるデータフレームに至るまで

まず初めのアプローチとして、あるユーザがお気に入りしている動画に含まれている食材のデータを用いることを検討しました。

user_id: あるユーザー
video_cnt: ユーザがお気に入りしているビデオの個数
ingredient_count_list: ユーザがお気に入りした動画に含まれている食材とその個数のリスト

f:id:syou818:20190910212432j:plain

しかしこのまま用いようとすると、ユーザのお気に入りしている食材の情報しか使用できません。また、個々の動画の情報も入れないと良いモデルは作れないだろうと考えました。

そこで、ユーザがお気に入りしている動画で使われている食材のカテゴリを使用することを考えます。しかし、このデータをAthenaから取り出すのにとても時間がかかってしまいました。さらにデータを取り出した後に、カテゴリでなく個々の食材をそのまま使用する方がいいのではないかと考え、結局苦労して取り出したデータは使用しないことにしました。(大きなタイムロスでした・・・)

このようなアプローチを続けていく中で、まずは以下のデータセットを試してみることにしました。

user_id: あるユーザー
video_id: ユーザーが見たビデオ
watch: ユーザーがその動画を見たら1、見ていないなら0
fav: ユーザーがその動画をお気に入りしていたら1、していないなら0
また全食材の列を作り、動画で使われている食材の列に1、使われていない食材の列に0

f:id:syou818:20190910212501j:plain

このうち「fav」と動画の食材を説明変数に、「watch」を目的変数にロジスティック回帰で学習させたところ、99%の正解率が出ました。
しかし考察したところ、

・ユーザー特性が何も入っていないこのモデルになんの意味があるのか?
・そもそもお気に入りしてるかを最初に知れることはありえないんじゃないのか?

となり、大幅な改良が必要であることが分かりました。

学習

これまでのことを踏まえ、以下のデータを特徴量とし、ユーザが動画を見るか推測するモデルを作りました。以下、学習はロジスティック回帰を使用し、グリッドサーチでハイパーパラメータチューニングを行い、k分割交差検証で評価(k = 10)で評価を行います。

・ユーザのアプリインストール日(days)(動画を見た日から何日前かが入っている)
・ビデオのカロリー(calorie)
・ビデオの再生時間(duration)
・ビデオの料理を作るのにかかる時間(cooking_time)
・ビデオに使われている食材1つ1つ(食材が使用されていればその食材の列に1、使用されていなければ0が入る)

f:id:syou818:20190910212528j:plain

テストデータに対して90.4%もの正解率が出たものの・・

f:id:syou818:20190901230733p:plain

上のような混同行列になり、またF1スコアは0.059となりました。これはつまり新規データに対して約6%程度でしか動画を見るか判断できないというものです。混同行列を見たときに、真陰性が7810と、他の要素より飛び抜けています。このことから、今回はとりあえず動画を見てない方に分類してしまえばおおよそ正解してしまうために、正解率は高く出たのだと推察されました。偽陰性が806であることからも上記のことが言えるはずです。

色々悩んだ挙句、どの特徴量を用いればより良いモデルを作れるか検討するために、ランダムフォレストを用いて、今回のモデルの特徴量ごとの重要度を算出してみることにしました。結果は以下のようになりました。値が大きい方がより重要な特徴量であり、範囲は 0 ~ 1 です。

days:0.42, dulation:0.04, calorie:0.03, cooking_time:0.02・・・

これより、daysだけとても重要であることが分かりました。今回ユーザの情報として用いたのはこのdaysだけであり、より良いモデルを作るために、ユーザの特徴量を増やしていけばいいのだと考えました。

精度向上に向けて

次の3つのことを行いました。

①特徴量ごとの分布を正規分布に近づける
学習率は下がってしまうけれども、今回のような予測では、癌予測のように癌である人を確実に当てなければいけないものというよりは、様々なデータに対して予測できる汎化性能の方が重要と考えたためです。正規分布に近づけるアプローチとして、それぞれの特徴量の箱ひげ図と基礎統計量を観察し、外れ値を除去するように、平均値と中央値が近づくように、データを切り取ることをしました。

②データ数を増やす
これまで使用したデータはベルヌーイサンプルによってランダム抽出を行なっていました。データ数を増やす事によって、さらに汎化性能が上がることが予想できます。

③特徴量を増やす
先程までの特徴量に加え、以下の特徴量を追加しました。
・ユーザがお気に入りしている動画の個数
・動画を見たときにユーザがログインしていたか(していれば1、していなければ0とした)
・ユーザがプレミアム会員か(プレミアム会員ならば1、通常会員ならば0とした)

この結果、

テストデータに対する正解率:94.2%

f:id:syou818:20190901233943p:plain

F1スコア:0.76

となり、これまでで最も良い結果が得られました。

このモデルを利用した機能提案

ユーザがアプリを開いたとき、そのユーザーに合ったおすすめ動画を4つ表示させる

ユーザがアプリを開いたときに、API通信をしてdatabaseにアクセスします。そのdatabaseには各ユーザに対して提案する4つの動画が含まれており、このdatabaseを作るのに先程までのモデルを使用します。以下イメージ図です。

f:id:syou818:20190910215259j:plain

databaseの作り方
各ユーザに対して任意の数の動画をモデルに入れます。そこであるユーザーに対して、見ると判断されたビデオが4つ以上あったら、ランダムに4つの動画をそのユーザーに対する推薦動画としてdatabaseに入れます。もし見ると判断されたビデオが4つ未満のときには、4つに満たない分だけビデオの視聴ランキングの上位から選択して追加し、そのユーザーに対する推薦動画としてdatabaseに入れます。このdatabaseは様々な条件を考慮しつつ適当な頻度で更新をかけます。

databaseに登録されていないユーザーに対しては、ビデオの視聴ランキング上位4つを推薦することとします。

4. データサイエンスチームの取り組みに参加した

以上までが、私個人が取り組ませていただいた課題になります。
この他に、データサイエンスチームとしての取り組みに、私も一部参加させていただきました。内容はsakuraさんの記事にうまくまとめられています。

tech.dely.jp

tech.dely.jp

成果報告会を行なった

インターンの成果発表会を1時間ほど行わせていただきました。開発部の他チームからも聴きに来てくださったり、多くの質問をしてくださったりなど、とても貴重な時間でした。

最初どういうバックグラウンドの人が聴きに来てくださるか分からなかったので、どこまで説明するかとても悩みました。また、結構緊張しましたが、終始柔らかいムードで聴いてくださったためとても話しやすかったです。

発表は、使い慣れてるPowerpointがパソコンに入っていなかったため、Jupyter NotebookのRISEを用いて行いました。

qiita.com

終わりに

いかがでしたでしょうか?
この1ヶ月でとても多くの経験をさせていただき、物凄く成長することができました。これにはデータサイエンスチームの方々が、私のどんな質問にも丁寧に答えてくださったり、多くの貴重なお話をしてくださったことに尽きると思います。リソースが限られている中で、私に多くのリソースを割いてくださり本当にありがとうございました。

急成長を続けているベンチャー企業のスピード感を肌で感じつつ、皆がプロダクトのために熱心に取り組んでいる環境で急成長を遂げたい方、是非インターンに挑戦してみてください。