以面向过程的方式给出《贝叶斯思维:统计建模的Python学习法》——第五章:决策分析代码

背景

《艾伯特贝叶斯思维:统计建模的Python学习法.pdf》以面向对象的方式给出代码,作为了一本介绍统计思想的书,我们只需要了解其逻辑即可(PS:其实是懒得去看书中代码的组织过程),因此,给出读这本书的时候自己写的代码。

简单复述

总结第五章决策分析的处理过程的简单逻辑:

1、基于历史数据得到各选手商品价格的分布,以及选手出价差的分布
2、选手见到商品,猜测一个价格,据下面的过程得到商品真实价格的后验
先验分布:商品历史分布,似然度:由第一步的价差分布给出
后验分布:商品真实价格分布
3、基于游戏规则计算己方出不同价格时的预期收益。
4、出预期收益最大的价格

导入常见模块

# %load "E:\桌面space\临时数据\python\个人自定义模块\ImportFile.py"
# Standard Scientific Import
import numpy as np
import scipy as sp
import pandas as pd
import matplotlib as mpl
from matplotlib import pyplot as plt
from matplotlib.pyplot import plot as plot
import sklearn
import seaborn as sns
import sys
import patsy

# 个人代码测试路径
sys.path.append(r"C:\Users\Administrator\PycharmProjects\QY_TS_Quant")
from QY_plot import *

plt.rcParams['font.sans-serif'] = ['SimHei']  # 中文字体设置-黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题
sns.set(font='SimHei',font_scale=1.25,style="ticks",rc={"xtick.major.size": 3, "ytick.major.size": 3})# 解决Seaborn中文显示问题

# Jupyter 默认设置
%matplotlib inline
%config InlineBackend.figure_format="retina"
%config InlineBackend.rc = {"figure.figsize": (7.5,4.5)}
# 多列输出
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

导入数据

# 本地数据地址
#url_2011 = "./data/showcases.2011.csv"
#url_2012 = "./data/showcases.2012.csv"
# 网络数据地址
url_2011 = "http://thinkbayes.com/showcases.2011.csv"
url_2012 = "http://thinkbayes.com/showcases.2012.csv"
df_2011 = pd.read_csv(url_2011, index_col=0, skiprows=[1,2,5,8]).T.assign(year=2011).reset_index(drop=True)
df_2012 = pd.read_csv(url_2012, index_col=0, skiprows=[1,4,7]).T.assign(year=2012).reset_index(drop=True)
df = df_2011.append(df_2012, ignore_index=True)
df_2011.head()
Showcase 1Showcase 2Bid 1Bid 2Difference 1Difference 2year
0509694542942000340008969114292011
1219013406114000599007901-258392011
23281553186320004500081581862011
34443231428270003800017432-65722011
4242732232018750230005523-6802011
df_2012.head()
Showcase 1Showcase 2Bid 1Bid 2Difference 1Difference 2year
04081162485220004050018811219852012
13125932972100002100021259119722012
241943247553950022500244322552012
324946346652151332000343326652012
4262574863523420350002837136352012

展品价格分布

df.groupby("year").describe().T.assign(minus=lambda x:x.diff(axis=1).iloc[:, -1]).filter(like="Show", axis=0)
year20112012minus
Showcase 1count191.000000122.000000-69.000000
mean29482.73822031578.1721312095.433911
std6713.2056637628.472048915.266384
min19563.00000020869.0000001306.000000
25%24470.50000025684.5000001214.000000
50%28762.00000029402.500000640.500000
75%32740.50000036599.5000003859.000000
max54579.00000058342.0000003763.000000
Showcase 2count191.000000122.000000-69.000000
mean30668.14659731641.868852973.722256
std8003.1037478728.088463724.984716
min18349.00000019290.000000941.000000
25%25310.50000024900.250000-410.250000
50%29460.00000029530.50000070.500000
75%34191.00000035764.0000001573.000000
max71628.00000066996.000000-4632.000000
df.filter(like="Show").describe()
Showcase 1Showcase 2
count313.000000313.000000
mean30299.48881831047.680511
std7145.7054058293.059002
min19563.00000018349.000000
25%24866.00000025264.000000
50%28958.00000029488.000000
75%34428.00000034665.000000
max58342.00000071628.000000
list(filter(lambda x:x.startswith("Show"), df.columns))
['Showcase 1', 'Showcase 2']
fig, axes = plt.subplots(1, 2, sharex=True, sharey=True, figsize=(18, 6))
for i, col in enumerate(filter(lambda x:x.startswith("Show"), df.columns)):
    sns.distplot(df[col], ax=axes[i]);
    axes[i].axvline(30000, c="r");
fig.suptitle("$2011-2012$正确商品价格分布", fontsize=15);
fig.subplots_adjust(wspace=0.05);

在这里插入图片描述

价差分析

# 出价差 = 商品正确价格 - 选手出价
# 猜测差 = 商品正确价格 - 选手猜测价格
# 由于猜测差不可得,以出价差估计,或者认为两者相等
fig, axes = plt.subplots(1, 2, sharex=True, sharey=True, figsize=(18, 6))
for i, col in enumerate(filter(lambda x:x.startswith("Diff"), df.columns)):
#     sns.distplot(df[col], ax=axes[i]);
    axes[i].hist(df[col], cumulative=True)
    axes[i].axvline(0., c="r");
fig.suptitle("$2011-2012$价差分析", fontsize=15);
fig.subplots_adjust(wspace=0.05);

在这里插入图片描述

# 选手一二出价过高过低概率分布 
# diff = 商品正确价格 - 选手出价
# 可以看出diff大于0的概率更高,即选手更倾向于往小了猜
# 这也是规则导致的,如果你的价格高于商品正确价格,你就输了
(df.filter(like="Diff")<0).apply(lambda x:x.value_counts(normalize=True))
Difference 1Difference 2
False0.7539940.709265
True0.2460060.290735

选手一对商品真实价格分析

选手一根据商品信息,预测商品为20000元,再结合历史信息,对商品真实价格的预测过程。

# 以选手一为对象,分析历史数据,可以得到商品最可能价格分布
# PS 这里是概率密度,未归一化
kde = sp.stats.gaussian_kde(df["Showcase 1"])
h = np.linspace(0, 75000, 101)
plt.plot(h, kde.evaluate(h))
[<matplotlib.lines.Line2D at 0x1e2396cb7b8>]

在这里插入图片描述

# 先验商品最可能的价格
# 概率密度,最大的点——PS:这里步长不是1
h[kde.evaluate(h).argmax()]
27750.0
# 先验概率
p_h = kde.evaluate(h)
# 在猜测商品为20000时,似然度,
# 以猜测差分布计算(假设猜测差等于出价差)
p_dh = sp.stats.norm.pdf(h-20000, loc=0, scale=df["Difference 1"].std())
def normlize(z):
    return z/np.sum(z)
# 此计算的商品价格的后验概率分布
p_hd = normlize(p_dh*p_h)
# 展示商品价格的概率分布
plt.plot(h, p_hd, h, normlize(kde.evaluate(h)))
plt.legend(["后验分布","先验分布"])
plt.title("选手一预测价格为20000时,结合历史展品信息与误差分布的后验分布");

在这里插入图片描述

# 选手一预测商品为20000时,商品最有可能的价格
h[p_hd.argmax()]
24000.0
# 后验分布均值
np.sum(p_hd * h)
25103.012921487145

最优报价分析

# 重申游戏规则:
# diff = 商品真实价格 - 出价价格
# 出价比真实价格高,一无所获(diff<0)
# 出价差比对手少,赢得奖品
# 而且,出价价差小于250元赢得对手的奖品(diff<=250)
plt.plot(h, p_hd)
[<matplotlib.lines.Line2D at 0x1e2399a3048>]

在这里插入图片描述

# 计算选手二的出价差分布函数
def cdf(x):
    return np.sum(df["Difference 2"]<x)/len(df)
# 在选手一猜测商品价格为20000时,根据前述以得到已方展品真实价格的分布
# 下面计算,选手一出不同价格时,可能获得的期望收益
return_s = []
for bid in h: #猜价格
    Er = 0.
    for price,prob in zip(h, p_hd): # 真实商品价格 及 概率
        diff = price - bid # 出价差 = 实际价格-猜测价格
        if diff<0: # 猜价过高,失败
            Er += 0
        else:
            probwin_1 = cdf(-1) # 选手二出价小于0 的概率
            probwin_2 = 1 - cdf(diff) # 选手二出价大于diff的概率
            probwin = probwin_1 + probwin_2 # 选手一赢的概率
            if diff<=250:
                 Er += 2*price*prob*probwin
            else:
                 Er += price*prob*probwin
    return_s.append(Er)
# 在选手一猜测商品价格为20000时,根据前述以得到已方展品真实价格的分布
# 下面展示,选手一出不同价格时,可能获得的期望收益
plt.plot(h, return_s)
[<matplotlib.lines.Line2D at 0x1e239e44dd8>]

在这里插入图片描述

# 最大预期收益,及最优出价
max(zip(return_s,h))
(16666.56998160178, 21000.0)
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值