code for nlp beginner, including Sentiment Analysis, NER, NLI and Language Model.
实现了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
进行转换。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
,以一行为单位进行切分,即将超长的诗切分为若干短诗;epoch
后,困惑度为400左右。Input the first word or press Ctrl-C to exit: 鸟
鸟渠霭乌秋,游王居信知。鹏未弟休不,深沙由意。寥五将不,两迹悄臣。生微心日,水复师尘。来称簸更,影乏魍无。