当前位置: 首页 > news >正文

模拟数据,真实学习:功效分析

原文:towardsdatascience.com/simulated-data-real-learnings-power-analysis-652045eeae22

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/58847e217e3d294c5929b791e2342b49.png

图片由 Pexels.com 的 Robert So 提供

引言

模拟是数据科学工具箱中的强大工具。阅读完这篇文章后,您将很好地理解如何使用模拟来估计设计实验的功率。这是关于模拟在数据科学和机器学习中有用性的多部分系列的第二部分。

下面是我们将要涵盖的内容:

  1. 功效分析概述

  2. 如何使用模拟计算功率——基于示例的方法

在这篇文章中,我将只简要定义数据模拟:

数据模拟是创建模仿现实世界特性的虚构数据。

在本系列的第一个部分,我更详细地讨论了数据模拟的定义——您可以在下面的链接中查看:

模拟数据,真实学习:第一部分


功效分析概述

实验是我们了解周围世界关系的黄金标准。在计划实验时有许多考虑因素。尽管实验是黄金标准,但一个计划不当的实验可能会产生无用或误导性的结果。功效分析是良好实验计划的一个关键组成部分。

在深入细节之前,让我们回答这个以价值为导向的问题:问题为什么在运行实验之前估计功率很重要?答案因为没有理解实验的功率,我们可能会浪费时间在无法检测到有意义结果的实验上。

在统计术语中,功效的定义是正确拒绝零假设的概率。虽然不够精确(并且特定于实验设计),但我喜欢将实验的功效定义为——在存在关系的情况下我们能够捕捉到关系的概率。

在实验中,功率是在存在关系的情况下我们能够捕捉到关系的概率

功率的计算是通过估计两种相互竞争的力量——(1)信号和(2)噪声来完成的。这两个变量的相对大小决定了我们能够多好地捕捉到趋势。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/16a4cc145b3cb827b3ab10932e5b21f8.png

在计算功效时,我们创建两个分布——一个分布的平均值为零(解释为我们的实验变量与响应变量没有关系)和另一个分布具有非零平均值(解释为我们的变量与响应变量有正相关关系)。请注意,第一个分布对应于零假设,第二个分布对应于备择假设。粗略地说,功效与这两个分布之间的重叠程度成反比——即重叠越多,功效越低,重叠越少,功效越高。

我从文章的下方拉取了下面的图片。我将快速讲解这张图片,然后转到这篇文章真正要讨论的内容——模拟!如果你在阅读这一部分后对功效分析还有很多疑问,不用担心,互联网上不止我一个人写过关于它!

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f5335d94c314e01592cea9595f809507.png

图片由作者提供

绿色分布是我们的零分布;表示如果我们的实验变量和响应变量之间没有关系,我们可能看到的估计关系值的概率分布。蓝色是另一种分布,表示如果实验变量和响应变量之间的关系是一个正数,可能的关系估计。红色线是零分布(绿色)前 5%的截止线。在这里我将跳过很多细节,只说蓝色分布中红色线右侧的区域是功效。如果这还不清楚,请记住,谷歌是你的朋友 😊 我们必须继续讨论这篇文章中的模拟!


如何使用模拟计算功效

现在我们已经快速讨论了什么是功效,让我们最终进入文章的核心内容——模拟如何帮助我们计算功效,从而帮助我们设计更好的实验!

我非常喜欢通过例子学习,所以在这个部分,我的主要教学媒介将通过一个模拟例子进行。

这里是场景:你为一家广告公司工作,该公司要求你估计一个特定设计实验的功效。这个实验试图了解广告策略对销售的影响。设计将国家分成多个子组,并随机选择一个组进行广告活动,另一个组作为对照组。

由于这不是一篇关于实验设计的文章,我们将做出简化的假设,即我们决定采用简单的差分-差分(DID)方法进行分析(我不会过多地深入这个方法——再次提醒,谷歌是你的朋友!)。差分-差分方法将我们的数据分为四个组(1)前/控制,(2)后/控制,(3)前/测试和(4)后/测试。只有后/测试数据集将受到活动的直接影响,其他三个数据集将不会收到任何活动的广告,并将用于控制混杂因素。

注意:虽然我们在这个例子中选择了 DID 方法,但我们仍然可以修改我们的代码/方法来计算任何分析方法的功率。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/187c29155e0a6fbf8ff165294b92b4f4.png

差分-差分方法的数据分离 – 图像由作者提供

为了估计我们测试的功率,我们将运行两个模拟。模拟 1:程序没有影响,模拟 2:程序具有我们设定的特定影响水平。第一个模拟对应于零假设(活动对销售没有影响),第二个模拟代表备择假设(活动对销售有积极影响)。每个模拟将为我们提供一个数据点(在我们的特定情况下,它将是 DID 计算)。例如,如果我们运行模拟 1 一次,我们将从那个模拟中计算出 DID 值。

下一步是多次运行这两个模拟,以获得我们 DID 指标的两个分布。这两个分布就是我们估计功率所需的所有。然后我们根据分布的重叠部分进行功率计算。重叠越小,功率越高,反之亦然。

下面是两个模拟对应的四个数据集的示意图。请注意,当我们创建模拟 2 数据时,我们将测试/后数据集的模拟影响(标记为“simulate impact >0”)设置为特定水平,例如销售增加 5%。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/e68bbe227e32e6394c67fb9a0d58ad76.png

break down of 2 types of simulations needed for power analysis

既然我们已经了解了我们如何运行我们的模拟,让我们开始编写一些 Python 代码来实际创建模拟数据并计算功率!

下面是如何将代码与我们刚才讨论的设置相联系:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/bf1540dbf038984f811045a3601bd935.png

importnumpyasnpfrommatplotlibimportpyplotaspltimportseabornassnsdefcalculate_diff_in_diff(pre_test,pre_control,post_test,post_control):''' Calculates the diff in diff given the 4 averages from the 4 data sets used to calculate diff in diff. inputs: pre_test (float) : average for the pre/test data pre_control (float) : average for the pre/control data pre_test (float) : average for the pre/test data post_control (float) : average for the post/control data output diff_in_diff_ratio (float) : diff in diff calculation '''test_diff=post_test-pre_test control_diff=post_control-pre_control diff_in_diff_ratio=test_diff-control_diffreturndiff_in_diff_ratiodefsimulate_group_data(n_customers,rv_dist_func,rv_inputs,program_impact=0):''' Simulates a single dataset for diff in diff simulation inputs: n_customers (int) : number of customers to be simulated in the dataset rv_dist_func (func) : function used to sample random variables rv_inputs (dict) : keyword inputs to the rv_dist_func program_impact (float) : additive impact that program has on probability of customer purchasing. Should only be non-zero for post/test data default = 0 output: purch_rate (float) : average purchase rate (total purchs / total custs) for the simulated data set '''purch_prob=rv_dist_func(**rv_inputs,size=n_customers)# add impact of treatment if simulating post/test datapurch_prob+=program_impact# convert to binaryconv_to_binary_prob=np.random.uniform(0,1,n_customers)purch_binary=np.where(purch_prob>=conv_to_binary_prob,1,0)purch_rate=np.sum(purch_binary)/len(purch_binary)returnpurch_ratedefsimulate_multiple_times(n_sims,pre_test_sim_inputs,post_test_sim_inputs,pre_control_sim_inputs,post_control_sim_inputs,cut_off_decimal=0.05):''' Uses functions that run a single simulation to run multiple simulation - aggregates the results of the multiple simulations inputs: n_sims (int) : number of simulations to run pre_test_sim_inputs (dict) : keyword args for running a single pre/test simulation post_test_sim_inputs (dict) : keyword args for running a single post/test simulation pre_control_sim_inputs (dict) : keyword args for running a single pre/control simulation post_control_sim_inputs (dict) : keyword args for running a single post/control simulation cut_off_decimal (float) : decimal form of significance level for power analysis, e.g. 5% = 0.05 default = 0.05 outputs: Nothing, but prints power at a significance level set with the cut_off_decimal input and creates visualization of the null and alternative histograms '''diff_in_diff_impact=[]# run with given impact for interventionforiinrange(n_sims):pre_test_sim=simulate_group_data(**pre_test_sim_inputs)post_test_sim=simulate_group_data(**post_test_sim_inputs)pre_control_sim=simulate_group_data(**pre_control_sim_inputs)post_control_sim=simulate_group_data(**post_control_sim_inputs)temp_diff_in_diff=calculate_diff_in_diff(pre_test_sim,pre_control_sim,post_test_sim,post_control_sim)diff_in_diff_impact.append(temp_diff_in_diff)# run w/o any impact for interventiondelpost_test_sim_inputs['program_impact']diff_in_diff_no_impact=[]foriinrange(n_sims):pre_test_sim=simulate_group_data(**pre_test_sim_inputs)post_test_sim=simulate_group_data(**post_test_sim_inputs)pre_control_sim=simulate_group_data(**pre_control_sim_inputs)post_control_sim=simulate_group_data(**post_control_sim_inputs)temp_diff_in_diff=calculate_diff_in_diff(pre_test_sim,pre_control_sim,post_test_sim,post_control_sim)diff_in_diff_no_impact.append(temp_diff_in_diff)# print power calculation resultcutoff=1-cut_off_decimal cutoff_index=int(len(diff_in_diff_no_impact)*cutoff)sorted_data=sorted(diff_in_diff_no_impact)top_5_percent_cutoff=sorted_data[cutoff_index]# calculate powerreject_region_ind=np.where(diff_in_diff_impact<=top_5_percent_cutoff,1,0)power=1-np.sum(reject_region_ind)/len(reject_region_ind)print(f'power for scenario specifics is{power}')# Kernel density estimation (KDE) to estimate the PDFssns.kdeplot(diff_in_diff_impact,color='blue',label='simulated impact',fill=True)sns.kdeplot(diff_in_diff_no_impact,color='green',label='no impact',fill=True)plt.axvline(x=top_5_percent_cutoff,color='red',linestyle='--')# Plot settingsplt.xlabel('Difference in Differences')plt.ylabel('Probability Density')plt.title('No Impact vs. Simulated Impact')plt.legend()plt.show()return# running simulations# set up sample sizestest_n_customers=1500control_n_customers=1500# set inputs for the four needed data setspre_test_sim_inputs={'n_customers':test_n_customers,'rv_dist_func':np.random.uniform,'rv_inputs':{'low':0,'high':0.60}}post_test_sim_inputs={'n_customers':test_n_customers,'rv_dist_func':np.random.uniform,'rv_inputs':{'low':0,'high':0.60},'program_impact':0.10}pre_control_sim_inputs={'n_customers':control_n_customers,'rv_dist_func':np.random.uniform,'rv_inputs':{'low':0,'high':0.80}}post_control_sim_inputs={'n_customers':control_n_customers,'rv_dist_func':np.random.uniform,'rv_inputs':{'low':0,'high':0.80}}# run multiple simulationssimulate_multiple_times(1000,pre_test_sim_inputs,post_test_sim_inputs,pre_control_sim_inputs,post_control_sim_inputs)

在上面的代码中,我们运行了两个模拟 1000 次。如果我们模拟 5%的影响(这意味着我们的程序使客户增加购买概率的可能性提高了 5%),并且样本大小为 1500 名客户,我们得到以下结果。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f5335d94c314e01592cea9595f809507.png

image by author

红线代表绿色“无影响”分布(对应模拟 1 的分布)的最高 5%的截止点。在 5%的显著性水平下,样本量为 1500,影响大小为 5%,我们的功效约为 63%——这意味着在模拟条件下,我们有 63%的几率会得出项目存在差异的结论。63%是蓝色分布中位于红线右侧的百分比。

从这里,模拟在功效分析中的魔力显现出来!63%的功效相当低。幸亏我们在实施实验之前检查了!使用我们的框架,我们现在可以探索如何解决低功效问题。

有两种非平凡的方法可以增加功效——(1)增加样本量,以及(2)增加测试的影响。让我们来看看两者!

我们将样本量从 1500 增加到 3000。这在代码中做起来很简单:

# set up sample sizes for test and controltest_n_customers=3000control_n_customers=3000

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1a7a72f0444925380be341ee843ad760.png

作者图片

现在,我们的功效约为 91%!我们可以在设计的实验中通过延长实验时间或增加将要包括在测试中的地理区域来实施样本量的增加。根据我们的功效分析,鉴于当前样本量的较低功效,我们绝对应该做其中之一。

第二种方法——增加影响大小——不那么直接。我们实际上只能在这个方向上产生一定的影响。如果我们知道如何精确地改变影响大小,我们就不需要运行测试(因为我们就会理解我们的实验变量和响应变量之间的关系)!如果我们想增加影响大小,我们必须提高处理水平——在这个例子中,这意味着更激进的广告活动。我们知道,如果销售和活动之间存在关系,增加活动的预算可能会增加项目的效果。但同样,我们不知道在更加强烈的活动下,影响会变得多大——我们只知道它会更大

我们可以通过模拟不同的影响水平来了解我们的功效是如何随着影响的增加而改变的。下表显示了与不同模拟影响水平相对应的功效水平。这可以帮助我们了解在不同水平上的信心。如果活动的影响小于 5%,我们不太可能检测到它。如果这不是可以接受的,我们要么增加样本量以减少噪声,要么提高活动水平,使其更有可能观察到更高的影响。

我们可以将这样的表格拿给我们的利益相关者,确保每个人都理解测试可能检测到的不同影响水平。如果每个人都接受检测不到<5%影响的低概率,那么我们可以继续前进。如果不可以,我们可以修改实验设计。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/906f8f043aab432c871904c5ff6ab274.png

模拟影响的力量 - 图片由作者提供

遵循这个模拟过程,我们假设的自我现在已经准备好做出一个明智的实验设计决策了!我们有了理解需要包含多少客户才能捕捉到一定水平功率的工具。我们还了解,给定一定数量的客户,我们检测到各种规模趋势的可能性有多大。这一切都归功于模拟!

结论

模拟可以是一个极其有用的工具,用于计算实验的功率。它不依赖于特定方法,无论是差异分析还是回归或传统假设检验,它都能很好地工作。我们可以从使用模拟进行功率分析中获得非常有用的关键见解。我们可以了解我们需要多大的样本量(想象一下如果我们创建了一个测试并且样本量太小或太大会有多大的浪费!)以及我们需要达到什么程度的影响才能检测到它。通过功率模拟计算,我们可以极大地提高我们实验的质量以及我们从实验中获得的学习成果!

http://www.jsqmd.com/news/615497/

相关文章:

  • OpenClaw技能组合技:Phi-3-mini-128k-instruct多模块协作处理
  • 【EI复现】考虑分布式电源不确定性的配电网鲁棒动态重构附Matlab代码
  • 2026年OpenClaw怎么搭建?阿里云9分钟保姆级流程+大模型APIKey配置、Skill集成
  • 2026铣床优质供应商推荐指南高性价比选型:数控车床/铣床/加工中心/磨床/雕铣机/选择指南 - 优质品牌商家
  • 北京中研世纪咨询有限公司联系方式查询指南:如何有效联系专业市场研究机构并了解其服务范畴. - 品牌推荐
  • 基尔霍夫定律
  • 电容是什么?一个“快充快放”的微型充电宝哺
  • 【并发心法】别把 RTOS 当 Linux 玩!撕碎“万物皆线程”的并发毒药,论“事件驱动”与“无阻塞”的算力霸权
  • 为什么顶尖金融科技公司集体弃用React转向Blazor?——2026真实项目ROI对比:开发效率↑41%,首屏加载↓68%,运维成本↓53%
  • OpenClaw+Kimi-VL-A3B-Thinking:24/7自动化内容审核方案
  • 2026年怎么安装OpenClaw?腾讯云5分钟喂奶级部署+大模型APIKey配置、Skill集成流程
  • 毕业设计实战:基于Java+MySQL的体育用品交易网站设计与实现指南
  • Spring Boot 4.0 Agent-Ready不是未来式——是今天上线就必须具备的生产红线(附GDPR/等保2.0合规增强checklist)
  • Autosar网络管理核心机制与工程实践
  • 有功功率 无功功率 视在功率 额定功率
  • 野人先生联系方式查询:关于品牌官方联系渠道获取与产品体验的几点通用建议 - 品牌推荐
  • 嵌入式开发编码规范与最佳实践
  • 微软发布的《生成式人工智能初学者.NET 第二版》课程辰
  • Calico IPIP 使用指南檀
  • Seeed-PCA9685 Arduino库详解:16路PWM伺服与LED控制
  • Go语言怎么做请求ID追踪_Go语言RequestID链路教程【基础】
  • 【升级心法】别把十万台设备变成砖头!撕碎 OTA 的互联网傲慢,论 Bootloader 的冷血独裁与“试错回滚”的绝对金身
  • 基于stm32的重工业园环境质量监测系统
  • FreeRTOS_SAMD21:Arduino平台Cortex-M0+实时操作系统移植指南
  • 寻找四川口碑矿用移动橡套软电缆工厂?看这里 - 2026年企业推荐榜
  • AI 编程盛行的时代,为什么 “『DC- WFW』” 仍然具有必要性?岛
  • 前端使用AI试水报告侣
  • cka-2026-etcd
  • .NET 诊断技巧 | 日志框架原理、手写日志框架学习咸
  • 无GPU方案:OpenClaw调用云端SecGPT-14B实现低成本安全分析