Как мы учим нейросеть понимать музыку, генерировать ее и сохранять в файл, чтобы послушать!
Ты включаешь музыку — и слышишь мелодию. А теперь представь: нейросеть тоже «слышит» музыку, запоминает её — и потом сочиняет свою! 🤯
💡 Мы создадим такую нейросеть с нуля. И начнём с самого первого шага — подготовим музыку в удобный формат для обучения, обучим модель и, наконец, сгенерируем первую композицию!
Открой терминал (или командную строку) и напиши:
pip install music21
📦 Это библиотека music21
. Она как музыкальный переводчик:
читает .mid
файлы (в них — музыка),
вытаскивает ноты и аккорды,
позволяет сохранять и создавать новые мелодии.
Это наш помощник, чтобы превратить музыку в данные, понятные для Python и нейросети.
Чтобы ИИ учился сочинять, ему нужны примеры. Как ребёнку: сначала он слушает, как поют взрослые, и только потом начинает напевать сам 🎵
🎼 Нам подойдут MIDI-файлы
— это такие «музыкальные черновики», где записано, какие ноты играются, в каком порядке и как долго.
🔍 Где взять?
Зайди на сайт вроде https://bitmidi.com
Скачай несколько мелодий (например, Бах или Бетховен)
Создай у себя рядом с кодом папку с именем midi_songs
Помести туда файлы с расширением .mid
Теперь — код. Он будет читать все MIDI-файлы, вытаскивать ноты и складывать их в список. Вот полный пример:
from music21 import converter, note, chord
import glob
notes = []
# Проходим по всем файлам в папке midi_songs
for file in glob.glob("midi_songs/*.mid"):
# Загружаем файл как музыкальное произведение
midi = converter.parse(file)
# Достаём все ноты и аккорды, игнорируя инструменты
elements = midi.flat.notes
for element in elements:
if isinstance(element, note.Note):
# Это одиночная нота — например, "C4" (до в 4-й октаве)
notes.append(str(element.pitch))
elif isinstance(element, chord.Chord):
# Это аккорд — например, "60.64.67"
# Мы берём номера всех нот в аккорде и соединяем в строку
notes.append('.'.join(str(n) for n in element.normalOrder))
📌 Объяснение:
glob.glob("midi_songs/*.mid")
— ищет все MIDI-файлы в папке.
converter.parse(file)
— читает файл и превращает его в объект, с которым можно работать.
midi.flat.notes
— достаёт только ноты (мы пока не трогаем ритм, темп и инструменты).
note.Note
— одиночные ноты (до, ре, ми и т.д.)
chord.Chord
— аккорды (одновременно несколько нот, как в аккорде на гитаре).
🎵 Почему мы сохраняем ноты в виде строк?
Потому что так проще передать их в нейросеть. Например:
"C4"
— обычная нота.
"60.64.67"
— аккорд из трёх нот, где каждая цифра — это номер ноты по высоте.
👉 В переменной notes
теперь лежит вся музыка из MIDI-файлов — нота за нотой, аккорд за аккордом.
Например:
notes[:10]
# ['E4', 'D4', 'C4', 'C4', 'D4', 'E4', 'E4', 'E4', 'D4', 'D4']
Это как если бы ты записал мелодию на слух — только не ушами, а кодом 🎧
✅ ИТОГ ПЕРВОЙ ЧАСТИ:
Мы установили нужную библиотеку
Скачали музыку
Превратили её в список нот
Это и есть "учебный материал" для ИИ.
В прошлый раз мы превратили музыку из .mid файлов в список нот. Теперь самое интересное — обучим ИИ понимать, как строится мелодия, и генерировать свою 🎶
Даже если ты только начал изучать Python — разберёшься! Погнали 🚀
Чтобы ИИ учился сочинять, ему нужны примеры: «Вот такой кусок нот — угадай, какая будет следующая». Как будто ты слушаешь знакомую песню и угадываешь, что будет дальше 🎧
# Получаем список уникальных нот
pitchnames = sorted(set(notes))
# Создаём словарь: нота -> число
note_to_int = {note: number for number, note in enumerate(pitchnames)}
sequence_length = 50 # длина куска (50 нот)
network_input = []
network_output = []
for i in range(len(notes) - sequence_length):
# Берём 50 подряд идущих нот
sequence_in = notes[i:i + sequence_length]
# Следующая за ними нота — это "ответ"
sequence_out = notes[i + sequence_length]
# Переводим ноты в числа
network_input.append([note_to_int[n] for n in sequence_in])
network_output.append(note_to_int[sequence_out])
📌 Здесь мы:
Находим все уникальные ноты (например, C4, D4, 60.64.67).
Превращаем каждую ноту в число — потому что нейросеть не понимает текст, только цифры.
🧠 Простыми словами:
Мы берём кусочек из 50 нот, как контекст.
И просим нейросеть угадать 51-ю ноту.
Таких примеров у нас получится тысячи, и нейросеть будет учиться на каждом.
Нейросеть работает с числами от 0 до 1, а не просто с номерами нот. Поэтому нормализуем входные данные:
import numpy as np
from tensorflow.keras.utils import to_categorical
n_patterns = len(network_input)
n_vocab = len(pitchnames)
# Переводим в нужный формат и делим на общее количество нот
network_input = np.reshape(network_input, (n_patterns, sequence_length, 1))
network_input = network_input / float(n_vocab)
# Переводим выходы в категории (one-hot)
network_output = to_categorical(network_output)
🔍 Что тут происходит:
Мы меняем форму входа с обычного списка на 3D-формат (нужно для работы нейросети).
Делим каждое число на общее количество нот — чтобы получились значения от 0 до 1.
Выходы (правильные ответы) превращаем в специальный вид, где каждая нота — это отдельный «выход» сети.
Теперь магия:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dropout, Dense
model = Sequential()
model.add(LSTM(256, input_shape=(sequence_length, 1)))
model.add(Dropout(0.3))
model.add(Dense(n_vocab, activation='softmax'))
📌 Пояснение:
LSTM
— это особый тип нейросети, который хорошо запоминает последовательности (например, музыку).
Dropout
— чтобы модель не «зазубривала», а училась по-настоящему.
Dense(n_vocab, activation='softmax')
— на выходе сеть скажет: «Я думаю, что с вероятностью 80% следующая нота — C4, 10% — D4…»
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.fit(network_input, network_output, epochs=50, batch_size=64)
💡 Обучение займёт немного времени. Суть такая:
Сеть смотрит на 50 нот.
Пытается угадать 51-ю.
Узнаёт, ошиблась или нет.
И подстраивает свою "логику", чтобы в следующий раз угадать точнее.
Так — тысячи раз подряд. И каждый раз она становится всё лучше и лучше. Как ребёнок, который учится сочинять мелодии на слух 🎶
🔥 Всё! Теперь у нас есть обученная модель, которая умеет предсказывать следующую ноту в мелодии.
Ты уже собрал данные, обучил нейросеть — и теперь наступает волшебный момент: 👉 ИИ сам сочинит музыку! И ты сможешь услышать результат.
Мы научили сеть: «Вот тебе 50 нот — угадай 51-ю». Теперь мы делаем наоборот: Даем ей 50 нот, она предсказывает следующую, потом ещё и ещё…
import random
import numpy as np
# Словарь: из числа — в ноту
int_to_note = {number: note for number, note in enumerate(pitchnames)}
# Выбираем случайную стартовую последовательность (50 нот)
start = random.randint(0, len(network_input) - 1)
pattern = network_input[start]
💡 Мы берём один случайный кусочек (тот же формат, что подавали при обучении) — это будет "затравка", начало новой мелодии.
Дальше мы будем 300 раз подряд спрашивать у модели: «Какую ноту ты хочешь поставить следующей?»
prediction_output = []
for i in range(300): # хотим 300 новых нот
# Подготавливаем вход: reshape + нормализация (от 0 до 1)
prediction_input = pattern.reshape(1, len(pattern), 1)
prediction_input = prediction_input / float(n_vocab)
# Предсказываем следующую ноту
prediction = model.predict(prediction_input, verbose=0)
# Берём индекс самой вероятной ноты
index = np.argmax(prediction)
# Превращаем число обратно в имя ноты
result = int_to_note[index]
prediction_output.append(result)
# Обновляем последовательность: удаляем 1-ю, добавляем новую
pattern = np.append(pattern[1:], [[index]], axis=0)
🔍 Что здесь важно:
.reshape(...)
— переводим данные в нужный формат (1 мелодия, 50 нот, 1 значение на ноту).
/ float(n_vocab)
— нормализуем значения, чтобы сеть могла правильно работать.
model.predict(...)
— сеть предсказывает вероятности для всех нот.
np.argmax(...)
— выбираем ту, которая получила наибольшую вероятность.
append(..., [[index]], ...)
— прокручиваем мелодию на один шаг.
📌 Так, шаг за шагом, ИИ сочиняет новую мелодию: сначала 51-ю ноту, потом 52-ю, и так до 300-й.
Теперь у нас есть список нот в виде строк: ['E4', 'F4', 'G4', '60.64.67', ...]
Это будущая мелодия, но чтобы её услышать, надо собрать из неё .mid
файл — это как черновик для музыкальной программы.
from music21 import stream, note, chord, instrument
output_notes = []
for pattern in prediction_output:
if '.' in pattern or pattern.isdigit():
# Это аккорд
notes_in_chord = pattern.split('.')
chord_notes = [note.Note(int(n)) for n in notes_in_chord]
new_chord = chord.Chord(chord_notes)
output_notes.append(new_chord)
else:
# Это одиночная нота, типа "C4"
new_note = note.Note(pattern)
new_note.storedInstrument = instrument.Piano()
output_notes.append(new_note)
📌 Объяснение:
Если строка содержит точки или только цифры — это аккорд (несколько нот).
Если обычная нота — делаем note.Note(...)
— и добавляем как отдельный звук.
Все ноты/аккорды складываем в output_notes
.
Теперь создаём музыкальный поток и сохраняем его в файл:
midi_stream = stream.Stream(output_notes)
midi_stream.write('midi', fp='generated_music.mid')
🎉 Всё! У тебя теперь есть файл generated_music.mid
— открой его в:
🎼 https://musescore.org/ — бесплатный редактор нот и проигрыватель
🧠 Даже в браузере: https://onlinesequencer.net/
Нажми Play — и послушай, что сочинил твой ИИ-композитор 🤖🎵
Превратил музыку в данные
Научил нейросеть продолжать мелодии
Получил свою первую сгенерированную композицию
🧑🎼 Это уже не просто Python-код. Это твой ИИ-соавтор!
🎁 Хочешь добавить:
Сочинение под определённый стиль?
Поддержку ритма и длительности?
Генерацию музыки по нажатию кнопки в веб-приложении?
Если получилось круто — поделись в Telegram или залей в TikTok — ИИ-музыканты сейчас в тренде 😎
Вы можете найти полный исходный код проекта на GitHub:
Не нашли нужной статьи?
Напишите нам и ее сделаем!