python:music21 构建 LSTM+GAN 模型生成爵士风格音乐

keras_lstm_gan_midi.py 这是一个结合 LSTM 和 GAN 生成爵士风格音乐的完整Python脚本。这个实现包含音乐特征提取、对抗训练机制和MIDI生成功能:

import numpy as np
from music21 import converter, instrument, note, chord, stream
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import (LSTM, Dense, Dropout, Input, Embedding, Reshape, Bidirectional, Conv1D, Flatten)
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.utils import to_categorical# 配置参数
MIDI_FILE = "jazz_swing.mid"  # 爵士训练数据
SEQ_LENGTH = 32               # 序列长度
NOISE_DIM = 100               # 噪声向量维度
BATCH_SIZE = 64
EPOCHS = 2000
STEPS_PER_EPOCH = 50
SAVE_INTERVAL = 100class JazzGAN:def __init__(self, vocab_size):self.vocab_size = vocab_sizeself.seq_length = SEQ_LENGTHself.noise_dim = NOISE_DIM# 构建模型self.generator = self.build_generator()self.discriminator = self.build_discriminator()self.gan = self.build_gan()# 配置优化器self.d_optimizer = Adam(0.0002, 0.5)self.g_optimizer = Adam(0.0001, 0.5)def build_generator(self):"""构建LSTM生成器"""model = Sequential([Input(shape=(self.noise_dim,)),Dense(256),Reshape((1, 256)),LSTM(512, return_sequences=True),Dropout(0.3),LSTM(256),Dense(self.vocab_size, activation='softmax')])return modeldef build_discriminator(self):"""构建CNN-LSTM判别器""" model = Sequential([Input(shape=(self.seq_length,)),Embedding(self.vocab_size, 128),Conv1D(64, 3, strides=2, padding='same'),Bidirectional(LSTM(128)),Dense(64, activation='relu'),Dropout(0.2),Dense(1, activation='sigmoid')])return modeldef build_gan(self):"""组合GAN模型"""self.discriminator.trainable = Falsegan_input = Input(shape=(self.noise_dim,))generated_seq = self.generator(gan_input)validity = self.discriminator(generated_seq)return Model(gan_input, validity)def preprocess_midi(self, file_path):"""处理MIDI数据"""notes = []midi = converter.parse(file_path)print("Extracting notes...")for element in midi.flat.notes:if isinstance(element, note.Note):notes.append(str(element.pitch))elif isinstance(element, chord.Chord):notes.append('.'.join(str(n) for n in element.normalOrder))# 创建字典映射unique_notes = sorted(set(notes))self.note_to_int = {n:i for i, n in enumerate(unique_notes)}self.int_to_note = {i:n for i, n in enumerate(unique_notes)}self.vocab_size = len(unique_notes)# 转换为整数序列int_sequence = [self.note_to_int[n] for n in notes]# 创建训练序列sequences = []for i in range(len(int_sequence) - self.seq_length):seq = int_sequence[i:i+self.seq_length]sequences.append(seq)return np.array(sequences)def train(self, X_train):# 标签平滑valid = np.ones((BATCH_SIZE, 1)) * 0.9fake = np.zeros((BATCH_SIZE, 1))for epoch in range(EPOCHS):# 训练判别器idx = np.random.randint(0, X_train.shape[0], BATCH_SIZE)real_seqs = X_train[idx]noise = np.random.normal(0, 1, (BATCH_SIZE, self.noise_dim))gen_seqs = self.generator.predict(noise)d_loss_real = self.discriminator.train_on_batch(real_seqs, valid)d_loss_fake = self.discriminator.train_on_batch(gen_seqs, fake)d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)# 训练生成器noise = np.random.normal(0, 1, (BATCH_SIZE, self.noise_dim))g_loss = self.gan.train_on_batch(noise, valid)# 输出训练进度if epoch % 100 == 0:print(f"Epoch {epoch} | D Loss: {d_loss[0]} | G Loss: {g_loss}")# 保存示例if epoch % SAVE_INTERVAL == 0:self.generate_and_save(epoch)def generate_and_save(self, epoch):"""生成示例音乐"""noise = np.random.normal(0, 1, (1, self.noise_dim))generated = self.generator.predict(noise)generated_indices = np.argmax(generated, axis=-1)# 转换为音符output_notes = []for idx in generated_indices[0]:output_notes.append(self.int_to_note[idx])# 创建MIDI流midi_stream = stream.Stream()for pattern in output_notes:# 添加爵士和弦扩展if '.' in pattern:notes_in_chord = pattern.split('.')chord_notes = [note.Note(int(n)) for n in notes_in_chord]# 添加7th扩展if len(chord_notes) == 3:root = chord_notes[0].pitchchord_notes.append(root.transpose(10))new_chord = chord.Chord(chord_notes)midi_stream.append(new_chord)else:new_note = note.Note(int(pattern))new_note.storedInstrument = instrument.Saxophone()midi_stream.append(new_note)# 添加摇摆节奏self.add_swing_rhythm(midi_stream)midi_stream.write('midi', fp=f'jazz_gan_{epoch}.mid')print(f"Saved sample at epoch {epoch}")def add_swing_rhythm(self, stream_obj):"""添加爵士摇摆节奏"""for i, n in enumerate(stream_obj.flat.notes):if i % 2 == 1:  # 每两个音符中的第二个n.offset += 0.08  # 轻微延迟if isinstance(n, note.Note):n.duration.quarterLength *= 0.9if __name__ == "__main__":# 初始化并预处理数据gan = JazzGAN(vocab_size=0)  # 初始占位sequences = gan.preprocess_midi(MIDI_FILE)# 训练GANgan.train(sequences)

使用说明:

  1. 准备数据

    • 需要至少10-20个爵士MIDI文件(建议包含钢琴三重奏、大乐队等风格)

    • 推荐数据集:Jazzomat Research Project

  2. 环境配置
    pip install tensorflow
    pip install music

实现亮点说明:

1.模型架构改进

  1. 混合架构设计

    • 生成器:使用双层LSTM结构,适合处理音乐时序特征

    • 判别器:结合CNN和BiLSTM,有效捕捉局部与全局模式

    • 加入Embedding层处理离散音符符号

  2. 爵士特征增强

    # 在和弦中自动添加7th音
    if len(chord_notes) == 3:root = chord_notes[0].pitchchord_notes.append(root.transpose(10))# 摇摆节奏处理
    n.offset += 0.08
    n.duration.quarterLength *= 0.9
    
  3. 训练优化技巧

    • 使用标签平滑(Label Smoothing)提升判别器鲁棒性

    • 分离生成器和判别器的学习率(0.0001 vs 0.0002)

    • 定期保存生成样本监控训练进度

  4.  训练建议

    • 使用GPU加速(至少需要8GB显存)

    • 初始阶段设置EPOCHS=500 以获得较好效果

    • 调整SEQ_LENGTH(32-64)匹配音乐片段长度

  5. 生成样本后处理

    • 使用DAW(如 Ableton Live)添加爵士乐器的真实音色

    • 人工调整和声进行确保功能性(II-V-I等典型进行)

性能优化方向

  1. 模型架构改进

    # 在生成器加入注意力机制
    from tensorflow.keras.layers import Attentiondef build_generator(self):inputs = Input(shape=(self.noise_dim,))x = Dense(256)(inputs)x = Reshape((1, 256))(x)x = LSTM(512, return_sequences=True)(x)x = Attention()([x, x])  # 自注意力x = LSTM(256)(x)outputs = Dense(self.vocab_size, activation='softmax')(x)return Model(inputs, outputs)
    

    2.数据增强: 

    # 实时数据增强
    def augment_sequence(seq):# 随机转调if np.random.rand() > 0.5:shift = np.random.randint(-3, 4)seq = (seq + shift) % self.vocab_size# 随机节奏缩放return seq
    

该脚本生成的爵士音乐将具备以下特征:

  • 复杂的和弦扩展(7th、9th、11th)

  • 摇摆节奏(Swing Feel)

  • 即兴化的旋律走向

  • 符合爵士和声进行规则(如替代和弦使用)

建议配合使用MIDI效果器(如iReal Pro的和声引擎)进行后期处理,可以获得更专业的爵士乐效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/38070.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

redis集群的原理是什么?

大家好,我是锋哥。今天分享关于【redis集群的原理是什么?】面试题。希望对大家有帮助; redis集群的原理是什么? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Redis 集群(Redis Cluster)是一种分布式解决方案&…

PicFlow:一个图片处理与上传工作流工具(图床上传工具)

自从学习搭建网站以来,我就把很多图片托管在七牛云等图床平台上。以前总是通过网页批量上传,需要登录并一步步跳转网页操作,久而久之就厌烦了,于是花了一天时间用 Python 写了一个工具 —— PicFlow,从名字可以看出&am…

常⻅CMS漏洞之一:WordPress

WordPress是⼀个以PHP和MySQL为平台的⾃由开源的博客软件和内容管理系统。WordPress具有插件架构和模板系统。截⾄2018年4⽉,排名前1000万的⽹站中超过30.6%使⽤WordPress。 WordPress是最受欢迎的⽹站 内容管理系统。全球有⼤约30%的⽹站(7亿5000个)都是使⽤WordP…

一文说清预训练与微调:AI的双重训练法则

什么是预训练? 预训练是大型语言模型训练的第一步。它在资金和计算能力的支持下,通过深入分析大量的文本数据,使模型建立起语言的基本构架。在这一阶段,模型通过学习海量的书籍、文章和网页,识别出语言的语法、句法和…

【TI MSPM0】Timer学习

一、计数器 加法计数器:每进入一个脉冲,就加一减法计算器:每进入一个脉冲,就减一 当计数器减到0,触发中断 1.最短计时时间 当时钟周期为1khz时,最短计时时间为1ms,最长计时时间为65535ms 当时…

Vue 中的日期格式化实践:从原生 Date 到可视化展示!!!

📅 Vue 中的日期格式化实践:从原生 Date 到可视化展示 🚀 在数据可视化场景中,日期时间的格式化显示是一个高频需求。本文将以一个邀请码关系树组件为例,深入解析 Vue 中日期格式化的 核心方法、性能优化 和 最佳实践…

C语言的数据类型与变量(完整版)

目录 一、基本数据类型 (一)字符类型 (二)整数类型 1、短整型 — short 2、整型 — int 3、长整型 — long 4、长长整型 — long long (三)布尔类型 (四)浮点类型 1、单精…

免费下载 | 2025低空经济产业发展报告

低空经济概览 产业链条:低空经济产业链分为上游的低空经济基础设施(如空管系统、飞行基地等)、中游的低空制造(包括无人机、eVTOL、直升机等飞行器的设计、研发、生产)和下游的低空运营及飞行服务。低空经济以低空空域…

git_version_control_proper_practice

git_version_control_proper_practice version control,版本控制的方法之一就是打tag 因为多人协作的项目团队,commit很多,所以需要给重要的commit打tag,方便checkout,检出这个tag 参考行业的实践方式。如图git、linux…

金桔网桥连载4-详解

上一节我讲到小王升职加薪,越活越年轻,然后我们的网络就成这样的 如果继续往下进行网络扩展,恐怕看的人就越看越糊涂,如果一篇文章看到人越少,那么存在的价值越小,使我想起了每年一部的梦工厂电影&#xff…

从GTC2025首次量子日看英伟达量子AI融合算力网络前景与趋势

GTC2025 Quantum Day 最新内容全部汇总: 技术名称描述合作伙伴/开发者应用场景/目标量子模拟器优化方案NVIDIA与IonQ、D-Wave合作,针对量子模拟器进行性能优化,提升量子计算任务效率。IonQ、D-Wave量子算法开发、复杂系统模拟混合量子-经典计算架构结合量子计算与经典GPU加速…

24.map和set的使用

一、序列式容器和关联式容器 序列式容器:逻辑结构为线性序列的容器,两个位置所存放的数据一般没有紧密关系,例如两个位置交换一下,逻辑结构没有改变。 关联式容器:通常是非线性结构(堆例外)&…

免费Typora1.8.6安装教程

🌟 Typora - 极简主义的 Markdown 编辑器免费指南 🌟 📌 什么是 Typora? Typora 是一款广受好评的 **所见即所得** 的 Markdown 编辑器,以极致简洁的界面和流畅的写作体验闻名。它让 Markdown 写作变得像使用 Word 一…

元音辅音及其字母组合发音

文章目录 单元音长元音/ɑː//ɔ://u://i://ɜː/// 短元音/ʌ//ɒ//ʊ//ɪ//ə//e/ 双元音/eɪ//aɪ//ɔɪ//ɪə//eə//ʊə//əʊ//aʊ/ 辅音3个鼻辅音m n ŋ 5个独立浊辅音w j r l h 20个清浊相对的辅音s zʃ ʒf vθ p bt dk gts dztʃ dʒtr dr 以下是列举的部分字母组合…

基于FPGA频率、幅度、相位可调的任意函数发生器(DDS)实现

基于FPGA实现频率、幅度、相位可调的DDS 1 摘要 直接数字合成器( DDS ) 是一种通过生成数字形式的时变信号并进行数模转换来产生模拟波形(通常为正弦波)的方法,它通过数字方式直接合成信号,而不是通过模拟信号生成技术。DDS主要被应用于信号生成、通信系统中的本振、函…

C++调用ffmpeg解复用、解码案例

框架 一个封装文件(mp4)如何播放?大体流程如下: 案例 本案例实现在windows环境下,调用ffmpeg4.4.5动态库实现上述从解封装、视频解码、音频解码的全部过程,案例测试通过。由于ffmpeg接口功能网上资料较多&a…

Linux(进程)

一.冯诺依曼体系结构 输入设备:键盘,鼠标,话筒,摄像头...网卡,磁盘 输出设备:显示器,磁盘,网卡,打印机 外设:输入设备输出设备 cpu(中央处理器&am…

[极客大挑战 2019]BabySQL—3.20BUUCTF练习day4(3)

[极客大挑战 2019]BabySQL-3.20BUUCTF练习day4(3) 做题过程 打开是以下页面(前几天有它的第一版和第二版出现)输入1’ 回显以下内容(还是字符型以单引号闭合,因为有报错信息回显) 输入1 order by 4%23回显成这个 被过…

[Effective C++]条款20:宁以 pass-by-reference-to-const替换 pass-by-value

. 在C中,函数参数与返回值的数据传递的方式,对程序的性能和正确性有着重要影响。C默认使用pass-by-value(传值)的方式传递参数。但这种方式在某些情况下会导致性能问题和对象切割问题。 C推荐使用pass-by-reference-to-const&…

文字变央视级语音转换工具

大家在制作短视频、广告宣传、有声读物、自媒体配音、学习辅助等场景的时候,经常会需要用到配音来增强视频的表现力和吸引力。然而,市面上的一些配音软件往往需要收费,这对于很多初学者或者预算有限的朋友来说,无疑增加了一定的负…