“句读”的自动生成

“句读”的自动生成

句读之不知,惑之不解,或师焉,或不焉,小学而大疑,吾未见其明也。
——韩愈 《师说》

古人读书,“句读”是帮助其断句、理解句子含义甚至消除歧义的重要技能。虽然现代人阅读的古文往往是经过人工添加了标点符号的,但仍有大量的文献是没有任何断句的,直接阅读这样的资料对于相关专业的学者恐怕也要耗费一番精力;而另一方面,完全依靠人工方法去标注这些文献的工作量是不可想象的。

今天在这里分享一些用深度学习的方法自动做“句读”的结果——结论是一个简单的模型都可以在很大程度上正确地为完全无标点的古文添加标点,甚至在风格相差较大的内容上也取得了不错的效果。


0. 数据选取

主要选取《续资治通鉴长编》作为数据集。该文献共520卷,按时间顺序记录了北宋时期的历史。训练集选取前514卷(99%),余下6卷为测试集;此外,还选取《历代名臣奏议》中的部分内容进一步验证结果。之所选取《历代名臣奏议》,是因为在网上找了好久也没找到这本书带标点的部分( @经略幽燕我童贯 嫖相帮忙确认下 :)),也算是写这篇文章的起因吧。

考虑的标点符号全部从《续资治通鉴长编》中提取,包括逗号(,)、句号(,)、冒号(:)、分号(;),问号(?)以及双引号(「和」)和双括号(()),再加上无标点共10种类别。


1. 基于卷积神经网络(CNN)的方法

虽然最开始还是想用循环神经网络做第一个模型,但考虑到“句读”不仅和断句处之前的内容相关(上文),也和之后的文字(下文)有紧密地联系。鉴于这种局部特性,决定先试验一下卷积神经网络(CNN)的效果。

由于我对CNN也是一知半解,第一个冒出的想法是使用一个1D的CNN;然后才意识到文字序列不像语音序列,每个字不能表示成一个具有数值意义的标量。简单查阅了一些论文,才发现似乎主流的做法还是通过one hot或word embedding的方法将1D的文字序列转换成2D的“图像”——直觉上感觉这样的做法还是比较奇怪的,因为毕竟在扩展的这一维度上并没有CNN期望的空间局部性质。无论如何,还是简单将网络结果设计如下:

CNN模型的网络结构

大体上,一个待句读的句子通过获取每个字的embedding表示成一张“伪”图像,经过两层卷积+池化层后,再经过一个全连接层,为每个字得到一个10位的logit值,表示其后接标点的log概率。这里之所以使用embedding而不直接使用one hot的表示,一是由于one hot维度太高导致训练效率极低,二是考虑embedding结构更紧密,我们希望使用更小的核函数就可以保证捕捉到足够的局部信息。损失函数使用交叉熵。

然而,理想很丰满,现实很骨感:训练结果甚至在训练集本身上都表现极差(几乎为每个字后面强行加上了冒号,不知道冒号有什么特别的地方)。虽然不确定是哪里出现问题,多半可能是网络结构的设计不合理。后来发现了一个基于CNN做加标点的工作([5]),但还没有仔细阅读。


2. 基于循环神经网络(RNN)的方法

不得已,退回到最初的想法,使用一个简单的LSTM单元构建的RNN,输入为word embedding,并将其输出再经过一个全连接层得到类似上面CNN中的10位logit值。网络结构很简单,这里就不赘述了。

下面给出了在测试集上的损失函数和准确度随迭代次数的变化(本文中所有模型均使用Tensorflow实现;训练过程使用Adam算法)。其中Accuracy on Punc是在所有标点位上的准确率(可能更确切一点应该叫召回率;考虑到绝大部分字后面不接标点,这一指标应是我们最关心的),Accuracy on non-Punc是在所有非标点位上的准确率,而Accuracy则是所有位置上的准确率。

RNN的训练过程

可以看到,Accuracy on Punc的准确率在30%左右——考虑到共有10种标点,随机猜测的准确率为10%(又由于一般逗号居多,只猜逗号可能更高一些),说明我们的结果已经要优于”瞎猜“了,但仍然不够理想。另外Accuracy和Accuracy on non-Punc分别超过80%和接近90%,但对于”句读“的任务来说并没有太大意义。


3. 基于双向循环神经网络(Bidirectional RNN)的方法

上面这种简单的RNN的效果并不理想的一个重要原因,也是我们一开始想要使用CNN的理由是:是否加标点同时和下文有关。同时结合上、下文信息的RNN,自然想到双向循环神经网络,于是设计网络结构如下:

Bidirectional RNN模型的网络结构

输入同样还是embedding,不过将其送入两个方向一前一后的LSTM单元中;两个LSTM单元的输出做element-wise product后,再分别结过一层全连接网络,得到各个字后面标点的logits。用测试集上的指标表示的训练过程如下:

Bidirectional RNN的训练过程

首先注意到的是,Accuracy on Punc的准确率已经提高到近60%,较前面简单的RNN模型提高了近一倍。另外,在模型收敛后似乎出现了数值精度的问题,导致了精度在图中近800个batch处发生了断崖式跌落,原因不详。


4. 具体结果示例

光给数据不如上几个具体的结果来得更直观。下面给出最终模型在算法训练过程中未见的6卷测试集中的三段话加注标点结果:

人工加注标点和模型加注标点的结果比较

可以看出,Bidirectional RNN生成的结果与人工标注的结果几乎毫无差别,对于阅读而言基本上达到了帮助读者断句释义的功能。

更进一步地,我们取《历代名臣奏议》中两段宋代大臣上奏的内容,得到如下结果(注意由于我们的字典完全取自《长编》,因而对只在《历代名臣奏议》中出现的字采取了直接过滤的处理方法,所以可能部分文字有缺失):

建中靖国元年给事中上官均论治天下在好学广问上奏曰:臣闻人主之治,天下一日万机,不可胜察也。而明君操术,盖有至要可以不劳而治。盖好学,则知天人之道,通古今之变,好问,则察臣之情,达天下之政,通古今而达事情物理,岂有不烛注措,岂有不善哉?说命曰:念终始典于学。扬雄曰:学之为王者事,其已久矣。此言人主之,不可不好学也。仲尼称:舜曰:舜好问而好察迩言孟轲称舜曰:大舜善与人同乐,取诸人以为善。仲虺之告。汤曰:好问则裕自用,则小此言人主之不可不广问也。然而人主之学异乎?人臣之学,何则?人臣之学,或以文词为工,或以博记为能,以文词为工,则有不适用之患,以博记为能,则有不烛理之蔽,非所谓善学也。人主之学,在乎简而知要达,而适用知要在乎明道明道,在乎味五经之言,适用在乎观前世治乱盛衰之迹,而近稽祖宗圣明相继,治天下之意,因已然之迹,而考其理乱,因理乱而鉴,其所以得失,可以知要而适用矣。此人主之好学所以为先务也。天下之政,有利有害,百官之有邪有正非广问而参稽之,则利害未易,见邪正未易,明,利害未尽见,则事,或过举邪正未尽明,则奸佞之徒,或乘间而害正,此人主之好问所以为政之要也。臣窃观陛下仁而有中正而不偏清净而寡,欲温恭而尽下,可谓有上圣之资矣。臣愿陛下退朝燕闲,观经阅史,以明理义之大,致达治乱之大体,因进对之臣心下问,以考政,事之得失。观臣之志,趣如此,则天下之义理,臣下之邪正判如白之辨矣。陶之告舜曰:在知人在安民禹曰:知人则哲能官人安民则惠黎民之烛义理而辨,邪正,则能官人能安民矣。尧、舜之治,天下不过如此矣。
……
光宗绍三年,御史台主簿彭龟年上疏曰:臣闻讲读之官,责任最重,故程頥谓天下重任,惟宰相与经筵,天下治乱,系宰相君成,就在经筵,以臣观之,君不修,虽治,难保要知经筵之重,尤在宰相之先,是以祖宗重此官具有成宪未得之则求之,惟恐其不广。既得之则亲之,惟恐其或揆之近时,颇非其旧。臣敢为陛下条列陈之。臣观祖宗精择经筵,不限资任,或以布衣而就职,或解政柄而复为,盖以劝讲之臣,当用明经之士,经须素业,人各有长。傥平时未尝留意于斯,则虽贤何以克堪其任?今不问所学,以序迁此,非其旧者一也。臣观祖宗引对臣僚莫如经筵,亲在太祖朝,非时召王昭素讲说经书,在太宗朝,命吕文仲为侍读,多以日晚,召见及真宗嗣位,首置侍读。侍讲学士,命邢昺杨徽之夏侯峤为之,常,令昺宿秘阁访问或至中夕,自此,遂为故事,夜直率置常员,不特与之究义理之亦欲籍之杜逸豫之隙。盖闻古今之治乱,则警惧易动,闻闾阎之艰苦,则忧念自生。退即宴闲必无过当,圣谟,深人未易知。窃见近日宣召,经筵,多用昼接,臣不知游息,深宫之际,何以为保养,夜气之方,此非其旧者二也。臣仰惟陛下留心问学,不愧古先,尝于郊禋之时,豫展讲读之日,厥修时敏何待人言,而臣之区区,犹及此者。臣尝见范祖禹所编帝学上下数千年,未有若祖宗好学之笃者,陛下欲法祖宗舍,此宜无大者也。臣愚欲望陛下柬拔名儒,置之讲席,但问经学之深,浅不校官资之崇卑,官大,则加之学士之名,官小则任以说书之职日与之讲论义理夜与之商古。今自此圣性日益,明圣日益盛大,既有义理之可乐,自然物欲之难移,保国宁家,莫先于是。惟陛下留神。

可以看到,对于风格有一定差别(《长编》中除了奏陈的内容,还有大量叙事、论述的文字)的内容,我们的模型也基本上按照语义添加了标点!这进一步说明我们的模型还是具有较好的泛化能力的。


5. 尾声

加标点的工作似乎并不常见,或许是因为对于当下生成的文字内容,绝大多数都是直接或间接由人工录入的;而一个可能生成未加标点文字的领域是语音识别,但考虑到通过语音中的停顿有助于识别效果,加标点在某种意义上可以看作语音识别的副产品,因而似乎也不是该领域中的研究热点。后知后觉地去google了一下,发现还是有几篇相关文章([1, 2, 3])和基于keras和theano的开源实现([4, 5])的,但都是近两年的内容,引用度也不甚高。但个人认为在我国历史文献处理工作中,相关工作还是有一定借鉴意义的。


参考文献

[1] A Neural Network Architecture for Multilingual Punctuation Generation

[2] Deep Learning for Punctuation Restoration in Medical Reports

[3] LSTM for Punctuation Restoration in Speech Transcripts

[4] ottokart/punctuator2

[5] vackosar/keras-punctuator

编辑于 2018-04-21