百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

蒙特卡洛模拟在采样成功指标中将信号与噪声分离(译文)

toyiye 2024-06-21 12:36 13 浏览 0 评论


通常,当您设置成功指标时,您可以直接衡量整体兴趣的价值。例如,Shopify 可以精确衡量商品总销量 (GMV),因为我们可以查询我们处理的每个订单的数据库。但是,有时无法获得告诉您是否正在产生影响的信息,或者收集起来太昂贵或太耗时。在这些情况下,您需要依靠抽样成功指标。

在一次性实验中,您可以估计达到给定置信区间所需的样本量。但是,成功指标通常会随着时间的推移进行跟踪,您需要在趋势的背景下而不是孤立地评估每个数据点。我们对我们对指标的影响的信心是累积的。那么,如何从采样噪声中提取成功信号呢?这就是蒙特卡罗模拟的用武之地。

蒙特卡洛模拟可用于了解响应可变输入的结果的可变性。下面,我们将详细介绍如何使用 Monte Carlo 模拟来确定可信抽样成功指标所需的数据点。我们将演练一个示例并分享如何在 Python 和 pandas 中实现它,这样您就可以自己动手了。

什么是蒙特卡洛模拟?

蒙特卡洛模拟可用于根据现实世界的假设生成一堆随机输入。为此,它通过一个近似于感兴趣的真实世界情况的函数来提供这些输入,并观察输出的属性以了解在合理场景下可能出现的结果的可能性。

在抽样成功指标的上下文中,您可以使用模拟来了解以下各项之间的权衡:

  • 您的样本量
  • 您从随机噪声中提取潜在人口指标趋势的能力

然后,这些结果可用于向您的非技术利益相关者解释复杂的统计概念。如何?您将能够简单地解释您的样本量产出的确定性百分比,以及收集更多数据的成本。

使用蒙特卡洛模拟来估计指标变异性

为了向您展示如何使用 Monte Carlo 模拟作为样本成功指标,我们将以 Shopify App Store 为例。Shopify App Store 是一个市场,我们的商家可以在其中找到应用程序和插件来自定义他们的商店。我们拥有 8,000 多个应用程序来解决一系列问题。我们为应用程序质量设定了高标准,其中 200 多项最低要求侧重于安全性、功能性和易用性。每个应用程序都需要满足这些要求才能上架,我们有各种手动和自动应用程序审核流程来确保满足这些要求。

我们希望不断评估我们的审查流程如何提高我们应用商店的质量。在最高级别,我们要回答的问题是,“我们的应用程序有多好?”。这可以定量地表示为“平均应用程序违反了多少要求?”。我们的应用程序商店中有数以千计的应用程序,我们无法每天检查每个应用程序。但我们可以从样本中推断。

通过每月审核随机抽样的应用程序,我们可以估算出一个指标,该指标告诉我们商家在平均安装的应用程序中遇到了多少违反要求的行为——我们将此指标称为商店问题率。然后,我们每个月都可以根据这个指标进行衡量,看看我们的各种应用审查流程是否对提高我们应用的质量产生了影响。这是我们的抽样成功指标。

通过模拟数据和参数,我们将向您展示如何使用蒙特卡洛模拟来确定我们每月需要审核多少应用程序,以便对我们的抽样成功指标有信心。然后,我们将重复模拟审计随机选择的应用程序,改变以下参数:

  • 样本量
  • 发行率的基本趋势

要了解我们的成功指标对相关参数的敏感性,我们需要执行五个步骤:

  1. 建立我们的模拟指标
  2. 定义我们要从中提取问题计数的分布
  3. 为一组参数运行模拟
  4. 为一组参数运行多个模拟
  5. 跨多个参数运行多个模拟

要使用 Monte Carlo 模拟,您需要在脑海中已经有一个成功指标。虽然如果您对它的当前值和它的来源分布有一些了解是理想的,但该方法的全部要点是查看从不同的可能场景中出现的结果范围。所以,如果您没有任何初始样本,请不要担心。

第 1 步:建立我们的模拟指标

我们从建立模拟指标开始。这些与我们的成功指标不同,因为它们描述了我们抽样成功指标的可变性。指标上的指标!

对于我们的示例,我们希望每月检查一次该指标,以了解我们的方法是否有效。因此,为了建立我们的模拟指标,我们问自己,“假设我们每月将人口中的商店发货率降低给定数量,我们的指标会在多少个月内下降?”。我们称此定制指标为:观察到的 1 个月减少1mDO

我们也可以在更长的时间段内问这个问题,比如连续两个月 (2mDO) 或一个完整的季度 (1qDO)。当我们每年制定计划时,我们希望模拟未来一年的这些指标。

在我们的模拟指标之上,我们还想测量平均绝对百分比误差 (MAPE)。MAPE 将帮助我们确定商店发行率每月偏离真实基础分布的百分比。

现在,随着我们建立了模拟指标,我们需要定义我们将从中提取的分布。

第 2 步:定义我们的抽样分布

出于我们示例的目的,假设我们将生成一年的随机应用程序审核,假设人口商店问题率(我们的成功指标)每月下降给定。我们要将我们的蒙特卡洛模拟生成的抽样商店问题率与生成它的人群的问题率进行比较。

我们通过从随机分布中抽取来生成我们的蒙特卡洛输入。对于我们的示例,我们已经确定应用程序存在的问题数量可以通过泊松分布很好地表示,泊松分布对一组独立伯努利试验的总和进行建模(其中对每个需求的评估都可以视为单独的试验)。但是,您感兴趣的度量可能与另一个匹配,例如正态分布。您可以在此处找到有关为您的数据拟合正确分布的更多信息。

泊松分布只有一个参数 λ (lambda),它最终是总体的均值和方差。对于正态分布,您需要指定总体均值和方差。

希望您已经有一些样本数据可用于估计这些参数。如果没有,我们将在下面处理的代码将允许您测试在不同假设下发生的情况。

第 3 步:使用一组参数值运行我们的模拟

请记住,我们的目标是使用您定制的模拟指标,在给定一组现实假设的情况下,量化样本均值与基础总体均值的差异程度。

我们知道我们需要设置的参数之一是泊松λ。我们还假设我们每个月都会对我们的指标产生真正的影响。我们希望将其指定为我们将每月减少 λ(或平均问题数)的百分比。

最后,我们需要设置要进行多少次随机审计(也就是我们的样本量)。随着样本量的增加,收集成本也会增加。对于利益相关者来说,这是一个非常重要的数字。我们可以使用我们的结果来帮助传达度量的确定性和收集数据的成本之间的权衡。

现在,我们将编写构建块函数,在给出有关应用程序问题分布参数的一些假设的情况下生成真实的采样时间序列。例如,我们可以从以下假设开始:

  1. 我们的总体平均值是每次安装 10 个问题。这是我们的 λ 参数。
  2. 我们的商店发货率每月下降 5%。这就是我们期望我们的应用审查流程产生的影响。

请注意,这些假设可能是错误的,但我们的目标不是让您的假设正确。我们将尝试多种假设组合,以了解我们的模拟指标如何在合理的输入参数范围内做出响应。

对于我们的第一个模拟,我们将从生成问题计数时间序列的函数开始,这些问题计数来自应用程序的分布,其中人口问题率实际上每月按给定百分比下降。对于此模拟,我们将从 100 个样本时间序列中抽取。这个样本大小将为我们提供一个相当稳定的模拟指标估计,而不会花费太长时间来运行。下面是模拟的输出:

import pandas as pd
from scipy.stats import norm

from matplotlib import pyplot as plt

def generate_error_count(l):
    '''Given population mean (l) issue count, draw a random issue count
    from the relevant Poisson distribution'''
    
    return np.random.poisson(l)

def generate_time_series(periods=12, 
                         monthly_decrease=0.05,
                         starting_mean=5,
                         audits_per_period=100):
    '''
    Generate a time series of sampled apps with 
    randomly generated issue counts.
    
    Also returns the true population SIR over the period.
    '''
    
    cols = range(periods)
    index = range(audits_per_period)
    df = pd.DataFrame(index=index, columns=cols)
    sample_df = pd.DataFrame(index=range(audits_per_period), columns=cols)
    
    mean = starting_mean
    
    true_sir = []
    for period in cols:
        app_error_counts = [generate_error_count(mean) for x in range(audits_per_period)]
        df[period] = app_error_counts
        multiplier = (1 - monthly_decrease)
        true_sir.append(mean)
        
        mean = mean * multiplier

    return (np.array(true_sir), df)

true_sir, sample_df = generate_time_series(audits_per_period=100, monthly_decrease=0.05, periods=12)

# Plot the generated data against the mean of the distribution that generated it
fig, ax = plt.subplots()
sample_df.mean().rename("Sampled Mean").plot(ax=ax, color='black', linestyle='--')
ax.plot(true_sir, label="Underlying Shop Issue Rate", color='black')
ax.set_ylim(0)
ax.set_xlabel('Month')
ax.set_ylabel('Shop Issue Rate')
ax.legend()

此函数返回 上应用程序的示例数据集n=audits_per_period,m=periods months其中每个应用程序的问题数均从泊松分布中得出。在下图中,您可以看到样本商店发行率如何围绕真实基础数字变化。我们可以看到 每月减少 5%。

我们第一次使用一组参数值进行蒙特卡洛模拟

现在我们已经运行了第一个模拟,我们可以计算我们的可变性指标 MAPE 和 1mDO。下面的代码块将为我们计算可变性指标:

def get_summary_stats(true_sir, sample_df):
    '''For a simulation of the issue rate time series, calculate
    variability metrics, including the Mean Absolute Percentage Error
    and the bespoke metric "# decreases observed" for multiple durations.
    '''
    sample_sir = sample_df.mean()
    error = true_sir - sample_sir
    abs_error = error.abs()
    mape = (abs_error/true_sir).mean()
    
    decreases_observed_over_period = []
    for period in sample_sir.index:
        diffs = sample_sir.diff(period+1)
        n_diffs = diffs.notna().sum()
        decreases_observed = (diffs < 0).sum() / n_diffs
        decreases_observed_over_period.append(decreases_observed)

    return mape, np.array(decreases_observed_over_period)

get_summary_stats(true_sir, sample_df)

此代码将告诉我们需要多少个月才能真正看到商店发货率下降。换句话说,“我们需要等待多长时间才能对这些数据采取行动?”。

在第一次模拟中,我们发现 MAPE 为 4.3%。换句话说,模拟的商店发货率与总体平均值平均相差 4.3%。我们的 1MDO 为 72%,这意味着我们的抽样指标在 72% 的月份中下降。这些结果不是很好,但这是侥幸吗?我们需要再运行几次模拟以确定您对模拟指标的信心。

第 4 步:使用相同的参数值运行多个仿真

下面的代码使用给定参数运行我们的generate_time_series函数时间,并为每次迭代返回我们的模拟指标。所以,如果我们用 50 次迭代运行它,我们将得到 50 个时间序列,每个时间序列每个月有 100 个抽样审计。通过对迭代进行平均,我们可以找到模拟指标的平均值。n=iterationsDataFrame

import warnings
warnings.filterwarnings('ignore')

def run_simulation(iterations, 
                   periods=12, 
                   monthly_decrease=0.05,
                   starting_mean=4.8,
                   audits_per_period=100):
    
    #results = pd.DataFrame(index=range(iterations), columns=['MAE','1p decreases observed', '2p decreases observed'])
    rows = []
    sample_dfs = []
    for i in range(iterations):
        true_sir, sample_df = generate_time_series(periods=periods,
                                               monthly_decrease=monthly_decrease,
                                               starting_mean=starting_mean,
                                               audits_per_period=audits_per_period)
        sample_dfs.append(sample_df)
        mae, dobs = get_summary_stats(true_sir, sample_df)
        rows.append([mae,dobs[0],dobs[1],dobs[2]])

    return pd.DataFrame(rows, columns=["MAPE", "1MDO","2MDO","1QDO"]), sample_dfs, true_sir
results_df, sample_dfs, true_sir = run_simulation(200)
results_df.mean()

现在,要运行的模拟次数取决于您的用例,但 50 次是一个不错的起点。如果您正在模拟毫米精度很重要的制造过程,您将需要运行数百或数千次迭代。这些迭代的运行成本很低,因此增加迭代次数以提高精度只意味着它们需要更长的时间才能完成。

具有相同参数值的四个样本蒙特卡罗模拟

对于我们的示例,50 个采样时间序列使我们有足够的信心相信这些指标代表了商店发货率的真实可变性。也就是说,只要我们的现实世界输入在我们的假设范围内。

第 5 步:跨参数值组合运行仿真

既然我们能够为任何输入集的指标获得代表性的确定性,我们就可以跨各种假设组合运行模拟。这将帮助我们了解我们的可变性指标如何响应输入的变化。这种方法类似于机器学习中超参数调整的网格搜索方法。请记住,对于我们的应用商店示例,我们想要确定我们的审核流程对月度百分比下降和月度样本量指标的影响。

我们将使用下面的代码为每月对我们的成功指标的影响指定一个合理的值范围,以及一些可能的样本大小。然后我们将运行run_simulation function这些范围。这段代码旨在让我们能够跨任何维度进行搜索。例如,我们可以将每月减少参数替换为初始平均发行数。这使我们能够了解我们的指标在两个以上维度上的敏感性。

pd.set_option('display.precision',2)

DECREASES = [0.02,0.05,0.075]
AUDIT_COUNTS = [50,100,150]

STARTING_MEAN=10

ITERATIONS=100

def grid_results(iterations, row_param, row_param_values, col_param, col_param_values, **kwargs):
    metric_names = ['MAPE','1MDO','2MDO','1QDO']
    
    result_columns = pd.MultiIndex.from_product([col_param_values, metric_names])
    result_columns.name = col_param

    results = pd.DataFrame(columns=result_columns, index=row_param_values)
    for col_val in col_param_values:
        row = []
        for row_val in row_param_values:
            params = {row_param: row_val, col_param: col_val}
            metrics, _, _ = run_simulation(iterations, **params, **kwargs)
            mean_metrics = metrics.mean()

            for metric in metric_names:
                results.at[row_val, (col_val, metric)] = mean_metrics.loc[metric]
    return results

results = grid_results(ITERATIONS, 
                       'monthly_decrease', 
                       DECREASES, 
                       'audits_per_period', 
                       AUDIT_COUNTS, 
                       starting_mean=STARTING_MEAN)

模拟将产生一系列结果。查看下面的结果,我们可以告诉我们的利益相关者,如果我们从每次审计 10 个平均问题开始,每月运行 100 次随机审计,并且每月将潜在问题率降低 5%,我们应该会看到我们的成功指标每月都在下降83% 的时间。在两个多月的时间里,我们预计 97% 的时间都会出现下降。

我们的蒙特卡罗模拟输出

通过我们的模拟,我们能够以我们的利益相关者可以理解和实施的方式清楚地表达不确定性权衡。例如,我们可以查看我们的结果并传达每月额外 50 次审计将在确定性方面产生可量化的改进。这种洞察力可以使我们的利益相关者就这种确定性是否值得额外支出做出明智的决定。

我们终于得到它了!下次您希望在采样的成功指标中将信号与噪声分开时,请尝试使用蒙特卡罗模拟。这个基本指南只是触及了这个复杂问题的表面,但它是一个很好的起点,我希望你以后能转向它。

作者:Tom Lowe

Tom is a data scientist working on systems to improve app quality at Shopify. In his career, he tried product management, operations and sales before figuring out that SQL is his love language. He lives in Brooklyn with his wife and enjoys running, cycling and writing code.

出处:https://shopify.engineering/monte-carlo-simulations-sampled-success-metrics

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码