代码之家  ›  专栏  ›  技术社区  ›  Sun Bear

如何使用scipy.stats.norm.CDF和matplotlib获得sigmodal CDF曲线?

  •  0
  • Sun Bear  · 技术社区  · 6 年前

    我试图绘制正态分布的S形累积分布函数(cdf)曲线。然而,我最终得到了一个统一的分布。我做错了什么?

    测试脚本

    import numpy as np
    from numpy.random import default_rng
    from scipy.stats import norm
    import matplotlib.pyplot as plt
    
    siz = 1000
    rg = default_rng( 12345 )
    a = rg.random(size=siz)
    rg = default_rng( 12345 )
    b = norm.rvs(size=siz, random_state=rg)
    c = norm.cdf(b)
    
    print( 'a = ', a)
    print( 'b = ', b)
    print( 'c = ', c)
    
    fig, ax = plt.subplots(3, 1)
    acount, abins, aignored = ax[0].hist( a, bins=20, histtype='bar', label='a', color='C0' )
    bcount, bbins, bignored = ax[1].hist( b, bins=20, histtype='bar', label='b', color='C1' )
    ccount, cbins, cignored = ax[2].hist( c, bins=20, histtype='bar', label='c', color='C2' )
    print( 'acount, abins, aignored = ', acount, abins, aignored)
    print( 'bcount, bbins, bignored = ', bcount, bbins, bignored)
    print( 'ccount, cbins, cignored = ', ccount, cbins, cignored)
    ax[0].legend()
    ax[1].legend()
    ax[2].legend()
    plt.show()
    

    enter image description here

    2 回复  |  直到 6 年前
        1
  •  1
  •   Zephyr    6 年前

    现在我不知道你的具体用途。但我认为问题在于,你正在为一些正态分布的随机数创建cdf的值。 下面您可以看到一个代码示例,该示例绘制了从-3到+3的标准法线的CDF

    import numpy as np
    from scipy.stats import norm
    import matplotlib.pyplot as plt
    
    x = np.arange(-3, 3, 0.1)
    c = norm.cdf(x)
    
    plt.plot(x, c)
    plt.show()
    

    标准正态分布函数
    1

        2
  •  1
  •   Sun Bear    6 年前

    为了绘制正态分布随机变量CDF的s形结果,我不应该使用matplotlib hist() 作用相反,我本可以使用 bar() 函数来绘制我的结果。

    @Laaggan 和 @dumbPy 答案指出,使用正则化和有序的x值是推导S形cdf曲线的方法。虽然通常这样做,但在使用随机变量时不适用。我已经将他们提到的方法的解决方案与我所做的进行了比较,以表明这两种方法给出了相同的结果。然而,我的结果(见下图)确实表明,通常获得cdf值的方法比使用随机变量产生更多的正态分布极值。排除这两个极端情况,出现的情况看起来是均匀分布的。

    我已经修改了我的脚本并提供了评论,以演示我是如何比较这两种方法的。我希望我的回答能帮助其他正在学习使用 rvs() , pdf() 和 cdf() scipy.stats.norm 班

    import numpy as np
    from numpy.random import default_rng
    from scipy.stats import norm
    import matplotlib.pyplot as plt
    
    mu = 0
    sigma = 1
    samples = 1000
    
    rg = default_rng( 12345 )
    a = rg.random(size=samples) #Get a  uniform distribution of numbers in the range of 0 to 1.
    print( 'a = ', a)
    
    # Get pdf and cdf values using normal random variates. 
    rg = default_rng( 12345 ) #Recreate Bit Generator to ensure a same starting point  
    b_pdf = norm.rvs( loc=mu, scale=sigma, size=samples, random_state=rg ) #Get pdf of normal distribution(mu=0, sigma=1 gives -3.26 to +3.26).
    b_cdf = norm.cdf( b_pdf, loc=mu, scale=sigma ) #get cdf of normal distribution using pdf values (always gives between 0 to 1).
    print( 'b_pdf = ', b_pdf)
    print( 'b_cdf = ', b_cdf)
    
    #To check b is normally distributed. Using the ordered x (commonly practiced): 
    c_x = np.linspace( mu - 3.26*sigma, mu + 3.26*sigma, samples )
    c_pdf = norm.pdf( c_x, loc=mu, scale=sigma )
    c_cdf = norm.cdf( c_x, loc=mu, scale=sigma  )
    print( 'c_x = ', c_x )
    print( 'c_pdf = ', c_pdf )
    print( 'c_cdf = ', c_cdf )
    
    
    fig, ax = plt.subplots(3, 1)
    bins=np.linspace( 0, 1, num=10 )
    acount, abins, aignored = ax[0].hist( a, bins=50, histtype='bar', label='a', color='C0', alpha=0.2, density=True  )
    bcount, bbins, bignored = ax[0].hist( b_cdf, bins=50, histtype='bar', label='b_cdf', color='C1', alpha=0.2, density=True )
    ccount, cbins, cignored = ax[0].hist( c_cdf, bins=50, histtype='bar', label='c_cdf', color='C2', alpha=0.2, density=True )
    
    bcount, bbins, bignored = ax[1].hist( b_pdf, bins=20, histtype='bar', label='b_pdf', color='C1', alpha=0.4, density=True  )
    cpdf_line = ax[1].plot(c_x, c_pdf, label='c_pdf', color='C2')
    
    bpdf_bar = ax[2].bar( b_pdf, b_cdf, label='b_cdf', color='C1', alpha=0.4, width=0.01)
    ccdf_line = ax[2].plot(c_x, c_cdf, label='c_cdf', color='C2')
    print( 'acount, abins, aignored = ', acount, abins, aignored)
    print( 'bcount, bbins, bignored = ', bcount, bbins, bignored)
    print( 'ccount, cbins, cignored = ', ccount, cbins, cignored)
    
    ax[0].legend(loc='upper left')
    ax[1].legend(loc='upper left')
    ax[2].legend(loc='upper left')
    plt.show()
    

    Results

        3
  •  0
  •   dumbPy    6 年前

    您正在绘制错误的值。 当你这样做的时候 b = norm.rvs(size=siz, random_state=rg) ,得到的是从标准正态分布中独立抽取的10个随机样本,即。, z

    因此,它们的直方图就是你们所看到的钟形曲线。

    norm.cdf 返回 cfd

    编辑:另一个答案给出了这种方法的代码,所以我不会再麻烦添加了。