机器学习(一)基本概念与信息熵

来源:互联网 发布:api打印编程 编辑:程序博客网 时间:2024/06/05 22:57

慢慢来入手机器学习吧。基本概念网上或者书中都有一大堆,理解个大概就行,至少懂得一些专业术语,以便于之后能够在神经网络的学习中至少能看懂。

信息熵。。。这是什么东西呢?相当于化学中的熵,我记得高中化学说过,熵是描述分子(是的吧?)有序程度的量。熵越大,越无序。这里的信息熵类似,熵越大,则表示信息越无序,这里,我盗用一下别人举的例子:一个事件或一个系统,准确的说是一个随机变量,它有着一定的不确定性。例如,“除东道主俄罗斯外,哪31个国家能进军2018年俄罗斯世界杯决赛圈”,这个随机变量的不确定性很高,要消除这个不确定性,就需要引入很多的信息,这些很多信息的度量就用“信息熵”表达。需要引入消除不确定性的信息量越多,则信息熵越高,反之则越低。例如“中国男足进军2018年俄罗斯世界杯决赛圈”,这个因为确定性很高,几乎不需要引入信息,因此信息熵很低。那信息熵如何计算呢?举个吴军在《数学之美》中一样的例子,假设世界杯决赛圈32强已经产生,那么随机变量“2018年俄罗斯世界杯足球赛32强中,谁是世界杯冠军?”的信息量是多少呢? 

根据香农(Shannon)给出的信息熵公式,对于任意一个随机变量X,它的信息熵定义如下,单位为比特(bit):

H(X)=−∑xεXP(x)logP(x))
那么上述随机变量(谁获得冠军)的信息量是: 
H=-(p1·logp1+p2·logp2+…p32·logp32)

其中,p1,p2,…,p32分别是这32强球队夺冠的概率。 
吴军的书中给出了几个结论:一是32强球队夺冠概率相同时,H=5;二是夺冠概率不同时,H<5;三是H不可能大于5。
对于第一个结论:结果是很显然的,夺冠概率相同,即每个球队夺冠概率都是1/32,所以H=-((1/32)·log(1/32)+(1/32)·log(1/32)+…+(1/32)·log(1/32))=-log(1/32)=log(32)=5(bit)

对于第二个结论和第三个结论:使用拉格朗日乘子法进行证明,详见《求约束条件下极值的拉格朗日乘子法》。这实际上是说系统中各种随机性的概率越均等,信息熵越大,反之越小。

从香农给出的数学公式上可以看出,信息熵其实是一个随机变量信息量的数学期望。

信息熵描述的是随机变量的不确定性。对于同一个随机变量,不同观测者从不同粒度上观察,得到的信息熵是不一样的。
还是举上面世界杯谁夺得冠军的例子,32强谁夺得冠军的信息熵是5比特;如果粒度再粗些,有人关注是哪个州夺得冠军,那么其可能性是5种(欧洲,南美,非洲,中北美州,亚洲),信息熵是2.32比特;如果我们只关注亚洲是否夺冠,那么可能性是2种,信息熵是1比特。 

再举个更随机的例子,中国股市的涨跌(假设非涨即跌,不算平盘),明天是涨还是跌,只有2种可能,信息量(信息熵)是1比特;假设股市只有蓝筹板,中小板,创业板3个板块,这三个板块的涨跌的可能性合计是8种,信息熵是3比特;如果关注的是每个股票的涨跌,2000个股票的可能性合计是22000种,信息熵是2000比特。


因此,对于不同的观测者来说,信息量(信息熵)是不同的,观测粒度越细则信息量(信息熵)越大,观测粒度越粗则信息量(信息熵)越小。

用熵来评价整个随机变量x平均的信息量,而平均最好的量度就是随机变量的期望,即熵的定义如下:
H[x]=-\sum_xp(x)log_2p(x)

这里的p(x)表示x发生的概率


计算字符的信息熵,参考代码如下:

package sk.ann;    import java.util.Scanner;    public class InfoEntropy {            public static double Entropy(String str) {          double H = .0;          int sum = 0;          int[] letter = new int[26];//26个字符          str = str.toUpperCase(); // 将小写字母转换成大写          for (int i = 0; i < str.length(); i++) { // 统计字母个数              char c = str.charAt(i);              if (c >= 'A' && c <= 'Z') {                  letter[c - 'A']++;                  sum++;              }          }          //计算信息熵,将字母出现的频率作为离散概率值          for (int i = 0; i < 26; i++) {              double p = 1.0 * letter[i] / sum;//单个字母的频率              if (p > 0)                  H += -(p * Math.log(p) / Math.log(2));// H = -∑Pi*log2(Pi)           }          return H;      }                    public static void main(String[] args) {              System.out.println("请输入字符串:");              Scanner scan = new Scanner(System.in);              String str = scan.next();              double H = Entropy(str);              System.out.printf("%4.2f\n", H);          }  }  

执行结果:

请输入字符串:  are you ok!yes i am ok!  1.58