周杰伦几乎陪伴了每个90后的青春,那如果AI写杰伦风格的歌词会写成怎样呢?

首先当然我们需要准备杰伦的歌词,这里一共收录了他的十几张专辑,近5000多行歌词。

原文档格式:

第一步数据预处理

def preprocess(data):
"""
对文本中的字符进行替换,空格转换成逗号;换行变为句号。
"""
data = data.replace(' ', ',')
data = data.replace('\n', '。')
words = jieba.lcut(data, cut_all=False) # 全模式切词 return words

处理后结果:

前10个词: ['想要', '有', '直升机', '。', '想要', '和', '你', '飞到', '宇宙', '去']

将处理完的数据写入内存并将文本转换完数字

# 构造词典及映射
vocab = set(text)
vocab_to_int = {w: idx for idx, w in enumerate(vocab)}
int_to_vocab = {idx: w for idx, w in enumerate(vocab)} # 转换文本为整数
int_text = [vocab_to_int[w] for w in text]

构建神经网络

a. 构建输入层

def get_inputs():
inputs = tf.placeholder(tf.int32, [None, None], name='inputs')
targets = tf.placeholder(tf.int32, [None, None], name='targets')
learning_rate = tf.placeholder(tf.float32, name='learning_rate')
return inputs, targets, learning_rate

b. 构建堆叠RNN单元

其中rnn_size指的是RNN隐层神经元个数

def get_init_cell(batch_size, rnn_size):
lstm = tf.contrib.rnn.BasicLSTMCell(rnn_size)
cell = tf.contrib.rnn.MultiRNNCell([lstm]) initial_state = cell.zero_state(batch_size, tf.float32)
initial_state = tf.identity(initial_state, 'initial_state')
return cell, initial_state

c. Word Embedding

因为单词太多,所以需要进行embedding,模型中加入Embedding层来降低输入词的维度

def get_embed(input_data, vocab_size, embed_dim):
embedding = tf.Variable(tf.random_uniform([vocab_size, embed_dim], -, ))
embed = tf.nn.embedding_lookup(embedding, input_data) return embed

d. 构建神经网络,将RNN层与全连接层相连

其中cell为RNN单元; rnn_size: RNN隐层结点数量;input_data即input tensor;vocab_size:词汇表大小; embed_dim: 嵌入层大小

def build_nn(cell, rnn_size, input_data, vocab_size, embed_dim):
embed = get_embed(input_data, vocab_size, embed_dim)
outputs, final_state = build_rnn(cell, embed) logits = tf.contrib.layers.fully_connected(outputs, vocab_size, activation_fn=None) return logits, final_state

e. 构造batch

这里我们根据batch_size和seq_length分为len//(batch_size*seq_length)个batch,每个batch包含输入和对应的目标输出

def get_batches(int_text, batch_size, seq_length):
'''
构造batch
'''
batch = batch_size * seq_length
n_batch = len(int_text) // batch int_text = np.array(int_text[:batch * n_batch]) # 保留能构成完整batch的数量 int_text_targets = np.zeros_like(int_text)
int_text_targets[:-], int_text_targets[-] = int_text[:], int_text[] # 切分
x = np.split(int_text.reshape(batch_size, -), n_batch, -)
y = np.split(int_text_targets.reshape(batch_size, -), n_batch, -) return np.stack((x, y), axis=) # 组合

模型训练

from tensorflow.contrib import seq2seq
train_graph = tf.Graph()
with train_graph.as_default():
vocab_size = len(int_to_vocab) # vocab_size
input_text, targets, lr = get_inputs() # 输入tensor
input_data_shape = tf.shape(input_text)
# 初始化RNN
cell, initial_state = get_init_cell(input_data_shape[], rnn_size)
logits, final_state = build_nn(cell, rnn_size, input_text, vocab_size, embed_dim)
# 计算softmax层概率
probs = tf.nn.softmax(logits, name='probs')
# 损失函数
cost = seq2seq.sequence_loss(
logits,
targets,
tf.ones([input_data_shape[], input_data_shape[]]))
# 优化函数
optimizer = tf.train.AdamOptimizer(lr)
# Gradient Clipping
gradients = optimizer.compute_gradients(cost)
capped_gradients = [(tf.clip_by_value(grad, -., .), var) for grad, var in gradients if grad is not None]
train_op = optimizer.apply_gradients(capped_gradients)

训练结果

Epoch   Batch   /   train_loss = 0.108
Epoch Batch / train_loss = 0.104
Epoch Batch / train_loss = 0.096
Epoch Batch / train_loss = 0.111
Epoch Batch / train_loss = 0.119
Epoch Batch / train_loss = 0.130
Epoch Batch / train_loss = 0.141
Epoch Batch / train_loss = 0.138
Epoch Batch / train_loss = 0.153
Model Trained and Saved

train_loss还不错,不过可能过拟合了。

最后让我们加载模型,看看生成情况

  # 加载模型
loader = tf.train.import_meta_graph(save_dir + '.meta')
loader.restore(sess, save_dir)
# 获取训练的结果参数
input_text, initial_state, final_state, probs = get_tensors(loaded_graph)
# Sentences generation setup
gen_sentences = [prime_word]
prev_state = sess.run(initial_state, {input_text: np.array([[]])})
# 生成句子
for n in range(gen_length):
dyn_input = [[vocab_to_int[word] for word in gen_sentences[-seq_length:]]]
dyn_seq_length = len(dyn_input[])
# 预测
probabilities, prev_state = sess.run(
[probs, final_state],
{input_text: dyn_input, initial_state: prev_state})
# 选择单词进行文本生成,用来以一定的概率生成下一个词
pred_word = pick_word(probabilities[][dyn_seq_length - ], int_to_vocab)
gen_sentences.append(pred_word)

哎哟不错哦!

最后的最后我还扩大了歌词库,这次引入了更多流行歌手,来看看效果吧。

好像更不错了!

如果你也喜欢杰伦,请点赞并分享生成的歌词。

点击关注,第一时间了解华为云新鲜技术~

除了方文山,用TA你也能帮周杰伦写歌词了的更多相关文章

  1. Spring Data JPA系列5:让IDEA自动帮你写JPA实体定义代码

    大家好,又见面了. 这是本系列的最后一篇文档啦,先来回顾下前面4篇: 在第1篇<Spring Data JPA系列1:JDBC.ORM.JPA.Spring Data JPA,傻傻分不清楚?给你 ...

  2. 几点建议帮你写出简洁的JS代码

    译者按: 规范的代码可以有效避免代码bug,fundebug才会报警少一点! 原文: Tips for Writing Cleaner Code 译者: Fundebug 为了保证可读性,本文采用意译 ...

  3. 推荐4款个人珍藏的IDEA插件!帮你写出不那么差的代码

    @ 目录 Codota:代码智能提示 代码智能补全 代码智能搜索 Alibaba Java Code Guidelines:阿里巴巴 Java 代码规范 手动配置检测规则 使用效果 CheckStyl ...

  4. 帮同事写了几行代码,在 安装/卸载 程序里 注册/卸载 OCX控件

    写了个小控制台程序,这个程序用来注册 / 卸载OCX控件,用在Inno Setup做的安装卸载程序里. #include "stdafx.h" #include <windo ...

  5. C++ 元编程 —— 让编译器帮你写程序

    目录 1 C++ 中的元编程 1.1 什么是元编程 1.2 元编程在 C++ 中的位置 1.3 C++ 元编程的历史 2 元编程的语言支持 2.1 C++ 中的模板类型 2.2 C++ 中的模板参数 ...

  6. 好不容易帮同事写的一个awk,要记下来

    给昌哥写的过滤的东东. 是实现了,但感觉丑,不规范. 记得下先. 原始数据格式: -- :: [ pool--thread-: ] - [ DEBUG ] origin match ::, user: ...

  7. 终于,帮开发写了一个bug

    写在文章的开头 最近项目比较紧,尤其前端的的需求比较多,作为一名测试,也会些vue,本着加快项目进度的美好想法,就自告奋勇的向组长承接了一部分开发的任务,其中有个需求需要在我们的广告管理后台新增一个上 ...

  8. 技术管理进阶——技术Leader如何拒绝业务方?

    原创不易,求分享.求一键三连 前段时间,有个粉丝在群里问了一个问题: 今天对接一个业务团队,要我帮他导数据,这种工作又臭又烦又没成长,而且边界模糊谁做都可以,我很想拒绝他,但又怕引起对方不满,大家有什 ...

  9. emberjs重写补充类之reopen方法和reopenClass方法

    无需一次性将类定义完全,你可以使用reopen方法来重新打开(reopen)一个类并为其定义新的属性. Person.reopen({ isPerson: true }); Person.create ...

随机推荐

  1. 3月28日考试 题解(二分答案+树形DP+数学(高精))

    前言:考试挂了很多分,难受…… --------------------- T1:防御 题意简述:给一条长度为$n$的序列,第$i$个数的值为$a[i]$.现让你将序列分成$m$段,且让和最小的一段尽 ...

  2. 重学c#系列——异常续[异常注意事项](七)

    前言 对上节异常的补充,也可以说是异常使用的注意事项. 正文 减少try catch的使用 前面提及到,如果一个方法没有实现该方法的效果,那么就应该抛出异常. 如果有约定那么可以按照约定,如果约定有歧 ...

  3. python获取系统内存占用信息的实例方法

    psutil是一个跨平台库(http://code.google.com/p/psutil/),能够轻松实现获取系统运行的进程和系统利用率(包括CPU.内存.磁盘.网络等)信息.它主要应用于系统监控, ...

  4. 异步文件通道Java NIO你需要了解多少,来看看这篇文章

    在Java 7,AsynchronousFileChannel 被添加到了Java NIO中.使用AsynchronousFileChannel可以实现异步地读取和写入文件数据. 创建一个Asynch ...

  5. 网易云音乐ncm格式分析以及ncm与mp3格式转换

    目录 NCM格式分析 音频知识简介 两种可能 GitHub项目 格式分析 总体结构 密钥问题 代码分析 main函数 导入模块 dump函数 参考资料 代码完整版 转换工具 ncmdump ncmdu ...

  6. P、NP、NPC问题详解

    转载地址 https://blog.csdn.net/bcb5202/article/details/51202589 P.NP.NPC 概念 > P问题:能够在多项式时间内解决的决策问题. - ...

  7. LeetCode 861翻转矩阵后得分详细解法

    1. 题目内容 有一个二维矩阵 A 其中每个元素的值为 0 或 1 . 移动是指选择任一行或列,并转换该行或列中的每一个值:将所有 0 都更改为 1,将所有 1 都更改为 0. 在做出任意次数的移动后 ...

  8. Java 语法 try catch使用容易忽略的细节 BigDecimal

    try catch使用细节 一. try catch的使用方式容易理解,两者最终都要执行finally中的代码,而当return在try和catch中又会有什么效果? 如果我们做一个简单的例子就会发现 ...

  9. 使用对称加密来加密Spring Cloud Config配置文件

    补充 使用Spring Cloud Config加密功能需要下载JCE扩展,用于生成无限长度的密文.链接:http://www.oracle.com/technetwork/java/javase/d ...

  10. 提升团队幸福感之:集成 GitLab && JIRA 实现自动化工作流

    佛罗伦萨 - 圣母百花圣殿(图) 前言 GitLab 和 Jira 是平时开发过程中使用非常高频的代码管理系统(开发人员)和项目管理系统(项目管理),通过两套系统的协作完成平常大多数的功能开发,但是两 ...