Giter Club home page Giter Club logo

code-for-nlp-beginner's Introduction

实现了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. pytorchRNN, GRU, LSTM以及TextCNN,其中自己编写的RNN, GRU, LSTM模型已经测试与pytorch内部nn.xxx一致。

  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来实现,便于理解其内部的处理流程。

model test accuracy paper test accuracy
0.86 0.88

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

数据集地址: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 gatebias初始为1,因为开始的时候记忆准确度不高。
  • 关于dropout,LSTM的输入和输出的时候都加dropout;字符embedding进入CNN前也要dropout
  • 关于优化器,论文是采用了SGD,每个epoch都对学习率进行调整,注意这里不能用pytorchSGD中的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格式的文本,这里需要自己 从文本读取的句子,也要自定义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: 鸟

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

code-for-nlp-beginner's People

Contributors

jiacheng-ye avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

code-for-nlp-beginner's Issues

您好,对任务一里用numpy实现的LogisticRegression有点疑问

范数正则化那里:
if self.regularization == "l2":
self.w += self.learning_rate * (gradients * self.C - self.w)
elif self.regularization == "l1":
self.w += self.learning_rate * (gradients * self.C - np.sign(self.w))
else:
self.w += self.learning_rate * gradients
l1和l2范数正则化时,正则化系数self.C为啥不是乘以右边的self.w和np.sign(self.w),而是左边的gradients吧?

您好关于task1的model.py文件里有些小问题想问您一下

  1. 在梯度下降function中对softmax中的w参数求导后的式子是不是应该为x的转置乘(预测值-真实值),也就是gradients = x.transpose().dot(probs - to_onehot(y, self.num_classes))
  2. probs = softmax(x.dot(self.w)) 这里使用 softmax(np.matmul(x, self.w)) 就会报错 ValueError: matmul: Input operand 0 does not have enough dimensions (has 0, gufunc core with signature (n?,k),(k,m?)->(n?,m?) requires 1)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.