Beispiel #1
0
def main(note_embedding_dim,
         meta_embedding_dim,
         num_layers,
         lstm_hidden_size,
         dropout_lstm,
         linear_hidden_size,
         batch_size,
         num_epochs,
         train,
         num_iterations,
         sequence_length_ticks):
    dataset_manager = DatasetManager()

    metadatas = [
       FermataMetadata(),
       TickMetadata(subdivision=4),
       KeyMetadata()
    ]
    chorale_dataset_kwargs = {
        'voice_ids':      [0, 1, 2, 3],
        'metadatas':      metadatas,
        'sequences_size': 8,
        'subdivision':    4
    }
    bach_chorales_dataset = dataset_manager.get_dataset(
        name='bach_chorales',
        **chorale_dataset_kwargs
        )
    dataset = bach_chorales_dataset

    deepbach = DeepBach(
        dataset=dataset,
        note_embedding_dim=note_embedding_dim,
        meta_embedding_dim=meta_embedding_dim,
        num_layers=num_layers,
        lstm_hidden_size=lstm_hidden_size,
        dropout_lstm=dropout_lstm,
        linear_hidden_size=linear_hidden_size
    )

    if train:
        deepbach.train(batch_size=batch_size,
                       num_epochs=num_epochs)
    else:
        deepbach.load()
        deepbach.cuda()

    print('Generation')
    score, tensor_chorale, tensor_metadata = deepbach.generation(
        num_iterations=num_iterations,
        length=sequence_length_ticks,
    )
    score.write('midi', fp = 'test.mid')
def init_app(note_embedding_dim, meta_embedding_dim, num_layers,
             lstm_hidden_size, dropout_lstm, linear_hidden_size,
             num_iterations, sequence_length_ticks, ticks_per_quarter, port):
    global metadatas
    global _sequence_length_ticks
    global _num_iterations
    global _ticks_per_quarter
    global bach_chorales_dataset

    _ticks_per_quarter = ticks_per_quarter
    _sequence_length_ticks = sequence_length_ticks
    _num_iterations = num_iterations

    dataset_manager = DatasetManager()
    chorale_dataset_kwargs = {
        'voice_ids': [0, 1, 2, 3],
        'metadatas': metadatas,
        'sequences_size': 8,
        'subdivision': 4
    }

    _bach_chorales_dataset: ChoraleDataset = dataset_manager.get_dataset(
        name='bach_chorales', **chorale_dataset_kwargs)
    bach_chorales_dataset = _bach_chorales_dataset

    assert sequence_length_ticks % bach_chorales_dataset.subdivision == 0

    global deepbach
    deepbach = DeepBach(dataset=bach_chorales_dataset,
                        note_embedding_dim=note_embedding_dim,
                        meta_embedding_dim=meta_embedding_dim,
                        num_layers=num_layers,
                        lstm_hidden_size=lstm_hidden_size,
                        dropout_lstm=dropout_lstm,
                        linear_hidden_size=linear_hidden_size)
    deepbach.load()
    deepbach.cuda()

    # launch the script
    # use threaded=True to fix Chrome/Chromium engine hanging on requests
    # [https://stackoverflow.com/a/30670626]
    local_only = False
    if local_only:
        # accessible only locally:
        app.run(threaded=True)
    else:
        # accessible from outside:
        app.run(host='0.0.0.0', port=port, threaded=True)
def main(note_embedding_dim, meta_embedding_dim, num_layers, lstm_hidden_size,
         dropout_lstm, linear_hidden_size, batch_size, num_epochs, train,
         update, num_iterations, sequence_length_ticks, model_id,
         include_transpositions, update_iterations, generations_per_iteration,
         num_generations, score_chorales, write_scores):

    print('step 1/3: prepare dataset')
    dataset_manager = DatasetManager()
    metadatas = [FermataMetadata(), TickMetadata(subdivision=4), KeyMetadata()]
    chorale_dataset_kwargs = {
        'voice_ids': [0, 1, 2, 3],
        'metadatas': metadatas,
        'sequences_size': 8,
        'subdivision': 4,
        'include_transpositions': include_transpositions,
    }

    bach_chorales_dataset: ChoraleDataset = dataset_manager.get_dataset(
        name='bach_chorales', **chorale_dataset_kwargs)
    dataset = bach_chorales_dataset
    load_or_pickle_distributions(dataset)

    print('step 2/3: prepare model')
    print(f'Model ID: {model_id}')
    deepbach = DeepBach(
        dataset=dataset,
        note_embedding_dim=note_embedding_dim,
        meta_embedding_dim=meta_embedding_dim,
        num_layers=num_layers,
        lstm_hidden_size=lstm_hidden_size,
        dropout_lstm=dropout_lstm,
        linear_hidden_size=linear_hidden_size,
        model_id=model_id,
    )

    if train:
        print('step 2a/3: train base model')
        deepbach.train(batch_size=batch_size,
                       num_epochs=num_epochs,
                       split=[0.85, 0.15])
    else:
        print('step 2a/3: load model')
        deepbach.load()
        deepbach.cuda()

    if update:
        print(
            f'step 2b/3: update base model over {update_iterations} iterations'
        )
        thres = get_threshold('data/chorale_scores.csv', col=-1)
        print(f'Threshold for selection: {thres}')
        update_file = open('data/update_scores.csv', 'w')
        reader = csv.writer(update_file)
        reader.writerow(['iteration', 'chorale ID', 'score'])
        for i in range(update_iterations):
            print(f'----------- Iteration {i} -----------')
            picked_chorales = []
            num_picked_chorales = 0
            ensure_dir(f'generations/{model_id}/{i}')
            for j in tqdm(range(generations_per_iteration)):
                chorale, tensor_chorale, tensor_metadata = deepbach.generation(
                    num_iterations=num_iterations,
                    sequence_length_ticks=sequence_length_ticks,
                )

                score = score_chorale(chorale, dataset)

                # write data to csv file
                reader.writerow([i, j,
                                 score])  # iteration, generation #, score

                # worst Bach chorale score rounded up to nearest .01
                if score > thres:
                    print(f'Picked chorale {j} with score {score}')
                    picked_chorales.append(chorale)
                    num_picked_chorales += 1

                chorale.write('midi', f'generations/{model_id}/{i}/c{j}.mid')

            print(
                f'Number of picked chorales for iteration {i}: {num_picked_chorales}'
            )

            if num_picked_chorales == 0:
                continue

            all_datasets.update({
                f'generated_chorales_{i}': {
                    'dataset_class_name': ChoraleDataset,
                    'corpus_it_gen':
                    GeneratedChoraleIteratorGen(picked_chorales)
                }
            })
            generated_dataset: ChoraleDataset = dataset_manager.get_dataset(
                name=f'generated_chorales_{i}',
                index2note_dicts=dataset.index2note_dicts,
                note2index_dicts=dataset.note2index_dicts,
                voice_ranges=dataset.voice_ranges,
                **chorale_dataset_kwargs)

            deepbach.dataset = generated_dataset
            deepbach.train(
                batch_size=batch_size,
                num_epochs=2,
                split=[1, 0],  # use all selected chorales for training
                early_stopping=False)

    # generate chorales
    if score_chorales:
        chorale_scores = {}
        print('Scoring real chorales')
        for chorale_id, chorale in tqdm(enumerate(dataset.iterator_gen()),
                                        total=num_generations):
            score = score_chorale(chorale, dataset)
            chorale_scores[chorale_id] = score
            if chorale_id == num_generations:
                break

        # write scores to file
        if write_scores:
            with open('data/chorale_scores.csv', 'w') as chorale_file:
                reader = csv.writer(chorale_file)
                reader.writerow(['', 'score'] + list(weights.keys()))
                for id, value in chorale_scores.items():
                    reader.writerow([id, value])

    if num_generations != 0:
        generation_scores = {}
        print('Generating and scoring generated chorales')
        ensure_dir(f'generations/{model_id}')
        for i in range(num_generations):
            chorale, tensor_chorale, tensor_metadata = deepbach.generation(
                num_iterations=num_iterations,
                sequence_length_ticks=sequence_length_ticks,
            )
            chorale.write('midi', f'generations/{model_id}/c{i}.mid')
            score = score_chorale(chorale, dataset)
            generation_scores[i] = score

        # write scores to file
        if write_scores:
            with open(f'data/model{model_id}_scores.csv',
                      'w') as generation_file:
                reader = csv.writer(generation_file)
                reader.writerow(['', 'score'] + list(weights.keys()))
                for id, value in generation_scores.items():
                    reader.writerow([id, value])
Beispiel #4
0
class Predictor(cog.Predictor):
    def setup(self):
        """Load the model"""

        # music21.environment.set("musicxmlPath", "/bin/true")

        note_embedding_dim = 20
        meta_embedding_dim = 20
        num_layers = 2
        lstm_hidden_size = 256
        dropout_lstm = 0.5
        linear_hidden_size = 256
        batch_size = 256
        num_epochs = 5
        train = False
        num_iterations = 500
        sequence_length_ticks = 64

        dataset_manager = DatasetManager()

        metadatas = [FermataMetadata(), TickMetadata(subdivision=4), KeyMetadata()]
        chorale_dataset_kwargs = {
            "voice_ids": [0, 1, 2, 3],
            "metadatas": metadatas,
            "sequences_size": 8,
            "subdivision": 4,
        }
        bach_chorales_dataset: ChoraleDataset = dataset_manager.get_dataset(
            name="bach_chorales", **chorale_dataset_kwargs
        )
        dataset = bach_chorales_dataset

        self.deepbach = DeepBach(
            dataset=dataset,
            note_embedding_dim=note_embedding_dim,
            meta_embedding_dim=meta_embedding_dim,
            num_layers=num_layers,
            lstm_hidden_size=lstm_hidden_size,
            dropout_lstm=dropout_lstm,
            linear_hidden_size=linear_hidden_size,
        )

        self.deepbach.load()

        # load fluidsynth fo rmidi 2 audio conversion
        self.fs = FluidSynth()

        # self.converter = music21.converter.parse('path_to_musicxml.xml')

    @cog.input(
        "num_iterations",
        type=int,
        help="Number of parallel pseudo-Gibbs sampling iterations",
        default=500,
    )
    @cog.input(
        "sequence_length_ticks",
        type=int,
        min=16,
        help="Length of the generated chorale (in ticks)",
        default=64,
    )
    @cog.input(
        "output_type",
        type=str,
        help="Output representation type: can be audio or midi",
        default="audio",
        options=["midi", "audio"],
    )
    @cog.input("seed", type=int, default=-1, help="Random seed, -1 for random")
    def predict(self, num_iterations, sequence_length_ticks, output_type, seed):
        """Score Generation"""
        if seed >= 0:
            random.seed(seed)
            np.random.seed(seed)
            torch.use_deterministic_algorithms(True)
            torch.manual_seed(seed)

        score, tensor_chorale, tensor_metadata = self.deepbach.generation(
            num_iterations=num_iterations,
            sequence_length_ticks=sequence_length_ticks,
        )

        if output_type == "audio":
            output_path_wav = Path(tempfile.mkdtemp()) / "output.wav"
            output_path_mp3 = Path(tempfile.mkdtemp()) / "output.mp3"

            midi_score = score.write("midi")
            self.fs.midi_to_audio(midi_score, str(output_path_wav))

            subprocess.check_output(
                [
                    "ffmpeg",
                    "-i",
                    str(output_path_wav),
                    "-af",
                    "silenceremove=1:0:-50dB,aformat=dblp,areverse,silenceremove=1:0:-50dB,aformat=dblp,areverse",  # strip silence
                    str(output_path_mp3),
                ],
            )

            return output_path_mp3

        elif output_type == "midi":
            output_path_midi = Path(tempfile.mkdtemp()) / "output.mid"
            score.write("midi", fp=output_path_midi)
            return output_path_midi