AI教程网 - 未来以来,拥抱AI;新手入门,从AI教程网开始......

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

AI前沿 AI君 47℃

我太爱北极猴子乐队了,但他们已经很久没有发行新单曲了。久久欠缺精神食粮的我某天晚上突然灵机一动,我可以自给自足呀!于是我写了个简单的代码,用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库包:

  1. import numpy as np 
  2. from tensorflow.keras.preprocessing.sequence import pad_sequences 
  3. from tensorflow.keras.layers import Embedding, LSTM, Dense, Dropout,Bidirectional 
  4. from tensorflow.keras.preprocessing.text import Tokenizer 
  5. from tensorflow.keras.models import Sequential 
  6. from tensorflow.keras.optimizers import Adam 
  7. from tensorflow.keras import regularizers 
  8. import tensorflow.keras.utils as ku 

接着,导入数据:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

从嵌入层开始

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

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

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

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

机器学习带你横扫乐坛,你就是下一个方文山
图源:unsplash

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

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

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

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

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

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

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

最后一步——Epochs

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

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

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

  1. seed_text = "I really like the Arctic Monkeys and  

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

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

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

作者:读芯术_今日头条
原文链接:https://www.toutiao.com/a6856972908959367692/

转载请注明:www.ainoob.cn » 机器学习带你横扫乐坛,你就是下一个方文山

喜欢 (0)or分享 (0)