こんにちは、エンジニアの建三です。今回も相変わらず機械学習に関するお話です。
前回のブログで顧客分析の話をしました。エンドユーザーが問い合わせから来店に進むかをアクセスログを使って予想するというものです。
同じことを弊社の自動追客&CRMツール「ノマドクラウド」でも試せないか試行錯誤してみました。
この人来店するの??
ノマドクラウドは多くの不動産会社で使われており、それぞれの店舗でお客様を管理しています。スーモやホームズなどからその店舗に問い合わせが入ると、自動的にお客様が登録される仕組みになっています。エンドユーザーにはエンドユーザー用のページがメールで送られ、そこで提案された物件を見たり、営業マンとチャットでやり取り出来る仕組みになってます。
ただ、物件の問い合わせをしたからといって、全員が店舗へ来店するとは限りません。どのお客さんがどのくらいの確率で来店するか分かれば営業の効率が上がって最高ですよね!ということで来店予想モデルを作りました。
前回のノマド顧客分析と大まかな流れは一緒ですが、違う点が2つあります。
1. 分類ではなく確率を出す
前回作ったモデルは、その後APIとしてデプロイし、次のフェーズへ進まなそうなお客さんへ自動でメッセージを送るBOTとして毎日動いてます。その際どのエンドユーザーにメッセージを送るか分類する必要があります。つまり、機械学習のアウトプットに対して取るべき行動が分かってる時は、はっきりと分類する必要があります。
しかしノマドクラウドに関しては、同じツールでも多くの不動産会社が使ってるので、会社単位、あるいは店舗単位で使い方が異なります。こちらで来店するかどうかを分類して解決策を作るよりも、まずは確率を表示し、それをどう役立てるかはそれぞれにお任せした方が良いのではないかと思いました。忙しい時は来店率の高いお客さんを優先して対応したり、逆に暇な時は来店率の低いお客さんに時間をかけて物件を提案することも出来ます。実力のある営業マンが来店率の低いお客さんを営業するというのもありかもしれません。
2. 一回予想して終わりではなく、毎日更新する
前回のモデルは、前日登録したエンドユーザーに対して一回使ってお終いというものでした。しかし今回は、常に顧客情報の一つとして表示することになります。お客様の現時点での来店率を表示するためには、頻繁に来店率を更新する必要があります。
モデルの作成
一番エンドユーザーの情報がつまってるのがアクセスログなので、今回もアクセスログを使いました。 問い合わせしてから1日しか経ってないお客様と、3ヶ月経ったお客様両方に対応するモデルを作らなければいけないため、結構苦戦しました。
メソッド1
モデルを幾つか作って問い合わせから何日経ってるかによって違うモデルを使おうかと思いましたが、さすがにそれは避けたいのでやめました。沢山のモデル学習させるのは面倒だし、データを分けなければならないのでそれぞれのモデルに使えるデータ量が減ってしまいます。
メソッド2
次に試みたのが、過去一週間分のデータのみ使うというものです。これは自然言語処理のn-gramからインスピレーションを受けました。データ構造はこんな感じです。実際pathはもっとあります。
1日前 | 2日前 | 3日前 | 4日前 | 5日前 | 6日前 | 7日前 | |
---|---|---|---|---|---|---|---|
/messages | 0 | 0 | 2 | 1 | 0 | 0 | 0 |
/contacts | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
このエンドユーザーは4日前に問い合わせしたので、それ以前は0になります。 これをLSTMに入れたり、平たくしてロジスティック回帰に入れたりしましたが、残念な結果となりました。過去一週間だけの行動で大体分かるだろうと思いましたがそうではなかったようです。考えられる理由としては、中には長期的にお部屋を探してるお客さんもいらっしゃいます。なので過去1週間アクセスが全くないとしても、昔アクセスがあった人と一回もアクセスしてない人ではやはり差があります。
メソッド3
アクセスログは昔のも捨てずに全部使った方が良いというのは分かりました。じゃあ全部足せば良いかというと、そんな単純な話ではありません。仮にあるエンドユーザーのアクセスログをpath毎に集計したとします。
/messages | /contacts | rooms/number | proposing_items | |
---|---|---|---|---|
log | 1 | 0 | 1 | 2 |
これだけだと、問い合わせてから何日経ってるかという重要な情報が抜け落ちてます。これが1日後のログならまあまあ来店する見込みありですが、1ヶ月経っててこれだと少ないので来店率は低くなるはずです。なんとかこれを解決する方法はないでしょうか?
とてもシンプルな方法としては、問い合わせからの日数を一つの特徴として入れてしまうことです。
/messages | /contacts | rooms/number | proposing_items | days | |
---|---|---|---|---|---|
log | 3 | 0 | 1 | 2 | 7 |
これで大分情報がリッチになりました。いつアクセスしたかの情報は失われていますが、十分でしょう。更にエンドユーザーが送ったメッセージ数も加えてみました。
/messages | /contacts | rooms/number | proposing_items | days | # of messages | |
---|---|---|---|---|---|---|
log | 3 | 0 | 1 | 2 | 7 | 2 |
確率が出せる分類器
今回はscikit-learnに入ってるアルゴリズムを色々試してみましたが、確率を出せるものと出せないものがあります。scikit-learnのドキュメンテーションを見ると分かりますが、predict_probaというメソッドがあるものは確率を出せるものです。
ただしpredict_probaがあるからといって何でも正確な確率を出せるとは限りません。例えば確率といえばNaive Bayesを思い浮かべますが、Naive Bayesはあくまで分類器として使うべきで、確率はあまり参考になりません。
K-nearest neighborも確率を出せます。この場合はKの中のクラスの割合によって確率が決まります。例えばK=5で3つのクラスが1で残り2つが0だったら、60%の確率で1となります。これだと全部同じクラスだった場合に確率が100%や0%になってしまいます。さすがに「このお客さんは100%の確率で来店します」とは言えないので、K-nearest neighborも確率を出すのには向いていません。
個人的にK-nearest neighborは好きなアルゴリズムトップ3に入るので使ってみたかったですが残念です。K-nearest neighborはテストタイムがかかるのでスピードを重視するものには使えませんが、今回はスピードは重要じゃないのでまさにぴったりだったのですが... ちなみにK-nearest neighborについてもっと知りたいという方は、僕が昔書いたブログ(英語)で詳しく解説してるので良かったら読んでみて下さい。
ちょっと話が逸れました... 確率を出すには、ロジスティック回帰やニューラルネットワークが良いでしょう。どちらもSigmoidやSoftmaxをアウトプットに使うので良い具合に確率を出してくれます。
まとめ
このモデルは来店率だけでなく様々なビジネスシーンで使えます。「チャーン率予想」は有名な例ですね。SaaSなどのビジネスではチャーン率を下げることが非常に重要なので、解約しそうなお客様を早期に予想して、そのお客様に割引を提供するなど何かしらのアクションを打つのに役立てることが出来ます。
もしこのようなビジネスの課題を抱えていたら是非お話を聞かせて下さい!きっとデータが答えを出してくれます。
そしてイタンジではビジネスの課題をITで解決したエンジニアを募集してますので、興味のある方は是非オフィスに遊びにいらして下さい!