作者:集智小仙女
我想在跑车里
想要一辆法拉利
想要钱 Money Money
统统的统统都得靠你自己
我外婆都见告我
.....
最近“中国有嘻哈”特殊火
本仙女也来跟风
以是本周的 NLP 教程是
拿循环神经网络(RNN)来天生嘻哈歌词。
本仙女以为行!
先让我们看看一个大略的深度神经网络模型,
能天生什么样的“嘻哈歌词”。
我的天下
能够有
识破
我的兄弟在我身边
每个人
或许他们是我的眼
我的能够将别约别约我
在这种角度
我便是你你的帮派
他们的声音
原来地方叫
别约你约我
别约我
别约我
看看起来还不错哈
那么……
不用买,我们自己做一个!
大略来说,中文句子中的每个字在统计上是干系的。比如对付“多想你陪我透透气”这句话,如果我们知道第一个字“多”,那下一字有可能是“想”;如果知道前两个字“多想”,那么第三个字是“你”的可能性就大些,以此类推,如果知道“多想你陪我透透”,那么末了一个字很有可能便是“气”字。
以是这次搭建的循环神经网络(RNN)模型,便是要在演习的过程中学习到“歌词之间的规律”。
我们只要给演习好的模型一个开头,比如“我们”,模型就能按照学习到的规律,连续预测天生“我们”之后的嘻哈歌词。
资源:
集智 AI 学园公众号(swarmAI) 回答“AI有嘻哈上”,获取本文的 Jupyter Notebook 文档!
清理演习数据:
首先准备演习模型的数据。
本仙女从网上爬了大约三万四千行嘻哈歌词。
lrc_lines = open('../data/rapper.txt').readlines()print(lrc_lines[:20])
['\n', ' 作曲 : Mixtape\n', ' 作词 : 啊之\n', '\n', '录音 MISO MUSIC\n', '混缩 MAI\n', 'MIX BY MAI\n', \"大众hey baby Don't worry\n\"大众, \公众hey baby Don't worry\n\公众, \"大众hey baby Don't worry\n\公众, \公众hey baby Don't worry\n\"大众, '抱歉我依旧不稳定 DAMN\n', '鱼龙殽杂的街头不但靠努力 REAL 别烦恼\n', '多想你陪我透透气 发发牢骚\n', '倾诉着最近不快意 let me let me\n', '这便是生活里 的问题 不必不报忧\n', '做真实的自己 不用比 早晚都能够\n', '我始终担心你 出问题 民气丢脸破\n', '我怎么都可以 唯有你 以是 以是\n', '我早已昼夜颠倒 烟酒成瘾 制作巧克力\n']
去除无关信息:歌词中包含“作词”,“作曲”等信息,这对演习模型天生歌词是没有任何帮助的,先去掉他们。
# 去除文本中不是属于歌词的行# 我的程序写的都比较水啦# 大家可以自由发挥写出更好的程序for i in range(len(lrc_lines)): line = lrc_lines[i] if \"大众作词\公众 in line or \"大众作曲\公众 in line or \"大众编曲\"大众 in line or \公众录音\"大众 in line or \"大众混缩\"大众 in line or \"大众制作人\"大众 in line: lrc_lines[i] = \公众\n\公众
不雅观察下已经去除作者信息的歌词文本:
print(lrc_lines[:20])
['\n', '\n', '\n', '\n', '\n', '\n', 'MIX BY MAI\n', \公众hey baby Don't worry\n\"大众, \"大众hey baby Don't worry\n\公众, \公众hey baby Don't worry\n\"大众, \"大众hey baby Don't worry\n\公众, '抱歉我依旧不稳定 DAMN\n', '鱼龙殽杂的街头不但靠努力 REAL 别烦恼\n', '多想你陪我透透气 发发牢骚\n', '倾诉着最近不快意 let me let me\n', '这便是生活里 的问题 不必不报忧\n', '做真实的自己 不用比 早晚都能够\n', '我始终担心你 出问题 民气丢脸破\n', '我怎么都可以 唯有你 以是 以是\n', '我早已昼夜颠倒 烟酒成瘾 制作巧克力\n']
可以看到现在歌词中还包括一些英文,这是嘻哈的特色。
减少措辞种类:演习数据中存在的措辞种类越多,意味着深度神经网络模型学习起来的难度越大。
由于这次做的是一个大略的模型,以是本仙女不打算让模型再去预测英文歌词,以是我要把歌词中的英文去掉。
import re
final_lrc = []
# 利用正则表达式的手段识别中文
# 中文(包括繁体)在unicode中的编码范围是u4e00~u9fa5
zhPattern = re.compile(u'[\u4e00-\u9fa5]+')
# 遍历所有歌词行
for line in lrc_lines:
# findall会返回一个列表
zh_list = zhPattern.findall(line)
# 将中文拷贝到 final_lrc 中去
for item in zh_list:
final_lrc.append(item + '\n')
# 这样就只剩中文啦!
print(final_lrc[:10])
['抱歉我依旧不稳定\n', '鱼龙殽杂的街头不但靠努力\n', '别烦恼\n', '多想你陪我透透气\n', '发发牢骚\n', '倾诉着最近不快意\n', '这便是生活里\n', '的问题\n', '不必不报忧\n', '做真实的自己\n']
建立“字典”:还是像之前一样对所有笔墨建立一个“笔墨表”,由于个中元素都是独立的汉字,以是这次我们称它为“字典”。
在字典中所有的笔墨都会有对应的一个索引号。
在演习神经网络模型的时候,传着迷经网络的是某个字的“索引号”,而不是这个字本身。
# 字典
word_to_ix = {}
for line in final_lrc:
for word in line:
if word not in word_to_ix:
# 在单词表的末端添加这个单词
word_to_ix[word] = len(word_to_ix)
# 打印出字典中的前10个元素,把稳它是无序的
for i, key in zip(range(10), word_to_ix):
print(key, \公众:\"大众, word_to_ix[key])
礼 : 848嘞 : 3243惬 : 212歪 : 3160以 : 73款 : 782遍 : 1182伸 : 2091體 : 2541獠 : 3167
除了“字典”,还须要建立一个“有序列表”。
“有序列表”便是将“字典”按照索引号从小到大的顺序排序。
import operator
# 排序
sorted_char_list = sorted(word_to_ix.items(), key=operator.itemgetter(1), reverse=False)
# 有序列表
# 这里把稳字典是“dict”类型
# 有序列表是“list”类型
char_list = []
for item in sorted_char_list:
char_list.append(item[0])
# 有序列表中的元素
print(char_list[:10])
# 不雅观察有序列表中的元素即字典的有序排列
for ch in char_list[:10]:
print(ch, \"大众:\"大众, word_to_ix[ch])
['抱', '歉', '我', '依', '旧', '不', '稳', '定', '\n', '鱼']
抱 : 0
歉 : 1
我 : 2
依 : 3
旧 : 4
不 : 5
稳 : 6
定 : 7
: 8
鱼 : 9
“字典”的长度代表演习数据中有多少不同的字,这个长度即是我们模型输入层的大小,我们建立一个变量 nn_characters 来保存它。
n_characters = len(word_to_ix)print(n_characters)
3801
演习前的准备:数据随机选择器:
这次搭建的神经网络模型是“字符级”的,即每次输入“一个字”。
以是先要把上面处理过后的“一条条”的数据,都保存到一个“大字符串”里,便于随机取用。
big_string = ''
for line in final_lrc:
for ch in line:
big_string += ch
print(big_string[:20])
抱歉我依旧不稳定鱼龙殽杂的街头不但靠努
然后我们再编写一个工具方法“random_chunk”,用于每次从演习数据中随机选择201个字。
import random
chunk_len = 200
# 随机选取200 + 1个字符的数据
def random_chunk():
# 出发点的可选范围:0 ~ final_lrc_len-chunk_len
start_index = random.randrange(0, len(big_string) - chunk_len)
end_index = start_index + chunk_len + 1
# 将抽取的列表项转化为字符串再返回
return big_string[start_index:end_index]
result = random_chunk()
print(len(result))
201
把稳这里选取的字符串长度实际为201,为什么是201,到下面建立输入和目标数据的时候你就知道。
将数据转化为张量(Tensor):
建立一个赞助方法“char_tensor”,用于将笔墨转化为张量(Tensor)。
张量中保存的是笔墨对应的索引。
import torch
import torch.nn as nn
from torch.autograd import Variable
def char_tensor(string):
# 先按指定长度创建一个longTensor,添补0
tensor = torch.zeros(len(string)).long()
# 逐字查找字典
# 取出每个字的索引号,保存到 Tensor 中
for c in range(len(string)):
tensor[c] = word_to_ix[string[c]]
return Variable(tensor)
# 来试试这个方法
index_tensor = char_tensor(random_chunk())
# 查看 Tensor 长度
print(len(index_tensor))
# 查看 Tensor 中保存的索引
print(index_tensor[:10])
201Variable containing: 200 189 1006 1458 8 395 426 119 195 173[torch.LongTensor of size 10]
输入和目标:上面我们建立了“random_chunk”,用于选取201条数据。
为什么是201条?让我们转头看看文章开头的那张图:
RNN 模型在输入“多”时,须要预测出“想”;在输入“想”时,须要预测“你”。
即如果我们随机选取的总数据是“多想你陪我透透气”,那么演习输入数据是“多想你陪我”,演习目标数据是“想你陪我透透气”。
演习输入数据与演习目标数据恰好错开一个字,那么当我们选取了201条数据,那输入数据和目标数据就恰好是各200条。
def random_training_set():
# 先选取201字符长度的文本
chunk = random_chunk()
# 将选取的文本全部转化为 Tensor
inp = char_tensor(chunk[:-1])
target = char_tensor(chunk[1:])
return inp, target
inp, target = random_training_set()
print(len(inp))
print(len(target))
200200
到这里我们在演习前要做的准备就全部完成了,下面要做的便是搭建模型、演习模型、评估模型了。
对模型操作的内容我都放在“终篇”中了,“终篇”将在周五晚间推送,敬请期待!
喜好实操的小伙伴们千万不要错过哦!
本期关键词:【AI有嘻哈上】
课程表第一期:PyTorch概要简析
第二期:小试牛刀:编写一个词袋分类器
本期:AI 有嘻哈:处理数据
续期:AI有嘻哈:演习评估模型 终篇
第四期:起名大师:利用RNN天生个好名字
第五期:AI翻译官:采取把稳力机制的翻译系统
第六期:探索词向量天下
第七期:词向量高等:单词语义编码器
第八期:是非影象神经网络(LSTM)序列建模
第九期:体验PyTorch动态编程,双向LSTM+CRF
如果您有任何关于Pytorch方面的问题,欢迎进【集智—清华】火炬群与大家互换磋商,添加集智小助手微信swarmaAI,备注(pytorch互换群),小助手会拉你入群。
推举阅读PyTorch圣殿|传奇NLP攻城狮发展之路(二)
传奇NLP攻城狮发展之路(一)|集智AI学园
你的免费GPU打算平台-Floyd利用教程(下)|集智AI学园
关注集智AI学园"大众年夜众号
获取更多更有趣的AI教程吧!
搜索微信公众年夜众号:swarmAI
集智AI学园QQ群:426390994
学园网站:campus.swarma.org