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

使用NumPy生成多元正态分布样本时偶现负维度错误排查

解决np.random.multivariate_normal偶现"negative dimensions are not allowed"的问题

这个错误跟你的协方差矩阵半正定与否完全没关系——make_spd_matrix生成的确实是正定矩阵,不会触发这类错误。真正的问题出在你分配给某一类的样本数变成了负数,当np.random.multivariate_normal接收到负数的size参数时,就会抛出这个"negative dimensions are not allowed"的报错。

为什么会出现负数样本数?

大概率是你手动按权重分配样本数时的浮点数精度问题:
比如你可能用了类似n_samples = np.array(weights * N, dtype=int)的代码,浮点数的舍入误差可能让某个权重乘以N后得到一个极小的负数(比如-0.0000000001),或者在调整样本数总和时操作失误——比如当各类样本数总和不等于N,手动增减某个类的数量时不小心让它变成了负数。

举个例子:如果N=20,k=5,你想均匀分配4个样本给每个类,但浮点数计算后可能得到[4,4,4,4,3],总和19,若错误地给某个类减1而非给最后一个类加1,就可能出现负数样本数。

解决方案:

1. 用更可靠的方式生成样本数

直接用np.random.multinomial来分配样本数,它会自动保证总和等于N,且每个类的样本数都是非负整数:

import numpy as np
from sklearn.datasets import make_spd_matrix

k = 5
N = 20
# 示例:均匀权重,可替换为自定义权重
weights = np.ones(k) / k  
# 生成每个类的样本数,总和严格等于N
n_samples_per_class = np.random.multinomial(N, weights)

2. 手动处理权重的精度问题

如果必须手动计算权重,记得先截断负数并重新归一化,避免出现无效权重:

# 假设weights是自定义计算得到的
weights = ... 
# 截断负数到0,避免出现负权重
weights = np.clip(weights, 0, 1)
# 重新归一化,确保权重总和为1
weights /= weights.sum()
# 计算样本数并调整总和
n_samples_per_class = np.array(weights * N, dtype=int)
diff = N - n_samples_per_class.sum()
if diff != 0:
    # 将差值加到第一个类,也可选择其他类
    n_samples_per_class[0] += diff
# 确保所有样本数至少为1,避免空样本
n_samples_per_class = np.maximum(n_samples_per_class, 1)

3. 生成样本前做参数检查

在调用np.random.multivariate_normal前,先确认样本数是正的,避免传入无效参数:

means = [[-20.0, -20.0], [-20.0, -6.666666666666666], [-20.0, 6.666666666666668], [-6.666666666666666, -20.0], [-6.666666666666666, -6.666666666666666]]
cov = make_spd_matrix(2)

samples = []
for mean, n in zip(means, n_samples_per_class):
    if n > 0:
        samples.append(np.random.multivariate_normal(mean, cov, size=n))
samples = np.concatenate(samples)

总结

这个偶现错误完全是样本数分配环节的问题,跟协方差矩阵无关。只要确保每个类的样本数都是正整数,且总和等于N,就能彻底解决这个问题。

内容的提问来源于stack exchange,提问作者Preetom Saha Arko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:23:43