diff --git a/data/kbes/README.md b/data/kbes/README.md new file mode 100644 index 00000000..9e885643 --- /dev/null +++ b/data/kbes/README.md @@ -0,0 +1,13 @@ +# Nkululeko pre-processing for KBES dataset + +Download the dataset from [1], place it in this directory or somewhere else and +ane make soft link here (`ln -sf`). + +```bash +# unzipt the dataset +unzip "KUET Bangla Emotional Speech (KBES) Dataset.zip" + +``` + +Reference: +[1] diff --git a/data/kbes/exp.ini b/data/kbes/exp.ini new file mode 100644 index 00000000..caeca931 --- /dev/null +++ b/data/kbes/exp.ini @@ -0,0 +1,29 @@ +[EXP] +root = /tmp/results/ +name = exp_kbes_hubert_all +[DATA] +databases = ['train', 'dev', 'test'] +train = ./data/kbes/kbes_train.csv +train.type = csv +train.absolute_path = False +train.split_strategy = train +dev = ./data/kbes/kbes_dev.csv +dev.type = csv +dev.absolute_path = False +dev.split_strategy = train +test = ./data/kbes/kbes_test.csv +test.type = csv +test.absolute_path = False +test.split_strategy = test +target = emotion +; labels = ['anger', 'fear', 'sad', 'happy'] +; get the number of classes from the target column automatically +[FEATS] +type = ['hubert-xlarge-ll60k'] +; no_reuse = False +scale = standard +[MODEL] +type = knn +; save = True +[RESAMPLE] +replace = True \ No newline at end of file diff --git a/data/kbes/process_database.py b/data/kbes/process_database.py new file mode 100644 index 00000000..399ae52c --- /dev/null +++ b/data/kbes/process_database.py @@ -0,0 +1,99 @@ +# process_database.py for KBES dataset + +import pandas as pd +import argparse +from nkululeko.utils.files import find_files +import os +from sklearn.model_selection import train_test_split + + +def process_database(data_dir, output_dir): + # check if data_dir exist + if not os.path.exists(data_dir): + raise FileNotFoundError(f"Directory {data_dir} not found.") + + # Create the output directory if it doesn't exist + os.makedirs(output_dir, exist_ok=True) + + # read all wav files + wavs = find_files(data_dir, relative=True, ext=["wav"]) + print(f"Found {len(wavs)} wav files.") + + # map emotion: 1 = Neutral, 2 = Happy, 3 = Sad, 4 = Angry, 5 = Disgust + emotion_mapping = { + 1: "neutral", + 2: "happy", + 3: "sad", + 4: "angry", + 5: "disgust" + } + + # map intensity, 1 = low, 2 = high + intensity_mapping = { + 1: 'low', + 2: 'high' + } + + # map gender 0 = female, 1 = male + gender_mapping = { + 0: 'female', + 1: 'male' + } + + data = [] + for wav in wavs: + # get basename + basename = os.path.basename(wav) + # get emotion + emotion = emotion_mapping[int(basename.split("-")[0])] + # get intensity + intensity = intensity_mapping[int(basename.split("-")[1])] + # get gender + gender = gender_mapping[int(basename.split("-")[2])] + # add language + language = "bangla" + # add to data list + data.append({ + "file": wav, + "emotion": emotion, + "gender": gender, + "intensity": intensity, + "language": language + }) + + # create dataframe from data + df = pd.DataFrame(data) + # split the data into train, dev, and test sets, balanced by emotion + train_df, temp_df = train_test_split( + df, test_size=0.3, stratify=df['emotion'], random_state=42) + dev_df, test_df = train_test_split( + temp_df, test_size=0.5, stratify=temp_df['emotion'], random_state=42) + # write dataframes to csv + train_df.to_csv(os.path.join( + output_dir, "kbes_train.csv"), index=False) + dev_df.to_csv(os.path.join(output_dir, "kbes_dev.csv"), index=False) + test_df.to_csv(os.path.join( + output_dir, "kbes_test.csv"), index=False) + print(f"Number of train samples: {len(train_df)}") + print(f"Number of dev samples: {len(dev_df)}") + print(f"Number of test samples: {len(test_df)}") + print("Database processing completed.") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Process KBES dataset") + parser.add_argument( + "--data_dir", + type=str, + default="KUET Bangla Emotional Speech (KBES) Dataset", + help="Directory containing the KBES data", + ) + parser.add_argument( + "--output_dir", + type=str, + default="./", + help="Directory to store the output CSV files", + ) + args = parser.parse_args() + + process_database(args.data_dir, args.output_dir) diff --git a/data/nemo/exp.ini b/data/nemo/exp.ini index 8a4c7674..38377ce8 100644 --- a/data/nemo/exp.ini +++ b/data/nemo/exp.ini @@ -1,6 +1,6 @@ [EXP] root = /tmp/results/ -name = exp_nemo_audmodel_svm_big4 +name = exp_nemo_audmodel_knn [DATA] databases = ['train', 'dev', 'test'] train = ./data/nemo/nemo_train.csv @@ -19,7 +19,7 @@ test.absolute_path = False test.split_strategy = test test.audio_path = ./nEMO/samples target = emotion -labels = ['anger', 'neutral', 'sadness', 'happiness'] +; labels = ['anger', 'neutral', 'sadness', 'happiness'] ; get the number of classes from the target column automatically [FEATS] type = ['audmodel'] diff --git a/nkululeko/data/dataset_csv.py b/nkululeko/data/dataset_csv.py index 60c434eb..73bbca95 100644 --- a/nkululeko/data/dataset_csv.py +++ b/nkululeko/data/dataset_csv.py @@ -21,7 +21,7 @@ def load(self): # exp_root = self.util.config_val("EXP", "root", "") # data_file = os.path.join(exp_root, data_file) root = os.path.dirname(data_file) - audio_path = self.util.config_val_data(self.name, "audio_path", "") + audio_path = self.util.config_val_data(self.name, "audio_path", "./") df = pd.read_csv(data_file) # special treatment for segmented dataframes with only one column: if "start" in df.columns and len(df.columns) == 4: @@ -49,7 +49,8 @@ def load(self): .map(lambda x: root + "/" + audio_path + "/" + x) .values ) - df = df.set_index(df.index.set_levels(file_index, level="file")) + df = df.set_index(df.index.set_levels( + file_index, level="file")) else: if not isinstance(df, pd.DataFrame): df = pd.DataFrame(df) @@ -63,7 +64,8 @@ def load(self): self.db = None self.got_target = True self.is_labeled = self.got_target - self.start_fresh = eval(self.util.config_val("DATA", "no_reuse", "False")) + self.start_fresh = eval( + self.util.config_val("DATA", "no_reuse", "False")) is_index = False try: if self.is_labeled and not "class_label" in self.df.columns: @@ -90,7 +92,8 @@ def load(self): f" {self.got_gender}, got age: {self.got_age}" ) self.util.debug(r_string) - glob_conf.report.add_item(ReportItem("Data", "Loaded report", r_string)) + glob_conf.report.add_item(ReportItem( + "Data", "Loaded report", r_string)) def prepare(self): super().prepare()