学习资料: https://www.youtube.com/watch?v=ogrJaOIuBx4&list=PL2-dafEMk2A7YdKv4XfKpfbTH5z6rEEj3&index=19 代码: https://github.com/llSourcell/How_to_make_a_text_summarizer/blob/master/vocabulary-embedding.ipynb
今天学习的是自动生成文本摘要。
当我们的身边的信息越来越多,数据越来越多,链接越来越多的时候,用一句简单的话就能把最重要的信息给表达出来,变得越来越重要。
有了这个技能,我们就可以让机器为我们提取一篇文章的重要信息,以后甚至是一本书的重要信息。
这个技术最早是在气象领域应用起来的,就是用一个固定的格式把预测出来的数据套入进去,后来在金融领域,医疗领域也得到广泛的应用,这样的工具可以很好的帮助从业人员节省一部分时间。
过去的方法是提取一个子集,而我们的大脑在对一篇文章进行总结的时候,利用的是抽象性思维,现在我们就可以用深度学习来模拟这个过程。
我们要用的数据是BBC新闻数据集。 http://mlg.ucd.ie/datasets/bbc.html
pickle, 可以将python的对象转化成character stream,我们可以很轻松的重建这个对象:
import cPickle as pickle
FN0 = 'tokens' # this is the name of the data file which I assume you already have
with open('data/%s.pkl'%FN0, 'rb') as fp:
heads, desc, keywords = pickle.load(fp) # keywords are not used in this project
返回的heads就是标题,desc就是相应的文章。
接着我们需要把整个文章变成一个一个的单词,并且一个词一个词的生成总结。
from collections import Counter
from itertools import chain
def get_vocab(lst):
vocabcount = Counter(w for txt in lst for w in txt.split())
vocab = map(lambda x: x[0], sorted(vocabcount.items(), key=lambda x: -x[1]))
return vocab, vocabcount
接着我们要用词向量来表示每个单词。 word2vec是一个用大量数据提前训练好的模型,我们可以直接下载。
词向量的每个维度可以表示一个性质,可以是性别或者是头衔等,词向量在每个维度的投影长度可以看作是这个单词在这个性质上的相关度。
另一种算法叫做GloVe,它属于 count based的, 每一行代表一个单词,每一列代表和这个单词出现在同一语境中的频数。 GloVe 比 word2vec 稍微快一点,
首先,将提前训练好的 glove 词向量下载到本地,然后用它们来初始化embedding matrix,我们先随机初始化,然后把 training vocabulary 出现的所有单词的 glove 权重复制一下。对于词汇表以外的单词,我们会找到离它最近的一个 glove 向量。
path = 'glove.6B.zip'
path = get_file(path, origin="http://nlp.stanford.edu/data/glove.6B.zip")
然后我们要用 seq2seq 模型,我们输入一句话。
encoder,输入就是 vocabulay 集,标签就是相应的一句话标题,embeddings 会在训练过程中不断地优化,loss 是 cross entropy。
decoder,和encoder一样的 lstm 结构,权重矩阵也是用同样的提前训练好的 glove embeddings,它用来生成 summary。
model = Sequential()
model.add(Embedding(vocab_size, embedding_size,
input_length=maxlen,
W_regularizer=regularizer, dropout=p_emb, weights=[embedding], mask_zero=True,
name='embedding_1'))
for i in range(rnn_layers):
lstm = LSTM(rnn_size, return_sequences=True, # batch_norm=batch_norm,
W_regularizer=regularizer, U_regularizer=regularizer,
b_regularizer=regularizer, dropout_W=p_W, dropout_U=p_U,
name='lstm_%d'%(i+1)
)
model.add(lstm)
model.add(Dropout(p_dense,name='dropout_%d'%(i+1)))
这里有一个很关键的点,就是我们需要记住这段文字中的哪些部分呢?关于记忆的话,我们会选择用 ltm 模型来做,而在这个问题上另一个重要的理论就是 attention,它可以学到哪些数据是最相关的最需要记忆的。
decoder 会先生成一个单词,然后把这个单词投入到下一层中,就会生成下一个单词,一直到生成一句标题。
我们在 decoder 这里会应用 attention 机制,对于每一个输出的单词,会计算每个输入单词的权重,来决定应该在这个单词上投入多少 attention。这些权重会被用来计算最后一个隐藏层的加权平均,然后投入到 softmax中。
可以看一下训练效果:
X = "What have you been listening to this year ? If you want to find out using cold , hard evidence , then Spotify 's new Year in Music tool will tell you ."
Y = "Spotify Will Make You Smarter for Your App"
samples = gensamples(X, skips=2, batch_size=batch_size, k=10, temperature=1)
HEADS:
12.9753409925 How To Make A <0>^