实现了nlp-beginner的几个任务,一方面自己练练手,另一方面供刚入门的朋友参考。才学疏浅,难免有不少问题,有任何问题可以发issue或者邮箱联系,万分感谢~
数据集地址:Classify the sentiment of sentences from the Rotten Tomatoes dataset
-
用
sklearn实现,n-gram特征提取直接用sklearn内置的CountVectorizer。 -
用
numpy实现:- 自定义
n-gram特征抽取类,用scipy的csr_matrix来保存doc-ngram稀疏矩阵; numpy实现用于二分类的Logistic Regression及用于多分类的Softmax Regression;- 实现三种梯度更新方式:
BGD、SGD以及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
-
老老实实一步步写分词、构建词典、数据向量化、加载词向量等;
-
用
pytorch写RNN,GRU,LSTM以及TextCNN,其中自己编写的RNN,GRU,LSTM模型已经测试与pytorch内部nn.xxx一致。 -
用
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模型,如上图左边所示,模型主要分三层,由下至上:- 第一层用
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输出。
- 第一层用
-
注意用
torchtext读取json文件的方式,及依赖解析数据的读取方式。其实torchtext内部有dataset.nli模块实现了nli数据读取方式,但是在代码中我还是用原版的FIELD来实现,便于理解其内部的处理流程。
| model test accuracy | paper test accuracy |
|---|---|
| 0.86 | 0.88 |
数据集地址:CONLL 2003
采用CNN+BiLSTM+CRF结构,复现论文End-to-end Sequence Labeling via Bi-directional LSTM-CNNs-CRF
- 数据采用
BIOES结构,用bio2bioes.py进行转换。 - 关于预处理,将数字都变为0;
- 设置预训练
embedding的时候需注意模糊匹配(大小写); - 设置
vocab的时候使要用到train以及dev+test中出现在embedding中的词; - 关于初始化,论文里有详细的设置,注意的是
LSTM里面的forget gate的bias初始为1,因为开始的时候记忆准确度不高。 - 关于
dropout,LSTM的输入和输出的时候都加dropout;字符embedding进入CNN前也要dropout。 - 关于优化器,论文是采用了
SGD,每个epoch都对学习率进行调整,注意这里不能用pytorch的SGD中的weight decay,因为它是对权重的衰减(L2正则),而我们要的是对学习率进行衰减。
| embedding | entity-level F1 | paper result |
|---|---|---|
| random (uniform) | 83.18 | 80.76 |
| glove 100 | 90.7 | 91.21 |
注意点:使用torchtext进行文本处理,需注意要由于torchtext只能处理tsv/csv/json格式的文本,这里需要自己
从文本读取的句子,也要自定义Dataset,make Example时的两种表现形式:
list形式,此时构建FIELD的时候FIELD内部的tokenizer不会起作用;str形式,word空格隔开,此时构建FIELD的时候必须传入tokenizer=lambda x:x.split()(针对该任务)来覆盖内部的tokenizer, 否则会用内部的来分词,得到的word可能不一样了,也就和label不对应了。
用CharRNN来写诗,评价指标为困惑度,是交叉熵损失取exp。
- 采用单向
LSTM,输入的最后一个为[EOS],对应的target为输入右移一位; - 控制诗的长度为
MAX_LEN,以一行为单位进行切分,即将超长的诗切分为若干短诗; - 训练200个
epoch后,困惑度为400左右。
Input the first word or press Ctrl-C to exit: 鸟
鸟渠霭乌秋,游王居信知。鹏未弟休不,深沙由意。寥五将不,两迹悄臣。生微心日,水复师尘。来称簸更,影乏魍无。
