机器学习带你横扫乐坛,你就是下一个方文山!


全文共3369字,预计学习时长9分钟

图源:unsplash

我太爱北极猴子乐队了,但他们已经很久没有发行新单曲了。久久欠缺精神食粮的我某天晚上突然灵机一动,我可以自给自足呀!于是我写了个简单的代码,用Keras和TensorFlow训练了一个文本生成模型,写出一首全新的北极猴子的歌。

 

不过条件有限,这玩意儿无法跟真正的北极猴子的歌曲相提并论,但安慰一下长期缺新歌的自己还是可以的。

本文将简单介绍这个代码,完整的代码放在笔者的GitHub上:https://github.com/Rajwrita/Sequence-Models-for-Literature/blob/master/NLP-AM2.0.ipynb

 

首先,你得建立一个几乎将全部北极猴子的歌曲包括在内的数据集(https://github.com/Rajwrita/Sequence-Models-for-Literature/blob/master/AM.txt),之后如果继续执行此代码,请尝试使用自己的数据集生成文本。

 

导入

 

首先要为深度学习模型导入通用的数据帧操作库以及TensorFlow和Keras库包:

 

import numpy as npfrom tensorflow.keras.preprocessing.sequence import pad_sequencesfrom tensorflow.keras.layers import Embedding, LSTM, Dense, Dropout,Bidirectionalfrom tensorflow.keras.preprocessing.text import Tokenizerfrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.optimizers import Adamfrom tensorflow.keras import regularizersimport tensorflow.keras.utils as ku

接着,导入数据:

 

data = open( AM.txt ).read()

再给文本装上一个分词器(tokenizer)。分词器可以生成覆盖整个语料库的单词词典,实质上就是键值对。键是单词,而值则是为该单词生成的标记。简言之,分词器将成句的字符串分解为独立的单词,然后赋予每个单词一个唯一整数值。这一步很关键,为后续嵌入层数据的准备打下基础。

 

获取单词索引的长度,可以得出语料库里单词的总量。在此基础上加1,就可以引入外部词汇。相应的代码如下:

 

tokenizer = Tokenizer()data = open( AM.txt ).read()tokenizer.fit_on_texts(corpus)total_words = len(tokenizer.word_index) + 1

再然后,使用token列表创建导入序列。导入序列说白了就是一个python列表,文本语料库的每一行都通过分词器生成一个token列表。是像这样的一行文本:

 

通过这道程序,就会将其转化为代表这些单词的一串token。数据集的每一行都会这样处理。其代码如下:

 

input_sequences = []for line in corpus:   token_list =tokenizer.texts_to_sequences([line])[0]   for i in range(1, len(token_list)):      n_gram_sequence = token_list[:i+1]      input_sequences.append(n_gram_sequence)

可以看出,导入序列只是被分解为短语的句子,紧接着要获取语料库中最长句子的长度。这一步很简单,只需要将所有句子遍历循环并找出最长那句即可。

 

max_sequence_len = max([len(x) for x in input_sequences])

现在填充所有序列使它们全部一样长。用零预填充序列,这样更容易提取到标签值,只要抓取最后一个标记就可以得到标签值了。

 

input_sequences = np.array(pad_sequences(input_sequences,maxlen=max_sequence_len, padding= pre ))

填充之后,创建预测值和标签值,这样序列基本上就被分解为x数组和y数组了。这里用到的是python的切片属性。代码如下:

 

predictors, label = input_sequences[:,:-1],input_sequences[:,-1]

现在,数据已经分为x数组和y数组,可以开始创建神经网络,对给定词组进行分类预测了。

 

从嵌入层开始

 

嵌入层是任何一种理解单词的深度学习模型不可或缺的一层,其实际作用是通过赋予同样含义词汇以同样数值,将较高维空间的向量投影到较低维空间,这样就可以直接对向量进行数学运算了。

在一行文本中,它处理了所有词汇并且赋予其在神经网络中的含义。第一个参数处理的是单词,第二个参数则是绘制单词矢量的维数,最后一个参数是输入维度的尺寸,其实就是最长序列的长度减1。减掉1是因为前面为了得到标签值,我们将每个序列的最后一个词砍掉了,所以得到的序列比最大序列长度要小1。

 

model.add(Embedding(total_words, 100, input_length=max_sequence_len-1))

添加LSTM(长短期记忆网络)层

 

图源:unsplash

LSTM层的细胞状态保存了整个上下文语境,从而保证了对下一个词汇产生影响的不止有相邻词汇。

 

除了单层的LSTM层,还可以使用堆叠多层的LSTM。使用双向LSTM层,我们可以从头到尾再从尾到头将原始数据导入学习算法中,这有助于神经网络更好地理解文本。双向LSTM还可以帮助神经网络更快收敛。

 

将返还序列标注设为True,这样就能将序列信息传递到第二层LSTM层,而不是直接到最终状态。

 

model.add(Bidirectional(LSTM(150, return_sequences = True)))

接下来,运用密集层进一步捕获线性关系,以上各层的输出将转化为单词概率。softmax激活函数会将所有输入单词概率从(-∞,∞ ) 转化为(0,1)。

 

model.add(Dense(total_words/2, activation= relu , kernel_regularizer=regularizers.l2(0.01)))model.add(Dense(total_words,activation= softmax ))

由于这里做的是categorical分类,所以要将定律设为分类交叉熵。至于优化器,这里选用adam优化器。

 

最后一步——Epochs

 

最后要花一点时间训练模型,数据集的数据不多,大概要训练模型500个epoch左右。

 

history = model.fit(predictors, label, epochs=100, verbose=1)

要预测的单词越多,产生的乱码也会越多,因为每一个单词都要预测,其下一个和下下个单词也是,那么下一个单词永远比上一个有更多不确定性。来看看网络最后预测出来的文本!

 

seed_text = "I really like the Arctic Monkeys and

建立覆盖足够单词的语料库,神经网络就可以在语料库上训练,并通过预测下一个单词,帮助我们预测一些复杂文本。

 

有了机器学习,产粮不再是难事,试试用这个代码为你的心水歌手写一首歌吧!


推荐阅读专题

留言点赞发个朋友圈

我们一起分享AI学习与发展的干货

编译组:黄壹格、吴子珺

相关链接:

https://medium.com/@rajwrita/using-text-generation-to-get-the-lyrics-for-the-next-arctic-monkey-song-f7c93a882c6f

如转载,请后台留言,遵守转载规范

推荐文章阅读

ACL2018论文集50篇解读

EMNLP2017论文集28篇论文解读

2018年AI三大顶会中国学术成果全链接

ACL2017论文集:34篇解读干货全在这里

10篇AAAI2017经典论文回顾

长按识别二维码可添加关注

读芯君爱你

猜你喜欢

转载自blog.csdn.net/duxinshuxiaobian/article/details/107804795