in

Generación de música a través de redes neuronales profundas

0058uKGtNwFsQAXY8

Tutoriales prácticos, aprendizaje profundo

Generación de música a través de redes neuronales profundas

Aplicación creativa de Machine Learning

Ramya Vidiyala

21 de oct de 2020·8 min de lectura

El aprendizaje profundo ha mejorado muchos aspectos de nuestras vidas, tanto de forma obvia como sutil. El aprendizaje profundo juega un papel clave en procesos como los sistemas de recomendación de películas, la detección de spam y la visión por computadora. Aunque existe una discusión en curso sobre el aprendizaje profundo como una caja negra y la dificultad de la capacitación, existe un gran potencial para ello en una amplia variedad de campos, incluidos la medicina, los asistentes virtuales y el comercio electrónico.

Un área fascinante en la que demiEl aprendizaje puede jugar un papel en la intersección del arte y la tecnología. Para explorar más esta idea, en este artículo veremos la generación de música de aprendizaje automático a través de procesos de aprendizaje profundo, un campo que muchos asumen está más allá del alcance de las máquinas (¡y otra área interesante de feroz debate!).

Contenido

  • Representación musical para modelos de aprendizaje automático
  • Conjunto de datos de música
  • Procesamiento de datos
  • Selección de modelo
  • Muchos-muchos RNN
  • Capa densa distribuida en el tiempo
  • Con estado
  • Capas de abandono
  • Capa Softmax
  • Optimizador
  • Generacion de musica
  • Resumen
1*XNAW HhJKgddajOM9ql7QQ

Representación musical para modelos de aprendizaje automático

Trabajaremos con la notación musical ABC. La notación ABC es una forma abreviada de notación musical que usa las letras de la A a la G para representar notas musicales y otros elementos para agregar valores. Estos valores agregados incluyen sostenidos, bemoles, la longitud de una nota, la clave y la ornamentación.

Esta forma de notación comenzó como un código de juego de caracteres ASCII para facilitar el intercambio de música en línea, agregando un lenguaje nuevo y simple para los desarrolladores de software diseñado para facilitar su uso. La Figura 1 es una instantánea de la notación ABC de la música.

0*wrM0VihCLA6vWCWk

Una ilustración de la notación ABC de la música (Fuente, editado por el autor)

Las líneas de la parte 1 de la notación musical muestran una letra seguida de dos puntos. Estos indican varios aspectos de la melodía, como el índice, cuando hay más de una melodía en un archivo (X :), el título (T :), la signatura de tiempo (M :), la longitud predeterminada de la nota (L 🙂 , el tipo de melodía (R 🙂 y la clave (K :). Las líneas que siguen a la designación de la tecla representan la melodía en sí.

1*XNAW HhJKgddajOM9ql7QQ

Conjunto de datos de música

En este artículo, usaremos los datos de código abierto disponibles en la versión ABC de la base de datos musical de Nottingham. Contiene más de 1000 melodías populares, la gran mayoría de las cuales se han convertido a la notación ABC.

Procesamiento de datos

Los datos se encuentran actualmente en un formato categórico basado en caracteres. En la etapa de procesamiento de datos, necesitamos transformar los datos en un formato numérico basado en números enteros, para prepararlos para trabajar con redes neuronales.

0*GmymwDQojs8bDUB3

Descripción general del procesamiento de datos (imagen creada por el autor)

Aquí, cada carácter se asigna a un número entero único. Esto se puede lograr usando una sola línea de código. La variable ‘texto’ son los datos de entrada.

char_to_idx = { ch: i for (i, ch) in enumerate(sorted(list(set(text)))) }

Para entrenar el modelo, convertimos la totalidad de los datos de texto a un formato numérico usando el vocabulario.

T = np.asarray([char_to_idx[c] for c in text], dtype=np.int32)
1*XNAW HhJKgddajOM9ql7QQ

Selección de modelo para la generación de música de aprendizaje automático

En los modelos tradicionales de aprendizaje automático, no podemos almacenar las etapas anteriores de un modelo. Sin embargo, podemos almacenar etapas anteriores con redes neuronales recurrentes (comúnmente llamadas RNN).

Un RNN tiene un módulo de repetición que toma la entrada de la etapa anterior y da su salida como entrada a la siguiente etapa. Sin embargo, los RNN solo pueden retener información de la etapa más reciente, por lo que nuestra red necesita más memoria para aprender las dependencias a largo plazo. Aquí es donde las redes de memoria a largo y corto plazo (LSTM) acuden al rescate.

Los LSTM son un caso especial de RNN, con la misma estructura en forma de cadena que los RNN, pero una estructura de módulo repetitivo diferente.

Descripción general de la estructura de LSTM (imagen creada por el autor)

RNN se utiliza aquí porque:

  1. No es necesario corregir la longitud de los datos. Para cada entrada, la longitud de los datos puede variar.
  2. Se almacena la memoria de secuencia.
  3. Se pueden utilizar varias combinaciones de longitudes de secuencia de entrada y salida.

Además del RNN general, lo personalizaremos para nuestro caso de uso agregando algunos ajustes. Usaremos un ‘personaje RNN’. En los RNN de caracteres, la entrada, la salida y la salida de transición están en forma de caracteres.

0*hKzLeKDYrMEkWGr3

Descripción general del personaje RNN (imagen creada por el autor)

Muchos-muchos RNN

Como necesitamos que nuestra salida se genere en cada marca de tiempo, usaremos un RNN de muchos-muchos. Para implementar un RNN de muchos-muchos, necesitamos establecer el parámetro ‘return_sequences’ en verdadero para que cada carácter se genere en cada marca de tiempo. Puede comprenderlo mejor si observa la figura 5, a continuación.

0*Q byJrLS1OsuHnT4

Descripción general de Many-Many RNN (imagen creada por el autor)

En la figura anterior, las unidades azules son la entrada, las amarillas son las unidades ocultas y las verdes son las unidades de salida. Esta es una descripción general simple de muchos RNN. Para obtener una visión más detallada de las secuencias RNN, aquí hay un recurso útil.

Capa densa distribuida en el tiempo

Para procesar la salida en cada marca de tiempo, creamos una capa densa distribuida en el tiempo. Para lograr esto, creamos una capa densa distribuida en el tiempo sobre las salidas generadas en cada marca de tiempo.

Con estado

La salida del lote se pasa al siguiente lote como entrada estableciendo el parámetro con estado en verdadero. Después de combinar todas las características, nuestro modelo se verá como la descripción general que se muestra en la figura 6, a continuación.

0*uyi9kt68bhnanpVk

Comprensión de la RNN con estado (imagen creada por el autor)

El fragmento de código para la arquitectura del modelo es el siguiente:

model = Sequential()
model.add(Embedding(vocab_size, 512, batch_input_shape=(BATCH_SIZE, SEQ_LENGTH)))
for i in range(3): model.add(LSTM(256, return_sequences=True, stateful=True))
model.add(Dropout(0.2))
model.add(TimeDistributed(Dense(vocab_size)))
model.add(Activation('softmax'))
model.summary()
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

Recomiendo encarecidamente jugar con las capas para mejorar el rendimiento.

Capas de abandono

Las capas de abandono son una técnica de regularización que consiste en una fracción de unidades de entrada a cero en cada actualización durante el entrenamiento para evitar el sobreajuste. La fracción está determinada por el parámetro utilizado con la capa.

Capa Softmax

La generación de música es un problema de clasificación de clases múltiples, donde cada clase es un carácter único de los datos de entrada. Por lo tanto, estamos usando una capa softmax encima de nuestro modelo y una entropía cruzada categórica como función de pérdida.

Esta capa da la probabilidad de cada clase. De la lista de probabilidad, seleccionamos el que tiene la mayor probabilidad.

0*TY6mWcX1M2Q mwKz

Comprender la salida de la capa Softmax (imagen creada por el autor)

Optimizador

Para optimizar nuestro modelo, utilizamos la Estimación de Momento Adaptativo, también llamada Adam, ya que es una muy buena opción para RNN.

0*oZJq0M9PFPabdACC

Descripción general del modelo entrenado creado (imagen creada por el autor)
1*XNAW HhJKgddajOM9ql7QQ

Generando Música

Hasta ahora, creamos un modelo RNN y lo entrenamos con nuestros datos de entrada. Este modelo aprendió patrones de datos de entrada durante la fase de entrenamiento. Llamemos a este modelo el ‘modelo entrenado’.

El tamaño de entrada utilizado en el modelo entrenado es el tamaño del lote. Y para la generación de música a través del aprendizaje automático, el tamaño de entrada es un solo carácter. Entonces creamos un nuevo modelo que es similar al modelo entrenado, pero con el tamaño de entrada de un solo carácter que es (1,1). A este nuevo modelo, cargamos los pesos del modelo entrenado para replicar las características del modelo entrenado.

model2 = Sequential()model2.add(Embedding(vocab_size, 512, batch_input_shape=(1,1)))for i in range(3): 
model2.add(LSTM(256, return_sequences=True, stateful=True))
model2.add(Dropout(0.2))
model2.add(TimeDistributed(Dense(vocab_size)))
model2.add(Activation(‘softmax’))

Cargamos los pesos del modelo entrenado al nuevo modelo. Esto se puede lograr usando una sola línea de código.

model2.load_weights(os.path.join(MODEL_DIR,‘weights.100.h5’.format(epoch)))model2.summary()
0*dLtmyulRd97kTL3P

Descripción general del modelo de música generado (imagen creada por el autor)

En el proceso de generación de música, el primer carácter se elige al azar del conjunto único de caracteres, el siguiente carácter se genera utilizando el carácter generado previamente y así sucesivamente. Con esta estructura generamos música.

0*W2wjwYziUviXnz5W

Descripción general del flujo de música generada (imagen creada por el autor)

Aquí está el fragmento de código que nos ayuda a lograrlo.

sampled = []for i in range(1024):   batch = np.zeros((1, 1))   if sampled:      batch[0, 0] = sampled[-1]   else:      batch[0, 0] = np.random.randint(vocab_size)   result = model2.predict_on_batch(batch).ravel()   sample = np.random.choice(range(vocab_size), p=result)   sampled.append(sample)print("sampled")print(sampled)print(''.join(idx_to_char[c] for c in sampled))

Aquí hay algunas piezas musicales generadas:

Generamos estas agradables muestras de música utilizando redes neuronales de aprendizaje automático conocidas como LSTM. Para cada generación, los patrones serán diferentes pero similares a los datos de entrenamiento. Estas melodías se pueden utilizar para una amplia variedad de propósitos:

  • Mejorar la creatividad de los artistas a través de la inspiración.
  • Como herramienta de productividad para desarrollar nuevas ideas
  • Como melodías adicionales a las composiciones de los artistas
  • Para completar un trabajo inacabado
  • Como pieza musical independiente

Sin embargo, este modelo aún se puede mejorar. Nuestros datos de entrenamiento consistieron en un solo instrumento, el piano. Una forma en que podríamos mejorar nuestros datos de entrenamiento es agregando música de varios instrumentos. Otra sería aumentar los géneros musicales, sus ritmos y sus firmas de tiempo.

En la actualidad, nuestro modelo genera algunas notas falsas y la música no es excepcional. Podríamos reducir estos errores y aumentar la calidad de nuestra música aumentando nuestro conjunto de datos de entrenamiento como se detalla anteriormente.

1*XNAW HhJKgddajOM9ql7QQ

Resumen

En este artículo, analizamos cómo procesar música para usar con redes neuronales, el funcionamiento en profundidad de modelos de aprendizaje profundo como RNN y LSTM, y también exploramos cómo ajustar un modelo puede resultar en la generación de música. Podemos aplicar estos conceptos a cualquier otro sistema donde generemos otros formatos de arte, incluida la generación de pinturas de paisajes o retratos humanos.

1*XNAW HhJKgddajOM9ql7QQ

¡Gracias por leer! Este artículo se publicó originalmente aquí. Si desea experimentar con este conjunto de datos personalizado usted mismo, puede descargar los datos anotados aquí y ver mi código en Github.

También voy a escribir más publicaciones para principiantes en el futuro. Sígueme en Medium para estar informado sobre ellos. Agradezco sus comentarios y me pueden contactar en Twitter. ramya_vidiyala y LinkedIn RamyaVidiyala. ¡Feliz aprendizaje!

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

buscar archivo fecha

Cómo encontrar rápidamente archivos por rango de fechas en Windows 10

J2SE 5.0