首页 > 解决方案 > 如何从 Python 中的非正态多变量分布生成样本?

问题描述

我有一个包含 10 个变量和 100 行的输入数据框 df_input。这些数据不是正态分布的。我想生成一个包含 10 个变量和 10,000 行的输出数据帧,以便新数据帧的协方差矩阵和均值与原始数据帧的相同。输出变量不应呈正态分布,而应具有与输入变量相似的分布。即: Cov(df_output) = Cov(df_input) 和 mean(df_ouput) = mean(df_input) 有没有 Python 函数可以做到这一点?

注意: np.random.multivariate_normal(mean_input,Cov_input,10000) 几乎可以做到这一点,但输出变量是正态分布的,而我需要它们与输入具有相同(或相似)的分布。

标签: python

解决方案


更新

我刚刚注意到你提到np.random.multivariate_normal......它一下子就相当于gen_like()下面!

我将把它留在这里以帮助人们理解其机制,但总结一下:

  1. 您可以将经验分布的均值和协方差与(旋转、缩放、平移)正态匹配;
  2. 为了更好地匹配更高的时刻,您应该查看 copula。

原始答案

由于您只对匹配两个第一时刻(均值、方差)感兴趣,因此可以使用简单的 PCA 来获得初始数据的合适模型。请注意,新生成的数据将是一个正常的椭圆体,经过旋转、缩放和平移以匹配初始数据的经验均值和协方差。

如果您想要对原始发行版进行更复杂的“复制”,那么您应该按照我在评论中所说的那样查看Copula 。

因此,仅在前两个时刻,假设您的输入数据是d0

from sklearn.decomposition import PCA

def gen_like(d0, n):
    pca = PCA(n_components=d0.shape[1]).fit(d0)
    z0 = pca.transform(d0)  # z0 is centered and uncorrelated (cov is diagonal)
    z1 = np.random.normal(size=(n, d0.shape[1])) * np.std(z0, 0)

    # project back to input space
    d1 = pca.inverse_transform(z1)
    return d1

例子:

# generate some random data

# arbitrary transformation matrix
F = np.array([
    [1, 2, 3],
    [2, 1, 4],
    [5, 1, 3],
])
d0 = np.random.normal(2, 4, size=(10000, 3)) @ F.T

np.mean(d0, 0)
# ex: array([12.12791066, 14.10333273, 17.95212292])

np.cov(d0.T)
# ex: array([[225.09691912, 257.39878551, 259.40288019],
#            [257.39878551, 338.34087242, 373.4773562 ],
#            [259.40288019, 373.4773562 , 566.29288861]])
# try to match mean, variance of d0
d1 = gen_like(d0, 10000)

np.allclose(np.mean(d0, 0), np.mean(d1, 0), rtol=0.1)
# often True (but not guaranteed)

np.allclose(np.cov(d0.T), np.cov(d1.T), rtol=0.1)
# often True (but not guaranteed)

有趣的是,您可以在圆孔中安装一个方形钉(即,证明实际上只有均值,方差匹配,而不是更高的时刻):

d0 = np.random.uniform(5, 10, size=(1000, 3)) @ F.T
d1 = gen_like(d0, 10000)

np.allclose(np.mean(d0, 0), np.mean(d1, 0), rtol=0.1)
# often True (but not guaranteed)

np.allclose(np.cov(d0.T), np.cov(d1.T), rtol=0.1)
# often True (but not guaranteed)

推荐阅读