Last active
April 24, 2023 06:15
-
-
Save llSourcell/0dc3bd7342483dbfd53197e9d54a5679 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #easier | |
| https://github.com/bhaktipriya/Blues | |
| ##Explain what he did, why we need better music | |
| modules in python | |
| #1 first tried a simple RNN with 2 LSTM layers | |
| #2 88 binary classification problem | |
| #3 multiclass classification, (two at same time) | |
| sigmoid cross entropy instead of softmax | |
| #4 Music is complex. | |
| #5 Assumptions make it easier to train on little | |
| data only 4/4 for signature, | |
| #quarter-note as maximum note resolution, no | |
| tempo changes. | |
| #6 trained on 3 songs (good overfitting, repeats | |
| same training) | |
| #play first clip | |
| https://soundcloud.com/reivalk/basic-rnn-joplin-example-overfitting?in=reivalk/sets/music-generator-experiments | |
| (overfitting) | |
| #400 songs | |
| #play next clip | |
| https://soundcloud.com/reivalk/basic-rnn-ragtime-1?in=reivalk/sets/music-generator-experiments | |
| #next experiment - encoder/decoder | |
| #The role of the encoder is to count the distance | |
| between the notes and compress that information | |
| into a single state vector. The decoder on the | |
| other end does exactly the opposite, generate a | |
| keyboard configuration from a state vector. | |
| #https://github.com/farizrahman4u/seq2seq, why? | |
| helps modularize, let networks become best at | |
| #what they do | |
| #talk about the composer class (where to save, | |
| initailze and train model) | |
| #Write and explain build_network in model.py | |
| #https://github.com/Conchylicultor/MusicGenerator | |
| import numpy as np # To generate random numbers | |
| import tensorflow as tf | |
| #hyperparameters like learning rate | |
| #rnns | |
| from deepmusic.moduleloader import ModuleLoader | |
| #predicts next key | |
| from deepmusic.keyboardcell import KeyboardCell | |
| #encapsulates song data, can run get scale, get relative note, etc. | |
| import deepmusic.songstruct as music | |
| def _build_network(self): | |
| #create the computation graph, encapsulates sessions and graph initialization | |
| input_dim = ModuleLoader.batch_builders.get_module().get_input_dim() | |
| # A placeholder exists solely to serve as the target of feeds. | |
| #It is not initialized and contains no data. A placeholder generates | |
| #an error if it is executed without a feed, so you won't forget to feed it. | |
| #for music data | |
| with tf.name_scope('placeholder_inputs'): | |
| self.inputs = [ | |
| tf.placeholder( | |
| tf.float32, # numerical data | |
| [self.args.batch_size, input_dim], #how much data | |
| name='input') | |
| for _ in range(self.args.sample_length) #size of input, 1 | |
| ] | |
| #0 or 1, 88 key binary classification | |
| with tf.name_scope('placeholder_targets'): | |
| self.targets = [ | |
| tf.placeholder( | |
| tf.int32, # 0/1 | |
| [self.args.batch_size], | |
| name='target') | |
| for _ in range(self.args.sample_length) | |
| ] | |
| #uses previous hidden state | |
| with tf.name_scope('placeholder_use_prev'): | |
| self.use_prev = [ | |
| tf.placeholder( | |
| tf.bool, | |
| [], | |
| name='use_prev') | |
| for _ in range(self.args.sample_length) | |
| ] | |
| # Define the network | |
| self.loop_processing = ModuleLoader.loop_processings.build_module(self.args) | |
| def loop_rnn(prev, i): | |
| """ Loop function used to connect one output of the rnn to the next input. | |
| The previous input and returned value have to be from the same shape. | |
| This is useful to use the same network for both training and testing. | |
| Args: | |
| prev: the previous predicted keyboard configuration at step i-1 | |
| i: the current step id (Warning: start at 1, 0 is ignored) | |
| Return: | |
| tf.Tensor: the input at the step i | |
| """ | |
| next_input = self.loop_processing(prev) | |
| #Tensors returned by the call to either fn1 or fn2. | |
| #If the callables return a singleton list, | |
| #the element is extracted from the list. | |
| #conditional | |
| # On training, we force the correct input, on testing, we use the previous output as next input | |
| return tf.cond(self.use_prev[i], lambda: next_input, lambda: self.inputs[i]) | |
| #built in seq2seq, outputs prediction notes, | |
| self.outputs, self.final_state = tf.nn.seq2seq.rnn_decoder( | |
| decoder_inputs=self.inputs, | |
| initial_state=None, # The initial state is defined inside KeyboardCell | |
| cell=KeyboardCell, | |
| loop_function=loop_rnn | |
| ) | |
| # For training only | |
| if not self.args.test: | |
| # Finally, we define the loss function | |
| # The network will predict a mix a wrong and right notes. | |
| For the loss function, we would like to | |
| # penalize note which are wrong. Eventually, the penalty | |
| should be less if the network predict the same | |
| # note but not in the right pitch (ex: C4 instead of C5), | |
| with a decay the further the prediction | |
| # is (D5 and D1 more penalized than D4 and D3 if the target is D2) | |
| #minimize error | |
| loss_fct = tf.nn.seq2seq.sequence_loss( | |
| self.outputs, | |
| self.targets, | |
| softmax_loss_function=tf.nn.softmax_cross_entropy_with_logits, | |
| average_across_timesteps=True, | |
| average_across_batch=True | |
| ) | |
| #Initialize the optimizer | |
| opt = tf.train.AdamOptimizer( | |
| learning_rate=self.current_learning_rate, | |
| beta1=0.9, | |
| beta2=0.999, | |
| epsilon=1e-08 | |
| ) | |
| self.opt_op = opt.minimize(loss_fct) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment