目录
LSTM 机器学习生成音乐 1
数据集介绍 1
将 mid 转成 note 数组 4
将 note 数组转成 mid 文件 5
获取数据集并将其保存 6
将 note 进行编号 7
构建数据集 8
截取数据 8
进行 one-hot 编码 10
构建模型 11
训练 13
生成音乐 13
加载数据 16
加载模型 16
构建 id 与 note 的映射 16
预测下一个 note 16
源源不断产生 note 数据 17
生成音乐 20
总结 20
参考 20
将 mid 转成 note 数组
下面定义get_notes,通过这个函数,我们可以将文件夹中所有mid文件变成一个名为all_note的数组。
关于具体怎么转化,实际上我们没有必要去关心,这个函数也是直接 copy 基于深度学习 lstm 算法生成音乐的,直接用即可。
from music21 import converter, instrument, note, chord, stream
def get_notes(song_path,song_names):
“”“获得midi音乐文件中的音符 :param song_path: [文件的保存地址] :type song_path: [str] :param song_names: [所有音乐文件的文件名] :type song_names: [list] :return: [所有符合要求的音符] :rtype: [list] “””
all_notes = []
for song_name in song_names:
stream = converter.parse(song_path+song_name)
instru = instrument.partitionByInstrument(stream)
if instru: # 如果有乐器部分,取第一个乐器部分
notes = instru.parts[0].recurse()
else: #如果没有乐器部分,直接取note
notes = stream.flat.notes
for element in notes:
# 如果是 Note 类型,取音调
# 如果是 Chord 类型,取音调的序号,存int类型比较容易处理
if isinstance(element, note.Note):
all_notes.append(str(element.pitch))
elif isinstance(element, chord.Chord):
all_notes.append(‘.’.join(str(n) for n in element.normalOrder))
return all_notes
将 note 数组转成 mid 文件
既然可以将mid文件转化成note数组,同理,也可以将note数组转成mid文件(也就是音乐)。定义一个create_music函数,同理这个函数也是copy基于深度学习lstm算法生成音乐的,同样也不需要关心其如何实现。
create_music函数在使用模型生成音乐的时候会用到(到后面看到的时候别懵逼了哦!!!!)。
def create_music(result_data,filename):
“”“生成mid音乐,然后进行保存 :param result_data: [音符列表] :type result_data: [list] :param filename: [文件名] :type filename: [str] “””
result_data = [str(data) for data in result_data]
offset = 0
output_notes = []
# 生成 Note(音符)或 Chord(和弦)对象
for data in result_data:
if (‘.’ in data) or data.isdigit():
notes_in_chord = data.split(‘.’)
notes = []
for current_note in notes_in_chord:
new_note = note.Note(int(current_note))
new_note.storedInstrument = instrument.Piano()
notes.append(new_note)
new_chord = chord.Chord(notes)
new_chord.offset = offset
output_notes.append(new_chord)
else:
new_note = note.Note(data)
new_note.offset = offset
new_note.storedInstrument = instrument.Piano()
output_notes.append(new_note)
offset += 1
# 创建音乐流(Stream)
midi_stream = stream.Stream(output_notes)
# 写入 MIDI 文件
midi_stream.write('midi', fp=filename+'.mid')
获取数据集并将其保存
通过前面的介绍,调用get_notes将使用music21库将文件夹中所有的mid文件变成一个note数组,但实际上这个过程是比较慢的,因此可以在第一次的时候将转换后的note数组保存起来,下面定义分别定义保存和读取的函数:
def save_data(filename,content):
“”“保存音符 :param filename: [保存的文件名] :type filename: [str] :param content: [内容] :type content: [list]] “””
with open(filename,“w”) as f:
for data in content:
f.write(str(data)+“\n”)
def get_data(filename):
“”“从文件中获取音符 :param filename: [文件名] :type filename: [str] :return: [返回音符] :rtype: [list] “””
with open(filename) as f:
all_notes = f.readlines()
return [ note[:len(note)-1] for note in all_notes]
接下来就是调用以上几个函数:将mid文件转成note数组——>将note数组进行保存。
import ossong_path = "./midi_songs/"song_names = os.listdir(song_path)
获取note数组all_notes = get_notes(song_path,song_names)# 保存文件save_data(“data.txt”,all_notes)