计算模拟历史
Submitted by kzeng on Sun, 2015-07-12 16:44以前闲着无聊的时候曾经做过一个《资治通鉴》的字频统计,单以频率计,中国历史不过是“王”与“人”,“义”与“忠”,“将军”与“刺史”,“长安”与“洛阳”。
既然有了频率,自然也就有了概率和条件概率。根据条件概率,当给出一个序列的字词后,预测下一个字词是什么,就变成了一个简单的最大似然估计问题。如果觉得这个序列太长,计算起来太麻烦,可以假设简化的马尔科夫结构,譬如假设下一个词的概率取决与之前的n个词而不是整个序列,这基本上就是计算语言学里的 n-gram
算法了。
所以我们可以用《资治通鉴》作为语料得出经验条件概率,然后来随机模拟出历史文本,产生原汁原味(至少是统计意义上的)史书 (技术细节见附录)。 虽然这只是文字游戏,但是仍然能从概率上看出《资治通鉴》记述的历史中,最容易重现怎样的事件。
譬如下面这则 (random seed = 2000):
撰 刘 崇 俊 以 惟 岳 又 从 入 关 , 宣 等 从 太 子 也 , 惧 履 危 亡 之 事 , 发 步 骑 二 十 骑 自 北 至 北 寺 狱 , 竟 不 使 宗 庙 社 稷 。 宗 元 为 柳 州 司 马 。 坚 大 怒 , 士 气 彫 沮 , 无 事 , 更 为 后 拒 , 倍 急 于 亡 命 聚 众 二 万 会 麻 秋 、 姚 、 宋 赤 眉 将 逢 安 为 新 都 , 剽 掠 。
我们可以这样翻译:
刘崇俊因为惟岳(人名,可能是李惟岳。刘崇俊是五代人,李惟岳是晚唐人,相差不算太远)一起入关(姑且认为是潼关,但是李惟岳在和河北,真实历史是不会入关的),而宣(人名)等人却追随太子而去,害怕这是危亡社稷的事情,于是发步骑二十骑(区区二十骑!估计是武林高手),从北面到北寺狱(这是东汉时候黄门署属下的监狱,鞫禁将相大臣的,好吧,晚唐也有宦官之祸,这里东汉的宦官乱入了,不过二十骑到北寺狱,难道是要劫狱?),最终也没有拜谒宗庙(不把皇帝放在眼中啊)。
柳宗元被任命为柳州司马(二王八司马嘛,承接上文,还是和阉祸有关)。
(某)坚大怒(不知道是孙坚?苻坚?杨坚?),士气不振,好在也没有什么大事,继续抗拒(王师?)。 因急于亡命,聚众两万人与麻秋汇合(麻秋登场,那么坚应该是苻坚了,但是麻秋很早就被苻坚的伯伯苻健杀死了)。
(与此同时)姚、宋(姚崇,宋璟?)率领赤眉军把逢安(这个地名是自动产生的,历史上似乎没有,权且当作是四川 蓬安 吧)作为新的都城,四处剽掠。
我们来梳理一下这段模拟历史的脉络:
这大概是一个王朝末年的乱象。 地方农民起义(赤眉),建立政权(所以有新都),负责讨伐的将领反而形成军阀割据,一些军阀随权臣(刘崇俊)入京,干预朝政(惟岳),一些军阀在地方反叛(坚),勾结外敌(麻秋是羯族人)。这一切的原因可能是因为朝廷宦官弄权已久(北寺狱),忠良被贬(柳宗元)。 军阀入京大概是打着清除宦官的名义(所以要发兵北寺狱),但是同时他们也不把社稷放在眼里。 京城在军阀到来前似乎已经被反贼攻克,所以皇帝和太子分道逃亡。如今皇帝似乎已经回到京城,而太子却还在外面招兵买马(宣等人追随),似乎有不臣之心。
简而言之: 中央朝政腐败,宦官专政,两宫不和。地方盗贼风起,军阀割据,外患不断。
难道这就是随机生成的中国历史最典型的场景? :-)
附录
文中使用的通鉴文本是从维普网上下载的,做了一些简单的清理,上传到了百度云(链接)。 为了避免古文分词的麻烦,在作 n-gram 的时候以字为单位,所以用 gsub 在每个字的后面加入空格。 n-gram
选择 n=2
.
library(ngram)
file<-"C:/Users/Zeng/Downloads/zztj.txt"
str=scan(file,"character",encoding="GB2312")
s = concat(str)
s = gsub("(.)", "\\1 ", s)
ng = ngram(s, 2)
o = babble(ng, 100,seed=2000)
Encoding(o)<-"UTF-8"
o