不知为不知--信息论和最大熵原则

版权声明:本文为博主原创,无版权,未经博主允许可以随意转载,无需注明出处,随意修改或保持可作为原创! https://blog.csdn.net/dog250/article/details/78944526

中学学的那些立体几何,解析几何很多人看来索然无味却基本上没有掉队的,就算是用背诵的方法,头悬梁锥刺股也要学,为什么?因为高考要考。

  大学通信课学的那些排队论,信息论这些,在很多人看来也是索然无味,却再也没有人去为之付出了,为什么?因为大多数公司的面试题中都不会把这些包含在考查范围内。

  2018年第一天,写一篇随笔吧,就想写一个关于那些索然无味的东西的。觉得这些理论性的东西还是挺有用的,就随便写写,正好昨天不是写了一篇关于CPU使用率100%的问题涉及到排队论了吗?本文介绍下信息论


描述世界

你相信吗?不断地问“是不是”,你就能了解整个世界。

  用二进制来描述世界是简单且优雅的。在创世之初神的世界,就有善恶二元之划分,世界本来就出自二元。这几乎是所有人的共识,同时也是几乎所有宗教的根基。

  这里有河吗?是的。河里有鱼吗?是的。河里的鱼是红色的吗?不。河里的鱼有黑色的吗?是的。河里的鱼有黄色的吗?是的。…

  根据上述描述,我们知道这里有一条河,河里有黑色以及黄色的鱼,但不确定是不是有红色的鱼。随着问题继续,整个世界都可以被完全描述出来,问题的多少取决于你如何组织问题,这简直就是一门学问,而且是一门真学问。同样的一个世界,问题组织的好,很少的问题就能描述,问题组织的不好,问题的数量就会很多。

  信息论就是研究这个的。特别是,信息论中有个最大熵原则,遵循这个原则是解决问题效率的关键,本文我将用实例来说明。


香农的信息论

我们先来看信息是什么,再来看如何度量信息。

  所谓的信息,就是以前不知道现在知道的事实,如果某件事以前就知道,当别人再告诉你时,你会忽略,这件事对你的认知没有任何影响,这就不叫信息,反之,如果某件事以前你不知道,有人告诉你了,你现在知道了,那么对你而言,这件事就是信息。

  让我们更进一步,看一件事带来的信息量的大小如何来度量。顾名思义,信息量就是度量信息大小的一种量,让我们看一个形象的例子。有人告诉你巴西赢了世界杯,那么这件事对大多数人而言,并不值得关注,它并没有带来多少惊喜,如果是中国赢得了世界杯,那么这件事可能会刷新很多人的世界观,这件事带来的信息量就特别大,我们常说的黑天鹅事件就是概率极低但确实发生了的事件。定性的说,小概率事件带来的信息量大,大概率事件带来的信息量小。下面我们看下以上这句话如何定量的描述。

  用概率来度量信息是合理的,这并不是空穴来风,半个多世纪之前,香农提出的信息论便是以概率论为基础。执果索因,我们先来看看香农为什么用事件发生概率的对数来度量信息量。

  客观的说,如果你不能把一件事用数学描述出来,那它就是不严谨的,问题是,你要选用哪中形式。我们已经知道,在物理学中,宇宙中很多定律遵循平方反比律,退一万步到一个特定的拥塞控制领域,在TCP拥塞算法中,CUBIC算法所依据的是一条三次曲线。问题是,这些数学式子是怎么想出来的呢。这就不得不提到拟合

  首先你要罗列出你所要描述的事情的性质,然后靠突然发现或者创造某种函数的曲线正好完美拟合这些性质,那么就是它了,剩余的事情就是求常数因子并待定系数了,我有一篇文章说了这个事情,参见:TCP拥塞控制算法-从BIC到CUBIC http://blog.csdn.net/dog250/article/details/53013410
我们看下用概率描述信息量的重要性质:

  1. 事件发生的概率越低,信息量越大;
  2. 事件发生的概率越高,信息量越低;
  3. 多个事件同时发生的概率是多个事件概率相乘,总信息量是多个事件信息量相加。

通过前两点,我们知道信息量,信息量和概率之间一定是减函数的关系,第三点要求确定了对数关系

y=log2x

这里的对数关系以及上述第三点其实非常好理解,即两件事情的信息量之和等于两件事情同时发生的信息量:

x1x2P(x1,x2)=P(x1)×P(x2)
x1x2log2P(x1)P(x2)=log2P(x1)+log2P(x2)

由此确定的信息量描述为:

I(x)=log2P(x)

也许看起来好像香农是拍脑袋拍出对数关系的,但不管怎样,这个式子能完美诠释他想要诠释的一切,这就是他天才的地方。这个式子简单,优美,是的,非常简单,就像E=mc2一样简单,优美。

  既然有了一件事发生的信息量的数学描述,给出事件确实发生后信息量的数学期望就简单了,它便可以被描述为:

H(X)=E(I(X))=niP(xi)log2P(xi)

这很好理解,事件发生的形式拥有不同的概率,每种可能性发生后的信息量乘以它发生的概率,将其加起来,就是事件发生后总信息量的数学期望

  以上就是关于信息的数学描述,首先我们要明白用对数可以定义一件特定事件发生后的信息量,其次我们要知道一个事件按照不同概率的特定形式发生后的信息量的数学期望。

  接下来我来针对这些数学式子做一个现代解释


信息论的二进制解释

现代计算机科学强调一切都是比特(bit),那么如果我们想描述一个信息,显而易见的形式当然是bit。所谓的信息量就是用多少bit可以描述一个事件。这件事不妨反过来理解,我来理一下:

1个bit可以描述2个事件
2个bit可以描述4个事件
3个bit可以描述8个事件;
...
n个bit可以描述m个事件;

现在我们来看下nm的关系:

m=2n
n=log2m

我把式子整理一下就清晰了:

n=log21m

此处,m中可能性提出负号整理之后变成了1m的概率,符合香农的公式形式和含义从这个二进制的意义上去理解信息论中信息量的式子,是不是更简单呢。

  不仅仅是帮助理解信息论,其实本节的内容连同香农的信息论可以指导如何用最短的bit来编码特定的信息,比如霍夫曼编码,出现概率越大的字符编码长度越短,详情请自行百度。

  接下来重头戏要来了。


最大熵原则-不知为不知

我先对“知之为知之,不知为不知,是知也(《论语·为政》)”以及是,就说是;不是,就说不是;若再多说,皆出于那恶者(《新约·马太福音》)给出一个数学上的证明,然后再说一下关于赌徒和运维人员的悲哀。

  在解释之前,先看看什么是

  这个词来自于热力学,后来引申到了信息论里,是为信息熵。所谓的熵指的就是混乱程度,最大熵指的当然就是最无序,最随机的情况了,我们已经知道,用一个事件各个概率发生的信息量与发生概率的加权之和可以表征该事件发生后其总信息量的数学期望,如果我们类比事件的信息量期望和熵这两个概念,会发现它们是一致的。

  信息熵越大,事件带来的信息量越多,这恰恰说明在事件发生前,系统越是不可预测。因此,所谓的信息熵,就是衡量事件发生后带来信息量多少的一个度量,它的数学表示其实就是上述的那个数学期望:

H(X)=E(I(X))=niP(xi)log2P(xi)

既然下文跟本节引出的最大熵相关,那么在以上定量的数学公式的基础上,难免要求一些极值来看个究竟了。下文分解。


二元最大熵

你对一件事一无所知的时候,你会怎么取猜测结局。

  最简单的例子,那就是猜硬币的正反面,你会去花时间思考到底是正面还是反面吗?其实最简单省力且最有效的策略就是一直猜正面或者一直猜反面。但是这是为什么?

  按照信息论的描述,假设出现正面的概率是p,我们知道抛硬币这件事包含信息量的数学期望是:

H=plog2p(1p)log2(1p)

这是一个典型的二元问题,二者选其一的问题。我们要知道,一次猜测追求的是信息量最大化,因为如果不这样,需要付出更大的代价来弥补你的误判,这个后面我要证明。暂且把这个当成结论,看看我们如何应对。

  既然我们承认了信息论的数学表述是对的,那么接下来我们就要信任基于这套数学表述推导出来的一切(不信任数学逻辑的请自便,比如哥德尔忠粉)。我先给出抛硬币这件事包含信息量的数学期望:

f(x)=xlog2x(1x)log2(1x)

如果能画出它的图像,我们便可以一目了然事情的真相,即我们如何猜能保证信息量期望最大化。幸亏我的电脑里有GeoGebra,我画出了它的图像:

这里写图片描述

一目了然,不是吗?从图上看,在概率取12的时候,信息量的数学期望是最大的,可以达到1,即最佳策略是按照50%的概率猜正反。

  然而这并不严谨,严谨的数学证明需要证明这条曲线在x取12的时候取最大值。这个证明是超级简单的。如下:


0<x<1时:
f(x)=xlog2x(1x)log2(1x)
f(x)=log2(1x)log2x
f(x)=1x(x1)×1ln2<0

我们看到,这个关于抛银币信息量期望的函数,其二阶导数恒为负,说明它是一个上凸函数,因此其一阶导数为0的时候则取函数本身的最大值,此时p的值就是12

  这里,我使用了最朴素的求一阶,二阶导数的方法来证明二元熵的曲线是一个上凸曲线,然而用一阶导数求出了其极值,其实更加正规且通用的方法是使用加权形式的Jensen不等式来证明,但是本文并没有涉及推广到多元变量的情况,所以就没有涉及关于Jensen不等式的内容,此外,更容易理解的方式就是用中值定理来理解。

  以上描述的就是二元最大熵原则,要想最终在所有情况下的信息量的期望最高,各种情况最好不偏不倚,均匀分布,这是从数学上可以证明的。


盲目假设的代价

现在来看看为什么要不知为不知

  仍以抛硬币为例,如果你知道有人对该硬币做了手脚并了解其细节,那么你肯定知道不会按照50%的概率猜正反,这是因为在整个事件(一次抛硬币事件)信息量一定的情况下你已经知道了部分信息(有人做手脚的细节),那么你接下来要获取的信息量就会减少

  然而事实上,如果你根本就不明就里,你还会假设出现正面的概率比出现反面的概率大吗?也许你相信神迹,但一般而言,我相信你会公平对待正反。如果你假设出现正面的概率比出现反面的概率大,事实上你是在基于假设赌博

  在没有任何事实支撑你的假设前提下,事情是下面这样子,你笃信小概率事件会大概率发生:

这里写图片描述

虽然并不能说人人都是赌徒,但至少人人都很懒惰,在总信息量一定的情况下,人们奢望一次操作的信息量达到最大化从而排除掉更大部分的情况让总的操作量变少,并且赌这种事一定会发生。于是人们按照自己的意志做出了一系列毫无根据的假设。

  然而这一切都是空中楼阁,如果人们赌的事情发生了,那么当然皆大欢喜,但是一旦没有发生,代价是巨大的,因为按照上图,一旦人们赌的事件没有发生,那么相当于相反的事件发生了,而这个事件是人们所不屑的,因为它才是合理的预期,当然这仅仅是占有少量信息量,于是乎,当人们赌输了的时候,被排除的仅仅是非常小的一部分信息,你赌的筹码越大,代价就越大:

这里写图片描述

赌输了这个事实发生后,你会发现,你之前押注的假设的大概率事件并没有发生,并且你还因此欠下了债,不但要承担赌博失败的失落,还要弥补赌赢和赌输之间的落差,你上次试图绕开的那些操作还是要补上的。

  也许这就是功总不能抵过的原因吧,因为代价不同。你试图避开的没有避开,仍要面对,又平添了失败的代价,这种负面的东西超过赌赢了会带来的收益。

  事实上,你做的毫无根据的假设越多,其发生的概率就越低,因为所有假设的事情同时发生的概率是所有独立事件发生概率的乘积!概率均小于1,越乘越小!

  如果你假设的事情如你所愿真的发生了,那只能说明你运气好,仅此而已。有一千万赌博的,总有至少1个是赢钱的,一千万炒股的,总有至少1个是稳赚的,但那是你吗?算一下那人就是你的概率是多少。大部分的赌徒都是会输的。当然了,信息这种东西只能进入一次,这次它是信息,下次同样的东西就不再是信息,那些赚钱的人肯定在背地里暗自摸索过(努力学习?暗箱操作?…),当他们站在赌场或者交易大厅里的时候,很多信息他们已经知道,所以即便是赚钱的人,也不是公平退场的。


针对运维的吐槽

本节的内容是很主观的吐槽,笔记整理而来,仅为记录可绕过,不喜勿喷
我无意贬损运维这个职业,我只是就事论事。

  在过去的8年职业生涯中,我作为程序员与运维打过无数次交道,当然也作为运维与程序员打过无数次交道,但更多次,我并不喜欢大多数运维们的态度,换句话说,也许是我的不幸,我并没有遇到几个好的运维。

  已经有十次,二十次,三十次…我已经记不清次数了。运维把问题抛给研发的时候,总会附带一句这个是你们程序的问题,和这个没关系,和那个没关系,好像问题抛给谁就是谁的问题一样,然而大多数问题排查到了最后,问题就出在他们所谓的那些没有关系的配置上。

  我要敬告那些信口开河的搞运维,请务必学习最大熵原理(如果你学不会贝叶斯的话),但同时不要觉得别人说你牛你就装。知之为知之,不知为不知,是知也。这就是最大熵的通俗解释。

  对于排查任何问题,如果你不能在逻辑上证明你是正确的并且有数据支撑,你就假设自己一无所知,不要对故障原因就行任何假设,这是最安全且高效的做法。否则你将对研发人员排查问题的思路产生误导。

  最烦听到的就是“这个跟XX没有关系”,你证明不了,且分析不出来个所以然,甩锅谁不会啊,往往XX指的就是这个人负责的那一块。

  责任才是第一,态度高于技术!运维本来事情就多,这个可以理解,但不能因此就把自己摆在甩锅者这么一个位置上。

  其实,对于上述被我吐槽的运维,他们事实上除了表现得自己很忙很辛苦并在抑扬顿挫后善于甩锅给研发之外,并没有什么技术实力的。这就是我前面所说的那些不好的运维

  在非要研发出面的情况下,如果运维仅仅描述了故障现象,那么他就是个好运维,如果运维注入了很多自己的判断,那80%以上的情况就是为了甩锅。我也终于明白了研发和运维,网管之间矛盾的根本原因。

  化解矛盾的方案非常简单,在有理有据的论证之前,三缄其口,用事实和数据说话,特别注意不要经常说我以为…

  我比较讨厌运维,这确实是我的偏见,但这就是事实,我不能因为这是我的偏见就说我讨厌运维这件事是错的。

  我讨厌运维的原因也许仅仅就是因为我接触到的运维大都是不好的运维,但这就是事实,因为我没有接触到过好的运维,所以在我眼里,运维大概率是不好的,但这就是事实。

  我承认,运维很忙,运维很辛苦,但这并不意味着运维就可以作为产品经理和研发之外的第三方凌驾于研发之上而肆意信口开河。东西反正不是我做的,出了问题那就肯定是谁做的找谁,在这个意义上,曾经有一段时间我也挺讨厌系统测试人员。

  然而,不管是运维还是测试,其职能都是更多的集中在发现问题并抑制风险的蔓延或者反馈,发现了问题,如果你解决不了,就不要再继续挖苦,恶意损伤研发人员,人非圣贤孰能无过。特别注意的是,此时的运维或者测试人员只需要详细报告问题就足够了,千万不要增加自己的主观判断,千万不要把所谓的笃爱和信仰增加到故障描述中,从而说什么这个跟XX没有关系,这是悲剧!

  其实,就在2017年倒数第二个工作日的晚上,我也犯了一个类似的错误。线上机器出现了批量问题,我在详细调查之前拍了一个结论,由于自然语言的局限性,这个结论当然是模棱两可的,每个人理解便不一致,最终造成了误解,牵扯进来的人晚上九点多还在就我带来的误解而忙碌,自我感到十分惭愧。次日,也就是2017年12月29日,我换了一种方式,把明确的信息一五一十摆出来并详述了事情的前因后果后,解决方案便迎刃而出了。以我自己的这个反例可以看出,信息一定要是明确的,而不能靠我以为,那真的是悲剧。


快速排序&冒泡排序

首先我们来看一棵完美的平衡二叉搜索树:

这里写图片描述

所谓的完美的平衡二叉搜索树本质上就是组织良好的一组问“是不是”的一般疑问句,每次询问的回答确定后都能排除掉当前的一半的结论,以此类推直到确定所有的问题回答完毕。

  每次回答能排除掉当前的一半结论意味着针对该次“是不是”的询问,无论你回答“是”还是回答“不是”,均有50%的概率,这是一次不偏不倚的询问。而这正符合二元最大熵原则

  虽然并不是所有情况,但就平均情况而言,二叉搜索是基于比较的所有搜索算法(并不包括哈希算法)中最好的搜索算法。这一点正是因为它遵循了二元最大熵原则,在总的信息量一定的情况下,每次操作获得的信息量越大,总的操作次数就越少,从而效率越高。

  既然如此,我们来看一下构建这棵树的最好的办法。在一个随机序列中构建这棵树的过程就是一个排序的过程!这相当于把查找操作倒了过来。

  显而易见,我们希望按照以下的方式进行构建:

  1. 在数序列中随机抓到一个“中位数”(并非真的中位数,而是我们希望它是中位数),比它小的放它左边作为数序列L,比它大的放它右边作为数序列H;
  2. 针对L和H重复按照步骤1操作。

这里写图片描述

我们可以看到,上面迭代的每一步,均仅仅涉及到将任意数和所选中位数“”的比较,这貌似是一次不偏不倚的比较。然而事实上却很难做到真的不偏不倚。

  如果我们真的选中了中位数,那么显然这运气太好了,但是如果我们恰恰选择了一个比较大的数,那么在接下来的比较中,数序列中的数比所选数更大的概率就比较低,这就出现了天平倾斜的情况:

这里写图片描述

这也就是说,上述的二叉树构建方法并不能保证不偏不倚。但是鉴于现代计算机完全基于门电路二进制实现,只能是非黑白二选一,因此你找不到比这个更好的实现方案。换句话说,如果有一种可以三选一,四选一的机制,在执行效率上就会好很多。不过即便会大概率(你一次随机找到中位数的概率只是1N)出现天平倾斜的情况,也只是影响到这一层二叉树节点的构建,接下来的层是不受影响的,你仍然可以继续期待自己找到下一层的真正的中位数!

  说了这么多,可以看到,上面描述的这种方法就是快速排序的方法!

  可谓快速排序是保持二元最大熵的一个正例,那么举一个反例就是冒泡排序了。以从小到大冒泡排序为例。

  从一趟冒泡中,我们可以看到该操作的过程就是一个破坏均衡性的过程,我们发现每执行一趟冒泡,整个序列就会更加有序,每一趟冒泡均在努力将更大的元素往上推,并且会影响到后续的冒泡过程,随着冒泡的进行,越往后没有意义的比较就会越多,因为越往后更大的元素将会占据后半部更多的空间,这样前面的元素与之比较时胜出的概率就会越来越低,这是和二元最大熵原则背道而驰的!因此如果按照比较和交换操作来度量算法的时间复杂度,那么显然冒泡排序是不如快速排序的。

  虽然二者在时间复杂度是一致的,但是按照信息论分析,在统计意义上,快速排序的最好情况更容易促成(因为它承认了自己的无知),而冒泡排序则更加容易堕化到最差的情况

  也许你还不明白为什么冒泡排序如此谨慎地比较最终却落个差评,我举一个例子好了。

  我手里有10个数字中的一个,09,我问到底是哪一个,你可以问我“是不是”这种一般疑问句并且我会给出回答,你如何能在最少次数的询问后得到答案?

  如果你问它是1,事实上你是在赌博,如果它是1,那么你很幸运,一次就猜对了,如果很不幸,我回答了不是,你相当于浪费了整个一次机会!保险的问法是,你先问它大于4,如果我回答是的,那么你应该接着问它大于7…这样在有限的次数内,你就能得到答案。用赌博的方案和二分的方案做比对,虽然在某次的较量中,赌博的方案可能会表现更好,但是综合平均来看,肯定是二分的方案更好,这是因为赌博的方案输的可能性更大,毕竟你的假设生效的概率太低了!你问一个数是不是1,概率只有110,而你问一个数是不是大于4,概率则有12,这就是原因!

  依然以09随机序列从小到大排序为例,冒泡排序之所以综合表现差,就是因为越往后就越容易问x大于8吗?“x大于7吗?“这种问题,这种问题大概率都是否定的答案,所以一次问题得到的信息量非常少,那势必增加问题的数量来弥补。反观快速排序便不存在这个问题。

区间概率

受限于计算机很难去直接操作区间,比如一下子定位一个数字所在的区间,所以很难真正实现满足最大熵原则的排序算法,你不能保证你取的比较元就是你期望的处在中位数四分距内的数。

  设想如果有一天计算机是万能的,比如说将来量子计算机大规模部署以后,我们的排序会是下面的这个样子:

这里写图片描述


知之与不知

如果你想保持最大熵,就不要对不知道的事情做任何假设,因为盲目的假设在概率上很难成立,盲目假设这种习惯事实上只是过度透支了本来允许你犯的那些无心错

  人类文明是伟大的,在东方伦理社会和西方二元论的希腊罗马社会的截然不同的表象之下,竟然蕴含着相似的道理,这也就难怪《论语》和《圣经》均成为经典了…


后记:关于考试

考试绝对是兴奋剂,我记得清清楚楚,当时背诵古文,那时还小,根本就不理解那些个字句,所以我一般懒得背,除非马上就考试了突击一下,或者老师逼得我再背不下来就要请家长了,不得已背诵一下。我不太了解班里其他同学是不是跟我一个想法,反正当时真喜欢这玩意儿的真不多。

  后来,上大学了,毕业了,再也不用考试了,至少是再也不用考古文了,轻松了很多,但随着阅历的增加和针对特定现象理解能力的强化,我反而渐渐喜欢上了古文,时不时就会看上几篇,慢慢的就背下来了,现在毕业已经15年了,在身边的同龄人面前吟诵几句,甚至很少有人能忆起曾经是不是学过这篇文章了…然而这些人在当年考试的时候可是一个个无需斗酒诗能百篇的啊,不禁在想,为什么知识已经沦落到了这般境地,为什么知识要被考试所吞噬

  有人问我怎么样系统学习网络协议和算法,我能怎样回答呢?如果我列学习提纲,摆道理,阐述方法论,可能去买一本书要比我说的更权威,所以很长一段时间我都不知道该怎么回答这个问得很好的问题。

  但在我知道了考试意味着什么的时候,我决心让考试发挥正面的作用,而不再作为知识的吞噬者,换句话说,我想让考试把吞噬掉人们的知识吐出来!所以我也就有了答案。

  去参加与网络技术相关的大型公司的面试即可

  我告诉一个朋友,如果你心仪的Cisco通知你下周参加一个核心网相关的一个职位面试,在这一周内你将可能快速掌握系统的网络协议方面的知识,虽然可能你并没有经验去做实际的事情,也不能举一反三,但至少你学会了它,即便是最终你没有面试通过,或者你可能压根就不是真的要去应聘,但这一周确实对于你而言是极度压缩的一周,事半功倍的一周。

  好的,就是这样,考试和学习的因果现在颠倒了。注意,不再是你为了考试而不得不学习,现在是你想学习而没有好的办法,那么考试给你带来了紧张感和急迫感,抛开考试本身的结果不说,你要学习的目标是达到了!

  也许你会反驳,既然我不是真的为了考试通过,我干嘛要付出百分百的精力去努力去面对呢。这里有一个例子,其实就是自尊心或者简单点说就是爱美之心在作怪。一个女生即便和一个自己不喜欢的男生约会(可能就是为了蹭一顿吃的),也会把自己按照女神的标准精心打扮的,就是这样的简单道理。


本文本来想写的短一点,可是在听完罗胖的跨年演讲之后,又罗里吧嗦一顿闲扯,好想自己有一天也办一个跨年演讲…

  关于本文正文中的主题,有点要声明的。

  本文只是一篇随笔,我也并不是通信专业毕业的,事实上我并没有特定的专业,自然而然我并不是信息论方面的专家,也不是排队论方面的专家,我只是懂而已,并且我喜欢思考它们在真实世界的缩影,仅此而已。写作本文的目的和之前一样,希望能帮到需要得到这方面信息却又在网上找不到资源的人,所以说我写的文章一般都比较冷门,而且很多都是别人不屑于写的,也可能是别人真的就是不知道,至少关于为什么VMware虚拟机的NAT模式不能用traceroute这个问题绝大多数的人是不知道的,而我感兴趣的,正是把这类问题的原因呈现出来。

  好了,新的一年来到,希望自己以及身边的亲朋好友同事们都比去年好。
  温州皮鞋,走向世界!

阅读更多

没有更多推荐了,返回首页