サービスの解約率・機械の故障率などが予測できる”生存時間分析”とは?

このエントリーをはてなブックマークに追加

こんにちは。データデザイン部でデータサイエンティストを担当しております。堀です。

AI・データ活用を検討している方々の中には、「広告などの施策の効果を確認したい」、「顧客のLTVを計算したい」、「サービスの離脱率を推計したい」などの目的を持っていらっしゃる方も多いのではないでしょうか?

そのような課題には生存時間分析という手法が適している場合が多いです。今回はその生存時間分析について、数式を極力使用せずPythonでの実装方法を交えながらご紹介させていただこうと思います。

目次

  • 生存時間分析とは
  • 生存時間分析の種類
  • 生存時間分析のPython実装
  • おわりに

生存時間分析とは

生存時間分析ではその名の通り、生存する時間を分析します。生存する時間とは、医療の分野では「感染や回復までの時間」、工業の分野では「機械や部品が故障するまでの時間」、ECなどのWEBサービスでは「ユーザーがサービスを解約するまでの時間」などを指します。
過去のデータを用いて、これらの生存する時間を統計的に明らかにし、予測していくのが生存時間分析です。

応用例としては、広告などの施策を行ったユーザーと行っていないユーザーにグループを分け、それぞれのグループで生存時間分析を行うことで、施策による解約率の差を計測することもできます。その他にもロイヤルカスタマーの定義が出来ているのであれば、ユーザーがロイヤルカスタマーになるまでの時間を推計することが出来ます。
また、後ほど説明しますが、Cox比例ハザードモデルなど説明変数(医療であれば投薬の有無や年齢など)を導入することで、その説明変数がどのように生存時間に影響するか明らかにする手法も存在します。

生存時間分析の種類

生存時間分析には様々な手法が存在しますが、大別するとパラメトリック、ノンパラメトリック、セミパラメトリックの3種類に分けることが出来ます。
それぞれの特徴や具体的な手法を紹介していきます。

パラメトリック分析

  • 生存時間の分布を統計的な分布を当てはめて計算する分析方法
  • 計算が簡単であり、説明が行いやすいことがメリットではあるものの、事前にある程度、分布を把握する必要があるため、分布を把握できない場合には活用できない
  • 手法には「指数分布」や「ワイブル分布」が活用される場合が多い

ノンパラメトリック分析

  • パラメトリックのように分布に当てはめることはせず、既存のデータから分布を導き出し計算する分析方法
  • パラメトリックのデメリットであった「分布を事前に把握する必要がある」という課題を解決できる
  • 基本的に過去の生存時間のみで生存時間を推計するため、説明変数を投入することが出来ない
  • 手法には「カプランマイヤー推定法」が用いられる場合が多い

セミパラメトリック分析

  • パラメトリックとノンパラメトリックの中間の分析方法
  • 説明変数を導入することもでき、ノンパラメトリックと同じく分布を仮定する必要がないため生存時間分析ではよく使用される
  • 説明変数を導入する際にはドメイン知識や統計学の知識を求められることが多いため、パラメトリック分析などと比較すると少々難易度が高い
  • 手法には「Cox比例ハザードモデル」が活用される場合が多い

生存時間分析のPython実装

Pythonなどのプログラミング言語やSAS等のツールを活用することで生存時間分析を簡単に行うことができます。今回はPythonでのCox比例ハザードモデルの実装方法をご紹介します。
Pythonの実行環境が無い方は こちらを参考に準備頂ければと思います。

1.ライブラリのインストール

はじめに分析で必要となるライブラリのインストールをしていきます。
Jupyter notebookのセル内に以下のコマンドを入力し実行してみましょう。

!conda install -c anaconda pandas seaborn scikit-learn -y
!conda install -c conda-forge lifelines matplotlib –y

続いて、インストールができたらライブラリをロードします。
以下のコードをセルに入力して実行しましょう。

mport pandas as pd
from lifelines.datasets import load_rossi
from lifelines import CoxPHFitter
import matplotlib.pyplot as plt

%matplotlib inline

これで分析の準備が整ったので、実際にデータをロードして分析していきます。

2.データのロード

今回は生存時間分析のライブラリである「lifelines」に入っている「ROSSI」データを使用します。
データをロードしていきます。

ROSSIデータとは1970年代に米国のメリーランド州の刑務所から釈放され、釈放後1年間追跡した432人の囚人に関するデータセットです。
元々このデータセットは再犯を減らすための実験において、財政支援を受けた囚人と受けなかった囚人にどのような違いがあるかを明らかにするために集められたものです。そのため、釈放された囚人のうち、半数は実験的措置としての財政支援を受けています。また、1年間再逮捕されなかった人たちは52週で観測を終了しています。
カラムの説明は以下のとおりです。

生存時間分析では「生存時間(ROSSIデータではweek)」と「イベント(ROSSIデータではarrest)」の2つの情報が必須です。2つの必須情報以外にも説明変数の効果を知りたい場合は、そのデータも集める必要があります。

3.Cox比例ハザードモデルでの推計

データがロードできたのでCox比例ハザードモデルを使用してみましょう。今回は説明変数として「財政支援の有無」、「年齢」、「過去の有罪判決回数」を使用します。以下がその実装方法です。

cph = CoxPHFitter()
cph.fit(rossi[["week", "arrest", "fin", "age", "prio"]], duration_col='week', event_col='arrest')

cph.print_summary()

「CoxPHFitter」でモデルを定義し、「fit」で学習を行っています。「fit」の「duration_col」には生存時間、「event_col」にはイベント(今回の場合は逮捕されたかどうか)のカラムを入力します。

「print_summary」を実行すると推計結果のサマリーが表示されます。ここで大事になってくるのが「exp(coef)」の値です。この値は「対応するカラムの値が1増えると死亡確率が何倍変化するか」を表しています。例えば、「fin(財政支援の有無)」は0.71ですが、これは財政支援があると逮捕される確率が0.71倍となることから、再逮捕の確率が減り、再犯の防止に効果的であるということになります。逆に「prio(過去の有罪回数)」などは、過去の有罪回数が1回増えるごとに1.1倍再逮捕される確率が増加します。

ここでは詳細に説明しませんが、説明変数は存在しているデータをすべて突っ込めばよいわけではなく、ドメイン知識や統計学の知識が必要です。全く効果のない変数を導入してもモデルを不安定にさせてしまいますし、意味やデータが似ている変数を導入してしまうとマルチコと呼ばれるモデルを不安定させる要因になってしまいます。そのため、実務で知識を蓄えている方々と我々のようなデータサイエンティストが一緒になってモデリングすることが良いのではないかと私は考えています。

4.推論

ここまではモデルを作成し、説明変数がどのように影響しているかを見ました。次は実際にモデルを使用して、個人ごとに再逮捕される確率がどのように変化するかを予測していきます。予測では以下のコードを使用します。

X = rossi.drop([“week”, “arrest”], axis=1)
result = cph.predict_survival_function(X)

plt.plot(result.index, result.iloc[:, 0:4])
plt.title("1~4人目までの生存関数")
plt.show()

学習したモデル(cph)で「predict_survival_function」を実行すると図のような生存関数と呼ばれる「ある時点まで生きている確率」を取得することが出来ます。また、予測ですので、必要なのは説明変数のみで、答えである「week」や「arrest」のカラムは必要ありません。
この生存関数を見ることで、「50日後に再逮捕されていない確率が50%以下なのはAさんとBさんだ」ということがわかります。
一方で「確率の図ではなく具体的な生存時間が知りたいんだ!」という方もいらっしゃると思います。その場合には以下のコードを実行してみてください。

surviv_duration = cph.predict_expectation(X)
display(surviv_duration)

これは先程の生存関数から生存時間の期待値(確率を考慮した平均値)を算出しており、対象の人がおおよそ何日後に再逮捕されるかを表しています。
このようにpythonでもlifelineライブラリを活用することにより、モデリングから予測までを簡単に行うことができました。今回使用したコードの全体を載せておきますので、ぜひご活用ください。(コード内にはnotebook専用のコマンドが記述してありますので、notebook以外の環境で動作しないことに注意してください)

!conda install -c anaconda pandas seaborn scikit-learn -y
!conda install -c conda-forge lifelines matplotlib –y

import pandas as pd
from lifelines.datasets import load_rossi
from lifelines import CoxPHFitter
import matplotlib.pyplot as plt

%matplotlib inline

rossi = load_rossi()
display(rossi.head())

cph = CoxPHFitter()
cph.fit(rossi[["week", "arrest", "fin", "age", "prio"]], duration_col='week', event_col='arrest')

cph.print_summary()

X = rossi.drop([“week”, “arrest”], axis=1)
result = cph.predict_survival_function(X)

plt.plot(result.index, result.iloc[:, 0:4])
plt.title("1~4人目までの生存関数")
plt.show()

surviv_duration = cph.predict_expectation(X)
display(surviv_duration)

おわりに

いかがでしたでしょうか?ROSSIデータでの解析結果を見て実用性を感じるのは一部の方かもしれませんが、この生存時間分析は様々な課題に対応できる分析手法です。特にマーケティングと相性がいいと思うので是非活用してみてください。
また、「自社のデータを活用してもっと具体的に分析して施策改善等につなげたい」等のご要望がありましたらお気軽にお問い合わせください。
最後までご覧いただきありがとうございました!

参考資料

無料でAI予測モデルが作れる【AIモデリングツール】のご案内

AI開発で、こんな課題はありませんか?
「AI開発にかかる費用のハードルが高い」「自社で開発して運用を行うスキルがない」「秘匿性の高いデータを外部に持ち出すことができず、ベンダーへの依頼が難しい」

そこで本ツールを活用することで、事業会社様側にて
手軽に無料でAI予測モデルの作成ができ、
予測や予測精度の評価を行うことが可能となります。
現在、回帰モデル(項目がどのような数値になるかを予測するモデル)、また分類モデル(項目がいずれのカテゴリーに属するかを予測するモデル)をご提供中です。
お申込後、すぐにご利用いただくことができます。
興味のある方はぜひご覧ください。

▼お申し込みはこちらから

WRITER

データサイエンティスト

堀   貴仁 Takahito Hori

複数業界にてAI活用プロジェクトのデータアナリティクス、データサイエンスを担当。大手飲食店様・不動産会社様のAIモデル構築実績あり。

SNSで最新情報を発信しています

最新記事

ページTOPへ