CAIL2018比赛总结

CAIL2018法研杯司法人工智能竞赛总结

CAIL2018线上测试阶段已于7月14日截至,初赛阶段一个有262个队伍参加,复赛阶段一共有207个队伍参加,然后接下来就是一个月的线下封闭测试阶段。由于我在团队中负责的是任务三刑期预测这个项目,最终线上测试阶段的成绩是75.0,官方的baseline成绩是50分的样子。排名是19th/207。所以这两天总结下比赛的一些总结与体会。

CAIL2018竞赛简介

法律智能旨在赋予机器阅读理解法律文本与定量分析案例的能力,完成罪名预测、法律条款推荐、刑期预测等具有实际应用需求的任务,有望辅助法官、律师等人士更加高效地进行法律判决。近年来,以深度学习和自然语言处理为代表的人工智能技术取得巨大突破,也开始在法律智能领域崭露头角,受到学术界和产业界的广泛关注。

为了促进法律智能相关技术的发展,在最高人民法院信息中心、共青团中央青年发展部的指导下,中国司法大数据研究院、中国中文信息学会、中电科系统团委联合清华大学、北京大学、中国科学院软件研究所共同举办“2018中国‘法研杯’法律智能挑战赛(CAIL2018)”。

挑战赛将提供海量的刑事法律文书数据作为数据集,旨在为研究者提供学术交流平台,推动语言理解和人工智能领域技术在法律领域的应用,促进法律人工智能事业的发展。

比赛项目与问题分析

这次比赛分成三个子项比赛,任务一是罪名预测,根据一段处理过后的法律文本描述(只保留fact犯罪事实部分)来预测被告人所犯了哪些罪名,初次看上去应该是个文本分类的问题,但是不同于一般的文本分类label往往对应的是单标签,我们根据一段文书预测的罪名往往可能涉及了多个罪名,所以它是一个多标签文本分类的问题。评分公式采用的是微平均F1值(Micro-F1-measure)和宏平均F1值(Macro-F1-measure)作为评价指标。

任务二是案由(法条)预测,即根据fact给出推荐的法条(即比如对被告人判罚的时候需要根据刑法或者民法的第xx条,判罚xx罪),在我看来,这个功能其实挺实用的,因为法条这么多,人工去寻找案件涉及的法条还是比较麻烦和耗费时间的,这个功能可以帮助法官快速查找法条。任务二从问题的本质来看和问题一是一样的二者都是多标签的文本分类问题。

任务三是刑期预测,根据fact来给出对被告人的刑期判决,个人的角度觉得任务三相比任务一和任务二要更难,因为罪名和法条往往对于同一条fact来说是确定的,没有变化的因素,然而对于刑期来说具有了更多的不确定性,同一个盗窃罪对于固定的犯罪金额而言不同的地区的判罚标准是不一样的,比如上海2000元的盗窃罪和合肥2000元的盗窃罪,当然如果当训练数据足够大的时候算法的确是能够学到这条规则的,但是除了地区因素之外,更多的是人为的因素,不仅仅不同的法官针对同样的一个案件判罚可能不同,而且还有个关键的因素就是被告人的律师,律师水平的好坏这很大的程度上面也能影响到刑期的判决。从刑期预测这个问题的名字来看它应该是个回归问题,然而它也可以当作分类问题来做。官方的baseline代码是把刑期从0到300个月分成8个区间段来预测。但是官方的baseline效果并不好线上只有50分的样子。评分标准是

\[\begin{equation} eva=ln(p+1)-ln(t+1)) \tag{1.1} \end{equation}\]

如果eva小于0.2,score就加1,如果eva小于0.4,score就加0.8....,燃气score求平均值就是最后的分数。所以根据评估公式来说更倾向于用分类去解决这个问题,笔者刚开开始的时候采用回归的方法去做,mse最终收敛到了4.0个月,但是分数只有70分的样子,再往上面提分就很难了。后来再分析了下评分公式,发线评分公式是倾向于对小的刑期十分敏感。即使整体的mse很小,但是如果在小的刑期上面差距确很大。ln300-ln260=0.2 虽然预测结果相差40,但是eva却在0.2之内,评估结果加了1.0的分数,对于评分公式来说,相当于准确的预测到了,ln2-ln1=0.7虽然预测结果只相差一个月的值,但是评估结果只加了0.2分。

数据分析与预处理

数据分析

1
2
3
4
5
%matplotlib inline
import pandas as pd
import seaborn as sns
data=pd.read_csv("data_train.csv")
sns.distplot(data['imprisonment'])
svg

svg

从图上可以看出刑期呈现一个长尾的分布,刑期主要集中在0~50这个区间之内。曲线和lnx的函数曲线很像。

之前看kaggle上面一个类似的文本分类的比赛会用使用一些文本的统计特征,但是不知道统计特征在刑期预测这上面是否有用。这里我们尝试一些统计特征进行相关性的分析。

1
2
3
4
5
6
7
8
def count_fact_length(x):
return len(x)
def count_word_num(x):
return len(x)


data['fact_length']=data['fact'].map(lambda x:count_fact_length(x))
data['word_num']=data['fact_cut_wd'].map(lambda x:count_word_num(x))
1
2
corr_data=data[['imprisonment','fact_length','word_num']].corr()
sns.heatmap(corr_data)
svg

svg

从第一行可以看出来fact_length文本的长度和word_num词汇的数量和刑期的相关性为0,所以在后面我直接放弃了统计特征

文本里面的数字处理方式

文本特征的处理一般有两种方式,一个是TF-IDF(词频-逆文件频率)算法,它的思想就是一个单词在这篇文章中出现的次数越多,在这整个文档中出现的次数越少,就越能够代表这篇文章。还有一种方式就是word embedding的方法,通过把单词训练成词向量,取一篇文章的前n个单词,作为输入特征。
无论是tf-idf还是word embedding的方法都无法数字的大小关系,所以针对这些数字特征我们需要把它们进行离散化表示。

模型的搭建与选择

TextCnn

这是CNN首次被应用于文本分类任务的开山之作,可以说,之后很多论文都是基于此进行拓展的。它是由Yoon Kim于2014年发表的。

textcnn

textcnn

上图很好地诠释了模型的框架。假设我们有一句句子需要对其进行分类。句子中每个词是由n维词向量组成的,也就是说输入矩阵大小为m*n,其中m为句子长度。CNN需要对输入样本进行卷积操作,对于文本数据,filter不再横向滑动,仅仅是向下移动,有点类似于N-gram在提取词与词间的局部相关性。图中共有三种步长策略,分别是2,3,4,每个步长都有两个filter(实际训练时filter数量会很多)。在不同词窗上应用不同filter,最终得到6个卷积后的向量。然后对每一个向量进行最大化池化操作并拼接各个池化值,最终得到这个句子的特征表示,将这个句子向量丢给分类器进行分类,至此完成整个流程。

Bi-Rnn(Bi-Lstm和Bi-Gru)

文本本身就是一堆字符按照某种规则排定而成的序列,Rnn循环神经网络本身解决的就是时序问题的学习。本质来说就是通过双向循环神经网络从文本中提取序列关系特征,然后链接到两个全连接层。最后连接一个softmax层。进行多分类的预测。

Bi-Rnn+Attention

Attention模型最早提出是用在图像识别上的,模仿人类的注意力机制,给图像不同的局部赋予不同的权重。在自然语言中使用最早是在机器翻译领域,这里我们在BiGru的基础上添加一个Attention Model,即对BiGru的隐层每一个时间步的向量学习一个权重,也就是在得到句子的向量表示时对评论文本中不同的词赋予不同的权值,然后由这些不同权值的词向量加权得到句子的向量表示。

使用不同的模型训练

1.TextCnn:使用textcnn模型效果在我们的实验中表现并不好相比于其它的两个模型,效果是最差的。textcnn模型作分类,线上分数只有64左右

我们的改进与创新点

2.Bi-Lstm:双向RNN的表现好与textcnn,我们针对rnn模型的做了特殊的特征工程,这帮助我们在线上提高了接近3分的进步。普通的对文本中金额和重量这些离散化可能只是简单的区间划分,比如把0~1万划分成[0,500,1000,5000,8000,10000]这样子。但是区间划分的太粗就容易在一些样本中赵不到很好的特征去拟合刑期(可能上海区的盗窃标准是2000起,而合肥是1000起),针对这种情况我们想出了一个很巧妙的数字的离散化表达方式,由于循环神经网络善于学习到序列间的关系,我们用数字的第一个数字+空格+数字的位数的方式对文书中金额,重量等进行表示。在我们线下测试的时候,使用了该方法模型的线下验证集的准确率由39%提升到41%。

3.Bi-RNN+Attention:在实验的三个模型中,该模型的效果是最好的。