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

带采样限制的混合概率分布构建方法咨询

构建带取值限制的混合概率分布并可视化

核心方案

用scipy的截断分布类处理单分布的取值限制,再通过权重组合成混合分布,完全兼容numpy数组操作,解决你提到的适配问题。这里以截断正态分布为例(匹配你需求里的均值、标准差和取值限制),步骤清晰可复用。

实现步骤与代码

1. 依赖导入

import numpy as np
from scipy.stats import truncnorm
import matplotlib.pyplot as plt

2. 定义混合分布参数

先明确每个子分布的配置:权重、均值、标准差、取值上下限

# 子分布配置:(权重, 均值, 标准差, 下限, 上限)
dist_params = [
    (0.3, 2, 3, -9, 5),    # 第一个截断正态分布
    (0.5, 10, 4, 7, 20),   # 第二个截断正态分布
    (0.2, -5, 2, -9, 0)    # 第三个截断正态分布
]

3. 生成截断分布实例

scipy的truncnorm需要先把原始上下限转换成标准化值((限 - 均值)/标准差),封装成函数方便复用:

def get_truncated_normal(mu, sigma, low, high):
    # 计算标准化上下限
    a = (low - mu) / sigma
    b = (high - mu) / sigma
    return truncnorm(a, b, loc=mu, scale=sigma)

# 生成所有子分布对象和对应的权重
distributions = []
weights = []
for w, mu, sigma, low, high in dist_params:
    distributions.append(get_truncated_normal(mu, sigma, low, high))
    weights.append(w)
# 归一化权重(确保总和为1)
weights = np.array(weights) / np.sum(weights)

4. 混合分布采样

两种采样方式,按需选择:

  • 方式一:先按权重选分布,再单样本采样(适合小批量)
def sample_mixed_dist(n_samples):
    samples = []
    # 按权重选择每个样本对应的分布索引
    dist_indices = np.random.choice(len(distributions), size=n_samples, p=weights)
    for idx in dist_indices:
        samples.append(distributions[idx].rvs())
    return np.array(samples)

# 生成10000个样本
samples = sample_mixed_dist(10000)
  • 方式二:按权重批量采样(效率更高)
def batch_sample_mixed_dist(n_samples):
    # 计算每个分布需要采样的数量
    counts = np.random.multinomial(n_samples, weights)
    all_samples = []
    for idx, cnt in enumerate(counts):
        if cnt > 0:
            all_samples.append(distributions[idx].rvs(size=cnt))
    # 打乱顺序模拟混合
    mixed_samples = np.concatenate(all_samples)
    np.random.shuffle(mixed_samples)
    return mixed_samples

samples = batch_sample_mixed_dist(10000)

5. 计算混合分布的PDF并绘图

# 生成绘图的x轴范围(覆盖所有子分布的上下限)
x_min = min(p[3] for p in dist_params)
x_max = max(p[4] for p in dist_params)
x = np.linspace(x_min, x_max, 1000)

# 计算混合PDF:每个子分布PDF乘以权重后求和
mixed_pdf = np.zeros_like(x)
for dist, w in zip(distributions, weights):
    mixed_pdf += w * dist.pdf(x)

# 绘图:直方图(样本)+ PDF曲线
plt.figure(figsize=(10, 6))
plt.hist(samples, bins=50, density=True, alpha=0.6, label='采样样本直方图')
plt.plot(x, mixed_pdf, 'r-', linewidth=2, label='混合分布PDF')
plt.xlabel('取值')
plt.ylabel('概率密度')
plt.title('取值限制在-9和20的混合概率分布')
plt.legend()
plt.grid(axis='y', alpha=0.3)
plt.show()

关键说明

  • scipy的截断分布对象生成的样本和计算的PDF都是numpy数组,完全兼容numpy的所有操作,不存在适配问题。你之前的困惑可能是没找到用scipy封装截断分布后再组合的正确方式。
  • 如果需要其他类型的截断分布(比如截断均匀、截断泊松),只需要替换truncnorm为对应的scipy截断分布类,调整参数转换逻辑即可。
  • 权重归一化是必要步骤,确保混合分布的概率和为1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 09:24:58