Skip to content
code for nlp beginner, including Sentiment Analysis, NER, NLI and Language Model.
Branch: master
Clone or download
Latest commit 3a62301 Jul 9, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Task1-Text Classification (LR) init Jul 2, 2019
Task2-Text Classification (RNN&CNN) init Jul 2, 2019
Task3-Natural Language Inference init Jul 9, 2019
Task4-Named Entity Recognization init Jul 5, 2019
Task5-Language Model init Jul 2, 2019
pics init Jul 2, 2019
README.md init Jul 9, 2019

README.md

实现了nlp-beginner的几个任务,一方面自己练练手,另一方面供刚入门的朋友参考。才学疏浅,难免有不少问题,有任何问题可以发issue或者邮箱联系,万分感谢~

任务一:基于机器学习的文本分类

数据集地址:Classify the sentiment of sentences from the Rotten Tomatoes dataset

  1. sklearn实现,n-gram特征提取直接用sklearn内置的CountVectorizer

  2. numpy实现:

    • 自定义n-gram特征抽取类,用scipycsr_matrix来保存doc-ngram稀疏矩阵;
    • numpy实现用于二分类的Logistic Regression及用于多分类的Softmax Regression
    • 实现三种梯度更新方式:BGDSGD以及MBGD
    方法 参数 准确度
    LR (sklearn) C=0.8; penalty='l1' 0.587
    SoftmaxRegression (numpy) C=0.8; penalty='l1' 0.548

任务二:基于深度学习的文本分类

数据集地址:Classify the sentiment of sentences from the Rotten Tomatoes dataset

  1. 老老实实一步步写分词、构建词典、数据向量化、加载词向量等;

  2. pytorchRNNBiRNN以及TextCNN

  3. torchtext简化数据的处理操作;

    方法 参数 准确度
    RNN epoch=5; hidden_size = 256; num_layers = 1; bidirectional = True; random embedding 0.629
    RNN epoch=5; hidden_size = 256; num_layers = 1; bidirectional = True; glove_200 embedding 0.633
    CNN epoch=5; num_filters = 200; kernel_sizes = [2, 3, 4]; random embedding 0.654
    CNN epoch=5; num_filters = 200; kernel_sizes = [2, 3, 4]; glove_200 embedding 0.660

说明:该实验glove词向量对结果提升不大,第四个实验效果较为显著;

任务三:基于注意力机制的文本匹配

数据集地址:SNLI

esim

  1. 实现ESIM模型,如上图左边所示,模型主要分三层,由下至上:

    • 第一层用BiLSTM来对句子的每个词向量进行重新编码,使其具备全局性;
    • 第二层先用Attention来提取前提与假设之间的关系,然后重构,以前提为例:
    # x1为前提,x2为假设,new_embed1是假设x1经过BiLSTM后的值,weight2是x2的每个词对x1的归一化相关程度,即attention值。
    # 1. 对假设x2进行加权求和,该值提取出了x2中与x1相关的部分;
    x1_align = torch.matmul(weight2, x2)
    # 2. 将四部分连接起来,用相减以及相乘来实现前提与假设的“交互推断”,文中说可以使得局部信息(如矛盾关系)更加明显;
    x1_combined = torch.cat([new_embed1, x1_align, new_embed1 - x1_align, new_embed1 * x1_align],dim=-1)
    • 第三层是将重构后的前提和假设再放到一个BiLSTM中,文中说为了控制模型复杂度,在传入前先经过一个单层FFN并且ReLU一下。
    • 第四层是输出层,先pooling一下,文中前提和假设都用了max-pooling以及average-pooling两种形式,再对两者连接后MLP输出。
  2. 注意用torchtext读取json文件的方式,及依赖解析数据的读取方式。其实torchtext内部有dataset.nli模块实现了 nli数据读取方式,但是在代码中我还是用原版的FIELD来实现,便于理解其内部的处理流程。

test data accuracy: 0.86

任务四:基于LSTM+CRF的序列标注

数据集地址:CONLL 2003

采用CNN+BiLSTM+CRF结构,复现论文End-to-end Sequence Labeling via Bi-directional LSTM-CNNs-CRF

  1. 数据采用BIOES结构,用bio2bioes.py进行转换。
  2. 关于预处理,将数字都变为0;
  3. 关于初始化,论文里有详细的设置,注意的是LSTM里面的forget gatebias初始为1,因为开始的时候记忆准确度不高。
  4. 关于dropout,LSTM的输入和输出的时候都加dropout;字符embedding进入CNN前也要dropout
  5. 关于优化器,论文是采用了SGD,每个epoch都对学习率进行调整,注意这里不能用pytorchSGD中的weight decay,因为它是对权重的衰减(L2正则),而我们要的是对学习率进行衰减。
embedding entity-level F1 paper result
random (uniform) 80.9 80.76
glove 100 84.7 91.21

从实验结果看,用glove并没有论文中的提升的那么多。

注意点:使用torchtext进行文本处理,需注意要由于torchtext只能处理tsv/csv/json格式的文本,这里需要自己 从文本读取的句子,也要自定义Datasetmake Example时的两种表现形式:

  • list形式,此时构建FIELD的时候FIELD内部的tokenizer不会起作用;
  • str形式,word空格隔开,此时构建FIELD的时候必须传入tokenizer=lambda x:x.split()(针对该任务)来覆盖内部的tokenizer, 否则会用内部的来分词,得到的word可能不一样了,也就和label不对应了。

任务五:基于神经网络的语言模型

CharRNN来写诗,评价指标为困惑度,是交叉熵损失取exp

  1. 采用单向LSTM,输入的最后一个为[EOS],对应的target为输入右移一位;
  2. 控制诗的长度为MAX_LEN,以一行为单位进行切分,即将超长的诗切分为若干短诗;
  3. 训练200个epoch后,困惑度为400左右。

Input the first word or press Ctrl-C to exit: 鸟

鸟渠霭乌秋,游王居信知。鹏未弟休不,深沙由意。寥五将不,两迹悄臣。生微心日,水复师尘。来称簸更,影乏魍无。

You can’t perform that action at this time.