微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在python中获取混合分布数组?

如何解决如何在python中获取混合分布数组?

我一直在研究称为 Conflation 的方法,该方法旨在将某种类型但不同形状/参数(均值和方差)的多个连续分布组合成一个连续分布。可以在以下链接中找到该问题:Conflation Method Question

所以,我想寻找一种方法来组合不同类型的连续分布而不是正态分布,但我一直在努力解决如何使用连续分布方程来形成合并分布数组(合并方程可以在上面的链接)具有范数分布。我收到以下错误消息:

错误信息:

Traceback (most recent call last):

  File "D:\Anaconda\Projects\untitled63.py",line 34,in <module>
    graph=conflate_pdf(dists,lb,ub)

  File "D:\Anaconda\Projects\untitled63.py",line 20,in conflate_pdf
    denom = quad(func=(prod_pdf),a=(lb),b=(ub),args=(dists))[0]

  File "D:\Anaconda\lib\site-packages\scipy\integrate\quadpack.py",line 351,in quad
    retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,File "D:\Anaconda\lib\site-packages\scipy\integrate\quadpack.py",line 463,in _quad
    return _quadpack._qagse(func,limit)

TypeError: prod_pdf() takes 1 positional argument but 2 were given

如何解决这个问题并获得合并的 PDF 数组?请找到以下代码

代码

from scipy.integrate import quad
from scipy import stats
import numpy as np

def prod_pdf(dists):
    for dist in dists:
        p_pdf=np.ones(dist.shape[0])
        for x in dist:
            p_pdf=p_pdf*x
    return p_pdf

def conflate_pdf(dists,ub):
    denom = quad(func=(prod_pdf),args=(dists))[0]
    return prod_pdf(dists)/denom

lb=-10
ub=10
domain=np.arange(lb,ub,.01)

dist_1 = stats.norm.pdf(domain,2,1)
dist_2 = stats.norm.pdf(domain,2.5,1.5)
dist_3 = stats.norm.pdf(domain,2.2,1.6)
dist_4 = stats.norm.pdf(domain,2.4,1.3)
dist_5 = stats.norm.pdf(domain,2.7,1.5)
dists=[dist_1,dist_2,dist_3,dist_4,dist_5]
graph=conflate_pdf(dists,ub)

from matplotlib import pyplot as plt
plt.plot(domain,graph)
plt.xlabel("domain")
plt.ylabel("pdf")
plt.title("Conflated PDF")
plt.show()

编辑 1:

我根据 @MindTheBandGap 修改函数,现在出现新错误。我在想可能是因为除法,使用数组进行集成,还是其他原因?在下面找到代码错误消息:

代码

def prod_pdf(x,pdfs):
    prod=np.ones(np.array(pdfs)[0].shape)
    for pdf in pdfs:
        print(prod)
        for c,y in enumerate(pdf):
            prod[c]=prod[c]*y
        print('final:',prod)
    return prod

def conflate_pdf(x,dists,ub):
    denom = quad(prod_pdf,args=(dists))
    print('Denom: ',denom)
    print('product pdf: ',prod_pdf(x,dists)[0])
    conflated_pdf=prod_pdf(x,dists)[0]/denom
    print(conflated_pdf)
    return conflated_pdf

lb=-10
ub=10
domain=np.arange(lb,.01)

dist_1 = st.norm.pdf(domain,1)
dist_2 = st.norm.pdf(domain,1.5)
dist_3 = st.norm.pdf(domain,1.6)
dist_4 = st.norm.pdf(domain,1.3)
dist_5 = st.norm.pdf(domain,1.5)

from matplotlib import pyplot as plt
plt.plot(domain,dist_1,'r')
plt.plot(domain,'g')
plt.plot(domain,'b')
plt.plot(domain,'y')
plt.plot(domain,dist_5,'c')

dists=[dist_1,dist_5]
graph=conflate_pdf(domain,ub)


plt.plot(domain,graph,'m')
plt.xlabel("domain")
plt.ylabel("pdf")
plt.title("Conflated PDF")
plt.show()

错误信息:

Traceback (most recent call last):

  File "D:\Anaconda\Projects\untitled62.py",line 85,in <module>
    graph=conflate_pdf(domain,ub)

  File "D:\Anaconda\Projects\untitled62.py",line 60,in conflate_pdf
    denom = quad(prod_pdf,limit)

TypeError: only size-1 arrays can be converted to Python scalars

编辑 2:

Answer 从这个链接 Conflation method question代码能够运行而不会出现大小为 1 数组的错误。这是带有输出和绘图的代码

代码

from scipy.integrate import quad
from scipy import stats
import numpy as np

def prod_pdf(x,dists):
    p_pdf=1
    print('Incoming Array:',p_pdf)
    for dist in dists:
        p_pdf=p_pdf*dist.pdf(x)
        print('final:',p_pdf)
    return p_pdf

def conflate_pdf(x,ub):
    print('Input product pdf: ',dists))
    denom = quad(prod_pdf,args=(dists,))[0]
    print('Denom: ',denom)
    conflated_pdf=prod_pdf(x,dists)/denom
    print('Conflated PDF: ',conflated_pdf)
    return conflated_pdf

lb=-10
ub=10
domain=np.arange(lb,1.5)
dists=[stats.norm(2,1),stats.norm(2.5,1.5),stats.norm(2.2,1.6),stats.norm(2.4,1.3),stats.norm(2.7,1.5)]

from matplotlib import pyplot as plt
plt.plot(domain,'r',label='dist. 1')
plt.plot(domain,'g',label='dist. 2')
plt.plot(domain,'b',label='dist. 3')
plt.plot(domain,'y',label='dist. 4')
plt.plot(domain,'c',label='dist. 5')

graph=conflate_pdf(domain,ub)
plt.plot(domain,'m',label='Conflated dist.')
plt.xlabel("domain")
plt.ylabel("pdf")
plt.title("Conflated PDF")
plt.legend()
plt.show()

这是输出的一小部分:

Incoming Array: 1
final: 0.15352177537004433
final: 0.034348669264845304
final: 0.006519131844904635
final: 0.0015040030811035296
final: 0.0003607258742065213
Incoming Array: 1
final: 0.042345986284209325
final: 0.006294747321619583
final: 0.0007651214249593444
final: 9.805307029794648e-05
final: 1.668121592516301e-05
Denom:  0.0029066671327537714
Incoming Array: 1
final: [2.14638374e-32 2.41991991e-32 2.72804284e-32 ... 6.41980576e-15
 5.92770938e-15 5.47278628e-15]
final: [4.75178372e-48 5.66328097e-48 6.74864868e-48 ... 7.03075979e-21
 6.27970218e-21 5.60806584e-21]
final: [2.80912097e-61 3.51131870e-61 4.38823989e-61 ... 1.32670185e-26
 1.14952951e-26 9.95834610e-27]
final: [1.51005552e-81 2.03116529e-81 2.73144352e-81 ... 1.76466623e-34
 1.46198598e-34 1.21092834e-34]
final: [1.09076800e-97 1.55234627e-97 2.20861552e-97 ... 3.72095218e-40
 2.98464396e-40 2.39335035e-40]
Conflated PDF:  [3.75264162e-95 5.34063998e-95 7.59844666e-95 ... 1.28014389e-37
 1.02682689e-37 8.23400219e-38]

剧情:

enter image description here

在我看来,它从一个提取每个密度值并将其与其他分布相乘。我尝试运行以下代码(基于链接中的答案),但是,我一直在获取一个变量,它在 product 函数之后获取整个数组,并且在 size-1 数组方面产生相同的错误。请参阅以下带有部分输出代码

代码

from scipy.integrate import quad
from scipy import stats
import numpy as np

def prod_pdf(x,p_pdf)
    for dist in dists:
        p_pdf=p_pdf*dist
        print('final:',p_pdf)
    return p_pd

def conflate_pdf(x,))[0]
    # denom = simps(prod_pdf)
    # denom = nquad(func=(prod_pdf),ranges=([lb,ub]),1.5)

from matplotlib import pyplot as plt
plt.xlabel("domain")
plt.ylabel("pdf")
plt.title("Conflated PDF")
plt.legend()
plt.plot(domain,label='dist. 5')

dists=[dist_1,dist_5]
print('distribution list: \n',dists)
graph=conflate_pdf(domain,ub)

plt.plot(domain,label='Conflated dist.')
plt.show()

这是输出的一小部分:

Incoming Array: 1
final: [2.14638374e-32 2.41991991e-32 2.72804284e-32 ... 6.41980576e-15
 5.92770938e-15 5.47278628e-15]
final: [4.75178372e-48 5.66328097e-48 6.74864868e-48 ... 7.03075979e-21
 6.27970218e-21 5.60806584e-21]
final: [2.80912097e-61 3.51131870e-61 4.38823989e-61 ... 1.32670185e-26
 1.14952951e-26 9.95834610e-27]
final: [1.51005552e-81 2.03116529e-81 2.73144352e-81 ... 1.76466623e-34
 1.46198598e-34 1.21092834e-34]
final: [1.09076800e-97 1.55234627e-97 2.20861552e-97 ... 3.72095218e-40
 2.98464396e-40 2.39335035e-40]
Input product pdf:  [1.09076800e-97 1.55234627e-97 2.20861552e-97 ... 3.72095218e-40
 2.98464396e-40 2.39335035e-40]
Incoming Array: 1
final: [2.14638374e-32 2.41991991e-32 2.72804284e-32 ... 6.41980576e-15
 5.92770938e-15 5.47278628e-15]
final: [4.75178372e-48 5.66328097e-48 6.74864868e-48 ... 7.03075979e-21
 6.27970218e-21 5.60806584e-21]
final: [2.80912097e-61 3.51131870e-61 4.38823989e-61 ... 1.32670185e-26
 1.14952951e-26 9.95834610e-27]
final: [1.51005552e-81 2.03116529e-81 2.73144352e-81 ... 1.76466623e-34
 1.46198598e-34 1.21092834e-34]
final: [1.09076800e-97 1.55234627e-97 2.20861552e-97 ... 3.72095218e-40
 2.98464396e-40 2.39335035e-40]

我设法查看了在链接中实现相同方法代码,我编辑了代码,它从每个分布中获取一个变量,但是,对于循环的其余部分,它继续打印相同的值,它确实不转到列表中的下一个值,并且 Conflated 分布是单个变量。请参阅以下带有部分输出代码

代码

from scipy.integrate import quad
from scipy import stats
import numpy as np

def prod_pdf(x,p_pdf)
    for c,dist in enumerate(dists):
        p_pdf=p_pdf*dist[c]
        print('final:',label='Conflated dist.')
plt.show()

输出的一部分:

Incoming Array: 1
final: 2.1463837356630605e-32
final: 5.0231307782193034e-48
final: 3.266239495519432e-61
final: 2.187514996217005e-81
final: 1.979657878680375e-97
Incoming Array: 1
final: 2.1463837356630605e-32
final: 5.0231307782193034e-48
final: 3.266239495519432e-61
final: 2.187514996217005e-81
final: 1.979657878680375e-97
Denom:  3.95931575736075e-96
Incoming Array: 1
final: 2.1463837356630605e-32
final: 5.0231307782193034e-48
final: 3.266239495519432e-61
final: 2.187514996217005e-81
final: 1.979657878680375e-97
Conflated PDF:  0.049999999999999996

编辑 3:

我实现了以下代码,它似乎有效,而且,我设法解决quad 的问题,如果我将 quad 的部分更改为 fixed_quad 和规范化pdf列表。我会得到同样的结果。代码如下:

import scipy.stats as st
import numpy as np
import scipy.stats as st
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler,normalizer,normalize,StandardScaler
from scipy.integrate import quad,simps,quad_vec,nquad,cumulative_trapezoid
from scipy.integrate import romberg,trapezoid,simpson,romb
from scipy.integrate import fixed_quad,quadrature,quad_explain
from scipy import stats
import time

def user_prod_pdf(x,dists):
p_list=[]
p_pdf=1
print('Incoming Array:',p_pdf)
for dist in dists:
print('Incoming distribution Array:',dist.pdf(x))
p_pdf=p_pdf*dist.pdf(x)
print('Product PDF:',p_pdf)
p_list.append(p_pdf)
print('final Product PDF:',p_pdf)
print('Product PDF list: ',p_list)
return p_pdf

def user_conflate_pdf(x,ub):
print('Input product pdf: ',user_prod_pdf(x,dists))
denom = quad(user_prod_pdf,))[0]
print('Denom: ',denom)
conflated_pdf=user_prod_pdf(x,dists)/denom
print('Conflated PDF: ',conflated_pdf)
return conflated_pdf

def user_conflate_pdf_2(pdfs):
"""
Compute conflation of given pdfs.

[ARGS]
- pdfs: PDFs numpy array of shape (n,x)
where n is the number of PDFs
and x is the variable space.

[RETURN]
A 1d-array of normalized conflated PDF.
"""
# conflate
conflation = np.array(pdfs).prod(axis=0)
# normalize
conflation /= conflation.sum()
return conflation

def my_product_pdf(x,p_pdf)
list_full_size=np.array(dists).shape
print('Full list size: ',list_full_size)
print('list size: ',list_full_size[0])
for x in range(list_full_size[1]):
p_pdf=1
for y in range(list_full_size[0]):
p_pdf=float(p_pdf)*dists[y][x]
print('Product value: ',p_pdf)
print('Product PDF:',p_list)
# return p_pdf
return p_list
# return np.array(p_list)

def my_conflate_pdf(x,ub):
print('\n')
# print('product pdf: ',dists))
print('product pdf: ',my_product_pdf(x,dists))
denom = fixed_quad(my_product_pdf,),n=1)[0]
print('Denom: ',denom)
# conflated_pdf=prod_pdf(x,dists)/denom
conflated_pdf=my_product_pdf(x,dists)/denom
# conflated_pdf=[i / j for i,j in zip(my_product_pdf(x,dists),denom)]
print('Conflated PDF: ',conflated_pdf)
return conflated_pdf

lb=-10
ub=10
domain=np.arange(lb,.01)

# dist_1 = st.norm(2,1)
# dist_2 = st.norm(2.5,1.5)
# dist_3 = st.norm(2.2,1.6)
# dist_4 = st.norm(2.4,1.3)
# dist_5 = st.norm(2.7,1.5)

# dist_1_pdf = st.norm.pdf(domain,1)
# dist_2_pdf = st.norm.pdf(domain,1.5)
# dist_3_pdf = st.norm.pdf(domain,1.6)
# dist_4_pdf = st.norm.pdf(domain,1.3)
# dist_5_pdf = st.norm.pdf(domain,1.5)

# dist_1_pdf /= dist_1_pdf.sum()
# dist_2_pdf /= dist_2_pdf.sum()
# dist_3_pdf /= dist_3_pdf.sum()
# dist_4_pdf /= dist_4_pdf.sum()
# dist_5_pdf /= dist_5_pdf.sum()

dist_1 = st.norm(2,1)
dist_2 = st.norm(4,2)
dist_3 = st.norm(7,4)
dist_4 = st.norm(2.4,1.3)
dist_5 = st.norm(2.7,1.5)

dist_1_pdf = st.norm.pdf(domain,1)
dist_2_pdf = st.norm.pdf(domain,4,2)
dist_3_pdf = st.norm.pdf(domain,7,4)
dist_4_pdf = st.norm.pdf(domain,1.3)
dist_5_pdf = st.norm.pdf(domain,1.5)

# dist_1_pdf /= dist_1_pdf.sum()
# dist_2_pdf /= dist_2_pdf.sum()
# dist_3_pdf /= dist_3_pdf.sum()
# dist_4_pdf /= dist_4_pdf.sum()
# dist_5_pdf /= dist_5_pdf.sum()

# User:
plt.xlabel("domain")
plt.ylabel("pdf")
plt.title("User Conflated PDF")
plt.plot(domain,dist_1_pdf,dist_2_pdf,dist_3_pdf,dist_4_pdf,dist_5_pdf,dist_5]
user_graph=user_conflate_pdf(domain,ub)
print('Final Conflated PDF: ',user_graph)

# user_graph /= user_graph.sum()

plt.plot(domain,user_graph,label='Conflated PDF')
plt.legend()
plt.show()

# User 2:
plt.xlabel("domain")
plt.ylabel("pdf")
plt.title("User Conflated PDF 2")
plt.plot(domain,label='dist. 5')

dists=[dist_1_pdf,dist_5_pdf]
user_graph=user_conflate_pdf_2(dists)
print('Final User Conflated PDF 2 : ',label='Conflated PDF')
plt.legend()
plt.show()

# My Code:
# from matplotlib import pyplot as plt
plt.xlabel("domain")
plt.ylabel("pdf")
plt.title("My Conflated PDF Code")
plt.plot(domain,dist_5_pdf]
my_graph=my_conflate_pdf(domain,my_graph)

my_graph /= np.array(my_graph).sum()

# my_graph = inverse_normalise(my_graph)

plt.plot(domain,my_graph,label='Conflated PDF')
plt.legend()
plt.show()

# Conflated PDF:
print('User Conflated PDF: ',user_graph)
print('My Conflated PDF: ',np.array(my_graph))

输出如下:

enter image description here

enter image description here

enter image description here

我的问题在这里,我知道我需要规范化 PDF 列表。但是,假设我没有对 PDF 进行标准化,我该如何修改我的合并代码以获得以下图?

enter image description here

要得到上面的图和我的混淆代码

# user_graph /= user_graph.sum()
# dist_1_pdf /= dist_1_pdf.sum()
# dist_2_pdf /= dist_2_pdf.sum()
# dist_3_pdf /= dist_3_pdf.sum()
# dist_4_pdf /= dist_4_pdf.sum()
# dist_5_pdf /= dist_5_pdf.sum()

我没有标准化的混淆代码图:

enter image description here

解决方法

那个代码没有意义。首先,如果您简单地绘制 prod_pdf 函数的图形,您将在零处得到一条平线。我认为 prod_pdf 需要包含: 对于 enumerate(dist) 中的 c,x: p_pdf[c]=p_pdf[c]*x 至于错误,我不认为这是可以使用 quad 函数的情况。您想对分布的值求和。也许你可以使用integrate.simpson()函数。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。