当前位置: 首页 > article >正文

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

这是一个使用 python的 music21 和 TensorFlow/Keras 构建 LSTM 模型生成爵士风格音乐的完整脚本。该脚本包含MIDI数据处理、模型训练和音乐生成全流程:

# -*- coding: utf-8 -*-
"""AI+ music21 和 TensorFlow/Keras 构建LSTM模型生成爵士风格音乐 """
import numpy as np
from music21 import converter, instrument, note, chord, stream
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
from tensorflow.keras.utils import to_categorical# 参数配置
MIDI_FILE = "jazz_samples.mid"  # 爵士风格MIDI训练数据
SEQ_LENGTH = 50                 # 输入序列长度
BATCH_SIZE = 64                 # 训练批次大小
EPOCHS = 50                     # 训练轮数
GENERATE_LENGTH = 200           # 生成音符数量# 1. MIDI数据预处理
def load_midi_data(file_path):"""解析MIDI文件,提取音符和和弦"""notes = []midi = converter.parse(file_path)print(f"Parsing {file_path}...")parts = instrument.partitionByInstrument(midi)if parts:  # 处理多声部文件for part in parts.recurse():if isinstance(part, instrument.Instrument):for element in part.recurse():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))else:      # 处理单声部文件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))return notes# 加载训练数据
notes = load_midi_data(MIDI_FILE)
unique_notes = sorted(set(notes))
note_to_int = dict((note, number) for number, note in enumerate(unique_notes))# 创建训练序列
sequence_in = []
sequence_out = []
for i in range(len(notes) - SEQ_LENGTH):seq_in = notes[i:i + SEQ_LENGTH]seq_out = notes[i + SEQ_LENGTH]sequence_in.append([note_to_int[char] for char in seq_in])sequence_out.append(note_to_int[seq_out])# 数据重塑
X = np.reshape(sequence_in, (len(sequence_in), SEQ_LENGTH, 1))
X = X / float(len(unique_notes))  # 归一化
y = to_categorical(sequence_out)# 2. 构建LSTM模型
model = Sequential([LSTM(256, input_shape=(X.shape[1], X.shape[2])),Dropout(0.3),Dense(128, activation='relu'),Dense(y.shape[1], activation='softmax')
])model.compile(loss='categorical_crossentropy', optimizer='adam')# 3. 训练模型
print("Training model...")
model.fit(X, y, epochs=EPOCHS, batch_size=BATCH_SIZE)# 4. 生成音乐
def generate_music(model, seed_sequence, length, temperature=0.7):"""使用模型生成新音符序列"""int_to_note = dict((number, note) for number, note in enumerate(unique_notes))generated = []pattern = seed_sequence.copy()for _ in range(length):# 预测下一个音符prediction_input = np.reshape(pattern, (1, len(pattern), 1))prediction_input = prediction_input / float(len(unique_notes))prediction = model.predict(prediction_input, verbose=0)[0]# 使用温度采样增加随机性prediction = np.log(prediction) / temperatureexp_preds = np.exp(prediction)probabilities = exp_preds / np.sum(exp_preds)index = np.random.choice(range(len(probabilities)), p=probabilities)result = int_to_note[index]generated.append(result)pattern.append(index)pattern = pattern[1:]  # 滑动窗口return generated# 使用随机种子开始生成
start = np.random.randint(0, len(sequence_in)-1)
seed = sequence_in[start]
generated_notes = generate_music(model, seed, GENERATE_LENGTH)# 5. 转换为MIDI文件
def create_midi(output_notes, filename="jazz_generated.mid"):"""将生成的音符序列转换为MIDI文件"""stream_obj = stream.Stream()for pattern in output_notes:# 处理和弦if '.' in pattern:notes_in_chord = pattern.split('.')chord_notes = []for current_note in notes_in_chord:new_note = note.Note(int(current_note))new_note.storedInstrument = instrument.Piano()chord_notes.append(new_note)new_chord = chord.Chord(chord_notes)stream_obj.append(new_chord)# 处理单音符else:new_note = note.Note(pattern)new_note.storedInstrument = instrument.Saxophone()  # 爵士常用乐器stream_obj.append(new_note)stream_obj.write('midi', fp=filename)print(f"Generated MIDI saved as {filename}")create_midi(generated_notes)

使用说明

  1. 准备训练数据

    • 需要至少1-2个爵士风格的MIDI文件(建议使用钢琴或萨克斯独奏)

    • 推荐数据集:Jazz-Ml-Dataset  Jazz-Ml-Dataset-master.zip
      解压到 D:/Music/Jazz-Ml-Dataset-master/Jazz_Midi/

  2. 环境依赖
    pip install tensorflow
    pip install keras
    pip install music21

  3. 关键功能

    • 自动解析MIDI中的和弦与音符

    • 使用双层LSTM网络学习音乐模式

    • 温度采样控制生成多样性

    • 自动生成萨克斯和钢琴音色组合

  4. 改进方向

    # 更复杂的模型结构
    model = Sequential([LSTM(512, return_sequences=True, input_shape=(X.shape[1], X.shape[2])),Dropout(0.3),LSTM(512),Dense(256, activation='relu'),Dense(y.shape[1], activation='softmax')
    ])# 添加节奏信息处理
    def load_data_with_duration(file_path):notes = []durations = []# 同时提取音符时值信息...# 使用注意力机制
    from tensorflow.keras.layers import Attention
    model.add(Attention())

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

  • 扩展和弦(7th、9th和弦)

  • 即兴旋律走向

  • 摇摆节奏倾向

  • 萨克斯与钢琴音色组合

建议使用Google Colab的GPU加速训练,对于复杂模型和大数据集可以获得更好的生成效果。


1. Sequential 模型的本质

Sequential 是 Keras 中的一种 线性堆叠模型,它允许你通过简单堆叠不同的神经网络层(Layer)来构建模型。你可以将它想象成 搭积木

  • 每一块积木代表一个网络层(如 LSTM、Dense 层等)

  • 积木按顺序叠放,数据从第一层输入,依次传递到最后一层输出

  • 这是构建简单神经网络的最高效方式。


2. 代码示例解析

假设你的代码片段如下:

model = Sequential([LSTM(256, input_shape=(X.shape[1], X.shape[2])),Dropout(0.3),Dense(128, activation='relu'),Dense(y.shape[1], activation='softmax')
])

各层的作用如下:

层类型参数作用
LSTMunits=256核心层,处理时间序列数据。256 表示该层有 256 个记忆单元(可学习复杂模式)
input_shape=(seq_len, 1)输入数据的形状:(时间步长, 特征数)(例如,50 个音符序列 × 1 个特征)
Dropoutrate=0.3随机丢弃 30% 的神经元,防止过拟合(类似让模型不要"死记硬背"训练数据)
Denseunits=128 + ReLU全连接层,将 LSTM 输出压缩到 128 维空间,ReLU 激活函数增加非线性
Denseunits=输出维度 + Softmax最后一层,输出每个可能音符的概率分布(例如,总共有 100 种音符,则输出 100 维概率向量)

3. 为什么用 LSTM?

(2) Dropout 层

(3) Dense 层


5. 模型可视化

假设输入序列长度为 50,模型结构如下:

复制

输入层 (50×1) → LSTM(256) → Dropout → Dense(128) → Dense(输出维度) → 音符概率


6. 模型如何生成音乐?

  • 音乐是时间序列数据:音符的前后顺序包含重要信息(如旋律走向、和弦进行)

  • LSTM 的优势:通过门控机制(输入门、遗忘门、输出门)记忆长期依赖关系,适合生成连贯的音乐片段。

  • 若想要更复杂的模型,可以堆叠多层 LSTM:

    model = Sequential([LSTM(256, return_sequences=True, input_shape=(X.shape[1], X.shape[2])),LSTM(512),  # 第二层 LSTMDropout(0.3),Dense(128, activation='relu'),Dense(y.shape[1], activation='softmax')
    ])
    
  • return_sequences=True 表示第一层 LSTM 返回完整序列(非仅最后输出),供下一层 LSTM 使用。

  • 4. 关键参数详解

    (1) LSTM 层
  • units=256:记忆单元数量,数值越大模型容量越高(但可能过拟合)

  • input_shape:必须指定输入数据的形状(模型第一层专用参数)

    • 例如 (50, 1) 表示输入 50 个时间步(音符),每个时间步 1 个特征(音高编码)

  • rate=0.3:训练时随机关闭 30% 的神经元,强制模型学习冗余特征(提高泛化性)

  • activation='softmax':将输出转化为概率分布(总和为 1),适合多分类任务(预测下一个音符)

  • 输入:形状为 (batch_size, 50, 1) 的序列数据

  • 输出:形状为 (batch_size, 输出维度) 的概率向量

  • 训练阶段:模型学习输入序列(如 [C4, E4, G4])到目标音符(如 C5)的映射关系。

  • 生成阶段

    • 给定初始序列(如 [C4, E4]

    • 模型预测下一个音符的概率分布

    • 根据概率采样得到新音符(如 G4

    • 将新音符加入序列,重复预测(类似自动续写)


总结

model = Sequential([...]) 是构建神经网络的核心声明,通过合理设计层结构和参数,你可以让模型学会生成具有爵士乐特征的音乐(如复杂的和弦进行、摇摆节奏)。理解每一层的数学含义和参数作用,是调优模型的关键。

相关文章:

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

这是一个使用 python的 music21 和 TensorFlow/Keras 构建 LSTM 模型生成爵士风格音乐的完整脚本。该脚本包含MIDI数据处理、模型训练和音乐生成全流程: # -*- coding: utf-8 -*- """AI music21 和 TensorFlow/Keras 构建LSTM模型生成爵士风格音乐 …...

vscode查看文件历史git commit记录

方案一:GitLens 在vscode扩展商店下载GitLens 选中要查看的文件,vscode界面右上角点击GitLens的图标,选择Toggle File Blame 界面显示当前打开文件的所有修改历史记录 鼠标放到某条记录上,可以看到记录详情,选中O…...

使用netDxf扩充LaserGRBL使它支持Dxf文件格式

为 LaserGRBL 扩展支持 DXF 文件格式,需要了解 LaserGRBL 的代码结构,并在其基础上添加 DXF 文件的解析和转换逻辑。以下是详细的扩展方案: 1. 了解 LaserGRBL LaserGRBL 是一个用于控制激光雕刻机的开源软件,支持 G 代码文件的加…...

GaussDB备份数据常用命令

1、常用备份命令gs_dump 说明:是一个服务器端工具,可以在线导出数据库的数据,这些数据包含整个数据库或数据库中指定的对象(如:模式,表,视图等),并且支持导出完整一致的数…...

数学建模 第三节

目录 前言 一 钻井布局问题 第一问分析 第二问分析 总结 前言 这里讲述99年的钻井布局问题,利用这个问题讲述模型优化,LINGO,MATLAB的使用 一 钻井布局问题 这个是钻井布局的原题,坐标的位置为 a [0.50,1.41,3.00,3.37,3…...

单调队列【C/C++】

当我在网上搜索了一大堆单调队列的文章后, 我人傻了!? 单调队列不应该很难吗?? 不应该是,像 优先队列 那样,站在 堆 的肩膀上,极尽升华吗??? …...

Spark DataFrame、Dataset 和 SQL 解析原理深入解析(万字长文多张原理图)

目录 1. Spark SQL 概述 1.1 Spark 整体架构概览 1.2 DataFrame 与 Dataset 简介 2. RDD 与 Spark 的分布式架构基础 2.1 弹性分布式数据集(RDD) 2.2 Spark 的分布式执行模型 3. SQL 解析流程与 Catalyst 优化器 3.1 SQL 解析流程概述 3.2 解析阶段与抽象语法树(AST…...

算法系列——有监督学习——3.逻辑回归

一、概述 逻辑回归是一种学习某个事件发生概率的算法。利用这个概率,可以对某个事件发生或不发生进行二元分类。虽然逻辑回归本来是二元分类的算法,但也可以用于三种类别以上的分类问题。为了理解这个算法,请思考以下例子。 你在回家的路上发…...

深入理解traceroute命令及其原理

traceroute 是一个网络诊断工具(Windows上叫tracert),用于显示数据包从本地主机到远程主机经过的路由(跳数)。它可以帮助您了解数据包在网络中的传输路径,以及每跳的延迟情况。这对于网络故障排除、分析网络…...

前后端联调解决跨域问题的方案

引言 在前后端分离的开发模式中,前端和后端通常在不同的服务器或端口运行,这样就会面临跨域问题。跨域问题是指浏览器因安全限制阻止前端代码访问与当前网页源不同的域、协议或端口的资源。对于 Java 后端应用,我们可以通过配置 CORS&#x…...

深入解析 .NET 中的依赖项加载机制:原理、实现与最佳实践

在现代应用程序的开发中,依赖项管理与加载是非常重要的组成部分,尤其是在大型系统中,如何高效地加载和管理依赖项可以极大地影响应用程序的性能、可维护性和扩展性。在 .NET 中,依赖项加载不仅涉及静态依赖的管理,还包…...

【vue2 + Cesium】相机视角移动+添加模型、模型点击事件

参考文章:vue2 使用 cesium 【第二篇-相机视角移动添加模型】 这篇文章在上篇文章的基础上继续开发,主要实现效果 相机视角移动 添加模型 点击事件 上篇文章:【vue2 Cesium】使用Cesium、添加第三方地图、去掉商标、Cesium基础配置、地…...

【AI】AI编程助手:Cursor、Codeium、GitHub Copilot、Roo Cline、Tabnine

文章目录 一、基本特性对比二、收费标准三、私有部署能力1、Tabnine2、Roo Code 三、代码补全与自然语言生成代码四、安装独立的IDE安装插件安装 五、基本使用(一)Cursor(二)GitHub Copilot1、获取代码建议2.聊天1)上下…...

我的uniapp自定义模板

uniapp自定义模板 如有纰漏请谅解,以官方文档为准后面这段时间我会学习小程序开发的知识,会持续更新可以查看我的github,后续我会上传我的uniapp相关练习代码有兴趣的话可以浏览我的个人网站,我会在上面持续更新内容,…...

如何将MediaPipe编译成Android中Chaquopy插件可用的 .whl 文件

环境准备 操作系统:建议使用 Ubuntu 20.04 或者 macOS(这篇博客会以 Ubuntu 为例)。Python 版本:Python 3.7 或以上版本。Android Studio:配置好 Android Studio 和 Android NDK(Native Development Kit&a…...

华为OD机试-绘图机器-双指针(Java 2025 A卷 100分)

题目描述 绘图机器的绘图笔初始位置在原点 (0, 0)。机器启动后按照以下规则绘制直线: 尝试沿着横坐标正向绘制直线,直到给定的终点 E。期间可以通过指令在纵坐标轴方向进行偏移,offsetY 为正数表示正向偏移,为负数表示负向偏移。给定的横坐标终点值 E 以及若干条绘制指令,…...

【C++】动态规划从入门到精通

一、动态规划基础概念详解 什么是动态规划 动态规划(Dynamic Programming,DP)是一种通过将复杂问题分解为重叠子问题,并存储子问题解以避免重复计算的优化算法。它适用于具有以下两个关键性质的问题: 最优子结构&…...

OpenCV计算摄影学(23)艺术化风格化处理函数stylization()

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 风格化的目的是生成不以照片写实为目标的多种多样数字图像效果。边缘感知滤波器是风格化处理的理想选择,因为它们能够弱化低对比度区…...

S32K144外设实验(三):ADC单通道连续采样(中断)

这次的实验比较简单,主要目的就是验证一下ADC的中断功能,思路是使用软件触发ADC的连续单通道采样,将采样值通过串口发送到上位机观察数是否正确。 其实官方并不推荐使用中断的方式,这种方式会占用大量的CPU资源,笔者安…...

LeetCode 第19~21题

LeetCode 第19题:删除链表的倒数第N个结点 题目描述 给你一个链表,删除链表的倒数第n个结点,并且返回链表的头结点。 难度:中等 题目链接:19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode) 示例…...

Web3 时代数据保护的关键挑战与应对策略

Web3 时代数据保护的关键挑战与应对策略 随着互联网技术的飞速发展,我们正步入 Web3 时代,这是一个以去中心化、用户主权和数据隐私为核心的新时代。在这个时代,数据保护成为了一个至关重要的议题。本文将探讨 Web3 时代数据保护面临的主要挑…...

为什么labelme框选图片后闪退

Labelme 软件框选图片后闪退的解决方案 Labelme 是一种常用的图像标注工具,但在实际使用过程中可能会遇到一些问题,比如框选图片后程序突然闪退。以下是针对该问题的具体分析和解决方法: 可能原因及对应解决措施 标签文件异常 如果某些图片…...

‌C# I/O 核心用法

在 C# 中,输入输出(I/O)操作是处理文件、目录、流等数据交互的核心功能。本文将从基础到高级,系统讲解 C# 中文件 I/O 的实现方式、最佳实践及常见场景解决方案。 一、核心类与命名空间‌ 1‌、System.IO 命名空间‌&#xff0c…...

SpringBoot之如何集成SpringDoc最详细文档

文章目录 一、概念解释1、OpenAPI2、Swagger3、Springfox4、Springdoc5. 关系与区别 二、SpringDoc基本使用1、导包2、正常编写代码,不需要任何注解3、运行后访问下面的链接即可 三、SpringDoc进阶使用1、配置文档信息2、配置文档分组3、springdoc的配置参数**1. 基…...

Oracle 数据迁移至 GaussDB 注意事项

将数据从 Oracle 迁移到 GaussDB(华为分布式数据库)时,需充分考虑架构差异、语法兼容性、数据一致性等核心问题。以下是关键注意事项及操作建议: 一、迁移前的准备工作 兼容性评估 语法差异:Oracle 使用 PL/SQL&#x…...

【智能体】| 知识库、RAG概念区分以及智能体是什么

文章目录 前言简介大模型“幻觉”问题如何解决“幻觉”问题? RAG、智能体、RAG智能体概念什么是检索增强型生成(RAG)模拟简单的RAG场景 AI系统中的智能体是什么什么是Agentic RAG?Agentic RAG如何工作?Agentic RAG架构…...

二分查找的应用

什么时候用二分查找&#xff1f; 数据具有二段性的时候 第一题&#xff1a; 题解代码&#xff1a; class Solution { public:int search(vector<int>& nums, int target) {int left 0,right nums.size()-1;while(left<right){int mid left (right-left)/2;//中…...

Android Compose 框架基础按钮模块深度剖析(四)

Android Compose 框架基础按钮模块深度剖析 一、引言 在现代 Android 应用开发中&#xff0c;Android Compose 框架以其声明式编程范式和简洁高效的开发体验&#xff0c;逐渐成为开发者构建用户界面的首选。而注解在 Android Compose 框架中扮演着至关重要的角色&#xff0c;…...

redis搭建一主一从+keepalived(虚拟IP)实现高可用

redis搭建一主一从keepalived(虚拟IP)实现高可用 前提 有两台机器&#xff1a;如 10.50.3.141 10.50.3.142&#xff0c;虚拟ip如&#xff1a;10.50.3.170 安装redis&#xff08;两台机器执行&#xff09;: # 启用Remi仓库&#xff08;CentOS 7&#xff09; sudo yum install…...

【Function】Azure Function通过托管身份或访问令牌连接Azure SQL数据库

【Function】Azure Function通过托管身份或访问令牌连接Azure SQL数据库 推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战目录 【Function】Azure Function通过托管身份或访问令牌连接Azu…...