![見出し画像](https://assets.st-note.com/production/uploads/images/89579411/rectangle_large_type_2_69d2581a5f0e5d8784dba43cffeb43e5.png?width=800)
書記が数学やるだけ#602 ポアソン回帰
ポアソン回帰についての実装例を示す。
問題
![スクリーンショット 2022-10-23 11.45.23](https://assets.st-note.com/production/uploads/images/89579419/picture_pc_288d5ce0cb5db8b4d31a416b56b90f6c.png?width=800)
説明
ポアソン回帰では,対数関数を連結関数としてポアソン分布で推測する。よく似たものとして対数正規モデルがあるが,連結関数が対数関数である点は同じだが,正規分布により推測する点が異なる。
![スクリーンショット 2022-10-23 11.12.35](https://assets.st-note.com/production/uploads/images/89577693/picture_pc_0528826ad469dc10f0586c6ccb1ad7aa.png?width=800)
ポアソン分布ではなさそうな場合のうち,過分散が疑われる場合には負の2項分布モデルを用いることがある。
![スクリーンショット 2022-10-23 11.13.14](https://assets.st-note.com/production/uploads/images/89577715/picture_pc_2f8c47a09d8fe139508314d03e2637b8.png?width=800)
使い分けについては以下を参照:
解答
import math
import numpy as np
import scipy.stats as stats
import statsmodels.api as sm
import statsmodels.formula.api as smf
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
# チップのデータセット
df = sns.load_dataset("tips")
df
![スクリーンショット 2022-10-23 11.14.54](https://assets.st-note.com/production/uploads/images/89577825/picture_pc_a2ba0477cd85ed2c39c3a43c48b20783.png?width=800)
可視化をするにはSeabornのjointplotが便利である。
sns.set(style="darkgrid")
sns.jointplot(x="total_bill", y="tip", data=df,
kind="scatter",
xlim=(0, 60), ylim=(0, 12),
color="b",
height=7);
![画像5](https://assets.st-note.com/production/uploads/images/89577852/picture_pc_7e7963d1ec03dc9948c93134c7c7702c.png)
ここで標本のパラメータを求めておく。
mean = df['tip'].mean()
var = df['tip'].var()
scale = math.sqrt(var)
print("平均:", mean, "分散:", var, "標準偏差:", scale)
平均: 2.9982786885245902 分散: 1.9144546380624725 標準偏差: 1.3836381890011826
説明変数の分布を見ると,裾が長い分正規分布には見えない気もする。正規分布とポアソン分布でのサンプリングを行なってみると,その違いが出てくる。
norm = np.random.normal(mean,scale,244)
poisson = np.random.poisson(mean,244)
bins = np.linspace(-4, 12, 10)
plt.hist(norm, bins=bins, alpha=0.6, label="noem")
plt.hist(poisson, bins=bins,alpha=0.6, label="poisson")
plt.legend()
![画像6](https://assets.st-note.com/production/uploads/images/89578036/picture_pc_b673add8af82d6b42b54cb50016a0ee6.png)
正規分布でのフィッテイングが妥当かどうか,いくつか試験してみる。
#Q-Qプロット,正規分布ではなさそう
stats.probplot(df['tip'], dist="norm", plot=plt)
![画像7](https://assets.st-note.com/production/uploads/images/89578292/picture_pc_36090874c0a540b050c147f023d771e3.png)
#シャピロ・ウィルク検定,帰無仮説「正規分布である」が棄却される
stats.shapiro(df["tip"])
ShapiroResult(statistic=0.897811233997345, pvalue=8.20057563521992e-12)
これらより,単純に正規分布でフィッティングするのは危ういかもしれない。
では,実際にいくつかモデルを立ててみる。まずは正規線形モデル,ここで定数項なしに設定していることに注意(会計を払わない人にチップはないだろう)。
#正規線形モデル,定数項なし
y = df['tip']
x = df['total_bill']
link = sm.families.links.identity()
family = sm.families.Gaussian(link)
model_norm = sm.GLM(y, x, family=family)
results_norm = model_norm.fit()
results_norm.summary()
![スクリーンショット 2022-10-23 11.28.20](https://assets.st-note.com/production/uploads/images/89578556/picture_pc_34ff52d36956c92b5447ef07deb7eb24.png?width=800)
この予測値を可視化してみると,割といい当てはまりに見える。
y_hat_norm = results_norm.predict(x)
plt.plot(x, y, "o")
plt.plot(x, y_hat_norm, "*", color="r")
plt.xlabel('x (total_bill)'), plt.ylabel('y (tips)')
plt.xlim(0, 60), plt.ylim(0, 12)
plt.show()
![画像9](https://assets.st-note.com/production/uploads/images/89579111/picture_pc_9d8d23cc8d2e4bc346099329200e75a3.png)
次にポアソンモデルを示す。
#ポアソンモデル
link = sm.families.links.log()
family = sm.families.Poisson(link)
model_poisson = sm.GLM(y, x, family=family)
results_poisson = model_poisson.fit()
results_poisson.summary()
![スクリーンショット 2022-10-23 11.39.59](https://assets.st-note.com/production/uploads/images/89579170/picture_pc_7ff2fca2e57fc8d0b1cfa91f67d3ce25.png?width=800)
y_hat_poisson = results_poisson.predict(x)
plt.plot(x, y, "o")
plt.plot(x, y_hat_poisson, "*", color="r")
plt.xlabel('x (total_bill)'), plt.ylabel('y (tips)')
plt.xlim(0, 60), plt.ylim(0, 12)
plt.show()
![画像11](https://assets.st-note.com/production/uploads/images/89579194/picture_pc_97abe6fa8260d812d1af359909233b23.png)
対数正規モデルも組んでみる。
#対数正規モデル
link = sm.families.links.log()
family = sm.families.Gaussian(link)
model_lognorm = sm.GLM(y, x, family=family)
results_lognorm = model_lognorm.fit()
results_lognorm.summary()
y_hat_lognorm = results_lognorm.predict(x)
plt.plot(x, y, "o")
plt.plot(x, y_hat_lognorm, "*", color="r")
plt.xlabel('x (total_bill)'), plt.ylabel('y (tips)')
plt.xlim(0, 60), plt.ylim(0, 12)
plt.show()
![画像12](https://assets.st-note.com/production/uploads/images/89579257/picture_pc_bef118c3ac18c90fda0221b0dd7bd43e.png)
本記事のもくじはこちら:
学習に必要な本を買います。一覧→ https://www.amazon.co.jp/hz/wishlist/ls/1XI8RCAQIKR94?ref_=wl_share