zoukankan      html  css  js  c++  java
  • https://blog.csdn.net/blmoistawinde/article/details/84329103

    背景
        很多场景需要考虑数据分布的相似度/距离:比如确定一个正态分布是否能够很好的描述一个群体的身高(正态分布生成的样本分布应当与实际的抽样分布接近),或者一个分类算法是否能够很好地区分样本的特征(在两个分类下的数据分布的差异应当比较大)。

        (例子:上图来自 OpenAI的 Radford A , Jozefowicz R , Sutskever I . Learning to Generate Reviews and Discovering Sentiment[J]. 2017. 他们发现他们训练的深度神经网络中有一个单独的神经元就对正负情感的区分度相当良好。)

        上图可以直接看出明显的分布区别,但是能够衡量这种分布的距离更便于多种方法间的比较。KL/JS散度就是常用的衡量数据概率分布的数值指标,可以看成是数据分布的一种“距离”,关于它们的理论基础可以在网上找到很多参考,这里只简要给出公式和性质,还有代码实现:

    KL散度
        有时也称为相对熵,KL距离。对于两个概率分布P、Q,二者越相似,KL散度越小。

    KL散度满足非负性
    KL散度是不对称的,交换P、Q的位置将得到不同结果。

    python3代码:

    import numpy as np
    import scipy.stats
    p=np.asarray([0.65,0.25,0.07,0.03])
    q=np.array([0.6,0.25,0.1,0.05])
    def KL_divergence(p,q):
    return scipy.stats.entropy(p, q)
    print(KL_divergence(p,q)) # 0.011735745199107783
    print(KL_divergence(q,p)) # 0.013183150978050884
    1
    2
    3
    4
    5
    6
    7
    8
    JS散度
    JS散度基于KL散度,同样是二者越相似,JS散度越小。

    JS散度的取值范围在0-1之间,完全相同时为0
    JS散度是对称的

    python3代码:

    import numpy as np
    import scipy.stats
    p=np.asarray([0.65,0.25,0.07,0.03])
    q=np.array([0.6,0.25,0.1,0.05])
    q2=np.array([0.1,0.2,0.3,0.4])
    def JS_divergence(p,q):
    M=(p+q)/2
    return 0.5*scipy.stats.entropy(p, M)+0.5*scipy.stats.entropy(q, M)
    print(JS_divergence(p,q)) # 0.003093977084273652
    print(JS_divergence(p,q2)) # 0.24719159952098618
    print(JS_divergence(p,p)) # 0.0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    实例:身高分布预测比较
        在实际运用中,我们往往并不是一开始就能得到概率分布的,我们手上的更多是像每个人的身高这样的具体数据,那么怎么在python把它们转化为概率分布然后衡量距离呢?
        我们需要把数据等间隔地切分成一些区间(也叫作桶bin),然后就可以把样本落在每个区间的概率作为分布。pandas提供了cut这个方便的函数可以完成这一点。
        下面我将演示一个身高分布预测比较的例子,用scipy的正态分布函数随机生成了真实的身高分布和两个预测,让我们用散度来评判哪个是更好的预测:
    上代码:

    from scipy.stats import norm
    import pandas as pd
    #1000个均值170,标准差10的正态分布身高样本
    h_real = norm.rvs(loc=170, scale=10, size=1000)
    h_predict1 = norm.rvs(loc=168, scale=9, size=1000)
    h_predict2 = norm.rvs(loc=160, scale=20, size=1000)
    def JS_div(arr1,arr2,num_bins):
    max0 = max(np.max(arr1),np.max(arr2))
    min0 = min(np.min(arr1),np.min(arr2))
    bins = np.linspace(min0-1e-4, max0-1e-4, num=num_bins)
    PDF1 = pd.cut(arr1,bins).value_counts() / len(arr1)
    PDF2 = pd.cut(arr2,bins).value_counts() / len(arr2)
    return JS_divergence(PDF1.values,PDF2.values)

    print(JS_div(h_real,h_predict1,num_bins=20)) # 0.0098
    print(JS_div(h_real,h_predict2,num_bins=20)) # 0.135
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    我为预测1设置的参数和真实值更加接近。而预测1的散度的确更低,说明它是更好的预测。
    ---------------------
    作者:blmoistawinde
    来源:CSDN
    原文:https://blog.csdn.net/blmoistawinde/article/details/84329103
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    河北省重大技术需求征集系统(10)
    河北省重大技术需求征集系统(9)
    大三上学期周总结
    河北省重大技术需求征集系统(8)
    《代码大全》阅读笔记(三)
    河北省重大技术需求征集系统(7)
    河北省重大技术需求征集系统(6)
    河北省重大技术需求征集系统(5)
    【自动化】Aritest+python实现客户端UI自动化
    【自动化】Monkey自动化测试实现总结
  • 原文地址:https://www.cnblogs.com/jfdwd/p/11037821.html
Copyright © 2011-2022 走看看