├── Code ├── __init__.py ├── generate.py ├── dataset.json ├── melodygenerator.py ├── melodypreprocessor.py ├── train.py └── transformer.py ├── data ├── en_c ├── En_c │ ├── sdfsd │ ├── La Cabuya_C.mxl │ ├── La Peluca_C.mxl │ ├── El Guacabo_C.mxl │ ├── La Millera_C.mxl │ ├── La Rebuscona_C.mxl │ ├── Cumbia Soledeña_C.mxl │ ├── Yo me llamo cumbia_C.mxl │ └── El Millo Se Modernizó_C.mxl ├── La Cabuya.mxl ├── La Peluca.mxl ├── El Flamenco.mxl ├── El Guacabo.mxl ├── La Millera.mxl ├── La Sonrisa.mxl ├── La Gallineta.mxl ├── La Rebuscona.mxl ├── Los Carnavales.mxl ├── Cumbia Soledeña.mxl ├── Chunks │ ├── La Millera 1.mxl │ ├── La Millera 2.mxl │ ├── La Millera 3.mxl │ ├── La Millera 4.mxl │ ├── La Peluca 1.mxl │ ├── La Peluca 2.mxl │ ├── La Peluca 3.mxl │ ├── La Peluca 4.mxl │ ├── La Peluca 5.mxl │ ├── La Peluca 6.mxl │ ├── La Peluca 7.mxl │ ├── La Rebuscona 1.mxl │ ├── La Rebuscona 2.mxl │ ├── La Rebuscona 3.mxl │ ├── La Rebuscona 4.mxl │ ├── La Rebuscona 5.mxl │ ├── La Sonrisa_C (1).mxl │ ├── La Sonrisa_C (2).mxl │ ├── La Sonrisa_C (3).mxl │ ├── La Sonrisa_C (4).mxl │ ├── La Sonrisa_C (5).mxl │ ├── La Sonrisa_C (6).mxl │ ├── La Sonrisa_C (7).mxl │ ├── Cumbia Soledeña_C_1.mxl │ ├── Cumbia Soledeña_C_2.mxl │ ├── Cumbia Soledeña_C_3.mxl │ ├── Cumbia Soledeña_C_4.mxl │ ├── Cumbia Soledeña_C_5.mxl │ ├── Cumbia Soledeña_C_6.mxl │ ├── La cabuya - Parte 1.mxl │ ├── La cabuya - Parte 2.mxl │ ├── La cabuya - Parte 3.mxl │ ├── La cabuya - Parte 4.mxl │ ├── La cabuya - Parte 5.mxl │ ├── La cabuya - Parte 6.mxl │ ├── El flamenco - Parte 1.mxl │ ├── El flamenco - Parte 2.mxl │ ├── El flamenco - Parte 3.mxl │ ├── El flamenco - Parte 4.mxl │ ├── El flamenco - Parte 5.mxl │ ├── El flamenco - Parte 6.mxl │ ├── El flamenco - Parte 7.mxl │ ├── El flamenco - Parte 8.mxl │ ├── El flamenco - Parte 9.mxl │ ├── La Gallineta - Parte 1.mxl │ ├── La Gallineta - Parte 2.mxl │ ├── La Gallineta - Parte 3.mxl │ ├── La Gallineta - Parte 4.mxl │ ├── La Gallineta - Parte 5.mxl │ ├── Yo me llamo cumbia 1.mxl │ ├── Yo me llamo cumbia 2.mxl │ ├── Yo me llamo cumbia 3.mxl │ ├── Yo me llamo cumbia 4.mxl │ ├── Yo me llamo cumbia 5.mxl │ ├── Yo me llamo cumbia 6.mxl │ ├── Yo me llamo cumbia 7.mxl │ ├── Yo me llamo cumbia 8.mxl │ ├── El millo se modernizó 1 - Parte 10.mxl │ ├── El millo se modernizó 1 - Parte 11.mxl │ ├── El millo se modernizó 1 - Parte 2.mxl │ ├── El millo se modernizó 1 - Parte 3.mxl │ ├── El millo se modernizó 1 - Parte 4.mxl │ ├── El millo se modernizó 1 - Parte 5.mxl │ ├── El millo se modernizó 1 - Parte 6.mxl │ ├── El millo se modernizó 1 - Parte 7.mxl │ ├── El millo se modernizó 1 - Parte 8.mxl │ └── El millo se modernizó 1 - Parte 9.mxl └── El Millo Se Modernizó.mxl ├── README.md ├── .DS_Store └── preprocces_data.py /Code/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /data/en_c: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /data/En_c/sdfsd: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cumbiaGEN 2 | Music ai team projects 3 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/.DS_Store -------------------------------------------------------------------------------- /data/La Cabuya.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/La Cabuya.mxl -------------------------------------------------------------------------------- /data/La Peluca.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/La Peluca.mxl -------------------------------------------------------------------------------- /data/El Flamenco.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/El Flamenco.mxl -------------------------------------------------------------------------------- /data/El Guacabo.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/El Guacabo.mxl -------------------------------------------------------------------------------- /data/La Millera.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/La Millera.mxl -------------------------------------------------------------------------------- /data/La Sonrisa.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/La Sonrisa.mxl -------------------------------------------------------------------------------- /data/La Gallineta.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/La Gallineta.mxl -------------------------------------------------------------------------------- /data/La Rebuscona.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/La Rebuscona.mxl -------------------------------------------------------------------------------- /data/Los Carnavales.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Los Carnavales.mxl -------------------------------------------------------------------------------- /data/Cumbia Soledeña.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Cumbia Soledeña.mxl -------------------------------------------------------------------------------- /data/En_c/La Cabuya_C.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/En_c/La Cabuya_C.mxl -------------------------------------------------------------------------------- /data/En_c/La Peluca_C.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/En_c/La Peluca_C.mxl -------------------------------------------------------------------------------- /data/Chunks/La Millera 1.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Millera 1.mxl -------------------------------------------------------------------------------- /data/Chunks/La Millera 2.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Millera 2.mxl -------------------------------------------------------------------------------- /data/Chunks/La Millera 3.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Millera 3.mxl -------------------------------------------------------------------------------- /data/Chunks/La Millera 4.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Millera 4.mxl -------------------------------------------------------------------------------- /data/Chunks/La Peluca 1.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Peluca 1.mxl -------------------------------------------------------------------------------- /data/Chunks/La Peluca 2.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Peluca 2.mxl -------------------------------------------------------------------------------- /data/Chunks/La Peluca 3.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Peluca 3.mxl -------------------------------------------------------------------------------- /data/Chunks/La Peluca 4.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Peluca 4.mxl -------------------------------------------------------------------------------- /data/Chunks/La Peluca 5.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Peluca 5.mxl -------------------------------------------------------------------------------- /data/Chunks/La Peluca 6.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Peluca 6.mxl -------------------------------------------------------------------------------- /data/Chunks/La Peluca 7.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Peluca 7.mxl -------------------------------------------------------------------------------- /data/En_c/El Guacabo_C.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/En_c/El Guacabo_C.mxl -------------------------------------------------------------------------------- /data/En_c/La Millera_C.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/En_c/La Millera_C.mxl -------------------------------------------------------------------------------- /data/En_c/La Rebuscona_C.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/En_c/La Rebuscona_C.mxl -------------------------------------------------------------------------------- /data/Chunks/La Rebuscona 1.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Rebuscona 1.mxl -------------------------------------------------------------------------------- /data/Chunks/La Rebuscona 2.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Rebuscona 2.mxl -------------------------------------------------------------------------------- /data/Chunks/La Rebuscona 3.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Rebuscona 3.mxl -------------------------------------------------------------------------------- /data/Chunks/La Rebuscona 4.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Rebuscona 4.mxl -------------------------------------------------------------------------------- /data/Chunks/La Rebuscona 5.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Rebuscona 5.mxl -------------------------------------------------------------------------------- /data/El Millo Se Modernizó.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/El Millo Se Modernizó.mxl -------------------------------------------------------------------------------- /data/Chunks/La Sonrisa_C (1).mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Sonrisa_C (1).mxl -------------------------------------------------------------------------------- /data/Chunks/La Sonrisa_C (2).mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Sonrisa_C (2).mxl -------------------------------------------------------------------------------- /data/Chunks/La Sonrisa_C (3).mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Sonrisa_C (3).mxl -------------------------------------------------------------------------------- /data/Chunks/La Sonrisa_C (4).mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Sonrisa_C (4).mxl -------------------------------------------------------------------------------- /data/Chunks/La Sonrisa_C (5).mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Sonrisa_C (5).mxl -------------------------------------------------------------------------------- /data/Chunks/La Sonrisa_C (6).mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Sonrisa_C (6).mxl -------------------------------------------------------------------------------- /data/Chunks/La Sonrisa_C (7).mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Sonrisa_C (7).mxl -------------------------------------------------------------------------------- /data/En_c/Cumbia Soledeña_C.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/En_c/Cumbia Soledeña_C.mxl -------------------------------------------------------------------------------- /data/Chunks/Cumbia Soledeña_C_1.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/Cumbia Soledeña_C_1.mxl -------------------------------------------------------------------------------- /data/Chunks/Cumbia Soledeña_C_2.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/Cumbia Soledeña_C_2.mxl -------------------------------------------------------------------------------- /data/Chunks/Cumbia Soledeña_C_3.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/Cumbia Soledeña_C_3.mxl -------------------------------------------------------------------------------- /data/Chunks/Cumbia Soledeña_C_4.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/Cumbia Soledeña_C_4.mxl -------------------------------------------------------------------------------- /data/Chunks/Cumbia Soledeña_C_5.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/Cumbia Soledeña_C_5.mxl -------------------------------------------------------------------------------- /data/Chunks/Cumbia Soledeña_C_6.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/Cumbia Soledeña_C_6.mxl -------------------------------------------------------------------------------- /data/Chunks/La cabuya - Parte 1.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La cabuya - Parte 1.mxl -------------------------------------------------------------------------------- /data/Chunks/La cabuya - Parte 2.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La cabuya - Parte 2.mxl -------------------------------------------------------------------------------- /data/Chunks/La cabuya - Parte 3.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La cabuya - Parte 3.mxl -------------------------------------------------------------------------------- /data/Chunks/La cabuya - Parte 4.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La cabuya - Parte 4.mxl -------------------------------------------------------------------------------- /data/Chunks/La cabuya - Parte 5.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La cabuya - Parte 5.mxl -------------------------------------------------------------------------------- /data/Chunks/La cabuya - Parte 6.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La cabuya - Parte 6.mxl -------------------------------------------------------------------------------- /data/En_c/Yo me llamo cumbia_C.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/En_c/Yo me llamo cumbia_C.mxl -------------------------------------------------------------------------------- /data/Chunks/El flamenco - Parte 1.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El flamenco - Parte 1.mxl -------------------------------------------------------------------------------- /data/Chunks/El flamenco - Parte 2.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El flamenco - Parte 2.mxl -------------------------------------------------------------------------------- /data/Chunks/El flamenco - Parte 3.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El flamenco - Parte 3.mxl -------------------------------------------------------------------------------- /data/Chunks/El flamenco - Parte 4.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El flamenco - Parte 4.mxl -------------------------------------------------------------------------------- /data/Chunks/El flamenco - Parte 5.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El flamenco - Parte 5.mxl -------------------------------------------------------------------------------- /data/Chunks/El flamenco - Parte 6.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El flamenco - Parte 6.mxl -------------------------------------------------------------------------------- /data/Chunks/El flamenco - Parte 7.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El flamenco - Parte 7.mxl -------------------------------------------------------------------------------- /data/Chunks/El flamenco - Parte 8.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El flamenco - Parte 8.mxl -------------------------------------------------------------------------------- /data/Chunks/El flamenco - Parte 9.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El flamenco - Parte 9.mxl -------------------------------------------------------------------------------- /data/Chunks/La Gallineta - Parte 1.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Gallineta - Parte 1.mxl -------------------------------------------------------------------------------- /data/Chunks/La Gallineta - Parte 2.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Gallineta - Parte 2.mxl -------------------------------------------------------------------------------- /data/Chunks/La Gallineta - Parte 3.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Gallineta - Parte 3.mxl -------------------------------------------------------------------------------- /data/Chunks/La Gallineta - Parte 4.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Gallineta - Parte 4.mxl -------------------------------------------------------------------------------- /data/Chunks/La Gallineta - Parte 5.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/La Gallineta - Parte 5.mxl -------------------------------------------------------------------------------- /data/Chunks/Yo me llamo cumbia 1.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/Yo me llamo cumbia 1.mxl -------------------------------------------------------------------------------- /data/Chunks/Yo me llamo cumbia 2.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/Yo me llamo cumbia 2.mxl -------------------------------------------------------------------------------- /data/Chunks/Yo me llamo cumbia 3.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/Yo me llamo cumbia 3.mxl -------------------------------------------------------------------------------- /data/Chunks/Yo me llamo cumbia 4.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/Yo me llamo cumbia 4.mxl -------------------------------------------------------------------------------- /data/Chunks/Yo me llamo cumbia 5.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/Yo me llamo cumbia 5.mxl -------------------------------------------------------------------------------- /data/Chunks/Yo me llamo cumbia 6.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/Yo me llamo cumbia 6.mxl -------------------------------------------------------------------------------- /data/Chunks/Yo me llamo cumbia 7.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/Yo me llamo cumbia 7.mxl -------------------------------------------------------------------------------- /data/Chunks/Yo me llamo cumbia 8.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/Yo me llamo cumbia 8.mxl -------------------------------------------------------------------------------- /data/En_c/El Millo Se Modernizó_C.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/En_c/El Millo Se Modernizó_C.mxl -------------------------------------------------------------------------------- /data/Chunks/El millo se modernizó 1 - Parte 10.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El millo se modernizó 1 - Parte 10.mxl -------------------------------------------------------------------------------- /data/Chunks/El millo se modernizó 1 - Parte 11.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El millo se modernizó 1 - Parte 11.mxl -------------------------------------------------------------------------------- /data/Chunks/El millo se modernizó 1 - Parte 2.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El millo se modernizó 1 - Parte 2.mxl -------------------------------------------------------------------------------- /data/Chunks/El millo se modernizó 1 - Parte 3.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El millo se modernizó 1 - Parte 3.mxl -------------------------------------------------------------------------------- /data/Chunks/El millo se modernizó 1 - Parte 4.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El millo se modernizó 1 - Parte 4.mxl -------------------------------------------------------------------------------- /data/Chunks/El millo se modernizó 1 - Parte 5.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El millo se modernizó 1 - Parte 5.mxl -------------------------------------------------------------------------------- /data/Chunks/El millo se modernizó 1 - Parte 6.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El millo se modernizó 1 - Parte 6.mxl -------------------------------------------------------------------------------- /data/Chunks/El millo se modernizó 1 - Parte 7.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El millo se modernizó 1 - Parte 7.mxl -------------------------------------------------------------------------------- /data/Chunks/El millo se modernizó 1 - Parte 8.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El millo se modernizó 1 - Parte 8.mxl -------------------------------------------------------------------------------- /data/Chunks/El millo se modernizó 1 - Parte 9.mxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetdog/cumbiaGEN/main/data/Chunks/El millo se modernizó 1 - Parte 9.mxl -------------------------------------------------------------------------------- /preprocces_data.py: -------------------------------------------------------------------------------- 1 | from music21 import converter, note 2 | 3 | def xml_to_melody(filepath): 4 | 5 | stream = converter.parse(filepath) 6 | melody = [f"{note.pitch.name}{note.pitch.octave}-{note.duration.quarterLength}" for note in stream.flat.notes] 7 | return melody -------------------------------------------------------------------------------- /Code/generate.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | from melodygenerator import MelodyGenerator 3 | from melodypreprocessor import MelodyPreprocessor 4 | from transformer import Transformer 5 | 6 | # Global parameters 7 | BATCH_SIZE = 32 8 | DATA_PATH = "/content/cumbiaGEN/Code/dataset.json" 9 | N_MELODIES=10 10 | 11 | transformer_model = Transformer( 12 | num_layers=2, 13 | d_model=64, 14 | num_heads=2, 15 | d_feedforward=128, 16 | input_vocab_size=vocab_size, 17 | target_vocab_size=vocab_size, 18 | max_num_positions_in_pe_encoder=MAX_POSITIONS_IN_POSITIONAL_ENCODING, 19 | max_num_positions_in_pe_decoder=MAX_POSITIONS_IN_POSITIONAL_ENCODING, 20 | dropout_rate=0.1, 21 | ) 22 | 23 | 24 | 25 | melody_preprocessor = MelodyPreprocessor(DATA_PATH, batch_size=BATCH_SIZE) 26 | 27 | 28 | for i in range(N_MELODIES): 29 | print("Generating a melody...") 30 | melody_generator = MelodyGenerator( 31 | transformer_model, melody_preprocessor.tokenizer 32 | ) 33 | start_sequence = ["C4-1.0", "D4-1.0", "E4-1.0", "C4-1.0"] 34 | new_melody = melody_generator.generate(start_sequence) 35 | print(f"Generated melody: {new_melody}") 36 | 37 | # save melody 38 | with open(f"/content/melody_{i}.txt", "w") as f: 39 | f.write(new_melody) -------------------------------------------------------------------------------- /Code/dataset.json: -------------------------------------------------------------------------------- 1 | [ 2 | "C4-1.0, C4-1.0, G4-1.0, G4-1.0, A4-1.0, A4-1.0, G4-2.0, F4-1.0, F4-1.0, E4-1.0, E4-1.0, D4-1.0, D4-1.0, C4-2.0, G4-1.0, G4-1.0, F4-1.0, F4-1.0, E4-1.0, E4-1.0, D4-2.0, G4-1.0, G4-1.0, F4-1.0, F4-1.0, E4-1.0, E4-1.0, D4-2.0", 3 | "C4-1.0, C4-0.5, D4-0.5, C4-1.0, F4-1.0, E4-2.0, C4-1.0, C4-0.5, D4-0.5, C4-1.0, G4-1.0, F4-2.0, C4-1.0, C4-1.0, C5-1.0, A4-1.0, F4-1.0, E4-1.0, D4-2.0, Bb4-1.0, Bb4-0.5, A4-0.5, F4-1.0, G4-1.0, F4-2.0", 4 | "E4-1.0, D4-1.0, C4-1.0, D4-1.0, E4-1.0, E4-1.0, E4-2.0, D4-1.0, D4-1.0, D4-2.0, E4-1.0, G4-2.0, G4-2.0, E4-1.0, D4-1.0, C4-1.0, D4-1.0, E4-1.0, E4-1.0, E4-2.0, D4-1.0, D4-1.0, E4-1.0, D4-1.0, C4-2.0", 5 | "E4-1.0, E4-1.0, F4-1.0, G4-1.0, G4-1.0, F4-1.0, E4-1.0, D4-1.0, C4-1.0, C4-1.0, D4-1.0, E4-1.0, E4-1.5, D4-0.5, D4-2.0, D4-1.0, D4-1.0, E4-1.0, C4-1.0, D4-1.0, E4-0.5, F4-0.5, E4-1.0, D4-1.0, C4-1.0, D4-1.0, G4-2.0", 6 | "E4-1.0, E4-1.0, E4-2.0, E4-1.0, E4-1.0, E4-2.0, E4-1.0, G4-1.0, C4-1.0, D4-1.0, E4-4.0, F4-1.0, F4-1.0, F4-1.0, F4-1.0, F4-1.0, E4-1.0, E4-1.0, E4-1.0, E4-1.0, E4-1.0, D4-1.0, D4-1.0, E4-1.0, D4-2.0, G4-2.0", 7 | "C4-1.0, C4-1.0, C4-1.0, D4-1.0, E4-2.0, E4-1.0, D4-1.0, E4-1.0, F4-2.0, G4-4.0, C4-1.0, C4-1.0, G4-1.0, G4-1.0, E4-1.0, E4-1.0, C4-1.0, C4-1.0, C4-1.0, C4-1.0, D4-1.0, E4-2.0, E4-1.0, D4-1.0, E4-1.0, F4-2.0, G4-4.0, C4-1.0, C4-1.0, G4-1.0, G4-1.0, E4-1.0, E4-1.0, C4-1.0" 8 | ] -------------------------------------------------------------------------------- /Code/melodygenerator.py: -------------------------------------------------------------------------------- 1 | """ 2 | melody_generator.py 3 | 4 | This script defines the MelodyGenerator class, which is responsible for generating 5 | melodies using a trained Transformer model. The class offers functionality to produce 6 | a sequence of musical notes, starting from a given seed sequence and extending it 7 | to a specified maximum length. 8 | 9 | The MelodyGenerator class leverages the trained Transformer model's ability to 10 | predict subsequent notes in a melody based on the current sequence context. It 11 | achieves this by iteratively appending each predicted note to the existing sequence 12 | and feeding this extended sequence back into the model for further predictions. 13 | 14 | This iterative process continues until the generated melody reaches the desired length 15 | or an end-of-sequence token is predicted. The class utilizes a tokenizer to encode and 16 | decode note sequences to and from the format expected by the Transformer model. 17 | 18 | Key Components: 19 | - MelodyGenerator: The primary class defined in this script, responsible for the 20 | generation of melodies. 21 | 22 | Usage: 23 | The MelodyGenerator class can be instantiated with a trained Transformer model 24 | and an appropriate tokenizer. Once instantiated, it can generate melodies by 25 | calling the `generate` method with a starting note sequence. 26 | 27 | Note: 28 | This class is intended to be used with a Transformer model that has been 29 | specifically trained for melody generation tasks. 30 | """ 31 | 32 | import tensorflow as tf 33 | 34 | 35 | class MelodyGenerator: 36 | """ 37 | Class to generate melodies using a trained Transformer model. 38 | 39 | This class encapsulates the inference logic for generating melodies 40 | based on a starting sequence. 41 | """ 42 | 43 | def __init__(self, transformer, tokenizer, temperature, max_length=50,): 44 | """ 45 | Initializes the MelodyGenerator. 46 | 47 | Parameters: 48 | transformer (Transformer): The trained Transformer model. 49 | tokenizer (Tokenizer): Tokenizer used for encoding melodies. 50 | max_length (int): Maximum length of the generated melodies. 51 | """ 52 | self.transformer = transformer 53 | self.tokenizer = tokenizer 54 | self.max_length = max_length 55 | self.temperature = temperature 56 | 57 | def generate(self, start_sequence): 58 | """ 59 | Generates a melody based on a starting sequence. 60 | 61 | Parameters: 62 | start_sequence (list of str): The starting sequence of the melody. 63 | 64 | Returns: 65 | str: The generated melody. 66 | """ 67 | input_tensor = self._get_input_tensor(start_sequence) 68 | 69 | num_notes_to_generate = self.max_length - len(input_tensor[0]) 70 | 71 | for _ in range(num_notes_to_generate): 72 | predictions = self.transformer( 73 | input_tensor, input_tensor, False, None, None, None 74 | ) 75 | predicted_note = self._get_note_with_highest_score(predictions) 76 | input_tensor = self._append_predicted_note( 77 | input_tensor, predicted_note 78 | ) 79 | 80 | generated_melody = self._decode_generated_sequence(input_tensor) 81 | 82 | return generated_melody 83 | 84 | def _get_input_tensor(self, start_sequence): 85 | """ 86 | Gets the input tensor for the Transformer model. 87 | 88 | Parameters: 89 | start_sequence (list of str): The starting sequence of the melody. 90 | 91 | Returns: 92 | input_tensor (tf.Tensor): The input tensor for the model. 93 | """ 94 | input_sequence = self.tokenizer.texts_to_sequences([start_sequence]) 95 | input_tensor = tf.convert_to_tensor(input_sequence, dtype=tf.int64) 96 | return input_tensor 97 | 98 | def _get_note_with_highest_score(self, predictions): 99 | """ 100 | Gets the note with the highest score from the predictions. 101 | 102 | Parameters: 103 | predictions (tf.Tensor): The predictions from the model. 104 | 105 | Returns: 106 | predicted_note (int): The index of the predicted note. 107 | """ 108 | 109 | latest_predictions = predictions[:, -1, :] 110 | # Apply temperature to the logits 111 | scaled_predictions = latest_predictions / self.temperature 112 | 113 | # Apply softmax to obtain probabilities 114 | soft_predictions = tf.nn.softmax(scaled_predictions) 115 | 116 | # Sample from the distribution 117 | predicted_note_index = tf.random.categorical(soft_predictions, 1) 118 | 119 | # Extract the sampled index 120 | predicted_note = predicted_note_index.numpy()[0, 0] 121 | return predicted_note 122 | 123 | def _append_predicted_note(self, input_tensor, predicted_note): 124 | """ 125 | Appends the predicted note to the input tensor. 126 | 127 | Parameters: 128 | input_tensor (tf.Tensor): The input tensor for the model. 129 | 130 | Returns: 131 | (tf.Tensor): The input tensor with the predicted note 132 | """ 133 | return tf.concat([input_tensor, [[predicted_note]]], axis=-1) 134 | 135 | def _decode_generated_sequence(self, generated_sequence): 136 | """ 137 | Decodes the generated sequence of notes. 138 | 139 | Parameters: 140 | generated_sequence (tf.Tensor): Tensor with note indexes generated. 141 | 142 | Returns: 143 | generated_melody (str): The decoded sequence of notes. 144 | """ 145 | generated_sequence_array = generated_sequence.numpy() 146 | generated_melody = self.tokenizer.sequences_to_texts( 147 | generated_sequence_array 148 | )[0] 149 | return generated_melody 150 | -------------------------------------------------------------------------------- /Code/melodypreprocessor.py: -------------------------------------------------------------------------------- 1 | """ 2 | melody_preprocessor.py 3 | 4 | This script defines the MelodyPreprocessor class, a utility for preparing melody 5 | datasets for training in a sequence-to-sequence Transformer model. The class 6 | focuses on processing melody data by tokenizing and encoding the melodies, and 7 | subsequently creating TensorFlow datasets suitable for training sequence-to-sequence 8 | models. 9 | 10 | The MelodyPreprocessor handles the entire preprocessing pipeline including loading 11 | melodies from a dataset file, parsing the melodies into individual notes, tokenizing 12 | and encoding these notes, and forming input-target pairs for model training. It 13 | also includes functionality for padding sequences to a uniform length. 14 | 15 | Key Features: 16 | - Tokenization and encoding of melodies. 17 | - Dynamic calculation of maximum sequence length based on the dataset. 18 | - Creation of input-target pairs for sequence-to-sequence training. 19 | - Conversion of processed data into TensorFlow datasets. 20 | 21 | Usage: 22 | To use the MelodyPreprocessor, initialize it with the path to a dataset containing 23 | melodies and the desired batch size. Then call `create_training_dataset` to prepare 24 | the dataset for training a Transformer model. 25 | 26 | 27 | Note: 28 | This script is intended to be used with datasets containing melody sequences in a 29 | specific format, where each melody is represented as a string of comma-separated 30 | musical notes (pitch with octave + duration in quarter length). 31 | """ 32 | 33 | 34 | import json 35 | 36 | import numpy as np 37 | import tensorflow as tf 38 | from keras.preprocessing.text import Tokenizer 39 | 40 | 41 | class MelodyPreprocessor: 42 | """ 43 | A class for preprocessing melodies for a Transformer model. 44 | 45 | This class takes melodies, tokenizes and encodes them, and prepares 46 | TensorFlow datasets for training sequence-to-sequence models. 47 | """ 48 | 49 | def __init__(self, dataset_path, batch_size=32): 50 | """ 51 | Initializes the MelodyPreprocessor. 52 | 53 | Parameters: 54 | dataset_path (str): Path to the dataset file. 55 | max_melody_length (int): Maximum length of the sequences. 56 | batch_size (int): Size of each batch in the dataset. 57 | """ 58 | self.dataset_path = dataset_path 59 | self.batch_size = batch_size 60 | self.tokenizer = Tokenizer(filters="", lower=False, split=",") 61 | self.max_melody_length = None 62 | self.number_of_tokens = None 63 | 64 | @property 65 | def number_of_tokens_with_padding(self): 66 | """ 67 | Returns the number of tokens in the vocabulary including padding. 68 | 69 | Returns: 70 | int: The number of tokens in the vocabulary including padding. 71 | """ 72 | return self.number_of_tokens + 1 73 | 74 | def create_training_dataset(self): 75 | """ 76 | Preprocesses the melody dataset and creates sequence-to-sequence 77 | training data. 78 | 79 | Returns: 80 | tf_training_dataset: A TensorFlow dataset containing input-target 81 | pairs suitable for training a sequence-to-sequence model. 82 | """ 83 | dataset = self._load_dataset() 84 | parsed_melodies = [self._parse_melody(melody) for melody in dataset] 85 | tokenized_melodies = self._tokenize_and_encode_melodies( 86 | parsed_melodies 87 | ) 88 | self._set_max_melody_length(tokenized_melodies) 89 | self._set_number_of_tokens() 90 | input_sequences, target_sequences = self._create_sequence_pairs( 91 | tokenized_melodies 92 | ) 93 | tf_training_dataset = self._convert_to_tf_dataset( 94 | input_sequences, target_sequences 95 | ) 96 | return tf_training_dataset 97 | 98 | def _load_dataset(self): 99 | """ 100 | Loads the melody dataset from a JSON file. 101 | 102 | Returns: 103 | list: A list of melodies from the dataset. 104 | """ 105 | with open(self.dataset_path, "r") as f: 106 | return json.load(f) 107 | 108 | def _parse_melody(self, melody_str): 109 | """ 110 | Parses a single melody string into a list of notes. 111 | 112 | Parameters: 113 | melody_str (str): A string representation of a melody. 114 | 115 | Returns: 116 | list: A list of notes extracted from the melody string. 117 | """ 118 | return melody_str.split(", ") 119 | 120 | def _tokenize_and_encode_melodies(self, melodies): 121 | """ 122 | Tokenizes and encodes a list of melodies. 123 | 124 | Parameters: 125 | melodies (list): A list of melodies to be tokenized and encoded. 126 | 127 | Returns: 128 | tokenized_melodies: A list of tokenized and encoded melodies. 129 | """ 130 | self.tokenizer.fit_on_texts(melodies) 131 | tokenized_melodies = self.tokenizer.texts_to_sequences(melodies) 132 | return tokenized_melodies 133 | 134 | def _set_max_melody_length(self, melodies): 135 | """ 136 | Sets the maximum melody length based on the dataset. 137 | 138 | Parameters: 139 | melodies (list): A list of tokenized melodies. 140 | """ 141 | self.max_melody_length = max([len(melody) for melody in melodies]) 142 | 143 | def _set_number_of_tokens(self): 144 | """ 145 | Sets the number of tokens based on the tokenizer. 146 | """ 147 | self.number_of_tokens = len(self.tokenizer.word_index) 148 | 149 | def _create_sequence_pairs(self, melodies): 150 | """ 151 | Creates input-target pairs from tokenized melodies. 152 | 153 | Parameters: 154 | melodies (list): A list of tokenized melodies. 155 | 156 | Returns: 157 | tuple: Two numpy arrays representing input sequences and target sequences. 158 | """ 159 | input_sequences, target_sequences = [], [] 160 | for melody in melodies: 161 | for i in range(1, len(melody)): 162 | input_seq = melody[:i] 163 | target_seq = melody[1 : i + 1] # Shifted by one time step 164 | padded_input_seq = self._pad_sequence(input_seq) 165 | padded_target_seq = self._pad_sequence(target_seq) 166 | input_sequences.append(padded_input_seq) 167 | target_sequences.append(padded_target_seq) 168 | return np.array(input_sequences), np.array(target_sequences) 169 | 170 | def _pad_sequence(self, sequence): 171 | """ 172 | Pads a sequence to the maximum sequence length. 173 | 174 | Parameters: 175 | sequence (list): The sequence to be padded. 176 | 177 | Returns: 178 | list: The padded sequence. 179 | """ 180 | return sequence + [0] * (self.max_melody_length - len(sequence)) 181 | 182 | def _convert_to_tf_dataset(self, input_sequences, target_sequences): 183 | """ 184 | Converts input and target sequences to a TensorFlow Dataset. 185 | 186 | Parameters: 187 | input_sequences (list): Input sequences for the model. 188 | target_sequences (list): Target sequences for the model. 189 | 190 | Returns: 191 | batched_dataset (tf.data.Dataset): A batched and shuffled 192 | TensorFlow Dataset. 193 | """ 194 | dataset = tf.data.Dataset.from_tensor_slices( 195 | (input_sequences, target_sequences) 196 | ) 197 | shuffled_dataset = dataset.shuffle(buffer_size=1000) 198 | batched_dataset = shuffled_dataset.batch(self.batch_size) 199 | return batched_dataset 200 | 201 | 202 | if __name__ == "__main__": 203 | # Usage example 204 | preprocessor = MelodyPreprocessor("dataset.json", batch_size=32) 205 | training_dataset = preprocessor.create_training_dataset() 206 | -------------------------------------------------------------------------------- /Code/train.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file contains the training pipeline for a Transformer model specialized in 3 | melody generation. It includes functions to calculate loss, perform training steps, 4 | and orchestrate the training process over multiple epochs. The script also 5 | demonstrates the use of the MelodyGenerator class to generate a melody after training. 6 | 7 | The training process uses a custom implementation of the Transformer model, 8 | defined in the 'transformer.py' module, and prepares data using the 9 | MelodyPreprocessor class from 'melodypreprocessor.py'. 10 | 11 | Global parameters such as the number of epochs, batch size, and path to the dataset 12 | are defined. The script supports dynamic padding of sequences and employs the 13 | Sparse Categorical Crossentropy loss function for model training. 14 | 15 | For simplicity's sake training does not deal with masking of padded values 16 | in the encoder and decoder. Also, look-ahead masking is not implemented. 17 | Both of these are left as an exercise for the student. 18 | 19 | Key Functions: 20 | - _calculate_loss_function: Computes the loss between actual and predicted sequences. 21 | - _train_step: Executes a single training step, including forward pass and backpropagation. 22 | - train: Runs the training loop over the entire dataset for a given number of epochs. 23 | - _right_pad_sequence_once: Utility function for padding sequences. 24 | 25 | The script concludes by instantiating the Transformer model, conducting the training, 26 | and generating a sample melody using the trained model. 27 | """ 28 | 29 | import tensorflow as tf 30 | from keras.losses import SparseCategoricalCrossentropy 31 | from keras.optimizers import Adam 32 | from melodygenerator import MelodyGenerator 33 | from melodypreprocessor import MelodyPreprocessor 34 | from transformer import Transformer 35 | import argparse 36 | from argparse import RawTextHelpFormatter 37 | import os 38 | import matplotlib.pyplot as plt 39 | 40 | # Loss function and optimizer 41 | sparse_categorical_crossentropy = SparseCategoricalCrossentropy( 42 | from_logits=True, reduction="none" 43 | ) 44 | optimizer = Adam() 45 | 46 | 47 | def train(train_dataset, transformer, epochs): 48 | """ 49 | Trains the Transformer model on a given dataset for a specified number of epochs. 50 | 51 | Parameters: 52 | train_dataset (tf.data.Dataset): The training dataset. 53 | transformer (Transformer): The Transformer model instance. 54 | epochs (int): The number of epochs to train the model. 55 | """ 56 | print("Training the model...") 57 | models_path = "/content/models" 58 | losses = [] 59 | 60 | if not(os.path.exists(models_path)): 61 | os.mkdir(models_path) 62 | for epoch in range(epochs): 63 | total_loss = 0 64 | # Iterate over each batch in the training dataset 65 | for (batch, (input, target)) in enumerate(train_dataset): 66 | # Perform a single training step 67 | batch_loss = _train_step(input, target, transformer) 68 | total_loss += batch_loss 69 | 70 | print( 71 | f"Epoch {epoch + 1} Batch {batch + 1} Loss {batch_loss.numpy()}" 72 | ) 73 | losses.append(total_loss) 74 | 75 | transformer.save_weights(os.path.join(models_path,f"epoch_{epoch}/"), save_format="tf") 76 | 77 | # plot loss at the end 78 | plt.plot(losses) 79 | plt.xlabel("epoch") 80 | plt.ylabel("loss") 81 | plt.savefig(f"training_curves.png") 82 | 83 | 84 | 85 | 86 | @tf.function 87 | def _train_step(input, target, transformer): 88 | """ 89 | Performs a single training step for the Transformer model. 90 | 91 | Parameters: 92 | input (tf.Tensor): The input sequences. 93 | target (tf.Tensor): The target sequences. 94 | transformer (Transformer): The Transformer model instance. 95 | 96 | Returns: 97 | tf.Tensor: The loss value for the training step. 98 | """ 99 | # Prepare the target input and real output for the decoder 100 | # Pad the sequences on the right by one position 101 | target_input = _right_pad_sequence_once(target[:, :-1]) 102 | target_real = _right_pad_sequence_once(target[:, 1:]) 103 | 104 | # Open a GradientTape to record the operations run 105 | # during the forward pass, which enables auto-differentiation 106 | with tf.GradientTape() as tape: 107 | # Forward pass through the transformer model 108 | # TODO: Add padding mask for encoder + decoder and look-ahead mask 109 | # for decoder 110 | predictions = transformer(input, target_input, True, None, None, None) 111 | 112 | # Compute loss between the real output and the predictions 113 | loss = _calculate_loss(target_real, predictions) 114 | 115 | # Calculate gradients with respect to the model's trainable variables 116 | gradients = tape.gradient(loss, transformer.trainable_variables) 117 | 118 | # Apply gradients to update the model's parameters 119 | gradient_variable_pairs = zip(gradients, transformer.trainable_variables) 120 | optimizer.apply_gradients(gradient_variable_pairs) 121 | 122 | # Return the computed loss for this training step 123 | return loss 124 | 125 | 126 | def _calculate_loss(real, pred): 127 | """ 128 | Computes the loss between the real and predicted sequences. 129 | 130 | Parameters: 131 | real (tf.Tensor): The actual target sequences. 132 | pred (tf.Tensor): The predicted sequences by the model. 133 | 134 | Returns: 135 | average_loss (tf.Tensor): The computed loss value. 136 | """ 137 | 138 | # Compute loss using the Sparse Categorical Crossentropy 139 | loss_ = sparse_categorical_crossentropy(real, pred) 140 | 141 | # Create a mask to filter out zeros (padded values) in the real sequences 142 | boolean_mask = tf.math.equal(real, 0) 143 | mask = tf.math.logical_not(boolean_mask) 144 | 145 | # Convert mask to the same dtype as the loss for multiplication 146 | mask = tf.cast(mask, dtype=loss_.dtype) 147 | 148 | # Apply the mask to the loss, ignoring losses on padded positions 149 | loss_ *= mask 150 | 151 | # Calculate average loss, excluding the padded positions 152 | total_loss = tf.reduce_sum(loss_) 153 | number_of_non_padded_elements = tf.reduce_sum(mask) 154 | average_loss = total_loss / number_of_non_padded_elements 155 | 156 | return average_loss 157 | 158 | 159 | def _right_pad_sequence_once(sequence): 160 | """ 161 | Pads a sequence with a single zero at the end. 162 | 163 | Parameters: 164 | sequence (tf.Tensor): The sequence to be padded. 165 | 166 | Returns: 167 | tf.Tensor: The padded sequence. 168 | """ 169 | return tf.pad(sequence, [[0, 0], [0, 1]], "CONSTANT") 170 | 171 | 172 | if __name__ == "__main__": 173 | # argument parser 174 | parser = argparse.ArgumentParser( 175 | description="""Resample a folder recusively with librosa 176 | Can be used in place or create a copy of the folder as an output.\n\n 177 | Example run: 178 | python TTS/bin/resample.py 179 | --input_dir /root/LJSpeech-1.1/ 180 | --output_sr 22050 181 | --output_dir /root/resampled_LJSpeech-1.1/ 182 | --file_ext wav 183 | --n_jobs 24 184 | """, 185 | formatter_class=RawTextHelpFormatter, 186 | ) 187 | 188 | parser.add_argument( 189 | "--data_path", 190 | type=str, 191 | default=None, 192 | required=True, 193 | help="Path to the file of preprocessed dataset", 194 | ) 195 | 196 | parser.add_argument( 197 | "--output_path", 198 | type=str, 199 | default=None, 200 | required=True, 201 | help="Path where the melodies are stored", 202 | ) 203 | 204 | parser.add_argument( 205 | "--batch_size", 206 | type=int, 207 | default=32, 208 | required=False, 209 | help="training batch size", 210 | ) 211 | 212 | parser.add_argument( 213 | "--epochs", 214 | type=int, 215 | default=32, 216 | required=False, 217 | help="training batch size", 218 | ) 219 | 220 | parser.add_argument( 221 | "--temperature", 222 | type=float, 223 | default=0.8, 224 | required=False, 225 | help="temperature for generation", 226 | ) 227 | 228 | parser.add_argument( 229 | "--positions", 230 | type=int, 231 | default=100, 232 | required=False, 233 | help="MAX_POSITIONS_IN_POSITIONAL_ENCODING", 234 | ) 235 | 236 | 237 | args = parser.parse_args() 238 | # Global parameters 239 | EPOCHS = args.epochs 240 | BATCH_SIZE = args.batch_size 241 | DATA_PATH = args.data_path 242 | OUTPUT_DIR = args.output_path 243 | MAX_POSITIONS_IN_POSITIONAL_ENCODING = args.positions 244 | TEMPERATURE=args.temperature 245 | 246 | melody_preprocessor = MelodyPreprocessor(DATA_PATH, batch_size=BATCH_SIZE) 247 | train_dataset = melody_preprocessor.create_training_dataset() 248 | vocab_size = melody_preprocessor.number_of_tokens_with_padding 249 | 250 | print("vocab_size", vocab_size) 251 | 252 | transformer_model = Transformer( 253 | num_layers=2, 254 | d_model=64, 255 | num_heads=2, 256 | d_feedforward=128, 257 | input_vocab_size=vocab_size, 258 | target_vocab_size=vocab_size, 259 | max_num_positions_in_pe_encoder=MAX_POSITIONS_IN_POSITIONAL_ENCODING, 260 | max_num_positions_in_pe_decoder=MAX_POSITIONS_IN_POSITIONAL_ENCODING, 261 | dropout_rate=0.1, 262 | ) 263 | 264 | train(train_dataset, transformer_model, EPOCHS) 265 | 266 | transformer_model.save_weights("/content/weigths/", save_format="tf") 267 | 268 | print("Generating a melody...") 269 | melody_generator = MelodyGenerator( 270 | transformer_model, melody_preprocessor.tokenizer,temperature=TEMPERATURE,max_length=25 271 | ) 272 | 273 | # create dir for saving melodies 274 | 275 | if not os.path.exists(OUTPUT_DIR): 276 | os.mkdir(OUTPUT_DIR) 277 | 278 | start_sequences = [["r-0.5", "G3-0.5", "C4-0.5", "D4-0.5", "E4-0.5"], 279 | ["r-0.5", "C4-0.5", "E4-0.5", "G4-0.5", "F4-1.0"], 280 | ["r-1.0", "A4-1.0", "E4-1.0", "A4-1.0", "E4-1.0"], 281 | ["r-2.0", "r-1.0", "D4-0.5", "F4-0.5", "E4-0.5", "D4-0.5"], 282 | ["r-2.0", "r-1.0", "D4-0.5","D4-1.0", "F4-1.0", "A4-1.0"], 283 | ["r-1.0", "A4-1.0", "E4-1.0", "A4-1.0", "r-0.5"], 284 | ["r-0.5", "G3-0.5", "C4-0.5", "D4-0.5", "E4-0.5"], 285 | ["r-0.5", "C4-0.5", "E4-0.5", "G4-0.5", "F4-1.0"], 286 | ["r-1.0", "A4-1.0", "E4-1.0", "A4-1.0", "E4-1.0"], 287 | ["r-2.0", "r-1.0", "D4-0.5", "F4-0.5", "E4-0.5", "D4-0.5"], 288 | ["r-2.0", "r-1.0", "D4-0.5","D4-1.0", "F4-1.0", "A4-1.0"], 289 | ["r-1.0", "A4-1.0", "E4-1.0", "A4-1.0", "r-0.5"]] 290 | 291 | for i, start_sequence in enumerate(start_sequences): 292 | 293 | new_melody = melody_generator.generate(start_sequence) 294 | print(f"Generated melody: {new_melody}") 295 | 296 | # save melody 297 | with open(os.path.join(OUTPUT_DIR, f"melody_{i}.txt"), "w") as f: 298 | f.write(new_melody) -------------------------------------------------------------------------------- /Code/transformer.py: -------------------------------------------------------------------------------- 1 | """ 2 | This script defines the Transformer model, a state-of-the-art model architecture used 3 | for a variety of natural language processing tasks, adapted here for music generation. 4 | The Transformer model relies on the mechanism of attention, differentially weighting 5 | the significance of different input elements. 6 | 7 | The script includes the implementation of various components of the Transformer 8 | architecture, including the Encoder, Decoder, and their respective layers. It also 9 | defines a sinusoidal positional encoding function that provides the model with 10 | information about the relative position of tokens in the sequence. 11 | 12 | Key Components: 13 | - Transformer: The main model class combining the Encoder and Decoder. 14 | - Encoder: Processes the input sequence and generates a context-rich representation. 15 | - Decoder: Generates the output sequence based on the Encoder's output and its own 16 | input. 17 | - EncoderLayer and DecoderLayer: Individual layers used in the Encoder and Decoder. 18 | - _get_angles and sinusoidal_position_encoding: Functions to generate positional 19 | encoding based on the sequence length and model dimensionality. 20 | 21 | Usage: 22 | To use the Transformer model, instantiate it with the required dimensions, number 23 | of layers, vocabulary sizes, and other parameters. The model can then be used for 24 | training or inference tasks in music generation or other sequence-to-sequence 25 | transformations. 26 | 27 | Note: 28 | This implementation of the Transformer model is designed for flexibility and can be 29 | adapted for various sequence-to-sequence tasks beyond music generation. 30 | """ 31 | 32 | import numpy as np 33 | import tensorflow as tf 34 | from keras.layers import ( 35 | Dense, 36 | Dropout, 37 | Embedding, 38 | LayerNormalization, 39 | MultiHeadAttention, 40 | ) 41 | 42 | 43 | def sinusoidal_position_encoding(num_positions, d_model): 44 | """ 45 | Compute positional encoding for a given position and dimension. 46 | 47 | Parameters: 48 | num_positions (int): Number of positions. 49 | d_model (int): Dimension of the model. 50 | 51 | Returns: 52 | Tensor: Positional encoding for the given position and dimension. 53 | """ 54 | 55 | angles = _get_angles( 56 | np.arange(num_positions)[:, np.newaxis], 57 | np.arange(d_model)[np.newaxis, :], 58 | d_model, 59 | ) 60 | 61 | # Apply sin to even indices in the array; 2i 62 | sines = np.sin(angles[:, 0::2]) 63 | 64 | # Apply cos to odd indices in the array; 2i+1 65 | cosines = np.cos(angles[:, 1::2]) 66 | 67 | pos_encoding = np.concatenate([sines, cosines], axis=-1) 68 | pos_encoding = pos_encoding[np.newaxis, ...] # (1, position, d_model) 69 | 70 | return tf.cast(pos_encoding, dtype=tf.float32) 71 | 72 | 73 | def _get_angles(pos, i, d_model): 74 | """ 75 | Compute the angles for the positional encoding. 76 | 77 | Parameters: 78 | pos (np.ndarray): Positions. 79 | i (np.ndarray): Indices. 80 | d_model (int): Dimension of the model. 81 | 82 | Returns: 83 | np.ndarray: Angles for the positional encoding. 84 | """ 85 | angle_dropout_rates = 1 / np.power( 86 | 10000, (2 * (i // 2)) / np.float32(d_model) 87 | ) 88 | return pos * angle_dropout_rates 89 | 90 | 91 | class Transformer(tf.keras.Model): 92 | """ 93 | The Transformer model architecture, consisting of an Encoder and Decoder. 94 | """ 95 | 96 | def __init__( 97 | self, 98 | num_layers, 99 | d_model, 100 | num_heads, 101 | d_feedforward, 102 | input_vocab_size, 103 | target_vocab_size, 104 | max_num_positions_in_pe_encoder, 105 | max_num_positions_in_pe_decoder, 106 | dropout_rate=0.1, 107 | ): 108 | """ 109 | Parameters: 110 | num_layers (int): Number of layers in both Encoder and Decoder. 111 | d_model (int): Dimension of the model. 112 | num_heads (int): Number of attention heads. 113 | d_feedforward (int): Dimension of the feed forward network. 114 | input_vocab_size (int): Size of the input vocabulary. 115 | target_vocab_size (int): Size of the target vocabulary. 116 | max_num_positions_in_pe_encoder (int): The maximum positions for input. 117 | max_num_positions_in_pe_decoder (int): The maximum positions for 118 | target. 119 | dropout_rate (float): Dropout dropout_rate. 120 | """ 121 | super(Transformer, self).__init__() 122 | self.encoder = Encoder( 123 | num_layers, 124 | d_model, 125 | num_heads, 126 | d_feedforward, 127 | input_vocab_size, 128 | max_num_positions_in_pe_encoder, 129 | dropout_rate, 130 | ) 131 | self.decoder = Decoder( 132 | num_layers, 133 | d_model, 134 | num_heads, 135 | d_feedforward, 136 | target_vocab_size, 137 | max_num_positions_in_pe_decoder, 138 | dropout_rate, 139 | ) 140 | 141 | self.final_layer = Dense(target_vocab_size) 142 | 143 | def call( 144 | self, 145 | input, 146 | target, 147 | training, 148 | enc_padding_mask, 149 | look_ahead_mask, 150 | dec_padding_mask, 151 | ): 152 | """ 153 | Process the input through the Transformer model. 154 | 155 | Parameters: 156 | input (Tensor): Input tensor to the Encoder. 157 | target (Tensor): Target tensor for the Decoder. 158 | training (bool): Whether the layer should behave in training mode. 159 | enc_padding_mask (Tensor): Padding mask for the Encoder. 160 | look_ahead_mask (Tensor): Look-ahead mask for the Decoder. 161 | dec_padding_mask (Tensor): Padding mask for the Decoder. 162 | 163 | Returns: 164 | Tensor: The final output of the Transformer. 165 | dict: Attention weights from the Decoder layers. 166 | """ 167 | enc_output = self.encoder( 168 | input, training, enc_padding_mask 169 | ) # (batch_size, input_seq_len, d_model) 170 | 171 | dec_output = self.decoder( 172 | target, enc_output, training, look_ahead_mask, dec_padding_mask 173 | ) # (batch_size, tar_seq_len, d_model) 174 | 175 | logits = self.final_layer( 176 | dec_output 177 | ) # (batch_size, target_seq_len, target_vocab_size) 178 | 179 | return logits 180 | 181 | 182 | class Encoder(tf.keras.layers.Layer): 183 | """ 184 | The Encoder of a Transformer model, consisting of multiple EncoderLayers. 185 | """ 186 | 187 | def __init__( 188 | self, 189 | num_layers, 190 | d_model, 191 | num_heads, 192 | d_feedforward, 193 | input_vocab_size, 194 | maximum_positions_in_pe, 195 | dropout_rate=0.1, 196 | ): 197 | """ 198 | Parameters 199 | num_layers (int): Number of EncoderLayers. 200 | d_model (int): Dimension of the model. 201 | num_heads (int): Number of attention heads. 202 | d_feedforward (int): Dimension of the feed forward network. 203 | input_vocab_size (int): Size of the input vocabulary. 204 | maximum_positions_in_pe (int): The maximum sequence length that 205 | this model might ever be used with. 206 | dropout_rate (float): Dropout dropout_rate. 207 | """ 208 | super(Encoder, self).__init__() 209 | self.d_model = d_model 210 | self.num_layers = num_layers 211 | 212 | self.embedding = Embedding(input_vocab_size, d_model) 213 | self.pos_encoding = sinusoidal_position_encoding( 214 | maximum_positions_in_pe, d_model 215 | ) 216 | self.enc_layers = [ 217 | EncoderLayer(d_model, num_heads, d_feedforward, dropout_rate) 218 | for _ in range(num_layers) 219 | ] 220 | self.dropout = Dropout(dropout_rate) 221 | 222 | def call(self, x, training, mask): 223 | """ 224 | Process the input through the Encoder. 225 | 226 | Args: 227 | x (Tensor): Input tensor. 228 | training (bool): Whether the layer should behave in training mode. 229 | mask (Tensor): Mask to be applied on attention weights. 230 | 231 | Returns: 232 | Tensor: Output of the Encoder. 233 | """ 234 | x = self.embedding(x) # (batch_size, input_seq_len, d_model) 235 | x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32)) 236 | 237 | sliced_pos_encoding = self._get_sliced_positional_encoding(x) 238 | x += sliced_pos_encoding 239 | 240 | x = self.dropout(x, training=training) 241 | 242 | for i in range(self.num_layers): 243 | x = self.enc_layers[i](x, training, mask) 244 | 245 | return x # (batch_size, input_seq_len, d_model) 246 | 247 | def _get_sliced_positional_encoding(self, x): 248 | """ 249 | Get a slice of the full positional encoding. 250 | 251 | Patameters: 252 | x (Tensor): Input tensor. 253 | 254 | Returns: 255 | Tensor: A slice of the full positional encoding. 256 | """ 257 | number_of_tokens = x.shape[1] 258 | return self.pos_encoding[:, :number_of_tokens, :] 259 | 260 | 261 | class Decoder(tf.keras.layers.Layer): 262 | """ 263 | The Decoder of a Transformer model, consisting of multiple DecoderLayers. 264 | """ 265 | 266 | def __init__( 267 | self, 268 | num_layers, 269 | d_model, 270 | num_heads, 271 | d_feedforward, 272 | target_vocab_size, 273 | maximum_positions_in_pe, 274 | dropout_rate=0.1, 275 | ): 276 | """ 277 | Parameters: 278 | num_layers (int): Number of DecoderLayers. 279 | d_model (int): Dimension of the model. 280 | num_heads (int): Number of attention heads. 281 | d_feedforward (int): Dimension of the feed forward network. 282 | target_vocab_size (int): Size of the target vocabulary. 283 | maximum_positions_in_pe (int): The maximum sequence length that 284 | this model might ever be used with. 285 | dropout_rate (float): Dropout dropout_rate. 286 | """ 287 | super(Decoder, self).__init__() 288 | self.d_model = d_model 289 | self.num_layers = num_layers 290 | 291 | self.embedding = Embedding(target_vocab_size, d_model) 292 | self.pos_encoding = sinusoidal_position_encoding( 293 | maximum_positions_in_pe, d_model 294 | ) 295 | 296 | self.dec_layers = [ 297 | DecoderLayer(d_model, num_heads, d_feedforward, dropout_rate) 298 | for _ in range(num_layers) 299 | ] 300 | self.dropout = Dropout(dropout_rate) 301 | 302 | def call(self, x, enc_output, training, look_ahead_mask, padding_mask): 303 | """ 304 | Process the input through the Decoder. 305 | 306 | Parameters: 307 | x (Tensor): Input tensor to the Decoder. 308 | enc_output (Tensor): Output from the Encoder. 309 | training (bool): Whether the layer should behave in training mode. 310 | look_ahead_mask (Tensor): Mask for the first MultiHeadAttention layer. 311 | padding_mask (Tensor): Mask for the second MultiHeadAttention layer. 312 | 313 | Returns: 314 | Tensor: The output of the Decoder. 315 | """ 316 | 317 | x = self.embedding(x) # (batch_size, target_seq_len, d_model) 318 | x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32)) 319 | 320 | sliced_pos_encoding = self._get_sliced_positional_encoding(x) 321 | x += sliced_pos_encoding 322 | 323 | x = self.dropout(x, training=training) 324 | 325 | for i in range(self.num_layers): 326 | x = self.dec_layers[i]( 327 | x, enc_output, training, look_ahead_mask, padding_mask 328 | ) 329 | 330 | return x 331 | 332 | def _get_sliced_positional_encoding(self, x): 333 | """ 334 | Get a slice of the full positional encoding. 335 | 336 | Patameters: 337 | x (Tensor): Input tensor. 338 | 339 | Returns: 340 | Tensor: A slice of the full positional encoding. 341 | """ 342 | number_of_tokens = x.shape[1] 343 | return self.pos_encoding[:, :number_of_tokens, :] 344 | 345 | 346 | class EncoderLayer(tf.keras.layers.Layer): 347 | """ 348 | Encoder Layer of a Transformer, consisting of MultiHeadAttention and 349 | Feed Forward Neural Network. 350 | """ 351 | 352 | def __init__(self, d_model, num_heads, d_feedforward, dropout_rate=0.1): 353 | """ 354 | Parameters: 355 | d_model (int): Dimension of the model. 356 | num_heads (int): Number of attention heads. 357 | d_feedforward (int): Dimension of the feed forward network. 358 | dropout_rate (float): Dropout dropout_rate. 359 | """ 360 | super(EncoderLayer, self).__init__() 361 | self.mha = MultiHeadAttention(key_dim=d_model, num_heads=num_heads) 362 | self.ffn = tf.keras.Sequential( 363 | [Dense(d_feedforward, activation="relu"), Dense(d_model)] 364 | ) 365 | self.layernorm1 = LayerNormalization(epsilon=1e-6) 366 | self.layernorm2 = LayerNormalization(epsilon=1e-6) 367 | self.dropout1 = Dropout(dropout_rate) 368 | self.dropout2 = Dropout(dropout_rate) 369 | 370 | def call(self, x, training, mask): 371 | """ 372 | Process the input through the Encoder layer. 373 | 374 | Parameters: 375 | x (Tensor): Input tensor. 376 | training (bool): Whether the layer should behave in training mode. 377 | mask (Tensor): Mask to be applied on attention weights. 378 | 379 | Returns: 380 | Tensor: Output of the Encoder layer. 381 | """ 382 | attn_output = self.mha(x, x, x, attention_mask=mask) 383 | attn_output = self.dropout1(attn_output, training=training) 384 | out1 = self.layernorm1(x + attn_output) 385 | 386 | ffn_output = self.ffn(out1) 387 | ffn_output = self.dropout2(ffn_output, training=training) 388 | out2 = self.layernorm2(out1 + ffn_output) 389 | 390 | return out2 391 | 392 | 393 | class DecoderLayer(tf.keras.layers.Layer): 394 | """ 395 | Decoder Layer of a Transformer, consisting of two MultiHeadAttention 396 | layers and a Feed Forward Neural Network. 397 | """ 398 | 399 | def __init__(self, d_model, num_heads, d_feedforward, dropout_rate=0.1): 400 | """ 401 | Parameters: 402 | d_model (int): Dimension of the model. 403 | num_heads (int): Number of attention heads. 404 | d_feedforward (int): Dimension of the feed forward network. 405 | dropout_rate (float): Dropout dropout_rate. 406 | """ 407 | super(DecoderLayer, self).__init__() 408 | self.mha1 = MultiHeadAttention(key_dim=d_model, num_heads=num_heads) 409 | self.mha2 = MultiHeadAttention(key_dim=d_model, num_heads=num_heads) 410 | 411 | self.ffn = tf.keras.Sequential( 412 | [Dense(d_feedforward, activation="relu"), Dense(d_model)] 413 | ) 414 | self.layernorm1 = LayerNormalization(epsilon=1e-6) 415 | self.layernorm2 = LayerNormalization(epsilon=1e-6) 416 | self.layernorm3 = LayerNormalization(epsilon=1e-6) 417 | self.dropout1 = Dropout(dropout_rate) 418 | self.dropout2 = Dropout(dropout_rate) 419 | self.dropout3 = Dropout(dropout_rate) 420 | 421 | def call(self, x, enc_output, training, look_ahead_mask, padding_mask): 422 | """ 423 | Process the input through the Decoder layer. 424 | 425 | Parameters 426 | x (Tensor): Input tensor to the Decoder layer. 427 | enc_output (Tensor): Output from the Encoder. 428 | training (bool): Whether the layer should behave in training mode. 429 | look_ahead_mask (Tensor): Mask for the first MultiHeadAttention layer. 430 | padding_mask (Tensor): Mask for the second MultiHeadAttention layer. 431 | 432 | Returns: 433 | Tensor: The output of the Decoder layer. 434 | """ 435 | attn1 = self.mha1(x, x, x, attention_mask=look_ahead_mask) 436 | attn1 = self.dropout1(attn1, training=training) 437 | out1 = self.layernorm1(attn1 + x) 438 | 439 | attn2 = self.mha2( 440 | out1, enc_output, enc_output, attention_mask=padding_mask 441 | ) 442 | attn2 = self.dropout2(attn2, training=training) 443 | out2 = self.layernorm2(attn2 + out1) 444 | 445 | ffn_output = self.ffn(out2) 446 | ffn_output = self.dropout3(ffn_output, training=training) 447 | out3 = self.layernorm3(ffn_output + out2) 448 | 449 | return out3 450 | 451 | 452 | if __name__ == "__main__": 453 | # Define Transformer parameters 454 | num_layers = 2 455 | d_model = 64 456 | num_heads = 2 457 | d_feedforward = 128 458 | input_vocab_size = 100 459 | target_vocab_size = 100 460 | dropout_dropout_rate = 0.1 461 | pe_input = 10 462 | pe_target = 10 463 | 464 | # Instantiate the Transformer model 465 | transformer_model = Transformer( 466 | num_layers, 467 | d_model, 468 | num_heads, 469 | d_feedforward, 470 | input_vocab_size, 471 | target_vocab_size, 472 | pe_input, 473 | pe_target, 474 | dropout_dropout_rate, 475 | ) 476 | 477 | # Dummy input shapes for encoder and decoder 478 | dummy_inp = tf.random.uniform( 479 | (1, 10), dtype=tf.int64, minval=0, maxval=input_vocab_size 480 | ) 481 | dummy_tar = tf.random.uniform( 482 | (1, 10), dtype=tf.int64, minval=0, maxval=target_vocab_size 483 | ) 484 | 485 | # Build the model using dummy input 486 | transformer_model( 487 | dummy_inp, 488 | dummy_tar, 489 | training=False, 490 | enc_padding_mask=None, 491 | look_ahead_mask=None, 492 | dec_padding_mask=None, 493 | ) 494 | 495 | # Display the model summary 496 | transformer_model.summary() 497 | --------------------------------------------------------------------------------