【问题标题】:iterative 2-D regression dependent truncated normal/laplace distribution迭代二维回归依赖截断正态/拉普拉斯分布
【发布时间】:2019-11-29 13:10:50
【问题描述】:

我需要您的帮助来创建一个正态或更好的截断拉普拉斯分布,该分布线性依赖于另一个拉普拉斯分布变量。

这是我迄今为止在派生的 y 分布中使用 NaN 所取得的成果:

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

slope = 0.2237
intercept = 1.066
spread = 4.8719

def dependency(x):
    y_lin = slope * x + intercept
    lower = slope / spread * 3 * x
    upper = slope * spread / 3 * x + 2 * intercept

    y_lin_noise = np.random.laplace(loc=0, scale=spread, size=len(y_lin)) + y_lin

    y_lin_noise[y_lin_noise < lower] = np.nan  # This is the desperate solution where
    y_lin_noise[y_lin_noise > upper] = np.nan  # NaNs are introduced

    return y_lin_noise

max = 100
min = 1
mean = 40
sigma = 25

x = truncnorm((min-mean)/sigma, (max-mean)/sigma, loc=mean, scale=sigma).rvs(5000)
y = dependency(x)

# Plotting
xx = np.linspace(np.nanmin(x), np.nanmax(x), 100)
yy = slope * xx + intercept
lower = slope/spread*3*xx
upper = slope*spread/3*xx + 2*intercept

mask = ~np.isnan(y) & ~np.isnan(x)
x = x[mask]
y = y[mask]

xy = np.vstack([x, y])
z = gaussian_kde(xy)(xy)
idz = z.argsort()
x, y, z = x[idz], y[idz], z[idz]

fig, ax = plt.subplots(figsize=(5, 5))
plt.plot(xx, upper, 'r-.', label='upper constraint')
plt.plot(xx, lower, 'r--', label='lower constraint')

ax.scatter(x, y, c=z, s=3)
plt.xlabel(r'$\bf X_{laplace}$')
plt.ylabel(r'$\bf Y_{{derived}}$')
plt.plot(xx, yy, 'r', label='regression model')
plt.legend()
plt.tight_layout()
plt.show()

我最终想要得到的是没有 NaN 的 y 分布,因此对于每个 x,在上限/下限范围内都有一个对应的 y。也就是说,回归线周围的下限/上截断分布。

我期待想法!

谢谢你和最好的问候。

【问题讨论】:

  • 您不想删除 x 和 y 的任何值,即使它们可能超出范围?或者是否可以删除异常值并确保您绘制的每个 x 在范围内都有对应的 y?
  • 我更愿意将拉普拉斯分布的先前创建限制在边界内,并且在最终派生的 Y 分布中没有任何 NaN。我的业余尝试在这里可能会令人困惑。
  • 那么您希望所有噪音都在范围内吗?所以你不在乎它不再是一个拉普拉斯随机分布?
  • 这正是我所需要的,你是对的:我不在乎数据是否不再是拉普拉斯分布或正态分布,但点在回归线上的频率仍然应该更高。

标签: python random distribution


【解决方案1】:

您想要做的基本上是重试超出您界限的值。您可以定义一个对每个值都执行此操作的函数,或者您可以定义初始值并循环遍历答案以“更正”超出范围的值,如下所示:

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

slope = 0.2237
intercept = 1.066
spread = 4.8719


#slow but effective
def truncated_noise(y, lower, upper):
    while True:
        y_noise = np.random.laplace(loc=0, scale=spread, size=1) + y
        if upper > y_noise > lower:
            return y_noise


def refine_noise(y, y_lin_noise, lower, upper):
    for i in range(len(y_lin_noise)):
        if upper[i] < y_lin_noise[i] or lower[i] > y_lin_noise[i]:
            y_lin_noise[i] = truncated_noise(y[i], lower[i], upper[i])
    return y_lin_noise


def dependency(x):
    y_lin = slope * x + intercept
    lower = slope / spread * 3 * x
    upper = slope * spread / 3 * x + 2 * intercept

    y_lin_noise = np.random.laplace(loc=0, scale=spread, size=len(y_lin)) + y_lin

    y_lin_noise = refine_noise(y_lin, y_lin_noise, lower, upper)

    return y_lin_noise

max = 100
min = 1
mean = 40
sigma = 25

x = truncnorm((min-mean)/sigma, (max-mean)/sigma, loc=mean, scale=sigma).rvs(5000)
y = dependency(x)

# Plotting
xx = np.linspace(np.nanmin(x), np.nanmax(x), 100)
yy = slope * xx + intercept
lower = slope/spread*3*xx
upper = slope*spread/3*xx + 2*intercept


xy = np.vstack([x, y])
z = gaussian_kde(xy)(xy)
idz = z.argsort()
x, y, z = x[idz], y[idz], z[idz]

fig, ax = plt.subplots(figsize=(5, 5))
plt.plot(xx, upper, 'r-.', label='upper constraint')
plt.plot(xx, lower, 'r--', label='lower constraint')

ax.scatter(x, y, c=z, s=3)
plt.xlabel(r'$\bf X_{laplace}$')
plt.ylabel(r'$\bf Y_{{derived}}$')
plt.plot(xx, yy, 'r', label='regression model')
plt.legend()
plt.tight_layout()
plt.show()

我不知道你想用它做什么,但我知道这不再是一个随机的拉普拉斯分布,所以如果你的函数需要它,就不要这样做。

【讨论】:

  • 很好用!非常感谢您提供这个聪明的解决方案!心中也有一些迭代解决方案,但我不知道如何实现它。
  • 我的初始答案通过 y 数组并带有噪声,但正确实现需要两者。所以请使用我最新的编辑;)(如果你没有使用最后一个)
猜你喜欢
  • 1970-01-01
  • 2021-03-27
  • 2018-02-26
  • 2014-07-16
  • 2021-10-17
  • 1970-01-01
  • 2021-03-03
  • 2022-11-24
相关资源
最近更新 更多