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

使用Numpy从两个均匀分布生成双峰分布的实现问题排查

问题:生成双峰分布样本时出现超出[0,1]范围的值,代码哪里错了?

我尝试复现某博客中的bimodalSample函数,以下是我的实现代码:

import numpy as np
    
def bimodal_pdf(distance: float, weight: float) -> np.ndarray:
    r = np.random.rand()

    if r < weight:
        return np.random.normal(r) * (1 - distance)
    else:
        return np.random.normal(r) * (1 - distance) + distance


n_samples = 100000
distance = 0.7
weight = 0.5


pdf = np.array([
    bimodal_pdf(distance=distance, weight=weight) for s in range(n_samples)
])

但生成的样本值出现小于0或大于1的情况,请问我的实现哪里出错了?


分析与修正

你的代码有两个核心错误:

  1. 正态分布参数使用错误
    np.random.normal(r)的写法完全不符合需求:该函数的第一个参数是均值,第二个是标准差(默认1)。你把r(0-1的随机数)当成均值传入,导致每个样本的正态分布均值都在随机变化,完全偏离了双峰分布(两个固定中心)的设计。

  2. 采样逻辑错误
    原目标函数应该是生成两个固定中心的正态分布混合样本:一个中心在0,另一个中心在distance,通过weight控制两个分布的采样比例。你的计算逻辑(乘以1-distance再加偏移)完全打乱了分布的中心和范围控制。

修正后的代码

import numpy as np

def bimodal_sample(distance: float, weight: float) -> float:
    # 用(1-distance)/3作为标准差,确保99.7%的样本落在[0,1]范围内
    std_dev = (1 - distance) / 3
    if np.random.rand() < weight:
        # 从中心为0的正态分布采样
        return np.random.normal(loc=0, scale=std_dev)
    else:
        # 从中心为distance的正态分布采样
        return np.random.normal(loc=distance, scale=std_dev)

n_samples = 100000
distance = 0.7
weight = 0.5

samples = np.array([bimodal_sample(distance, weight) for _ in range(n_samples)])
# 可选:过滤极端小概率出现的超出范围值
samples = np.clip(samples, 0, 1)

说明

  • 设定标准差为(1-distance)/3:这样中心在0的分布,99.7%的样本会落在0 ± 3*std_dev = 0 ± (1-distance),即0到1-distance,不会小于0;中心在distance的分布,99.7%的样本会落在distance ± (1-distance),即2distance-1到1(当distance=0.7时,下限为0.4),刚好不会超出1。
  • 函数更名:bimodal_pdf改为bimodal_sample,因为该函数是生成样本而非计算概率密度,命名更准确。
  • 可选的np.clip:用于处理极端小概率出现的超出范围值,进一步确保样本落在[0,1]区间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 15:02:13