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

独立随机变量和与分布卷积不符?numpy实验问题排查

问题1:为什么numpy.convolve结果和变量和的分布不匹配?

你混淆了采样数据的卷积和概率分布的卷积。numpy.convolve是对输入的数值序列做数学上的卷积运算,而随机变量和的分布对应的是它们**概率密度函数(PDF)**的卷积,不是直接对采样出来的随机数数组做卷积。

错误原因

你直接用np.random.uniform生成的采样数组做卷积,本质是把两个长度1e5的序列做卷积,得到的是长度199999的序列,这些数值是两个数组中元素的乘积和,完全不是概率分布的卷积。

正确做法:对概率密度函数做卷积

要得到两个均匀分布和的三角分布,需要先构造它们的离散PDF,再做卷积:

import numpy as np
import matplotlib.pyplot as plt

# 构造[0,1]均匀分布的离散PDF
n_bins = 1000
x = np.linspace(0, 1, n_bins)
pdf_uniform = np.ones(n_bins)  # 均匀分布PDF为1

# 计算两个PDF的卷积,再归一化(因为卷积后总面积是1*1=1,但离散化需要调整)
convolution_pdf = np.convolve(pdf_uniform, pdf_uniform, mode='full')
# 卷积后的x轴范围是0到2,对应长度2n_bins-1
x_convolve = np.linspace(0, 2, 2*n_bins - 1)
# 归一化,保证总面积为1
convolution_pdf = convolution_pdf / np.trapz(convolution_pdf, x_convolve)

# 对比采样和的分布与PDF卷积结果
plt.figure(figsize=(10,5))

plt.subplot(1,2,1)
uniform_sum = np.random.uniform(0,1,100000) + np.random.uniform(0,1,100000)
plt.hist(uniform_sum, bins=50, density=True, alpha=0.7, label='Sample Sum')
plt.title('Sum of Uniform Distributions')
plt.legend()

plt.subplot(1,2,2)
plt.plot(x_convolve, convolution_pdf, label='PDF Convolution')
plt.title('Convolution of Uniform PDFs')
plt.legend()

plt.show()

运行后你会看到右边的曲线和左边的直方图完全匹配,是标准的三角分布。


问题2:状态转移矩阵中求解总成本分布(动态规划+卷积)

针对带成本分布的状态转移问题,核心思路是动态规划+分布卷积,逐步计算每个状态的总成本分布。

核心逻辑

  1. 状态定义:用dp[s]表示到达状态s时的总成本分布,存储为离散的PDF数组(包含x轴取值和对应的概率密度)。
  2. 初始状态:起始态start的总成本分布是点分布——成本为0,概率密度无穷大(离散化后是一个峰值,总面积为1)。
  3. 状态转移:对于每个状态s,遍历所有从s到s'的转移:
    • 转移概率为p
    • 转移成本的分布为cost_dist(离散PDF)
    • 则到达s'的新增成本分布是dp[s]和cost_dist的卷积(对应两步成本的和)
    • 将这个新增分布乘以p,加到dp[s']的现有分布上
  4. 终止条件:当处理到终态,或者所有可能的转移都迭代完成后,dp[end]就是所求的总成本分布。

实现细节

  • 离散分布表示:用两个数组存储,比如(x_vals, pdf_vals),x_vals是成本的离散取值,pdf_vals是对应的概率密度。
  • 卷积优化:对于大规模计算,用numpy.fft实现快速卷积(FFT卷积),比直接用np.convolve快得多。
  • 分布合并:当多个转移路径贡献同一状态的成本分布时,需要将它们的PDF按x轴对齐后相加(加权转移概率)。

简单示例代码

假设我们有3个状态:start→mid→end,转移规则:

  • start到mid:概率0.6,成本服从[0,1]均匀分布;概率0.4,成本服从[1,2]均匀分布
  • mid到end:概率1.0,成本服从正态分布N(1, 0.1)
import numpy as np
import matplotlib.pyplot as plt

def create_discrete_dist(x_start, x_end, n_bins, dist_type='uniform', **kwargs):
    """创建离散概率分布"""
    x = np.linspace(x_start, x_end, n_bins)
    if dist_type == 'uniform':
        pdf = np.ones(n_bins)
    elif dist_type == 'normal':
        mu = kwargs.get('mu')
        sigma = kwargs.get('sigma')
        pdf = np.exp(-(x - mu)**2 / (2 * sigma**2)) / (sigma * np.sqrt(2 * np.pi))
    # 归一化
    pdf = pdf / np.trapz(pdf, x)
    return x, pdf

def convolve_dist(dist1, dist2):
    """卷积两个离散分布,返回新的(x, pdf)"""
    x1, pdf1 = dist1
    x2, pdf2 = dist2
    # 计算卷积后的x轴范围
    x_min = x1[0] + x2[0]
    x_max = x1[-1] + x2[-1]
    # 用FFT做快速卷积
    n = len(pdf1) + len(pdf2) - 1
    fft1 = np.fft.fft(pdf1, n)
    fft2 = np.fft.fft(pdf2, n)
    conv_pdf = np.fft.ifft(fft1 * fft2).real
    # 生成新的x轴
    x_conv = np.linspace(x_min, x_max, n)
    # 归一化
    conv_pdf = conv_pdf / np.trapz(conv_pdf, x_conv)
    return x_conv, conv_pdf

# 初始化状态分布
n_bins = 500
dp = {}
# 起始态:成本0,概率1(离散化为窄峰)
start_x = np.array([0.0])
start_pdf = np.array([1e10])  # 近似点分布
dp['start'] = (start_x, start_pdf)

# 定义转移规则
transitions = {
    'start': [
        {'to': 'mid', 'prob': 0.6, 'cost_dist': create_discrete_dist(0, 1, n_bins)},
        {'to': 'mid', 'prob': 0.4, 'cost_dist': create_discrete_dist(1, 2, n_bins)}
    ],
    'mid': [
        {'to': 'end', 'prob': 1.0, 'cost_dist': create_discrete_dist(0.7, 1.3, n_bins, dist_type='normal', mu=1, sigma=0.1)}
    ]
}

# 执行动态规划迭代
for _ in range(2):  # 这里只有两步转移,迭代2次足够
    new_dp = dp.copy()
    for s in transitions:
        if s not in dp:
            continue
        for trans in transitions[s]:
            to_s = trans['to']
            prob = trans['prob']
            cost_dist = trans['cost_dist']
            # 卷积当前状态分布和转移成本分布
            conv_x, conv_pdf = convolve_dist(dp[s], cost_dist)
            # 加权转移概率
            conv_pdf *= prob
            # 合并到目标状态的分布
            if to_s not in new_dp:
                new_dp[to_s] = (conv_x, conv_pdf)
            else:
                # 对齐x轴(这里简化处理,实际可以用插值)
                target_x, target_pdf = new_dp[to_s]
                # 插值到相同的x轴
                interp_pdf = np.interp(target_x, conv_x, conv_pdf, left=0, right=0)
                new_dp[to_s] = (target_x, target_pdf + interp_pdf)
    dp = new_dp

# 绘制终态的总成本分布
x_end, pdf_end = dp['end']
plt.figure(figsize=(8,5))
plt.plot(x_end, pdf_end)
plt.title('Total Cost Distribution to End State')
plt.xlabel('Total Cost')
plt.ylabel('Probability Density')
plt.show()

注意事项

  • 当状态和转移数量很大时,需要优化离散化的精度和卷积效率,避免内存溢出。
  • 对于无限状态或长路径,可以采用迭代收敛的方式,直到分布变化足够小为止。
  • 如果成本分布是连续的,离散化的 bins 数量需要权衡精度和计算速度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 03:35:08