吸収マルコフ連鎖を用いたプロダクト分析アイデア

はじめに

プロダクトの分析においては、ユーザーを任意にセグメンテーションして、より好ましいセグメントに遷移してもらうように施策を考える、ということを行います。例えば RFM 分析では Recency, Frequency, Monetaly の 3 つの尺度でユーザーを分類して、現状を把握し、優良グループを増やすなどの施策を考えます。
このとき、任意に定義された状態をユーザーは時間に応じて移動していくことになります。複数の状態を遷移していくような行動をモデリングする際にはマルコフ連鎖を用いるアイデアがあります。

今回は例として下記のような 3 つの状態を定義して、月次でのユーザーの状態遷移をマルコフ連鎖でモデリングするアイデアについて書いていこうと思います。

  • 定着ユーザー: 前月も今月もアクティビティがあるユーザー

  • 休眠ユーザー: 前月にアクティビティが 1 度もなかったユーザー

  • 復帰ユーザー: 前月休眠だったが今月アクティビティがあるユーザー

単純マルコフ連鎖

マルコフ連鎖は、時間とともに変化していく状態が次の 2 つの仮定を満たす過程を指します。

  1. 推移確率行列が時間に応じて一定であること

  2. 次の状態が前の状態のみに影響をうけること

  1. の推移確率行列とは、前の各状態から次の各状態へと遷移する確率を行列で表現したものです。例えば、A と B という 2 つの状態をユーザーが行き来するとして、次が成り立っているとします。

  • 今 A にいて次に A にいる確率は 0.3

  • 今 A にいて次に B にいる確率は 0.7

  • 今 B にいて次に A にいる確率は 0.6

  • 今 B にいて次に B にいる確率は 0.4

このとき、推移確率行列 $P$ は次のようになります。行が from, 列を to とした表現です。

$$
P = \begin{pmatrix}0.3&0.7\\0.6&0.4\end{pmatrix}
$$

マルコフ性を仮定できれば、今の状態のベクトルに推移確率行列を掛け合わせることで次の状態を予測することができます。

仮に現在 A にいれば 1 時点後は

$$
\begin{pmatrix}1&0\end{pmatrix} \begin{pmatrix}0.3&0.7\\0.6&0.4\end{pmatrix}=\begin{pmatrix}0.3&0.7\end{pmatrix}
$$

となり、2 時点先はもう 1 回 $${P}$$ を掛け合わせて

$$
\begin{pmatrix}1&0\end{pmatrix} \begin{pmatrix}0.3&0.7\\0.6&0.4\end{pmatrix}\begin{pmatrix}0.3&0.7\\0.6&0.4\end{pmatrix}=\begin{pmatrix}0.51&0.49\end{pmatrix}
$$ 

となります。これは A 地点をスタートして 2 時点先に A にいる確率が 51%, B にいる確率が 49% ということを意味しています。

ユーザーの状態遷移の定義と予測

今回は仮で次のような遷移があると考えてみます。

  • 定着ユーザーは 0.6 の確率で翌月休眠し、0.4 の確率で翌月もアクティビティがある。

  • 休眠ユーザーは 0.9 の確率で翌月も休眠したままで、0.1 の確率で復帰する

  • 復帰ユーザーは 0.3 の確率で翌月もアクティブで定着ユーザーとなり、0.7 の確率で再び休眠する

このとき、推移確率行列は次のようになります。行は上から(定着, 休眠, 復帰) の順に並べています。

$$
P=\begin{pmatrix}.4&.6&0\\0&.9&.1\\.3&.7&0\end{pmatrix}
$$

現在のユーザーが翌月それぞれの状態である確率は次のように $${P^2}$$ を計算して求められます。

import numpy as np

P = np.array([
    [.4, .6, 0],
    [0, .9, .1],
    [.3, .7, 0]
])

P2 = np.linalg.matrix_power(P, 2)
print(P2)

"""
array([[0.16, 0.78, 0.06],
       [0.03, 0.88, 0.09],
       [0.12, 0.81, 0.07]])
"""

P3 = np.linalg.matrix_power(P, 3)
print(P2)

"""
array([[0.082, 0.84 , 0.078],
       [0.039, 0.873, 0.088],
       [0.069, 0.85 , 0.081]])
"""

定着ユーザーであった場合に2ヶ月も定着ユーザーである確率は 16%, 3 ヶ月後も定着している確率は 8.2% となりました。

ここで定着ユーザーの翌月定着率を 0.4 -> 0.5 に上げられたとするとどの程度の効果が見込めそうか試算してみたいと思います。
定着 -> 定着が 0.5 になるので、定着 -> 休眠は 0.5 に変わり、それを推移確率行列に反映させましょう。

P = np.array([
    [.4, .6, 0],
    [0, .9, .1],
    [.3, .7, 0]
])

P2 = np.linalg.matrix_power(P, 2)
print(P2)

"""
array([[0.25, 0.7 , 0.05],
       [0.03, 0.88, 0.09],
       [0.15, 0.78, 0.07]])
"""

現在定着ユーザーである人が 2 月後も定着ユーザーである確率は 25% と推定されました。

さて、単純マルコフ連鎖には、十分長い未来においては、初期の状況と独立して特定の行列に収束していく性質があります。初期状態がどの状態を出発しても、十分長い未来においては、各々の状態にたどり着く確率は同じになります。
実際に 6 ヶ月先, 12 ヶ月先, 24 ヶ月先を見てみましょう。

print(np.linalg.matrix_power(P, 6))
"""
array([[0.0595  , 0.85572 , 0.08478 ],
       [0.050868, 0.862768, 0.086364],
       [0.05562 , 0.858888, 0.085492]])
"""

print(np.linalg.matrix_power(P, 12))
"""
array([[0.05178448, 0.8620197 , 0.08619582],
       [0.05171749, 0.86207439, 0.08620812],
       [0.05175437, 0.86204428, 0.08620135]])
"""

print(np.linalg.matrix_power(P, 24))
"""
array([[0.05172414, 0.86206896, 0.0862069 ],
       [0.05172414, 0.86206897, 0.0862069 ],
       [0.05172414, 0.86206896, 0.0862069 ]])
"""

print(np.linalg.matrix_power(P, 30))
"""
array([[0.05172414, 0.86206897, 0.0862069 ],
       [0.05172414, 0.86206897, 0.0862069 ],
       [0.05172414, 0.86206897, 0.0862069 ]])
"""

最終的に `[0.05172414, 0.86206896, 0.0862069 ]` という値に収束しました。どの初期状態(`[1, 0, 0]` | `[0, 1, 0]` | `[0, 0, 1]`)で出発してもこのベクトルが計算結果として得られます。マルコフ性の仮定が正しいのであれば、ずっと定着するユーザーは最終的には 5% 程度となり、86% は休眠してしまう結末が待っていることになります。

吸収マルコフ連鎖

さて、この状態に達したらずっとその状態に留まってしまう、ブラックホールのような状態を追加で考えると、また別で面白いことがわかります。一度入ったら抜け出せない状態は吸収状態といい、吸収状態を持つマルコフ連鎖を吸収マルコフ連鎖と呼びます。

例として、解約ユーザーという状態を追加で考え、一度解約したら二度と再登録しないと仮定します。そうすると、解約という状態は吸収状態と考えられます。
先ほどの状態遷移図に解約ユーザーを追加しましょう。解約状態ヘはそのほかのどの状態からも遷移できるとして、既存の状態遷移確率にも修正を加えます。

吸収マルコフ連鎖においては、吸収状態を推移確率行列の左上におくと後々便利です。具体的には次のように表現します。行の上から (解約, 定着, 休眠, 復帰) の並びです。

$$
\begin{pmatrix}1&0&0&0\\.05&.4&.55&0\\.1&0&.8&.1\\.5&.3&.2&0\end{pmatrix}
$$

吸収マルコフ連鎖からわかること

吸収状態を持たせると新たに次がわかるようになります。

① 非吸収状態に留まる平均的な期間の長さ

② 非吸収状態から吸収状態へ移動するまでの平均的な期間の長さ

③ 特定の非吸収状態から特定の吸収状態へいく確率 ※今回のケースでは吸収状態が 1 つしかないので、どこから出発しても確率 100% で解約の状態へ行きます。複数の吸収状態がある場合には嬉しい内容です。

① 非吸収状態に留まる平均的な期間の長さ

吸収状態が含まれているため、非吸収状態で十分長い期間を考えると、いずれは吸収状態へすべて遷移してしまいます。ですので、こちらは右下領域の $${Q}$$ について未来の各期のを足し合わせていけば求めることができます。途中から $${Q^{n}}$$ は $${O}$$ になり、一意に値が求まります。この $${(I - Q)^{-1} = N}$$ はマルコフ連鎖の基本行列というそうです。

$$
I + Q + Q^2 + Q^3 + ... = (I - Q)^{-1}
$$

Q = np.array([
    [.4, .55, 0],
    [0, .8, .1],
    [.3, .2, 0]
])

I = np.eye(3)

N = np.linalg.inv(I - Q)
print(N)

"""
array([[1.96721311, 6.01092896, 0.6010929 ],
       [0.32786885, 6.55737705, 0.6557377 ],
       [0.6557377 , 3.1147541 , 1.31147541]])
"""

上記は、定着ユーザーが出発であった場合(解約するまでに)定着ユーザーに留まる長さは平均して 1.97 ヶ月間, 休眠に留まる長さは平均して 6.01 ヶ月, 復帰に留まる長さは 0.60 ヶ月であるということになります。

② 非吸収状態から吸収状態へ移動するまでの平均的な期間の長さ

① で非吸収状態の各状態に留まる平均期間がわかっているため、それらの合計を求めれば ② も求まります。例えば定着ユーザーが出発点だった場合は、`[1.96721311, 6.01092896, 0.6010929 ]`このベクトルを足し合わせれば良いことになります。
次のようにして出発時の各状態を一括で計算することができます。

np.dot(N, np.ones(3))

"""
array([8.57923497, 7.54098361, 5.08196721])
"""

③ 特定の非吸収状態から特定の吸収状態へいく確率

今回の場合は吸収状態が「解約」という 1 つしかないため、最終的に解約に行く確率はどこを出発としても自明に 1 になります。ですが複数の吸収状態がある場合を想定して求め方をメモしておきます。

次の 1 ステップで非吸収状態->吸収状態へ遷移する確率は分解した行列の左下部分 $${R}$$ で表現されています。 定着->解約は 5%, 休眠->解約は 10%, 復帰->解約は 50% です。
ところで、① で(出発地点が定着ユーザーの場合)各非吸収状態に留まる平均期間は `[1.96721311, 6.01092896, 0.6010929 ]` と得られていました。ですので例えば定着状態にある 1.97 ヶ月の間で毎月 5% の確率で解約する可能性があったことになり、合計して $${ 1.96721311 \times 0.05 = 0.098 }$$ だけ定着状態から解約する確率があったことになります。
同様にして、休眠状態には 6.01 ヶ月間いてその間毎月 10% の確率で解約する可能性があったため、合計 $${6.01092896 \times 0.10 = 0.60}$$ 復帰から解約は $${0.6010929 \times 0.50 = 0.30054645}$$ となります。
これらを合計すると 1 となり、これが求めたい確率です。

この計算は $${N}$$ と $${R}$$ の行列積をとることですべてのパターンを一括で計算できます。

np.dot(N, R)

"""
array([1., 1., 1.])
"""

おわりに

実際のところはマルコフ性の仮定が満たされることは例に挙げたケースではそう無いように思います。ただし、例えば過去に施策をしていなければこうなっていただろう、あるいは現在何も手を打たなければこうなるだろう、といった反実仮想チックな参考情報として見るなど、仮に仮定が満たされていたらとして考えてみるのは有用かもしれません。

参考書籍により詳しくマルコフ連鎖モデル(あるいは他の数理モデル)の説明があります。さまざまな社会学のテーマに対して数理的にアプローチする考え方がとても面白くて、読み始めるとあっという間に時間がたってしまう良書でした。

Reference

I. ブラッドリー, R. L. ミーク  社会のなかの数理[新装版]


最後まで目を通していただきありがとうございました。もし内容に誤りを見つけていただいた場合はご指摘いただけますと幸いです🙇‍♂️

この記事が気に入ったらサポートをしてみませんか?