Введение

Сегодня мы попробуем создать простую музыку с помощью сетей LSTM. Цель этой статьи — указать практические возможности сетей. Пожалуйста, оставляйте ссылки на свои результаты в комментариях; было бы интересно посмотреть, какой результат получат читатели.

Минимальные навыки, которые должен иметь читатель, чтобы сделать свою собственную версию:

  • Python3
  • БАШ
  • Юпитер-блокнот.

В первой части я покажу, как читать песню с помощью Jupyter-ноутбука.
В следующем абзаце я покажу сгенерированную музыку (в формате midi) сетью LSTM.

Я не вдавался здесь во все математические/технические вопросы машинного обучения. Для более подробной информации прикрепляю ссылки в футере.

Подготовка данных и прослушивание образцов музыки.

Используем входные данные в формате ABC.

Некоторые образцы:

[V: S] (BA) !p!G2 |z AGA|(FG) A2| w: ple -na, Do-mi-nus te -cum, [V: A] F2 E2|z FEC|(DE) F2 | w: ple-na, Do-mi-nus te -cum, [V: T] (dc) c2|z ccA|(Ac) c2 | w: ple -na, Do-mi-nus te -cum, [V: B] (B,,F,) C,2|z F,C,F,|(D,C,) F,2 | w: ple -na, Do-mi-nus te -cum,

Примеры наборов данных в формате ABC можно скачать здесь.

Прочитать файл с песней

Я предлагаю использовать Jupyter-ноутбук для вашего удобства, но это не обязательно. Вы также можете попробовать совместную работу с Google или просто скрипт Python.

import numpy as np 
import matplotlib.pyplot as plt 
import tensorflow as tf
#read the data my_song.abc
with open('my_song.abc', 'r') as f:
    text = f.read()

Прослушивание песни

Чтобы прослушать песню, нам нужно установить некоторые дополнительные инструменты в нашей среде:

#in jupyter notebook 
!apt-get install -y -qq abcmidi timidity

Как сохранить песню в файл?

#this step depends on format of input data, you should be careful
song = text.split('\n\n') 
with open('my_song.abc', "w") as f:
    f.write(song)

Чтобы получить музыку в формате волны:

#in jupyter notebook
!abc2midi "my_song.abc" -o "my_song.mid" && timidity "my_song.mid" -Ow "my_song.wav"

Послушайте результаты

from IPython.display import Audio 
Audio('my_song.wav')
#link to generated music
#https://github.com/fuwiak/Habr/blob/master/my_song.wav

Время до LSTM

Чтобы проверить потенциал LSTM, нам нужно правильно подготовить обучающий набор, включая кодирование входных данных в числовые значения и преобразование входных данных в правильную форму.

#unique symbols
vocab = set(text)
#char encoding
char_to_index = {char_ :ind for ind, char_  in enumerate (vocab)} ind_to_char = np.array(vocab) 
text_as_int = np.array([char_to_index[c] for c in text])
# 'X:1\nT:dfkjds ' ----- > [49 22 13  0 45 22 26 67 60 79 56 69 59]

Подготовка формы ввода и вывода

Входной и выходной формат:

  • input_text: строка из 100 символов.
  • target_text: строка из 100 символов, сдвинутая на 1 символ.
seq_length = 100 
step = 10  
sequences = np.array([text_as_int[i:i+seq_length+1] for i in range(0, len(text_as_int)-seq_length-1,step)]) 
input_text = np.array([seq[:-1] for seq in sequences])  
target_text = np.array([seq[1:] for seq in sequences])

LSTM-модель

from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, LSTM, Dense, Embedding
vocab_size = len(vocab) 
embedding_dim = 256*2 
rnn_units = 1024*2  
x = Input(shape=(seq_length,)) 
e = Embedding(vocab_size, embedding_dim)(x) 
l = LSTM(rnn_units, return_sequences=True)(e) 
d = Dense(vocab_size, activation='softmax')(l) 
model = Model(inputs=x, outputs=d) 
model.summary()

Сетевое обучение

from tensorflow.keras.optimizers import Adam model.compile(optimizer=Adam(),loss='sparse_categorical_crossentropy')  
EP=5 # you could try with other value
BS = 128  # you could try with other value
hist = model.fit(input_text, target_text, batch_size=BS, epochs=EP)

Генерация музыки из модели

def generate_text(model, start_string, generation_length=100):
    input_eval = np.array([char_to_index[s] for s in start_string])
    x = np.zeros((1, seq_length))   
    x[0,-len(input_eval):] = input_eval[:]
    text_generated = []    
    
    model.reset_states()   
    for i in range(generation_length):
        predictions = model.predict(x)[0,-1]
        predictions = predictions.astype(np.float64)
        predictions = predictions/np.sum(predictions)
        predicted_id = np.argmax(np.random.multinomial(1, predictions))
        x[0,:-1] = x[0,1:]
        x[0,-1] = predicted_id
        text_generated.append([ind_to_char[predicted_id]])
    
    return (start_string + ''.join(text_generated))

Новая песня

new_song = generate_text(model, “X:”, generation_length=500)

Конвертируйте сгенерированную музыку в формат волны и слушайте

with open(‘new_song.abc’, “w”) as f: 
    f.write(new_song)
#in jupyter notebook
!abc2midi "new_song.abc" -o "new_song.mid" && timidity "new_song.mid" -Ow "new_song.wav"
Audio('new_song.wav') #https://github.com/fuwiak/Habr/blob/master/new_song.wav

Результат можно было послушать здесь.

Используя LSTM, мы смогли легко создать неплохую музыку. Но это только одна из возможностей. Вы также можете использовать этот код для создания коротких текстов, таких как сообщения в Twitter, Facebook и т. д. Небо или, по крайней мере, ваше воображение — это предел.

Ссылки:

Первоначально опубликовано на https://habr.com.