美文网首页
使用Sentencepiece +CNN进行文本分类

使用Sentencepiece +CNN进行文本分类

作者: 烛之文 | 来源:发表于2020-11-23 11:42 被阅读0次

    1 前言

    Sentencepiece是google开源的文本Tokenzier工具,其主要原理是利用统计算法,在语料库中生成一个类似分词器的工具,外加可以将词token化的功能;对比开源的分词器,它会将频繁出现的字符串作为词,然后形成词库进行切分,所以它会切分的粒度会更大些。

    例如“机器学习领域“这个文本,按jieba会分“机器/学习/领域”,但你想要粒度更大的切分效果,如“机器学习/领域”或者不切分,这样更有利于模型捕捉更多N-gram特征。为实现这个,你可能想到把对应的大粒度词加到词表中就可以解决,但是添加这类词是很消耗人力。然而对于该问题,利用sentencepiece可以得到一定程度解决,甚至能完美解决你的需求。

    基于上述的场景,本项目主要探究利用sentencepiece进行文本分类,对比开源的分词器,会有怎样的效果
    。在实验中,选择的是中文新闻文本数据集,对比的开源分词器选择的是jieba。若想对sentencepiece有更多的了解,可以查看sentencepiece原理与实践

    2 环境

    python3
    tensorflow2.0
    jieba
    sentencepiece
    numpy

    3 数据集及前期处理

    本实验同样是使用THUCNews的一个子集进行训练与测试,数据集请自行到THUCTC:一个高效的中文文本分类工具包下载,请遵循数据提供方的开源协议;

    文本类别涉及10个类别:categories = ['体育', '财经', '房产', '家居', '教育', '科技', '时尚', '时政', '游戏', '娱乐'],每个分类6500条数据;

    cnews.train.txt: 训练集(5000*10)
    cnews.val.txt: 验证集(500*10)
    cnews.test.txt: 测试集(1000*10)

    训练所用的数据,可以下载:链接: https://pan.baidu.com/s/1DOgxlY42roBpOKAMKPPKWA, 密码: up9d

    其实,本项目是基于词级别的CNN for text classification, 只是这个词一个从jieba切分过来的,一个是sentencepiece训练的模型识别出来的。在预处理过程中,本项目中只是简单的过滤标点符号,数字类型的词,具体code体现在loader.py 文中的 re_han=re.compile(u"([\u4E00-\u9FD5a-zA-Z]+)")。

    4 超参数说明

    class TextConfig():
    
        embedding_size=100    #dimension of word embedding
        vocab_size=8000     #number of vocabulary
    
        seq_length=600        #max length of sentence
    
        num_filters=128       #number of convolution kernel
        filter_sizes=[2,3,4]
        num_classes=10
        hidden_unit=128
    
        drop_prob=0.5          #droppout
        lr= 1e-3               #learning rate
    
        num_epochs=10          #epochs
        batch_size=64          #batch_size
        spm=True               #use sentencepiece
    
        train_dir='./data/cnews.train.txt'
        val_dir='./data/cnews.val.txt'
        test_dir='./data/cnews.test.txt'
        vocab_dir='./data/vocab.txt'
    

    在与jieba对比的时, 默认设定的vocab_size=8000, spm参数控制是否use sentencepiece,其他参数都是一致的;./data/vocab.txt是用jieba切分后前8000的高频词;

    5 实验对比

    (1) 训练和验证准确率对比

    模型 train_accuracy val_accuracy test_accuracy
    jieba+word2vec+cnn 1.000 0.971 0.9723
    jieba+cnn 0.9988 0.9686 0.9706
    spm+cnn 0.9972 0.9704 0.9667

    (2) 训练中损失变化对比

    从训练结果来看,二者相差并不大,利用spm+cnn在验证集上有一定的提升,但在测试集jieba+cnn表现好一些。通过这些微小数据对比,个人觉得利用sentencepiece相对jieba这类正规分词器来说,更容易过拟合些,换个角度来说,它捕捉的特征更多些,但也带来更多噪声特征的影响。

    (3) 载入数据集的消耗时间

    模型 cost_time(seconds)
    jieba+cnn 475
    spm+cnn 80

    对比jieba分词器,sentencepiece切分效率是它的近6倍,基于这个优势,是可以看出sentencepiece的使用价值的,尤其当处理文档级文本的时候。

    (4) 是不是词表越大越好
    在与jieba对比中,设定的是8000个高频词,可能有疑问:是不是词表越大效果会越好?对此,本实验在spm+cnn模型下,对比了词表8000,20000,320000(sentencepiece能训练的最大词表),效果如下:

    可以看出,随着词表增大,在训练集上更早的达到“潜在的最好效果”,而在验证集上的表现越来越差。理论上不是词表越大越好吗,它毕竟降低了未登录词出现的概率。其实,我想是这样的,该新闻数据集的各个label区分度是很高的,也就是说影响每个label的特征都是很明显的,而且这些影响特征都是可用高频词汇组合出来的。如果加大词表,就相当于training过程中,让model学到很多label的噪声特征,导致在验证集上效果降低。

    还有一个原因:该数据集不论基于字,词,或者加上word2vec词向量,它的train_accuracy都很高;如果一个数据集的train_accuracy较低,增加词表应该会有正向的提升。

    (4) spm不同词表下切分效果对比
    在训练sentencepiece,可以设定输出词表的大小。本实验训练了8000,20000,320000三个级别的spm model,对比jieba,看看它们切分文本的效果,如下:

    模型 text
    no_segement 新浪体育讯北京时间4月27日,NBA季后赛首轮洛杉矶湖人主场迎战新奥尔良黄蜂
    jieba 新浪\体育讯\北京\时间\4\月\27\日\,\NBA\季后赛\首轮\洛杉矶\湖人\主场\迎战\新奥尔良\黄蜂
    spm_8000 \新浪体育讯北京时间\4\月\27\日,\NBA\季后赛\首\轮\洛杉矶\湖人\主场\迎\战\新\奥\尔\良\黄蜂
    spm_20000 \新浪体育讯北京时间\4\月\27\日,\NBA\季后赛\首轮\洛杉矶湖人\主场迎战\新\奥尔良\黄蜂
    spm_320000 新浪体育讯北京时间\4\月\27\日,\NBA\季后赛首轮\洛杉矶湖人主场迎战新奥尔良黄蜂

    对比显示:随着词表增大,spm切分的粒度越来越大;三个spm模型都将“新浪体育讯北京时间”当一个词块,说明语料库中该词块出现的频率很高;在spm_320000模型下,将“洛杉矶湖人主场迎战新奥尔良黄蜂”切在一起,粒度是相当的大,直接是将一句话当成一个词块。

    此外,可以看出spm_8000下粒度太细了,很多单字情况,这种情况明显是没有jieba效果好,也就影响了模型的训练,试想:如果在训练spm模型的时候,是不是可以限定下词的长度,只要长度2以上的高频词汇,是不是再去词token化效果会好些。

    我之前也尝试:让jieba先切分下,形成词列表,然后再用sentencepiece去训练,这样二者就有种互补的效果,一来减少jieba因为词库的原因导致很多高频词组切开的影响,二来可利用sentencepiece的切分效率。但在实际操作中,并没有实现,不知道是对开源的sentencepiece工具没搞清楚,还是它本事就有这个问题。之前也有朋友遇到同样的问题,也与他探讨过,当目前还是没解决...

    6 结语

    利用sentencpiece代替分词器进行下游任务,是完全可行的,一来它与正规分词器对比效果是相当的,二来它的切分效率很高,可降低模型在token化消耗的时间,这对在工业上应用是合适的。只是在使用过程中,可调式下词表大小,不宜过高,但也要具体场景具体对比看下,是否有必要把词表加大。此外,如果在领域性很强的任务时,或者在做multi-label任务时,我想sentencpiece带来的效果应该更明显。当然,上述提到的问题,若能解决,会让sentencpiece在中文处理上更有价值。对此感兴趣的朋友,若有啥问题,可与我私下交流~

    7 参考

    1. Text classification with CNN and Word2vec
    2. sentencepiece原理与实践
    3. SentencePiece

    更多文章可关注笔者公众号:自然语言处理算法与实践

    相关文章

      网友评论

          本文标题:使用Sentencepiece +CNN进行文本分类

          本文链接:https://www.haomeiwen.com/subject/oximiktx.html