周杰伦几乎陪伴了每个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. C笔记-左值与右值

    目录 前言:工欲善其事,必先利其器 两种资料 参考资料及其使用说明 官方对于左值和右值的定义 实际使用时的疑问 左值的涵盖范围 重要概念: 左值转化(lvalue conversion) 左值与指针 ...

  2. Python网络数据采集PDF高清完整版免费下载|百度云盘|Python基础教程免费电子书

    点击获取提取码:jrno 内容提要 本书采用简洁强大的 Python 语言,介绍了网络数据采集,并为采集新式网络中的各种数据类 型提供了全面的指导.第一部分重点介绍网络数据采集的基本原理:如何用 Py ...

  3. POJ 2443 Set Operation 题解

    本文同时发布于 博客园 洛谷博客 题目链接 题目分析 给你n个集合,每个集合里面都有可能会重复的数字 q个询问,每次询问两个数是否会在同一集合内 $n<=1000$ $q<=200000$ ...

  4. day17.json模块、时间模块、zipfile模块、tarfile模块

    一.json模块 """ 所有的编程语言都能够识别的数据格式叫做json,是字符串 能够通过json序列化成字符串与如下类型: (int float bool str l ...

  5. MyFirstJavaWeb

    源代码: Register.jsp <%@ page language="java" contentType="text/html; charset=utf-8&q ...

  6. akka-typed(9) - 业务分片、整合,谈谈lagom, 需要吗?

    在讨论lagom之前,先从遇到的需求开始介绍:现代企业的it系统变得越来越多元化.复杂化了.线上.线下各种系统必须用某种方式集成在一起.从各种it系统的基本共性分析:最明显的特征应该是后台数据库的角色 ...

  7. 谁先执行?props还是data或是其他? vue组件初始化的执行顺序详解

    初入vue的朋友可能会疑惑,组件初始化的时候,created,props,data到底谁先执行? 今天,我就带大家从源码的角度看看到底谁先执行? 我们知道,vue是个实例 那我们就从new Vue() ...

  8. 在java中,怎样创建编写javascript的环境?

    刚开始还没有学到这一块的时候,预习的时候也是在网上搜索这一类的信息时候, 可是都是八竿子碰不到边的!在此也是呕心沥血的为读者献上最好的: 1.首先:点击空白处>右键>project: 2. ...

  9. Windows10 + Ubuntu 20.04 LTS 双系统安装 (UEFI + GPT)(图文,多图预警)

    版权声明:本文为CSDN博主「ZChen1996」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/ZChen1 ...

  10. Mybatis如何在插入(ID是后台生成的)后返回ID?

    获得ID方法: