YKTのどっちがいいかな?

実世界連動地域貢献型すごろくゲームのアプリ開発状況を書いていきます。

YKT's キッチン

皆さんおはようございます。YKTです。さぁ今日もよろしくお願いします。

原資〇円でキャッシュバックキャンペーンを企画したいのですが、期間中のユーザー数の変動が読めないために、1回当たりのキャッシュバック額が決められずに困っています。プログラミングで何とかならないでしょうか? キャパカリオン(27歳)

キャッシュバック、いいですよね。
早速作っていきましょう。




今日作りたくなる、簡単プログラムを紹介!




f:id:labhea:20190316203623p:plain

毎回茶番に時間かけすぎ説

今回はキャパカリオンさんからおもしろそうな題材を頂きましたので、収支計算はいったんお休みです。こういうのは鮮度が大事だからね。

ただ、内容的にレベルがあがってしまいますので、プログラミング講座としてではなく読み物としてお楽しみいただければと思います。

もちろんコードは載せますのでやる気のある読者は解読にチャレンジしてみてください。(意外とついてこれるんじゃないかなとも思ってます)

問題設定

さて、まずは頂いた画像をそのまま載せます(許可は取ってるよ!)

f:id:labhea:20190316203653j:plain

なるほど。わからん。(おい)

なにはともあれ、提供いただいた例題を(私の勝手な解釈を交えて)まとめてみましょう。

前提

  • キャンペーンは1年間(52週)
  • キャンペーンへの投資額は1億円
  • キャンペーン開始前にn万人のプレミアム会員とa万人の無料会員がいる

キャンペーン内容

  • プレミアム、無料会員ともに1週間に1回キャッシュバックガチャを引ける
  • キャッシュバック額の期待値はプレミアムと無料会員で異なる

インプット

  • プレミアム会員の増加予測(最終m万人)
  • 無料会員の増加予測(最終b万人)

アウトプット(知りたい値)

  • キャッシュバック額の期待値(プレミアム会員用、無料会員用)

なるほど。どこの企業でも直面しそうな問題ですね。

今回はこの問題を、マーケティングのマの字も知らないどころか、企業勤めすらしたことない私が独断と偏見で考えるというお話です(笑)

問題の簡略化

ただ、このままですと少し煩雑ですので、もう少し問題を簡略化したいと思います。

特にプレミアム会員と無料会員の区別があるとややこしいので、会員の種類は1つにしてしましょう。

前提

  • キャンペーンは1年間(52週)
  • キャンペーンへの投資額は1億円
  • キャンペーン開始前に100万人の会員がいる

キャンペーン内容

  • 会員は1週間に1回キャッシュバックガチャを引ける

インプット

  • 会員の増加予測

アウトプット(知りたい値)

  • キャッシュバック額の期待値

今回のシステム

問題に入る前に、今回のシステムについて前置きしておきますね。

今回は、今まで通りにコードを実行できる埋め込み環境(paiza.ioというサービスです)は使っておりません。

その代わりjupyter-notebookの実行結果(皆さんはいじれません)を貼り付けています。

jupyter-notebookとは何ぞやって感じかと思いますが、ざっくりいうと、richなコメント文とpythonコード、および実行結果を1つのファイルとしてまとめておくことができるシステムです。

うん。わからんわな。これじゃ。とにかく何でもありのすごいシステムなんです。

詳しく知りたい人は以下の記事を参照してください。

pythondatascience.plavox.info

特に初学者はぜひjupyter-notebookをつかってpythonを勉強するのが良いかと思います。

さて、残念なのは、このjupyter-notebookはPCにpython環境を整えないと使えません。

正直環境構築はそんなに難しいものでもないのですが、学習意欲の障壁になるのは言わずもがな。

なんかいい方法はないかと探してみると・・・ありました(笑)

なんとgoogle先生がjupyter-notebookを魔改造してました。

その名もcolaboratory。

colab.research.google.com

googleアカウントさえ持っていれば誰でもwebブラウザでjupyter-notebookが使えちゃいます。すごすぎ、先生。

webブラウザなのでもちろんスマホでも動きます。

一番最後に、簡単に使い方を書きますので、今回のコードを動かしてみたい・値を変えてみたいという優良な読者の方々は試してみてください。

もうちょっとだけ前置き

本題に入る前にもうちょい前置き。今回は関数の定義モジュールの利用がありますので簡単に説明しておきます。

関数の定義

前回少しふれた関数を自分で作る方法についてです。オリジナルスペルとか言ってたやつですね。

基本文型は以下の通りです。

def 関数名(引数)
    ...なんか処理...
    return 戻り値

例題

#定義
def original_spell(a, b, c):
    x = a + b
    y = c * b
    return x, y

#使う
omochi, mochimochi = original_spell(1,2,'mochi')

引数

引数とは、関数を使用するときに値を格納する変数です。例題でいうと

a = 1
b = 2
c = 'mochi'

が入ることになります。

続いて、関数のインデント内の処理(x=a+bとy=c*b)が実行されます。

戻り値

関数の処理結果は戻り値として返却することができます。

返したい値はreturnのあとにコンマで列挙すればOKです。例題でいうとxとyが戻り値として返されていて、それぞれomochi, mochimochiという変数に格納されます。

関数の意義

関数の意義はコードの可読性と制作効率の向上です。例えば以下のようなコードがあったとしましょう。

x = 1000 * 1.08
y = 2000 * 1.08
print(x, y)

簡単な計算ですが、なんの計算をしたいのかぱっと見ではわかりません。

では次はどうでしょうか。

def apply_tax(x):
    return x * 1.08

x = apply_tax(1000)
y = apply_tax(2000)
print(x,y)

計算自体は先ほどと同じですが、関数名のおかげで、税の計算をしていることが伝わりますね。

また、xとyで同じ関数を使いまわしていますね。今回の例では関数内の処理は1.08をかけるだけですが、これが数十行にも及ぶ処理だった場合、コードが大分簡略化できますよね。

余談ですが、消費税は変わっていくものですので

TAX = 0.08

def apply_tax(x):
    return x * (1 + TAX)

x = apply_tax(1000)
y = apply_tax(2000)
print(x,y)

のようにパラメータにしておくとよいでしょう。

モジュールの利用

さて、自作関数の作り方がわかった人なら当然こう思うはずです。

誰か便利な関数作ってるんちゃうん?と。

正解です。というより、pythonは、野生のプログラマーによって作られた神がかった関数群が多く公開されており、強みの1つになっています。

こうした関数群はモジュールと呼ばれています。まあ魔法大辞典みたいなもんだと思ってください。

使い方は簡単です。

import numpy

みたいに書くだけです。あとはいままでのお約束通り、

numpy.sum(x)

みたいにピリオドで中身の魔法を取り出せます。

大辞典の名前とがが長ったらしい場合は、

import matplotlib.pyplot as plt

みたいにpltって呼びますよってしたり、ほしい機能だけ使いたいみたいなときに、

from scipy import integrate

みたいな書き方をしますが、英語の通りです。

ようやく本題

結局、プログラミング講座してしまったよ(笑)

本題に入ります。

ユーザーの増加予想をどうするか

まずは、ユーザーの増え方をモデル化しなければ話が始まりません。

そしてここが、企業のノウハウ、マーケティングセンスが出るところですね。

例えば類似企画によるユーザー推移の知見があればそれを参考にするのがいいでしょう。

さて、私には当然そんなノウハウなんてないので、ざっくり決めてきましょう(笑)

グーグル先生に聞いてみると成長曲線といえばロジスティック方程式というS字カーブが 有名だそうです。

ja.wikipedia.org

本来は生物の個体増加の関数らしいですが、顧客の増加予測にも使われるとかなんとか。

そして、よくよく調べてみるとロジスティック方程式は個人的に馴染み深いシグモイド関数と同義だということがわかりました。

シグモイド関数ディープラーニングでよく使われる(使われていた、かな?)関数で数式はこんな感じです。

 \sigma (x) = \frac{S}{1+e^{-a(x-x_0)}}

まずは、こいつの性質を見てみましょう。

gist.github.com

シグモイド関数の性質は大体わかりましたね。

繰り返しになりますが、このパラメータ決定は企業のセンスが絡んでくるところです。

特に増加速度やオフセットの部分はキャンペーンの宣伝戦略にも直結するところでしょう。

今回はincrease_speed = 0.2, offset = 20で続きを検討していきます。

いざ計算

顧客の増加関数が決められれば、あとは簡単です。

各ユーザー1週間に1回ガチャれるわけですから、ユーザー曲線を週に対して積分してやればキャンペーン中の総ガチャ回数がわかります。

原資をガチャ回数で割ればガチャ一回当たりに投資してよいキャッシュバック額になりますね。

ちなみにシグモイド関数積分は解析的に解けて、

 \int \sigma (x) dx = -\frac{S}{a} \log (1 - \frac{\sigma (x)}{S}) + C

です。

それではLet's coding!

gist.github.com

企業の腕の見せどころ part2

ここまでで、キャンペーンによる会員の増加数とガチャ1回にかけていいキャッシュバック額の関係がわかりました。

では、グラフから「100万人増を望むから1.2万円に設定しよう!」と決めればいいかというと当然NO!です。

なぜなら、

  • 原資1億円・100万人増 → 1.2万円/回が適切

  • 平均1.2万円が当たるガチャキャンペーン → 100万人増

は別事象だからです。

つまり、1.2万円が100万人増ほどの集客力があるのかどうか、吟味する必要があります。

一番手っ取り早いのは、ユーザーの関心度をモデル化してしまうことです。

当然キャッシュバック額が増えれば増えるほど会員数は増加するはずですよね。

このキャンペーンに対するユーザー関心度をマーケティングセンスを駆使することでモデル化に成功したとします。

ではこれを先ほどの計算結果とともにグラフにしてみましょう。

f:id:labhea:20190316204754p:plain

青線が先ほどの計算結果(x-yが入れ替わっています)で、キャッシュバック額をx万円に設定したときに原資1億円でカバーできる増加人数を、オレンジがキャッシュバック額x万円につられて増えるだろうユーザー人数を表しています。

結局これらの交点(1.5万円で45万人増)が、本キャンペーンにおいてユーザーの関心度と企業の投資額がかみ合うシナリオといえます。

まとめ

相変わらずなげぇ記事だなあ(笑)

さて、ここ最近プログラミングの基礎ばっか勉強してきて飽きてきたところかと思いますが、今回の実例で少しでも興味を持ってもらえればとうれしい限りです。

今回の例は結局、会員数の増加曲線とユーザーの関心度をどう予測するかが肝です。

そういうことを考えるのが得意だったり、仕事としている人がプログラミングできるようになると、よりよい意思決定ができるのではないかと思います。

なんかほかにもいい題材があったら募集します。

colaboratoryの使い方

まずは下記にアクセスします。

colab.research.google.com

colaboratoryが開くと思います。

開いた状態では閲覧しかできませんので、
[ファイル] - [ドライブにコピーを保存]
を選んで、自分のgoogle drive上にコピーします。

あとは適当にコードの値をいじってみて
[ランタイム] - [全てのセルを実行]
を選択してみてください。

グラフが変われば成功です。

その他、基本的な使い方は下記のサイトがとても丁寧にまとめてくれています。

deepinsider.jp