You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scipy等库中是否有支持离散/连续分布相加的优化函数?

问题:是否有scipy或其他库的优化函数可以实现概率分布相加

现有多个概率分布,请问scipy(或其他库)中是否存在可用于分布相加的优化函数?参考如下简单示例:
假设我有1个6面骰子和1个20面骰子,需要得到掷出2到26点数对应的概率质量函数。

from scipy.stats import randint
import pandas as pd
import plotly.express as px
x_points_6 = [x+1 for x in range(6)]
x_points_20 = [x+1 for x in range(20)]

dist_6_sided = [randint.pmf(k,1,7) for k in x_points_6]
dist_20_sided = [randint.pmf(k,1,21) for k in x_points_20]
total_dist = add_dist(x_points_6, dist_6_sided, x_points_20, dist_20_sided)
df = pd.DataFrame({'x':total_dist[0], 'y':total_dist[1]})

我目前自行实现了一个偏暴力计算的分布相加函数:

def add_dist(value1, prob1, value2, prob2):
    result_value = []
    result_prob = []
    for prob1_i, value1_i in zip(prob1, value1):
        for prob2_i, value2_i in zip(prob2, value2):
            value = value1_i + value2_i
            prob = prob1_i * prob2_i
            result_value.append(value)
            result_prob.append(prob)
    unique_values = set(result_value)
    count_x = []
    for i in unique_values:
        count_x.append(result_value.count(i))
    return([result_value, result_prob])

通过该函数可以得到最终的分布结果:

df_added_pdfs = df.groupby(['x']).sum()
fig = px.bar(df_added_pdfs)
fig.show()

结果图示
我希望找到可以支持scipy内置任意离散或连续分布函数相加的解决方案,不限于简单的均匀分布场景。我猜测可能是搜索关键词不正确没有找到对应功能,这类常规需求应该在scipy或numpy中有内置实现,因此想要寻找更优化的库函数实现方案。


解答

两个独立随机变量和的概率分布本质是各自分布的卷积,numpy和scipy都有高度优化的内置卷积实现,性能远高于手动双重循环实现。

离散分布求和

离散分布的PMF求和直接用numpy.convolve即可,对应你举的骰子示例改造代码如下:

import numpy as np
from scipy.stats import randint

# 定义两个分布的取值和PMF
val_6 = np.arange(1, 7)
pmf_6 = randint.pmf(val_6, 1, 7)
val_20 = np.arange(1, 21)
pmf_20 = randint.pmf(val_20, 1, 21)

# 直接计算卷积得到和的PMF
sum_pmf = np.convolve(pmf_6, pmf_20, mode="full")
# 自动生成和的取值范围
sum_val = np.arange(val_6.min() + val_20.min(), val_6.max() + val_20.max() + 1)

# 验证概率和为1
print(sum_pmf.sum()) # 输出1.0,符合概率分布要求

该方案不需要后续手动分组求和,输出结果直接对应每个取值的概率,时间复杂度为O(n+m),远高于现有实现的O(n*m)。如果是非均匀取值的离散分布,先对齐到相同步长的网格再做卷积即可。

连续分布求和

连续分布的PDF求和推荐用scipy.signal.fftconvolve,基于FFT实现,大采样量下性能优势极其明显,示例如下:

import numpy as np
from scipy.stats import norm, gamma
from scipy.signal import fftconvolve

# 定义计算网格,步长越小精度越高
step = 0.01
x = np.arange(-10, 30, step)

# 两个连续分布的PDF
pdf_norm = norm.pdf(x, loc=0, scale=1)
pdf_gamma = gamma.pdf(x, a=2, scale=2)

# 卷积计算和的PDF,乘步长做数值积分修正保证概率和为1
sum_pdf = fftconvolve(pdf_norm, pdf_gamma, mode="same") * step
sum_x = x

注意事项

以上方法仅适用于相互独立的随机变量,若变量不独立,需要基于联合分布计算,无法直接用卷积实现。如果需要符号推导和的分布闭式解,可以用sympy的概率模块实现。


内容的提问来源于stack exchange,提问作者Docuemada

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 20:06:06