熵的理解

熵在信息论中代表随机变量不确定度的度量。一个离散型随机变量X的熵H(X)定义为: $$ H(X)=- \sum_{x \in X} p(x) \cdot logp(x) $$ 明确定义的科学名词且与内容无关,而且不随信息的具体表达式的变化而变化。是独立于形式,反映了信息表达式中统计方面的性质。是统计学上的抽象概念。信息熵的一种解释是,它表示的是最短的平均编码长度。同样的,不确定性越大,熵就越大。信息熵的单位是比特(bit)。我们举两个简单的例子: 第一个例子: 32支球队,在无任何先验信息的前提下,用二分法猜冠军队伍,最多猜5次,即: $$ log\frac{1}{32}=5log\frac{1}{32}=5bit $$ 第二个例子:赌马比赛里,有4匹马A,B,C,D,获胜概率分别为 $$ \frac{1}{2},\frac{1}{4},\frac{1}{8},\frac{1}{8} $$

  • 如果 X=A ,那么需要问1次(问题1:是不是A?),概率为 $$ \frac{1}{2} $$
  • 如果 X=B ,那么需要问2次(问题1:是不是A?问题2:是不是B?),概率为 $$ \frac{1}{4}$$
  • 如果 X=C ,那么需要问3次(问题1,问题2,问题3),概率为
    $$ \frac{1}{8}$$
  • 如果 X=D ,那么同样需要问3次(问题1,问题2,问题3),概率为 $$ \frac{1}{8}$$

通过熵的定义得到

$$ H(x)=-\sum_{x \in {A,B,C,D}}p(x)\cdot log p(x)=\frac{1}{2} \cdot log2+\frac{1}{4} \cdot log4+\frac{1}{8} \cdot log8+\frac{1}{8} \cdot log8=1.75 $$

在二进制计算机中,一个比特为0或1(代表二元问题)。在计算机中,我们给哪一匹马夺冠这个事件进行编码,所需要的平均码长为1.75个比特。其定义为:

$$ L©=\sum_{x \in X}p(x)l(x) $$

为了尽可能减少码长,我们要给发生概率p(x)较大的事件,分配较短的码长l(x)。所以那么 $${A,B,C,D}$$ 四个实践,可以分别由 $${0,10,110,111}$$ 表示. (1)信息熵只反映内容的随机性,与内容本身无关。不管是什么样内容的文件,只要服从同样的概率分布,就会计算得到同样的信息熵。 (2)信息熵越大,表示占用的二进制位越长,因此就可以表达更多的符号。所以,人们有时也说,信息熵越大,表示信息量越大。不过,由于第一点的原因,这种说法很容易产生误导。较大的信息熵,只表示可能出现的符号较多,并不意味着你可以从中得到更多的信息。 (3)信息熵与热力学的熵,基本无关。

相对熵(KL离散度)

相对熵又叫做KL离散度,其定义为: $$ KL(f(x)||g(x))=-\sum_{x \in X} f(x) \cdot log\frac{f(x)}{g(x)} $$ KL 散度是两个概率分布f(x)和g(x)差别的非对称性的度量。KL散度是用来度量使用基于f(x)的编码来编码来自g(x)的样本平均所需的额外的位元数。 很容易证明,有三个结论: (1) 两函数完全相同时,KL=0 (2) KL越大,差异越大 (3) 对概率分布或者概率密度函数(>0), KL可用来衡量两个随机变量分布的差异性。

交叉熵

对一随机事件,其真实概率分布为p(i),从数据中得到的概率分布为q(i),则我们定义,交叉熵为: $$ H(p,q)=\displaystyle\sum _{x}p(x)log\frac{1}{q(x)}=-\sum _{x}p(x)logq(x) $$

核心理解: * 用p来衡量识别一个样本的信息量即最小编码长度(信息熵)。

$$ H(p)=\sum p \cdot log\frac{1}{p} $$

  • q来估计真实分布为p的样本的信息量.

$$ H(q,p)=\sum p \cdot \frac{1}{q} $$

  • 则估算多出来的冗余信息量.

$$ D(p||q)=H(p,q)-H(p)=\sum p \cdot log\frac{p}{q}(KL离散度) $$

在机器学习中,p通常设定为真实标记的分布,q设定为训练后模型预测标记的分布:

$$ H(p,q)=H(p)+D_{KL}(pq) $$

即:交叉熵=信息熵+KL散度(相对熵) 由于信息熵H(p)H(p)是固定不变的,因此我们在机器学习中就用交叉熵作为损失函数。常见的做法是先用Softmax函数将神经网络的结果转换为概率分布,然后用交叉熵刻画估算的概率分布与真实的概率分布的”距离”。

Python进阶系列三

Python 进阶

我们在Python进阶教程(二),介绍了一些Python进阶用法。今天给大家介绍的是和c/c++混合编程的用法。我们都知道特别是Python2.x版本GIL的影响造成多线程计算方面是鸡肋,并且常常在高性能计算方面依赖很多包。如果我们想切合我们自己的业务处理,比如高性能部分我们用C/C++生成动态链接库,Python调用该动态链接库。我们今天主要介绍Python在和c/c++混合编程。

Python和C/C++混合编程

在和C/C++代码进行混合编程时,我们通常需要采用以下几个技术点: * Ctypes:C++编译成动态链接库(DLL,即运行时动态调用),然后通过ctypes来解析和加载动态链接库,python调用该动态链接库。从ctypes的文档中可以推断,在各个平台上均使用了对应平台动态加载动态链接库的方法,并通过一套类型映射的方式将Python与二进制动态链接库相连接。ctypes 实现了一系列的类型转换方法,Python的数据类型会包装或直接推算为C类型,作为函数的调用参数;函数的返回值也经过一系列的包装成为Python类型。 优点: 1.Python内建,不需要单独安装 2.可以直接调用二进制的动态链接库 3.在Python一侧,不需要了解Python内部的工作方式 4.在C/C++一侧,也不需要了解Python内部的工作方式 5.对基本类型的相互映射有良好的支持 缺点: 1.平台兼容性差 2.不能够直接调用动态链接库中未经导出的函数或变量 3.对C++的支持差 * SWIG:通过提供的接口文件来调用。 * Python/C在C中直接扩展Python的代码。

Python进阶系列二

概述

在上一篇博客中,我们介绍了Python进阶系列一,还有一些新的技巧没有翻译完,我们下面来继续我们的翻译。

Intermediate Python 中译(二)

Decorators

Decorators装饰器是Pytho非常重要的特性,相当于Java注解功能。装饰器是修饰函数的一种语法特性,可以使其功能发生一些改变。在Python函数也是第一等公民,可以直接赋值对象和使用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def hi(name="brian"):
    return "hi,"+name
print(hi())
#输出
hi,brian
greet = hi
print(greet())
#输出
hi,brian
#此时已经删除hi对象,无法运行hi()方法,但是可以通过greet()方法运行
del hi
print(greet())
#输出
hibrian

我们也可以在函数内定义函数,比如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
def hi(name="brian"):
    print("now you are inside in the hi() method")
    def greet():
        return "now you are in inside the greet() method"
    def welcome():
        return "now you are in inside the welcome() method"
    print(greet())
    print(welcome())
    print("now you are back in the hi() method")
hi()
#输出为
now you are inside in the hi() method
now you are in inside the greet() method
now you are in inside the welcome() method
now you are back in the hi() method

我们可以看到在函数(主函数)内定义函数(子函数),只要是不调用子函数,子函数只是声明并不执行,当执行完子函数时又返回了主函数。由于Python只是函数第一等公民的功能特性,那么在Python代码中是可以将Python的函数可以作为变量使用并将其作为返回值亦可。从主函数中返回子函数(即从函数中返回函数)