Skip to content

Commit

Permalink
Merge pull request #48 from abarton51/musicnet_preprocessing
Browse files Browse the repository at this point in the history
karpagam cnn testing
  • Loading branch information
abarton51 authored Dec 3, 2023
2 parents 6ad447e + 71bd433 commit ad6ece4
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 12 deletions.
Binary file modified src/musicNet/Utils/__pycache__/basic_cnn.cpython-310.pyc
Binary file not shown.
Binary file modified src/musicNet/Utils/__pycache__/cnn_trainer.cpython-310.pyc
Binary file not shown.
Empty file.
Binary file not shown.
95 changes: 95 additions & 0 deletions src/musicNet/cnn_composer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import os
import numpy as np
from music21 import converter, stream, note, chord
from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
from tensorflow.keras.utils import to_categorical

# converting midi files to input data
def midi_to_input_data(file_path, num_timesteps=64):
stream = converter.parse(file_path)
parts = stream.parts

# getting the nodes and chords and other music stuff
elements_to_parse = []
for part in parts:
elements_to_parse.extend(part.flat.notesAndRests)

# list to hold the string representation of elements
notes = []
for element in elements_to_parse:
if isinstance(element, note.Note):
notes.append(str(element.pitch))
elif isinstance(element, chord.Chord):
notes.append('.'.join(str(n) for n in element.normalOrder))
elif isinstance(element, note.Rest):
notes.append('Rest')

# making sequeneces
input_sequences = []
for i in range(0, len(notes) - num_timesteps, 1):
sequence = notes[i:i + num_timesteps]
input_sequences.append(sequence)

return input_sequences

# creating cnn model
def create_model(input_shape, num_classes):
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return model

# preprocessing data and training model
def train_model(dataset_path, num_timesteps=64, epochs=10):
composers = os.listdir(dataset_path)
num_composers = len(composers)
composer_to_index = {composer: idx for idx, composer in enumerate(composers)}

# loading midi data
X, y = [], []
for composer in composers:
composer_path = os.path.join(dataset_path, composer)
for file in os.listdir(composer_path):
file_path = os.path.join(composer_path, file)
sequences = midi_to_input_data(file_path, num_timesteps)
X.extend(sequences)
y.extend([composer_to_index[composer]] * len(sequences))

# sequences --> numerical format
unique_elements = list(set(element for sequence in X for element in sequence))
element_to_index = {element: idx for idx, element in enumerate(unique_elements)}
X_numerical = np.array([[element_to_index[element] for element in sequence] for sequence in X])

# labels --> categorical format
y_categorical = to_categorical(y, num_classes=num_composers)

# split data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X_numerical, y_categorical, test_size=0.2, random_state=42)

# reshaping data for cnn input
input_shape = (num_timesteps, 1, 1) # Add dimensions for CNN input
X_train = X_train.reshape(X_train.shape[0], *input_shape)
X_test = X_test.reshape(X_test.shape[0], *input_shape)

# creat/compile model
model = create_model(input_shape, num_composers)

# train model
model.fit(X_train, y_train, epochs=epochs, validation_data=(X_test, y_test))

return model

# replace 'dataset_path' with the path to MIDI dataset
#dataset_path = 'C:\Users\Karpagam\Documents\CLASSES\Fall_2023\CS_4641\final_project' # replace line -- some dummy path for testing data
#dataset_path = 'src\\musicNet\\processed_data\\train_data_midi.npy'
#trained_model = train_model(dataset_path, num_timesteps=64, epochs=10)

# save the trained data?
#trained_model.save('composer_classification_model.h5')
20 changes: 8 additions & 12 deletions src/musicNet/cnn.py → src/musicNet/cnn_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,33 @@

data_path = 'C:\\Users\\Teddy\\Documents\\Academics\\Machine Learning\\Projects\\CS_4641_Project\\src\\musicNet\\data'
orig_set = torchvision.datasets.ImageFolder(
root=data_path + '\\midi_rolls',
root=data_path + '\\mel_specs',
transform=torchvision.transforms.ToTensor()
)
n = len(orig_set) # total number of examples
n_test = int(0.1 * n) # take ~10% for test
test_set = torch.utils.data.Subset(orig_set, range(n_test)) # take first 10%
n_test = int(0.1 * n) # take % for test
test_set = torch.utils.data.Subset(orig_set, range(n_test)) # take %
train_set = torch.utils.data.Subset(orig_set, range(n_test, n)) # take the rest

trainloader = torch.utils.data.DataLoader(
train_set,
batch_size=64,
batch_size=32,
num_workers=0,
shuffle=True
)
testloader = torch.utils.data.DataLoader(
test_set,
batch_size=64,
batch_size=32,
num_workers=0,
shuffle=True
shuffle=False
)

cnn = CNNMusicNet()

trainer = Trainer(cnn, trainloader, testloader, num_epochs=500, batch_size=32, init_lr=1e-3, device="cpu")
trainer = Trainer(cnn, trainloader, testloader, num_epochs=10, batch_size=32, init_lr=1e-3, device="cpu")
trainer.train()

classes = set(os.listdir(data_path + '/musicnet_midis'))
print(classes)

# Choose best device to speed up training
device = ("cuda" if torch.cuda.is_available()
else "cpu")
print(f"Using {device} device")

print(f"Using {device} device")
61 changes: 61 additions & 0 deletions src/musicNet/cnn_nb.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING:tensorflow:From c:\\Users\\Teddy\\anaconda3\\envs\\deep_deconv\\Lib\\site-packages\\keras\\src\\losses.py:2976: The name tf.losses.sparse_softmax_cross_entropy is deprecated. Please use tf.compat.v1.losses.sparse_softmax_cross_entropy instead.\n",
"\n"
]
}
],
"source": [
"import cnn_composer"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"dataset_path = 'C:\\\\Users\\\\Teddy\\\\Documents\\\\Academics\\\\Machine Learning\\\\Projects\\\\CS_4641_Project\\\\src\\\\musicNet\\\\data\\\\musicnet_midis'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"trained_model = cnn_composer.train_model(dataset_path, num_timesteps=64, epochs=10)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "deep_deconv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
67 changes: 67 additions & 0 deletions src/musicNet/upload_mel_specs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import sys
sys.path.append('../')
import os
from tqdm import tqdm

import numpy as np
import pandas as pd

import matplotlib.pyplot as plt
import matplotlib.lines as mlines

import librosa
import librosa.display
import IPython

import musicnet4641

seed = 12
np.random.seed(seed)

data_path = 'C:\\Users\\Teddy\\Documents\\Academics\\Machine Learning\\Projects\\CS_4641_Project\\src\\musicNet\\data'
melspec_path = data_path + '/mel_specs'
musicnet_path = data_path + '/musicnet'
train_data_path = musicnet_path + '/train_data'
test_data_path = musicnet_path + '/test_data'

hop_length = 512
n_fft = 2048

df = pd.read_csv(data_path + '/musicnet_metadata.csv')
composers = np.unique(df['composer'].values)
id_dict = musicnet4641.create_id_dict(df)

fail_count = {}
for composer in composers:
fail_count[composer] = 0
total_fail_count = 0

def upload_melspecs(data_path, save_path, id_dict, fail_count):
for i, wav_file in enumerate(os.listdir(data_path)):
data, sampling_rate = librosa.load(data_path + '/' + wav_file)
mel_spec = librosa.feature.melspectrogram(y=data, sr=sampling_rate, hop_length=hop_length)
mel_spec_db = librosa.amplitude_to_db(mel_spec, ref=np.max)


img = librosa.display.specshow(mel_spec_db, sr=sampling_rate, hop_length=hop_length, x_axis='time', y_axis='log', cmap='cool')
plt.colorbar(img)

composer = None
for key in id_dict.keys():
if int(os.path.splitext(wav_file)[0]) in id_dict[key]:
composer = str(key)
break

plt.savefig(save_path + '/' + composer + '/' + os.path.splitext(wav_file)[0])
plt.close()
print(fail_count)

upload_melspecs(data_path=train_data_path, save_path=melspec_path, id_dict=id_dict, fail_count=total_fail_count)

"""
import warnings
with warnings.catch_warnings():
warnings.simplefilter("ignore", UserWarning)
warnings.simplefilter("ignore", FutureWarning)
upload_melspecs(data_path=train_data_path, save_path=melspec_path, id_dict=id_dict, fail_count=total_fail_count)
"""
File renamed without changes.

0 comments on commit ad6ece4

Please sign in to comment.