見出し画像

友だちPython ep4. lifetimes

はじめに


友だちPython シリーズのご紹介

友だちPython シリーズは、Python の小ネタを短文でお届けします。
小さなエピソードを重ねてPythonと仲良しになれたら、と願ってシリーズ名を付けました。

話題


Pythonによる時系列分析: 予測モデル構築と企業事例

書籍「Pythonによる時系列分析: 予測モデル構築と企業事例」(オーム社)をご紹介いたします。

この書籍は、時系列データの一般的な分析手法から、売上・LTV・マーケティングROI・異常検知といった企業事例に沿ったシナリオまで、幅広く、わかりやすく解説しています。
そして何と言ってもPythonでサクッと動かせます!
Pythonの時系列モデルを試してみたい方、Pythonの経営管理/マーケティング活用をご検討されている方などにおすすめいたします!

この記事は、この書籍のコードで生じた問題対処を取り扱います。

今回の友だち

■ lifetimes (ライフタイムス)
顧客生涯価値(CLV)を予測するパッケージです。

公式サイトのリンクはこちらです。

問題の概要

第5章、5.6「LTVマネジメントのためのLTV予測(ECサイト)」のcode 5-105「LTV予測モデルの構築(全データ期間のRFMデータセット)」(312ページ)で問題が生じました。
lifetimesのBetaGeoFitter(ベータ・ジオ・フィッター)の実行時にエラーが発生して、コードが動きません

実行環境
・lifetimes のバージョン: 0.11.3
・Anaconda 環境
・VS code の Jupyter Notebook で実行

問題の詳細

見たことのないエラーです。

ConvergenceError:
The model did not converge. Try adding a larger penalizer to see if that helps convergence.

(Google翻訳)
収束エラー:
モデルは収束しませんでした。より大きなペナルティを追加して、それが収束に役立つかどうかを確認してください。

より大きな penalizer を追加するのがよさそうです。
これって何?

原因

こちらのサイトで解決の糸口を見つけることができました。
ありがとうございます!

「BetaGeoFitter」の引数「penalizer_coef」(正則化の係数)を指定してみます。
penalizer_coef のデフォルト値は 0 。
0 以上で小さな値を指定してみます。

対策の実施

penalizer_coef に 「1e-11」($${1 \times 10^{-11}}$$)を指定して、無事にエラー発生を回避できました!
ちなみに、「1e-12」を指定すると、収束しないエラーが発生します。

# code 105
# LTV予測モデルの構築(全データ期間のRFMデータセット)

# BG/NBDモデルの学習(購買回数)
bgf = BetaGeoFitter(penalizer_coef=1e-11).fit(   # 変更点:penalizer_coef=1e-11
    rfm['frequency'],  # リピート回数
    rfm['recency'],    # アクティブ期間(最初に購入してから最近の購入までの期間)
    rfm['T']           # 最初に購入してからデータセットが終了するまでの期間
)

# GGモデルの学習(1回あたりの購買金額)
ggf = GammaGammaFitter().fit(
    rfm['frequency'],      # リピート回数
    rfm['monetary_value'], # リピート時の平均購入金額
)

改善後

少し先の code 5-107 の実行結果として表示される「ltv」の数値は、小数点以下で誤差が生じたものの、概ね書籍の実行結果とほぼ同じでした。
実用上の影響はおそらく無いでしょう。

無事にltvを予測できました

ひとまず動いてよかったです!!!
でも、なぜ書籍の実行環境ではエラーにならず、この環境ではエラーになったのでしょう???
少々のもやもやが残る結果になりました。

おまけ

code 5-108 で出力する12か月先のLTV降順リストをカンマ区切りにしてみました。
指数表示よりも頭に入ってきます!

# code 5-108
# LTV降順リスト

# pandasの浮動小数点数をカンマ付き表示に設定
pd.options.display.float_format = '{:,.1f}'.format

# LTV降順リストの表示
display(rfm[['ltv']].sort_values('ltv', ascending=False))

# pandasの表示オプションをクリア
pd.options.display.float_format = None
カンマ区切りにしたLTV金額
指数表示のLTV金額

後日談

残念なことに、lifetimesはメンテナンスモードに入り、新機能の開発を実施しないそうです。
PyMC-Marketingが後継プロジェクトとのこと。
新しい友だちと仲良く、ですね。

おわり

ブログの紹介


noteで3つのシリーズ記事を書いています。
ぜひ覗いていってくださいね!

1.のんびり統計
統計検定2級の問題集を手がかりにして、確率・統計をざっくり掘り下げるブログです。
雑談感覚で大丈夫です。ぜひ覗いていってくださいね。
統計検定2級公式問題集CBT対応版に対応しています。

2.Python機械学習プログラミング実践記
書籍「Python機械学習プログラミング PyTorch & scikit-learn編」を学んだときのさまざまな思いを記事にしました。
この書籍は、scikit-learnとPyTorchの教科書です。
よかったらぜひ、お試しくださいませ。

3.データサイエンスっぽいことを綴る
統計、データ分析、AI、機械学習、Pythonのコラムを不定期に綴っています。
「統計」「Python」「数学とPython」「R」のシリーズが生まれています。

最後までお読みいただきまして、ありがとうございました。

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