generated from just-the-docs/just-the-docs-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #48 from abarton51/musicnet_preprocessing
karpagam cnn testing
- Loading branch information
Showing
9 changed files
with
231 additions
and
12 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
This file contains 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
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') |
This file contains 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
This file contains 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
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 | ||
} |
This file contains 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
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.