RNN+Attention(HAN) 文本分类 阅读笔记

转自:https://zhuanlan.zhihu.com/p/42121435

Part I:论文模型

Part II:代码理解

Part III:后记


本文主要记录一下对 Hierarchical Attention Network for Document Classification (HAN)及其相应复现代码(tensorflow)的理解。


Part I:论文模型

一、直觉上的理解

要对一篇文章进行文本分类,人工的做法通常是抓住中心句或者中心词汇,并将其归类。那么,一篇文章中每个句子的重要程度、一个句子中每个词汇的重要程度,都是不一样的。不同的词汇和句子对文章的表达有不同的影响,词汇和句子的重要性是严重依赖于上下文的,即使是相同的词汇和句子,在不同的上下文中重要性也不一样。

当我们人对文章进行分类时,通常会将文章分成多个句子,再对每个句子进行分析,这个可以类比于我们平时做英语的阅读理解。于是论文的作者这样的分层思路,便提出了论文中的模型。

二、论文模型

HAN 论文模型

其实模型是相对简单且好理解的。从下往上看,其实只是一些层的叠加。

  1. word encoder:对词汇进行编码,建立词向量。接着用双向 GRU 从单词的两个方向汇总信息来获取单词的注释,因此将上下文信息合并到句子向量中。
  2. word attention:接着对句子向量使用 Attention 机制。
  3. sentence encoder:与上面一样,根据句子向量,使用双向 GRU 构建文档向量。
  4. sentence attention:对文档向量使用 Attention 机制。
  5. softmax:常规的输出分类结果。

三、两向 GRU 的好处

单向的 RNNLSTMGRU),是根据前面的信息推出后面的但有时候只看前面的词是不够的例如我今天不舒服我打算__一天只根据不舒服‘,可能推出我打算去医院‘,‘睡觉‘,‘请假等等但如果加上后面的一天‘,能选择的范围就变小了,‘去医院这种就不能选了请假‘‘休息之类的被选择概率就会更大

四、Attention 机制的个人理解

举个翻译的例子,比如将“我爱机器学习”逐词翻译成“I love machine learning”。

在翻译“机器学习”的时候,前面的“我爱”对“机器学习”的影响并不是特别大,所以我们可以将大部分“注意力”集中在“机器学习”,极小的“注意力”放在“我爱”上;而不用留意整个句子(无注意力机制)。

文中作者使用的 attention 其实只是 mlp + softmax:

关于注意力机制原理的图,感觉并不太好理解。相关论文:FEED-FORWARD NETWORKS WITH ATTENTION CAN SOLVE SOME LONG -TERM MEMORY PROBLEMS

 


Part II:代码理解

这里主要讲一下对 论文复现代码(很详细) 的理解吧。反正我自己是不会写= =。

代码链接:

博主的代码其实是有一些问题的,我做了一点小修改,但是还有 bug。不知道咋解决了。

直接贴修改的代码吧

DataUtils.py

#将所有的评论文件都转化为30*30的索引矩阵也就是每篇都有30个句子每个句子有30个单词
# 不够的补零多余的删除并保存到最终的数据集文件之中
with open('yelp_academic_dataset_review.json', 'rb') as f:
    for line in f:
        doc = []
        review = json.loads(line)
        sents = sent_tokenizer.tokenize(review['text'])
        for i, sent in enumerate(sents):
            if i < max_sent_in_doc:
                word_to_index = []
                for j, word in enumerate(word_tokenizer.tokenize(sent)):
                    if j < max_word_in_sent:
                            word_to_index.append(np.array(vocab.get(word, UNKNOWN)))

                #add padding 
                npad = (0,30-len(word_to_index))
                word_to_index = np.pad(word_to_index, pad_width=npad, mode='constant', constant_values=0)#padding
                doc.append(np.array(word_to_index))
                
        label = int(review['stars'])
        labels = [0] * num_classes
        labels[label-1] = 1
        data_y.append(labels)
        # print(np.array(doc).shape)
        # print(np.array(doc).ndim)
        #add padding
        if np.array(doc).ndim == 1:
            continue
        npad2 = ((0,30-len(doc)), (0,0))
        doc = np.pad(doc, pad_width=npad2, mode='constant', constant_values=0)#padding
        data_x.append(np.array(doc))

    pickle.dump((data_x, data_y), open('yelp_data', 'wb'))
    print(len(data_x)) #229907

load_data.py(改这里是因为数据太多了,我电脑吃不消)

def read_dataset():
    with open('yelp_data', 'rb') as f:
        data_x, data_y = pickle.load(f)
        length = len(data_x) // 100
        train_x, dev_x = data_x[:int(length*0.9)], data_x[int(length*0.9)+1 : int(length)]
        train_y, dev_y = data_y[:int(length*0.9)], data_y[int(length*0.9)+1 : int(length)]
        return train_x, train_y, dev_x, dev_y

一、数据预处理

1,对单词进行计数、统计词频、并排序,去掉出现次数较少的那些单词。

2,将所有的评论文件都转化为30*30的索引矩阵,也就是每篇都有30个句子,每个句子有30个单词。不够的补零,多余的删除。

3,保存到最终的数据集文件之中。

二、模型构建

1,embedding 层、word2vec 层、sent2vec 层

2,在word2vec 层和 sent2vec 层中使用了封装的 GRU 和 Attention。

3,这里的层数有点多,要特别注意一下各个层的 shape。

三、训练及测试

1,使用简单好用的分批次读入进行训练和训练。 通常的套路大概就是:model、loss、optimizer、accuracy、train、test

2,对一些变量进行 summary 并可视化。

3,保存 checkpoint。 4,贴一个新学到的东西:梯度截断。嗯,其实我不太理解为啥用了 GRU 还会出现梯度消失或者梯度弥散的现象。。

其实 GRU、LSTM 是用来解析梯度消失问题的,梯度爆炸还是需要用梯度截断为解决。

# RNN中常用的梯度截断,防止出现梯度过大难以求导的现象
    tvars = tf.trainable_variables()
    grads, _ = tf.clip_by_global_norm(tf.gradients(loss, tvars), FLAGS.grad_clip)
    grads_and_vars = tuple(zip(grads, tvars))
    train_op = optimizer.apply_gradients(grads_and_vars, global_step=global_step)

 


Part III:后记

今天看了一遍 tensorflow 的入门视频,感觉浪费了好多时间。其实看书就可以懂的。不过昨天没睡好,今天一整天不在状态,也只能看看视频,安慰自己,有在学习。

本来想着照着代码敲一遍的,但是所有人都说这样没用,也就放弃了。他们都说代码看多了慢慢就会写了。。希望自己早点提高代码能力吧。

接下来的学习计划应该是看看文本分类的几个模型吧:用深度学习(CNN RNN Attention)解决大规模文本分类问题 - 综述和实践

另外会跟着大佬的步伐走:专栏:深度学习与NLP--论文笔记和TensorFlow实现 - CSDN博客

posted @ 2018-10-22 20:30  mxp_neu  阅读(228)  评论(0)    收藏  举报