您的位置:首页 > 其它

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

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

信息熵。。。这是什么东西呢?相当于化学中的熵,我记得高中化学说过,熵是描述分子(是的吧?)有序程度的量。熵越大,越无序。这里的信息熵类似,熵越大,则表示信息越无序,这里,我盗用一下别人举的例子:一个事件或一个系统,准确的说是一个随机变量,它有着一定的不确定性。例如,“除东道主俄罗斯外,哪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平均的信息量,而平均最好的量度就是随机变量的期望,即熵的定义如下:



这里的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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: