使用LSTM-GAN为歌词谱曲

更新时间:2023-06-08 20:30:33 阅读: 评论:0

使⽤LSTM-GAN为歌词谱曲
在本⽂中,我将⾸先介绍基于AI的⾳乐⽣成的最新发展,然后介绍我创建的系统并讨论其组成,包括Yi Yu等⼈的“Lyrics-to-Melody” AI 模型等。 。 [6]和Google的Music Transformer模型[7]。 然后,我将演⽰⼀个⽰例,该⽰例从(Robert Frost)的诗歌中⽣成歌曲,并介绍其他⽣成的歌曲的集合。
背景
在过去的五个⽉中,我⼀直在研究如何将⼈⼯智能(AI)和机器学习(ML)⽤于创新活动。
尽管最先进的⼈⼯智能模型可以⽣成优秀的图⽚和⽂字,但到⽬前为⽌,⼈⼯智能模型在作曲⽅⾯还没有那么好。有些⾳乐⽣成模型还不错,⽐如⾕歌[3]的various Magenta models,OpenAI[4]的MuNet模型,以及AIVA[5]的商业产品。但⼤多数产⽣AI模型的⾳乐输出往往是杂乱⽆章和不连贯的。似乎缺少的是歌曲的整体结构。让我们看看我们是否可以通过注⼊抒情诗歌来弥补这⼀点。
系统总览
我使⽤的是由Yi Yu和她的同事设计和训练的Lyrics-to-Melody AI模型。他们称之为有条件的LSTM-GA
汽车仪表盘指示N,⽤于从歌词中⽣成旋律[6]。
系统接受了约12K带有歌词的MIDI歌曲进⾏训练。 它使⽤单词及其⾳节作为输⼊,并经过训练以预测⾳乐的⾳符,持续时间和静息持续时间作为输出。 这是对“I’ve Been Working on the Railroad”的五个条形的分析,以黄⾊显⽰输⼊,以蓝⾊显⽰预期输出。 请注意,“day”⼀词之后的其余部分如何与下⼀个⾳节“ I’ve”相关联。
我使⽤的第⼆个主要系统是Music Transformer [7],它是⾕歌的Magenta模型套件的⼀部分。该模型⾃动为给定的旋律⽣成⾳乐伴奏。它训练了作为雅马哈年度电⼦钢琴⽐赛[8]的⼀部分数据,⼤约400个由约翰·塞巴斯蒂安·巴赫的合唱团和1100个由专家钢琴家捕捉的表演。
下⾯是⼀个组件图,它显⽰了整个系统的流程,左边是作为⽂本的⼀⾸诗歌,右边是作为MIDI⽂件⽣成⼀⾸新歌。
每⼀⾏选定的诗被输⼊系统,⼀次⼀⾏。它使⽤⼀个名为Pyphen的模块,使⽤Hunspell连字符字典[9]将⾏中的每个单词分解成⾳节。将结果输⼊到歌词到旋律模型中。 该模型是GAN和长短期记忆(LST
M)模型之间的混合体,⽤来进⾏MIDI格式的⾳符⽣成。
使⽤MIT的Music21库[10]分析所得的乐句,确定其所处的⾳调。然后将该乐句转换为C⼤调(或A Minor),并使⽤Music21量化为⼗六分⾳符。 ⽣成所有⾳乐⾏之后,将⽣成的MIDI⽂件输⼊到Music Transformer模型中,该模型添加⼀个伴随的⾳乐声部,并以具有表现⼒的键盘速度和定时来营造⼈性化的感觉。
最后,使⽤⾕歌的Magenta 库[11]对最终的MIDI⽂件进⾏⼀些后处理,⽐如分配乐器声⾳。
在下⼀节中,我将详细介绍这些步骤,并显⽰为⾃定义处理编写的Python代码。
系统演练
在演练中,我们将使⽤Robert Frost的⼀⾸简短⽽完整的诗歌,称为“Plowmen” [12]。 我将展⽰⽤于将这⾸诗转换为歌曲的Python代码的主要摘要。
准备诗歌
处理的第⼀步涉及将每个单词分解为⾳节,并创建要嵌⼊到LSTM-GAN中的单词嵌⼊。
这是⽰例诗。
**Plowmen
**A plow, they say, to plow the snow.
They cannot mean to plant it, no–
Unless in bitterness to mock
At having cultivated rock.
- Robert Frost
这是将每个单词分解为⾳节并将其输⼊LSTM-GAN的代码段。 您可以看到它使⽤Word2Vec [13]为单词和⾳节创建并输出了嵌⼊内容。Google表⽰:“事实证明,通过Word2Vec学习到的嵌⼊在各种下游⾃然语⾔处理任务上都是成功的。”
dels import Word2Vec
syllModel = Word2Vec.load(syll_model_path)
wordModel = Word2Vec.load(word_model_path)
import pyphen
dic = pyphen.Pyphen(lang='en_US')
poem = '''A plow, they say, to plow the snow.艺术大学
They cannot mean to plant it, no–
Unless in bitterness to mock
At having cultivated rock.'''
lines = poem.split('\n')
for line in lines:
line = re.sub(r'[^a-zA-Z ]+', '', line.strip())
line = re.sub(' +', ' ', line)
words = line.split(' ')
lyrics = []
for word in words:
syllables = dic.inrted(word).split('-')
if len(syllables) > 0:
for syllable in syllables:
if len(syllable) is 0:
continue
lyric_syllables.append(syllable)
if syllable in syllModel.wv.vocab and word in wordModel.wv.vocab:
lyrics.append([syllable, word])
el:
lyrics.append(["la", "la"])
el:
lyric_syllables.append(word)
if len(syllable) is 0:
continue
if word in wordModel.wv.vocab and syllable in syllModel.wv.vocab:
lyrics.append([word, word])
el:
lyrics.append(["la", "la"])
您还可以看到我是如何处理不在字典中的单词的嵌⼊。如果⼀个单词没有在字典⾥,我只需要⽤“la”来代替正确的⾳节数。这是词曲作者的⼀个传统,当他们还没有写完所有的歌词。
这是这⾸诗诗句的⾳节。
A plow, they say, to plow the snow.
都江堰美食
['A', 'plow', 'they', 'say', 'to', 'plow', 'the', 'snow']
They cannot mean to plant it, no–
['They', 'can', 'not', 'mean', 'to', 'plant', 'it', 'no']
Unless in bitterness to mock
['Un', 'less', 'in', 'bit', 'ter', 'ness', 'to', 'la']
At having cultivated rock.
鸡胸肉['At', 'hav', 'ing', 'la', 'la', 'la', 'la', 'rock']
你可以看到单词mock和cultivated变成了la。
⽣成旋律
⼀旦单词和⾳节的嵌⼊设置好了,就很容易产⽣旋律。这⾥的代码。
length_song = len(lyrics)
cond = []
for i in range(20):
if i < length_song:
syll2Vec = syllModel.wv[lyrics[i][0]]
word2Vec = wordModel.wv[lyrics[i][1]]
cond.atenate((syll2Vec, word2Vec)))
el:
cond.atenate((syll2Vec, word2Vec)))
flattened_cond = []
for x in cond:
for y in x:
flattened_cond.append(y)
pattern = generate_melody(flattened_cond, length_song)商务信函格式
length_song变量设置为⽂本⾏传递的⾳节数。 该模型经过硬编码,可以容纳20个⾳节,因此代码将限制输⼊,并在必要时通过重复最后⼀个⾳节来填充输⼊。 注意,该填充将被模型忽略,并且我们将得到⼀个⾳符向量,该⾳符等于⾏中⾳节的数量。 这是旋律。
处理旋律
LSTM-GAN的输出⾮常好,但存在⼀些问题:⾳乐没有量化,⽽且每⼀⾏的键都在变化。LSTM-GAN系统的原始代码具有将旋律“离散化”并将其转置为统⼀键的功能。但是我选择使⽤Music21库来执⾏这些功能。
下⾯的代码显⽰了如何将每个⾳符量化为⼗六分⾳符(第12和13⾏),以及如何将最后⼀个⾳符扩展到⼩节的末尾(第22⾏)。
import music21
def transpo_notes(notes, new_key):
midi_stream = music21.stream.Stream(notes)
key = midi_stream.analyze('key')
interval = music21.interval.ic, ic)
new_stream = anspo(interval)
return s
# quantize the start times and note durations
for c, n in enumerate(pattern):
n.offt = int(float(n.offt)*4+0.5) / 4
n.quarterLength = int(float(n.quarterLength)*4+0.5) / 4
n.offt += song_length
new_notes.append(n)
pattern_length += n.quarterLength
# stretch the last note out to hold the time
pattern_length_adjusted = float(pattern_length-0.125)
new_length = 4 * (1 + pattern_length_adjusted//4)
diff = new_length - float(pattern_length)
new_notes[-1].quarterLength += diff
the_key = music21.key.Key("C") # C Major
# transpo
new_notes = transpo_notes(new_notes, the_key)
您还可以看到如何使⽤Music21(第27⾏在第3⾏调⽤该函数)将每⾏换位到C⼤调中。 这是⽣成的旋律。杨苏安
地漏款式
下⼀步是将旋律传递到Music Transformer以创建⼀个伴随的轨道,并使旋律更⼈性化。这⾥的代码。
model_name = 'transformer'
hparams_t = 'transformer_tpu'
ckpt_path = 'gs://magentadata/models/music_transformer/checkpoints/melody_conditioned_model_16.ckpt'
class MelodyToPianoPerformanceProblem(score2perf.AbsoluteMelody2PerfProblem):
@property
def add_eos_symbol(lf):
漫兴return True
problem = MelodyToPianoPerformanceProblem()
melody_conditioned_encoders = _feature_encoders()
inputs = melody_conditioned_encoders['inputs'].encode_note_quence(melody_ns)
# Generate sample events.
decode_length = 4096
sample_ids = next(melody_conditioned_samples)['outputs']
# Decode to NoteSequence.
midi_filename = decode(
sample_ids,
encoder=melody_conditioned_encoders['targets'])
accompaniment_ns = note_q.midi_file_to_note_quence(midi_filename)
前11⾏代码将设置transformer。代码的其余部分采⽤名为melody_ns的⾳符序列,并⽣成与原旋律合并为伴奏的⾳轨。处理的最后步骤是分配乐器并通过保留最后的⾳符作为额外的措施来创建结尾。 这是最后步骤的代码。
def find_clost_note(n, notes):
clost = None
smallest_diff = float("inf")
for x in notes:
if n.pitch == x.pitch:
diff = abs(n.start_time - x.start_time)
if (diff < smallest_diff):
clost = x
smallest_diff = diff
return clost
for n in s:
n.instrument = 1
n.program = 2 # piano
clost_notes = []
for n in s:
clost_note = find_clost_note(n, s)
clost_note.instrument = 0
clost_note.program = 26 # guitar
clost_notes.append(clost_note)
lyric_times.append(clost_note.start_time)
lyric_pitches.append(clost_note.pitch)
# map to the clost notes in the original melody
for c in range(len(clost_notes)-1):
if (clost_notes[c].end_time > clost_notes[c+1].start_time and
clost_notes[c+1].start_time > clost_notes[c].start_time):
clost_notes[c].end_time = clost_notes[c+1].start_time
# hold the last 5 notes to create an ending
pitches = []
for i in range(1,6):
n = s[-i]
if n.pitch not in pitches:

本文发布于:2023-06-08 20:30:33,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/905361.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:模型   旋律   歌曲   代码   单词   系统
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图