ИИ-композитор на Python

Как научить нейросеть сочинять музыку: первый шаг — подготовка данных. Простое объяснение, даже если вы только начинаете с Python и ML.

🎼 ИИ-композитор на Python: Создаем музыку с нуля

Как мы учим нейросеть понимать музыку, генерировать ее и сохранять в файл, чтобы послушать!

Ты включаешь музыку — и слышишь мелодию. А теперь представь: нейросеть тоже «слышит» музыку, запоминает её — и потом сочиняет свою! 🤯

💡 Мы создадим такую нейросеть с нуля. И начнём с самого первого шага — подготовим музыку в удобный формат для обучения, обучим модель и, наконец, сгенерируем первую композицию!


🔧 Часть 1: Подготовка данных и основы

1. Устанавливаем инструмент для работы с музыкой

Открой терминал (или командную строку) и напиши:

pip install music21

📦 Это библиотека music21. Она как музыкальный переводчик:

  • читает .mid файлы (в них — музыка),

  • вытаскивает ноты и аккорды,

  • позволяет сохранять и создавать новые мелодии.

Это наш помощник, чтобы превратить музыку в данные, понятные для Python и нейросети.

2. Подготовим музыку

Чтобы ИИ учился сочинять, ему нужны примеры. Как ребёнку: сначала он слушает, как поют взрослые, и только потом начинает напевать сам 🎵

🎼 Нам подойдут MIDI-файлы — это такие «музыкальные черновики», где записано, какие ноты играются, в каком порядке и как долго.

🔍 Где взять?

  1. Зайди на сайт вроде https://bitmidi.com

  2. Скачай несколько мелодий (например, Бах или Бетховен)

  3. Создай у себя рядом с кодом папку с именем midi_songs

  4. Помести туда файлы с расширением .mid

3. Читаем музыку в Python

Теперь — код. Он будет читать все 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']

Это как если бы ты записал мелодию на слух — только не ушами, а кодом 🎧

✅ ИТОГ ПЕРВОЙ ЧАСТИ:

  • Мы установили нужную библиотеку

  • Скачали музыку

  • Превратили её в список нот

Это и есть "учебный материал" для ИИ.


🔁 Часть 2: Обучение нейросети

В прошлый раз мы превратили музыку из .mid файлов в список нот. Теперь самое интересное — обучим ИИ понимать, как строится мелодия, и генерировать свою 🎶

Даже если ты только начал изучать Python — разберёшься! Погнали 🚀

1. Разбиваем музыку на кусочки

Чтобы ИИ учился сочинять, ему нужны примеры: «Вот такой кусок нот — угадай, какая будет следующая». Как будто ты слушаешь знакомую песню и угадываешь, что будет дальше 🎧

# Получаем список уникальных нот
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-ю ноту.

  • Таких примеров у нас получится тысячи, и нейросеть будет учиться на каждом.

2. Подготовим данные для нейросети

Нейросеть работает с числами от 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.

  • Выходы (правильные ответы) превращаем в специальный вид, где каждая нота — это отдельный «выход» сети.

    3. Строим простую нейросеть

    Теперь магия:

    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…»

    4. Обучаем нейросеть

    model.compile(loss='categorical_crossentropy', optimizer='adam')
    model.fit(network_input, network_output, epochs=50, batch_size=64)

    💡 Обучение займёт немного времени. Суть такая:

    • Сеть смотрит на 50 нот.

    • Пытается угадать 51-ю.

    • Узнаёт, ошиблась или нет.

    • И подстраивает свою "логику", чтобы в следующий раз угадать точнее.

    Так — тысячи раз подряд. И каждый раз она становится всё лучше и лучше. Как ребёнок, который учится сочинять мелодии на слух 🎶

    🔥 Всё! Теперь у нас есть обученная модель, которая умеет предсказывать следующую ноту в мелодии.


    🎼 Часть 3: Генерация и сохранение музыки

    Ты уже собрал данные, обучил нейросеть — и теперь наступает волшебный момент: 👉 ИИ сам сочинит музыку! И ты сможешь услышать результат.

    1. Стартуем с небольшой мелодии

    Мы научили сеть: «Вот тебе 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]

    💡 Мы берём один случайный кусочек (тот же формат, что подавали при обучении) — это будет "затравка", начало новой мелодии.

    2. Генерируем продолжение мелодии

    Дальше мы будем 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-й.

    3. Превращаем ноты обратно в музыку

    Теперь у нас есть список нот в виде строк: ['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.

    4. Сохраняем музыку в файл

    Теперь создаём музыкальный поток и сохраняем его в файл:

    midi_stream = stream.Stream(output_notes)
    midi_stream.write('midi', fp='generated_music.mid')

    🎉 Всё! У тебя теперь есть файл generated_music.mid — открой его в:

    Нажми Play — и послушай, что сочинил твой ИИ-композитор 🤖🎵


    ✅ Что ты сделал:

    • Превратил музыку в данные

    • Научил нейросеть продолжать мелодии

    • Получил свою первую сгенерированную композицию

    🧑‍🎼 Это уже не просто Python-код. Это твой ИИ-соавтор!

    🎁 Хочешь добавить:

    • Сочинение под определённый стиль?

    • Поддержку ритма и длительности?

    • Генерацию музыки по нажатию кнопки в веб-приложении?

    Если получилось круто — поделись в Telegram или залей в TikTok — ИИ-музыканты сейчас в тренде 😎

Исходный код

Вы можете найти полный исходный код проекта на GitHub:

https://github.com/Coursme/ai-composer-python

Бесплатно
Кодик: Интерактивное обучение!
Изучай HTML, JavaScript, CSS, Python, PHP, SQL, Git
Проходи практические уроки!
Получи сертификат!
Вам может быть интересно

Не нашли нужной статьи?
Напишите нам и ее сделаем!

Бесплатно
Кодик: Интерактивное обучение!
Изучай HTML, JavaScript, CSS, Python, PHP, SQL, Git
Проходи практические уроки!
Получи сертификат!
Главная
Курсы
Блог
Меню