nkululeko 0.87.0__py3-none-any.whl → 0.88.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nkululeko/constants.py +1 -1
- nkululeko/demo.py +3 -2
- nkululeko/ensemble.py +158 -0
- nkululeko/feat_extract/feats_ast.py +118 -0
- nkululeko/feat_extract/feats_wav2vec2.py +2 -4
- nkululeko/feat_extract/feats_wavlm.py +7 -4
- nkululeko/feature_extractor.py +5 -9
- nkululeko/test_predictor.py +1 -3
- nkululeko/utils/util.py +24 -19
- {nkululeko-0.87.0.dist-info → nkululeko-0.88.0.dist-info}/METADATA +10 -1
- {nkululeko-0.87.0.dist-info → nkululeko-0.88.0.dist-info}/RECORD +14 -12
- {nkululeko-0.87.0.dist-info → nkululeko-0.88.0.dist-info}/WHEEL +1 -1
- {nkululeko-0.87.0.dist-info → nkululeko-0.88.0.dist-info}/LICENSE +0 -0
- {nkululeko-0.87.0.dist-info → nkululeko-0.88.0.dist-info}/top_level.txt +0 -0
nkululeko/constants.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
VERSION="0.
|
1
|
+
VERSION="0.88.0"
|
2
2
|
SAMPLING_RATE = 16000
|
nkululeko/demo.py
CHANGED
@@ -20,13 +20,14 @@ Options: \n
|
|
20
20
|
import argparse
|
21
21
|
import configparser
|
22
22
|
import os
|
23
|
+
|
23
24
|
import pandas as pd
|
25
|
+
from transformers import pipeline
|
24
26
|
|
27
|
+
import nkululeko.glob_conf as glob_conf
|
25
28
|
from nkululeko.constants import VERSION
|
26
29
|
from nkululeko.experiment import Experiment
|
27
|
-
import nkululeko.glob_conf as glob_conf
|
28
30
|
from nkululeko.utils.util import Util
|
29
|
-
from transformers import pipeline
|
30
31
|
|
31
32
|
|
32
33
|
def main(src_dir):
|
nkululeko/ensemble.py
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
|
5
|
+
import configparser
|
6
|
+
import time
|
7
|
+
from argparse import ArgumentParser
|
8
|
+
from pathlib import Path
|
9
|
+
|
10
|
+
import pandas as pd
|
11
|
+
|
12
|
+
from nkululeko.constants import VERSION
|
13
|
+
from nkululeko.experiment import Experiment
|
14
|
+
from nkululeko.utils.util import Util
|
15
|
+
|
16
|
+
|
17
|
+
def ensemble_predictions(config_files, method, no_labels):
|
18
|
+
"""
|
19
|
+
Ensemble predictions from multiple experiments.
|
20
|
+
|
21
|
+
Args:
|
22
|
+
config_files (list): List of configuration file paths.
|
23
|
+
method (str): Ensemble method to use. Options are 'majority_voting', 'mean', 'max', or 'sum'.
|
24
|
+
no_labels (bool): Flag indicating whether the predictions have labels or not.
|
25
|
+
|
26
|
+
Returns:
|
27
|
+
pandas.DataFrame: The ensemble predictions.
|
28
|
+
|
29
|
+
Raises:
|
30
|
+
ValueError: If an unknown ensemble method is provided.
|
31
|
+
AssertionError: If the number of config files is less than 2 for majority voting.
|
32
|
+
|
33
|
+
"""
|
34
|
+
ensemble_preds = []
|
35
|
+
# labels = []
|
36
|
+
for config_file in config_files:
|
37
|
+
if no_labels:
|
38
|
+
# for ensembling results from Nkululeko.demo
|
39
|
+
pred = pd.read_csv(config_file)
|
40
|
+
labels = pred.columns[1:-2]
|
41
|
+
else:
|
42
|
+
# for ensembling results from Nkululeko.nkululeko
|
43
|
+
config = configparser.ConfigParser()
|
44
|
+
config.read(config_file)
|
45
|
+
expr = Experiment(config)
|
46
|
+
module = "ensemble"
|
47
|
+
expr.set_module(module)
|
48
|
+
util = Util(module, has_config=True)
|
49
|
+
util.debug(
|
50
|
+
f"running {expr.name} from config {config_file}, nkululeko version"
|
51
|
+
f" {VERSION}"
|
52
|
+
)
|
53
|
+
|
54
|
+
# get labels
|
55
|
+
labels = expr.util.get_labels()
|
56
|
+
# load the experiment
|
57
|
+
# get CSV files of predictions
|
58
|
+
pred = expr.util.get_pred_name()
|
59
|
+
print(f"Loading predictions from {pred}")
|
60
|
+
preds = pd.read_csv(pred)
|
61
|
+
|
62
|
+
ensemble_preds.append(preds)
|
63
|
+
|
64
|
+
# pd concate
|
65
|
+
ensemble_preds = pd.concat(ensemble_preds, axis=1)
|
66
|
+
|
67
|
+
if method == "majority_voting":
|
68
|
+
# majority voting, get mode, works for odd number of models
|
69
|
+
# raise error when number of configs only two:
|
70
|
+
assert (
|
71
|
+
len(config_files) > 2
|
72
|
+
), "Majority voting only works for more than two models"
|
73
|
+
ensemble_preds["predicted"] = ensemble_preds.mode(axis=1)[0]
|
74
|
+
|
75
|
+
elif method == "mean":
|
76
|
+
for label in labels:
|
77
|
+
ensemble_preds[label] = ensemble_preds[label].mean(axis=1)
|
78
|
+
|
79
|
+
elif method == "max":
|
80
|
+
for label in labels:
|
81
|
+
ensemble_preds[label] = ensemble_preds[label].max(axis=1)
|
82
|
+
# get max value from all labels to inver that labels
|
83
|
+
|
84
|
+
elif method == "sum":
|
85
|
+
for label in labels:
|
86
|
+
ensemble_preds[label] = ensemble_preds[label].sum(axis=1)
|
87
|
+
|
88
|
+
else:
|
89
|
+
raise ValueError(f"Unknown ensemble method: {method}")
|
90
|
+
|
91
|
+
# get the highest value from all labels to inver that labels
|
92
|
+
# replace the old first predicted column
|
93
|
+
ensemble_preds["predicted"] = ensemble_preds[labels].idxmax(axis=1)
|
94
|
+
|
95
|
+
if no_labels:
|
96
|
+
return ensemble_preds
|
97
|
+
|
98
|
+
# Drop start, end columns
|
99
|
+
ensemble_preds = ensemble_preds.drop(columns=["start", "end"])
|
100
|
+
|
101
|
+
# Drop other column except until truth
|
102
|
+
ensemble_preds = ensemble_preds.iloc[:, : len(labels) + 3]
|
103
|
+
|
104
|
+
# calculate UAR from predicted and truth columns
|
105
|
+
|
106
|
+
truth = ensemble_preds["truth"]
|
107
|
+
predicted = ensemble_preds["predicted"]
|
108
|
+
uar = (truth == predicted).mean()
|
109
|
+
Util("ensemble").debug(f"UAR: {uar:.3f}")
|
110
|
+
|
111
|
+
# only return until 'predicted' column
|
112
|
+
return ensemble_preds
|
113
|
+
|
114
|
+
|
115
|
+
def main(src_dir):
|
116
|
+
parser = ArgumentParser()
|
117
|
+
parser.add_argument(
|
118
|
+
"configs",
|
119
|
+
nargs="+",
|
120
|
+
help="Paths to the configuration files of the experiments to ensemble. \
|
121
|
+
Can be INI files for Nkululeko.nkululeo or CSV files from Nkululeko.demo.",
|
122
|
+
)
|
123
|
+
parser.add_argument(
|
124
|
+
"--method",
|
125
|
+
default="majority_voting",
|
126
|
+
choices=["majority_voting", "mean", "max", "sum"],
|
127
|
+
help="Ensemble method to use (default: majority_voting)",
|
128
|
+
)
|
129
|
+
parser.add_argument(
|
130
|
+
"--outfile",
|
131
|
+
default="ensemble_result.csv",
|
132
|
+
help="Output file path for the ensemble predictions (default: ensemble_predictions.csv)",
|
133
|
+
)
|
134
|
+
|
135
|
+
# add argument if true label is not available
|
136
|
+
parser.add_argument(
|
137
|
+
"--no_labels",
|
138
|
+
action="store_true",
|
139
|
+
help="True if true labels are not available. For Nkululeko.demo results.",
|
140
|
+
)
|
141
|
+
|
142
|
+
args = parser.parse_args()
|
143
|
+
|
144
|
+
start = time.time()
|
145
|
+
|
146
|
+
ensemble_preds = ensemble_predictions(args.configs, args.method, args.no_labels)
|
147
|
+
|
148
|
+
# save to csv
|
149
|
+
ensemble_preds.to_csv(args.outfile, index=False)
|
150
|
+
print(f"Ensemble predictions saved to: {args.outfile}")
|
151
|
+
print(f"Ensemble done, used {time.time()-start:.2f} seconds")
|
152
|
+
|
153
|
+
print("DONE")
|
154
|
+
|
155
|
+
|
156
|
+
if __name__ == "__main__":
|
157
|
+
cwd = Path(__file__).parent
|
158
|
+
main(cwd)
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# feats_ast.py
|
2
|
+
import os
|
3
|
+
|
4
|
+
import numpy as np
|
5
|
+
import pandas as pd
|
6
|
+
import torch
|
7
|
+
import torch.nn.functional as F
|
8
|
+
import torchaudio
|
9
|
+
from tqdm import tqdm
|
10
|
+
from transformers import AutoProcessor, ASTModel
|
11
|
+
|
12
|
+
import nkululeko.glob_conf as glob_conf
|
13
|
+
from nkululeko.feat_extract.featureset import Featureset
|
14
|
+
|
15
|
+
|
16
|
+
class Ast(Featureset):
|
17
|
+
"""Class to extract AST (Audio Spectrogram Transformer) embeddings"""
|
18
|
+
|
19
|
+
def __init__(self, name, data_df, feat_type):
|
20
|
+
super().__init__(name, data_df, feat_type)
|
21
|
+
cuda = "cuda" if torch.cuda.is_available() else "cpu"
|
22
|
+
self.device = self.util.config_val("MODEL", "device", cuda)
|
23
|
+
self.model_initialized = False
|
24
|
+
self.feat_type = feat_type
|
25
|
+
|
26
|
+
def init_model(self):
|
27
|
+
self.util.debug("loading AST model...")
|
28
|
+
model_path = self.util.config_val(
|
29
|
+
"FEATS", "ast.model", "MIT/ast-finetuned-audioset-10-10-0.4593"
|
30
|
+
)
|
31
|
+
self.processor = AutoProcessor.from_pretrained(model_path)
|
32
|
+
self.model = ASTModel.from_pretrained(model_path).to(self.device)
|
33
|
+
print(f"initialized AST model on {self.device}")
|
34
|
+
self.model.eval()
|
35
|
+
self.model_initialized = True
|
36
|
+
|
37
|
+
|
38
|
+
def extract(self):
|
39
|
+
"""Extract the features or load them from disk if present."""
|
40
|
+
store = self.util.get_path("store")
|
41
|
+
storage = f"{store}{self.name}.pkl"
|
42
|
+
extract = self.util.config_val("FEATS", "needs_feature_extraction", False)
|
43
|
+
no_reuse = eval(self.util.config_val("FEATS", "no_reuse", "False"))
|
44
|
+
if extract or no_reuse or not os.path.isfile(storage):
|
45
|
+
if not self.model_initialized:
|
46
|
+
self.init_model()
|
47
|
+
self.util.debug("extracting wavlm embeddings, this might take a while...")
|
48
|
+
emb_series = pd.Series(index=self.data_df.index, dtype=object)
|
49
|
+
length = len(self.data_df.index)
|
50
|
+
for idx, (file, start, end) in enumerate(
|
51
|
+
tqdm(self.data_df.index.to_list())
|
52
|
+
):
|
53
|
+
signal, sampling_rate = torchaudio.load(
|
54
|
+
file,
|
55
|
+
frame_offset=int(start.total_seconds() * 16000),
|
56
|
+
num_frames=int((end - start).total_seconds() * 16000),
|
57
|
+
)
|
58
|
+
# make mono if stereo
|
59
|
+
if signal.shape[0] == 2:
|
60
|
+
signal = torch.mean(signal, dim=0, keepdim=True)
|
61
|
+
|
62
|
+
assert (
|
63
|
+
sampling_rate == 16000
|
64
|
+
), f"sampling rate should be 16000 but is {sampling_rate}"
|
65
|
+
emb = self.get_embeddings(signal, sampling_rate, file)
|
66
|
+
emb_series.iloc[idx] = emb
|
67
|
+
self.df = pd.DataFrame(emb_series.values.tolist(), index=self.data_df.index)
|
68
|
+
self.df.to_pickle(storage)
|
69
|
+
try:
|
70
|
+
glob_conf.config["DATA"]["needs_feature_extraction"] = "false"
|
71
|
+
except KeyError:
|
72
|
+
pass
|
73
|
+
else:
|
74
|
+
self.util.debug(f"reusing extracted {self.feat_type} embeddings")
|
75
|
+
self.df = pd.read_pickle(storage)
|
76
|
+
if self.df.isnull().values.any():
|
77
|
+
# nanrows = self.df.columns[self.df.isna().any()].tolist()
|
78
|
+
# print(nanrows)
|
79
|
+
self.util.error(
|
80
|
+
f"got nan: {self.df.shape} {self.df.isnull().sum().sum()}"
|
81
|
+
)
|
82
|
+
|
83
|
+
|
84
|
+
def get_embeddings(self, signal, sampling_rate, file):
|
85
|
+
"""Extract embeddings from raw audio signal."""
|
86
|
+
try:
|
87
|
+
inputs = self.processor(signal.numpy(), sampling_rate=sampling_rate, return_tensors="pt")
|
88
|
+
|
89
|
+
inputs = {k: v.to(self.device) for k, v in inputs.items()}
|
90
|
+
|
91
|
+
with torch.no_grad():
|
92
|
+
# Get the hidden states
|
93
|
+
outputs = self.model(**inputs)
|
94
|
+
|
95
|
+
# Get the hidden states from the last layer
|
96
|
+
last_hidden_state = outputs.last_hidden_state
|
97
|
+
|
98
|
+
# print(f"last_hidden_state shape: {last_hidden_state.shape}")
|
99
|
+
# Average pooling over the time dimension
|
100
|
+
embeddings = torch.mean(last_hidden_state, dim=1)
|
101
|
+
embeddings = embeddings.cpu().numpy()
|
102
|
+
|
103
|
+
# convert the same from (768,) to (1, 768)
|
104
|
+
# embeddings = embeddings.reshape(1, -1)
|
105
|
+
print(f"hs shape: {embeddings.shape}")
|
106
|
+
|
107
|
+
|
108
|
+
except Exception as e:
|
109
|
+
self.util.error(f"Error extracting embeddings for file {file}: {str(e)}, fill with")
|
110
|
+
return np.zeros(
|
111
|
+
self.model.config.hidden_size
|
112
|
+
) # Return zero vector on error
|
113
|
+
return embeddings.ravel()
|
114
|
+
|
115
|
+
def extract_sample(self, signal, sr):
|
116
|
+
self.init_model()
|
117
|
+
feats = self.get_embeddings(signal, sr, "no file")
|
118
|
+
return feats
|
@@ -47,9 +47,7 @@ class Wav2vec2(Featureset):
|
|
47
47
|
config.num_hidden_layers = layer_num - hidden_layer
|
48
48
|
self.util.debug(f"using hidden layer #{config.num_hidden_layers}")
|
49
49
|
self.processor = Wav2Vec2FeatureExtractor.from_pretrained(model_path)
|
50
|
-
self.model = Wav2Vec2Model.from_pretrained(model_path, config=config).to(
|
51
|
-
self.device
|
52
|
-
)
|
50
|
+
self.model = Wav2Vec2Model.from_pretrained(model_path, config=config).to(self.device)
|
53
51
|
print(f"intialized Wav2vec model on {self.device}")
|
54
52
|
self.model.eval()
|
55
53
|
self.model_initialized = True
|
@@ -90,7 +88,7 @@ class Wav2vec2(Featureset):
|
|
90
88
|
self.util.debug("reusing extracted wav2vec2 embeddings")
|
91
89
|
self.df = pd.read_pickle(storage)
|
92
90
|
if self.df.isnull().values.any():
|
93
|
-
nanrows = self.df.columns[self.df.isna().any()].tolist()
|
91
|
+
# nanrows = self.df.columns[self.df.isna().any()].tolist()
|
94
92
|
# print(nanrows)
|
95
93
|
self.util.error(
|
96
94
|
f"got nan: {self.df.shape} {self.df.isnull().sum().sum()}"
|
@@ -79,8 +79,8 @@ class Wavlm(Featureset):
|
|
79
79
|
self.util.debug(f"reusing extracted {self.feat_type} embeddings")
|
80
80
|
self.df = pd.read_pickle(storage)
|
81
81
|
if self.df.isnull().values.any():
|
82
|
-
nanrows = self.df.columns[self.df.isna().any()].tolist()
|
83
|
-
print(nanrows)
|
82
|
+
# nanrows = self.df.columns[self.df.isna().any()].tolist()
|
83
|
+
# print(nanrows)
|
84
84
|
self.util.error(
|
85
85
|
f"got nan: {self.df.shape} {self.df.isnull().sum().sum()}"
|
86
86
|
)
|
@@ -104,11 +104,14 @@ class Wavlm(Featureset):
|
|
104
104
|
# pool result and convert to numpy
|
105
105
|
y = torch.mean(y, dim=1)
|
106
106
|
y = y.detach().cpu().numpy()
|
107
|
+
|
108
|
+
# print(f"hs shape: {y.shape}")
|
109
|
+
|
107
110
|
except RuntimeError as re:
|
108
111
|
print(str(re))
|
109
|
-
self.util.error(f"
|
112
|
+
self.util.error(f"Couldn't extract file: {file}")
|
110
113
|
|
111
|
-
return y.
|
114
|
+
return y.ravel()
|
112
115
|
|
113
116
|
def extract_sample(self, signal, sr):
|
114
117
|
self.init_model()
|
nkululeko/feature_extractor.py
CHANGED
@@ -39,12 +39,10 @@ class FeatureExtractor:
|
|
39
39
|
self.feats = pd.DataFrame()
|
40
40
|
for feats_type in self.feats_types:
|
41
41
|
store_name = f"{self.data_name}_{feats_type}"
|
42
|
-
self.feat_extractor = self._get_feat_extractor(
|
43
|
-
store_name, feats_type)
|
42
|
+
self.feat_extractor = self._get_feat_extractor(store_name, feats_type)
|
44
43
|
self.feat_extractor.extract()
|
45
44
|
self.feat_extractor.filter()
|
46
|
-
self.feats = pd.concat(
|
47
|
-
[self.feats, self.feat_extractor.df], axis=1)
|
45
|
+
self.feats = pd.concat([self.feats, self.feat_extractor.df], axis=1)
|
48
46
|
return self.feats
|
49
47
|
|
50
48
|
def extract_sample(self, signal, sr):
|
@@ -77,7 +75,7 @@ class FeatureExtractor:
|
|
77
75
|
return TRILLset
|
78
76
|
|
79
77
|
elif feats_type.startswith(
|
80
|
-
("wav2vec2", "hubert", "wavlm", "spkrec", "whisper")
|
78
|
+
("wav2vec2", "hubert", "wavlm", "spkrec", "whisper", "ast")
|
81
79
|
):
|
82
80
|
return self._get_feat_extractor_by_prefix(feats_type)
|
83
81
|
|
@@ -107,15 +105,13 @@ class FeatureExtractor:
|
|
107
105
|
prefix, _, ext = feats_type.partition("-")
|
108
106
|
from importlib import import_module
|
109
107
|
|
110
|
-
module = import_module(
|
111
|
-
f"nkululeko.feat_extract.feats_{prefix.lower()}")
|
108
|
+
module = import_module(f"nkululeko.feat_extract.feats_{prefix.lower()}")
|
112
109
|
class_name = f"{prefix.capitalize()}"
|
113
110
|
return getattr(module, class_name)
|
114
111
|
|
115
112
|
def _get_feat_extractor_by_name(self, feats_type):
|
116
113
|
from importlib import import_module
|
117
114
|
|
118
|
-
module = import_module(
|
119
|
-
f"nkululeko.feat_extract.feats_{feats_type.lower()}")
|
115
|
+
module = import_module(f"nkululeko.feat_extract.feats_{feats_type.lower()}")
|
120
116
|
class_name = f"{feats_type.capitalize()}Set"
|
121
117
|
return getattr(module, class_name)
|
nkululeko/test_predictor.py
CHANGED
@@ -6,13 +6,12 @@
|
|
6
6
|
|
7
7
|
import ast
|
8
8
|
|
9
|
-
import numpy as np
|
10
9
|
import pandas as pd
|
11
10
|
from sklearn.preprocessing import LabelEncoder
|
12
11
|
|
12
|
+
import nkululeko.glob_conf as glob_conf
|
13
13
|
from nkululeko.data.dataset import Dataset
|
14
14
|
from nkululeko.feature_extractor import FeatureExtractor
|
15
|
-
import nkululeko.glob_conf as glob_conf
|
16
15
|
from nkululeko.scaler import Scaler
|
17
16
|
from nkululeko.utils.util import Util
|
18
17
|
|
@@ -42,7 +41,6 @@ class TestPredictor:
|
|
42
41
|
scale = self.util.config_val("FEATS", "scale", False)
|
43
42
|
labelenc = LabelEncoder()
|
44
43
|
data_df[self.target] = labelenc.fit_transform(data_df[self.target])
|
45
|
-
# data_df[self.target] = self.label_encoder.fit_transform(data_df[self.target])
|
46
44
|
if scale:
|
47
45
|
self.scaler = Scaler(data_df, None, feats_df, None, scale)
|
48
46
|
feats_df, _ = self.scaler.scale()
|
nkululeko/utils/util.py
CHANGED
@@ -37,8 +37,7 @@ class Util:
|
|
37
37
|
import nkululeko.glob_conf as glob_conf
|
38
38
|
|
39
39
|
self.config = glob_conf.config
|
40
|
-
self.got_data_roots = self.config_val(
|
41
|
-
"DATA", "root_folders", False)
|
40
|
+
self.got_data_roots = self.config_val("DATA", "root_folders", False)
|
42
41
|
if self.got_data_roots:
|
43
42
|
# if there is a global data rootfolder file, read from
|
44
43
|
# there
|
@@ -108,19 +107,17 @@ class Util:
|
|
108
107
|
if self.got_data_roots:
|
109
108
|
try:
|
110
109
|
if len(key) > 0:
|
111
|
-
return self.data_roots["DATA"][dataset +
|
112
|
-
"." + key].strip("'\"")
|
110
|
+
return self.data_roots["DATA"][dataset + "." + key].strip("'\"")
|
113
111
|
else:
|
114
112
|
return self.data_roots["DATA"][dataset].strip("'\"")
|
115
113
|
except KeyError:
|
116
114
|
if default not in self.stopvals:
|
117
115
|
self.debug(
|
118
|
-
f"value for {key} not found, using default:"
|
119
|
-
|
116
|
+
f"value for {key} not found, using default:" f" {default}"
|
117
|
+
)
|
120
118
|
return default
|
121
119
|
if default not in self.stopvals:
|
122
|
-
self.debug(
|
123
|
-
f"value for {key} not found, using default: {default}")
|
120
|
+
self.debug(f"value for {key} not found, using default: {default}")
|
124
121
|
return default
|
125
122
|
|
126
123
|
def set_config(self, config):
|
@@ -131,6 +128,10 @@ class Util:
|
|
131
128
|
store = self.get_path("store")
|
132
129
|
return f"{store}/{self.get_exp_name()}.pkl"
|
133
130
|
|
131
|
+
def get_pred_name(self):
|
132
|
+
store = self.get_path("store")
|
133
|
+
return f"{store}/pred_df.csv"
|
134
|
+
|
134
135
|
def is_categorical(self, pd_series):
|
135
136
|
"""Check if a dataframe column is categorical"""
|
136
137
|
return pd_series.dtype.name == "object" or isinstance(
|
@@ -163,10 +164,8 @@ class Util:
|
|
163
164
|
if len(df) == 0:
|
164
165
|
return df
|
165
166
|
if not isinstance(df.index, pd.MultiIndex):
|
166
|
-
self.debug(
|
167
|
-
|
168
|
-
df.index = audformat.utils.to_segmented_index(
|
169
|
-
df.index, allow_nat=False)
|
167
|
+
self.debug("converting to segmented index, this might take a while...")
|
168
|
+
df.index = audformat.utils.to_segmented_index(df.index, allow_nat=False)
|
170
169
|
return df
|
171
170
|
|
172
171
|
def _get_value_descript(self, section, name):
|
@@ -209,7 +208,11 @@ class Util:
|
|
209
208
|
mt = f'{self.config["MODEL"]["type"]}'
|
210
209
|
# ft = "_".join(ast.literal_eval(self.config["FEATS"]["type"]))
|
211
210
|
ft_value = self.config["FEATS"]["type"]
|
212
|
-
if
|
211
|
+
if (
|
212
|
+
isinstance(ft_value, str)
|
213
|
+
and ft_value.startswith("[")
|
214
|
+
and ft_value.endswith("]")
|
215
|
+
):
|
213
216
|
ft = "_".join(ast.literal_eval(ft_value))
|
214
217
|
else:
|
215
218
|
ft = ft_value
|
@@ -237,8 +240,9 @@ class Util:
|
|
237
240
|
["FEATS", "wav2vec2.layer"],
|
238
241
|
]
|
239
242
|
for option in options:
|
240
|
-
return_string += self._get_value_descript(
|
241
|
-
|
243
|
+
return_string += self._get_value_descript(option[0], option[1]).replace(
|
244
|
+
".", "-"
|
245
|
+
)
|
242
246
|
return return_string
|
243
247
|
|
244
248
|
def get_plot_name(self):
|
@@ -284,8 +288,7 @@ class Util:
|
|
284
288
|
return self.config[section][key]
|
285
289
|
except KeyError:
|
286
290
|
if default not in self.stopvals:
|
287
|
-
self.debug(
|
288
|
-
f"value for {key} not found, using default: {default}")
|
291
|
+
self.debug(f"value for {key} not found, using default: {default}")
|
289
292
|
return default
|
290
293
|
|
291
294
|
def config_val_list(self, section, key, default):
|
@@ -293,10 +296,12 @@ class Util:
|
|
293
296
|
return ast.literal_eval(self.config[section][key])
|
294
297
|
except KeyError:
|
295
298
|
if default not in self.stopvals:
|
296
|
-
self.debug(
|
297
|
-
f"value for {key} not found, using default: {default}")
|
299
|
+
self.debug(f"value for {key} not found, using default: {default}")
|
298
300
|
return default
|
299
301
|
|
302
|
+
def get_labels(self):
|
303
|
+
return ast.literal_eval(self.config["DATA"]["labels"])
|
304
|
+
|
300
305
|
def continuous_to_categorical(self, series):
|
301
306
|
"""
|
302
307
|
discretize a categorical variable.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: nkululeko
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.88.0
|
4
4
|
Summary: Machine learning audio prediction experiments based on templates
|
5
5
|
Home-page: https://github.com/felixbur/nkululeko
|
6
6
|
Author: Felix Burkhardt
|
@@ -201,6 +201,11 @@ Here is an overview of the interfaces/modules:
|
|
201
201
|
All of them take *--config <my_config.ini>* as an argument.
|
202
202
|
|
203
203
|
* **nkululeko.nkululeko**: do machine learning experiments combining features and learners
|
204
|
+
* **nkululeko.ensemble**: combine several nkululeko experiments and report on late fusion results
|
205
|
+
* *configurations*: which experiments to combine
|
206
|
+
* *--method* (optional): majority_voting, mean, max, sum
|
207
|
+
* *--outfile* (optional): name of CSV file for output
|
208
|
+
* *--no_labels* (optional): indicate that no ground truth is given
|
204
209
|
* **nkululeko.multidb**: do [multiple experiments](http://blog.syntheticspeech.de/2024/01/02/nkululeko-compare-several-databases/), comparing several databases cross and in itself
|
205
210
|
* **nkululeko.demo**: [demo the current best model](http://blog.syntheticspeech.de/2022/01/24/nkululeko-try-out-demo-a-trained-model/) on the command line
|
206
211
|
* *--list* (optional) list of input files
|
@@ -351,6 +356,10 @@ F. Burkhardt, Johannes Wagner, Hagen Wierstorf, Florian Eyben and Björn Schulle
|
|
351
356
|
Changelog
|
352
357
|
=========
|
353
358
|
|
359
|
+
Version 0.88.0
|
360
|
+
--------------
|
361
|
+
* added ensemble late fusion and AST features
|
362
|
+
|
354
363
|
Version 0.87.0
|
355
364
|
--------------
|
356
365
|
* added class probability output and uncertainty analysis
|
@@ -2,14 +2,15 @@ nkululeko/__init__.py,sha256=62f8HiEzJ8rG2QlTFJXUCMpvuH3fKI33DoJSj33mscc,63
|
|
2
2
|
nkululeko/aug_train.py,sha256=YhuZnS_WVWnun9G-M6g5n6rbRxoVREz6Zh7k6qprFNQ,3194
|
3
3
|
nkululeko/augment.py,sha256=4MG0apTAG5RgkuJrYEjGgDdbodZWi_HweSPNI1JJ5QA,3051
|
4
4
|
nkululeko/cacheddataset.py,sha256=lIJ6hUo5LoxSrzXtWV8mzwO7wRtUETWnOQ4ws2XfL1E,969
|
5
|
-
nkululeko/constants.py,sha256=
|
6
|
-
nkululeko/demo.py,sha256=
|
5
|
+
nkululeko/constants.py,sha256=KhD5BoAv4ItEdg4vSAq1wew4zjdCOGPQxR6syd9NoEo,39
|
6
|
+
nkululeko/demo.py,sha256=bLuHkeEl5rOfm7ecGHCcWATiPK7-njNbtrGljxzNzFs,5088
|
7
7
|
nkululeko/demo_feats.py,sha256=sAeGFojhEj9WEDFtG3SzPBmyYJWLF2rkbpp65m8Ujo4,2025
|
8
8
|
nkululeko/demo_predictor.py,sha256=es56xbT8ifkS_vnrlb5NTZT54gNmeUtNlA4zVA_gnN8,4757
|
9
|
+
nkululeko/ensemble.py,sha256=huRbXUuabm6QYxGBHjkwEU95e-0qxtO0Z6UdXFgtaMY,4947
|
9
10
|
nkululeko/experiment.py,sha256=s9PIjm45dR9yzmHu_69JpBjX9qMVzi5wIgPfMR3F44A,31530
|
10
11
|
nkululeko/explore.py,sha256=lDzRoW_Taa5u4BBABZLD89BcQWnYlrftJR4jgt1yyj0,2609
|
11
12
|
nkululeko/export.py,sha256=mHeEAAmtZuxdyebLlbSzPrHSi9OMgJHbk35d3DTxRBc,4632
|
12
|
-
nkululeko/feature_extractor.py,sha256=
|
13
|
+
nkululeko/feature_extractor.py,sha256=UnspIWz3XrNhKnBBhWZkH2bHvD-sROtrQVqB1JvkUyw,4088
|
13
14
|
nkululeko/file_checker.py,sha256=LoLnL8aHpW-axMQ46qbqrManTs5otG9ShpEZuz9iRSk,3474
|
14
15
|
nkululeko/filter_data.py,sha256=w-X2mhKdYr5DxDIz50E5yzO6Jmzk4jjDBoXsgOOVtcA,7222
|
15
16
|
nkululeko/glob_conf.py,sha256=KL9YJQTHvTztxo1vr25qRRgaPnx4NTg0XrdbovKGMmw,525
|
@@ -25,7 +26,7 @@ nkululeko/scaler.py,sha256=4nkIqoajkIkuTPK0Z02ifMN_awl6fP_i-GBYdoGYgGM,4101
|
|
25
26
|
nkululeko/segment.py,sha256=YLKckX44tbvTb3LrdgYw9X4guzuF27sutl92z9DkpZU,4835
|
26
27
|
nkululeko/syllable_nuclei.py,sha256=Sky-C__MeUDaxqHnDl2TGLLYOYvsahD35TUjWGeG31k,10047
|
27
28
|
nkululeko/test.py,sha256=1w624vo5KTzmFC8BUStGlLDmIEAFuJUz7J0W-gp7AxI,1677
|
28
|
-
nkululeko/test_predictor.py,sha256=
|
29
|
+
nkululeko/test_predictor.py,sha256=DEHE_D3A6m6KJTrpDKceA1n655t_UZV3WQd57K4a3Ho,2863
|
29
30
|
nkululeko/test_pretrain.py,sha256=ZWl-bR6nmeSmXkGAIE6zyfQEjN8Zg0rIxfaS-O6Zbas,8465
|
30
31
|
nkululeko/augmenting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
31
32
|
nkululeko/augmenting/augmenter.py,sha256=XAt0dpmlnKxqyysqCgV3rcz-pRIvOz7rU7dmGDCVAzs,2905
|
@@ -51,6 +52,7 @@ nkululeko/feat_extract/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
51
52
|
nkululeko/feat_extract/feats_agender.py,sha256=Qm69G4kqAyTVVk7wwRgrXlNwGaDMGRYyKGpuf0vOEgM,3113
|
52
53
|
nkululeko/feat_extract/feats_agender_agender.py,sha256=tgH2BnwcxpvuLmOkrMbVdBSX0Onfz2MG12FsddalRKI,3424
|
53
54
|
nkululeko/feat_extract/feats_analyser.py,sha256=Y9hMpZ9WsQOrxTP3B1diHnzMeOgwbVpVFWVlIyhHMJs,12722
|
55
|
+
nkululeko/feat_extract/feats_ast.py,sha256=LolDaRTfNB9L8-CUqz9tOfkXntL8c9GJs4kqMmg5BSo,4724
|
54
56
|
nkululeko/feat_extract/feats_auddim.py,sha256=VlzKKXTXa5kjLgQBWyEFy-daIyU1SkOwCCOIhKsWCvE,3162
|
55
57
|
nkululeko/feat_extract/feats_audmodel.py,sha256=VjBNgAoxsHJhwr6Kwt9CxX6SaCM4RK_OV-GU2W5-bhU,3187
|
56
58
|
nkululeko/feat_extract/feats_clap.py,sha256=nR6eEIRdsMHcfmD1bNtt5WfDvkxKjvEbukSSrXHm-HU,3489
|
@@ -66,8 +68,8 @@ nkululeko/feat_extract/feats_spectra.py,sha256=5Pex8awIQC3cjQRHSu4NQFmg4quamG0RL
|
|
66
68
|
nkululeko/feat_extract/feats_spkrec.py,sha256=VK4ma3uWzM0YZStsgRTirfkbzjWIfRWSgsYI038QlRY,4803
|
67
69
|
nkululeko/feat_extract/feats_squim.py,sha256=Y31YmDmscuG0YozvxyBZIutO3id8t7IZJWCfKucw-6M,4617
|
68
70
|
nkululeko/feat_extract/feats_trill.py,sha256=K2ahhdpwpjgg3WZS1POg3UMP2U44i8cLZZvn5Rq7fUI,3228
|
69
|
-
nkululeko/feat_extract/feats_wav2vec2.py,sha256=
|
70
|
-
nkululeko/feat_extract/feats_wavlm.py,sha256=
|
71
|
+
nkululeko/feat_extract/feats_wav2vec2.py,sha256=XyxD4NcrF4VFWSeHkXCKWdEOdr8VMzgVUz8N4mwhdyo,5248
|
72
|
+
nkululeko/feat_extract/feats_wavlm.py,sha256=O9cfc39VF5aPJRRATKb37pHT4W11i2cu5O1mY9LOjIA,4755
|
71
73
|
nkululeko/feat_extract/feats_whisper.py,sha256=0N7Vj65OVi2PNoB_NrDjWT5lP6xZNKxFOZZIoxkJvcA,4533
|
72
74
|
nkululeko/feat_extract/featureset.py,sha256=ll7tyKAdr--TDShyOYJg0FB4I9NqBq0Ni1k_kUJ-2Vw,1541
|
73
75
|
nkululeko/feat_extract/feinberg_praat.py,sha256=EP9pMALjlKdiYInLQdrZ7MmE499Mq-ISRCgqbqL3Rxc,21304
|
@@ -104,9 +106,9 @@ nkululeko/segmenting/seg_silero.py,sha256=lLytS38KzARS17omwv8VBw-zz60RVSXGSvZ5Ev
|
|
104
106
|
nkululeko/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
105
107
|
nkululeko/utils/files.py,sha256=UiGAtZRWYjHSvlmPaTMtzyNNGE6qaLaxQkybctS7iRM,4021
|
106
108
|
nkululeko/utils/stats.py,sha256=eC9dMO-by6CDnGLHDBQu-2B4-BudZNJ0nnWGhKYdUMA,2968
|
107
|
-
nkululeko/utils/util.py,sha256=
|
108
|
-
nkululeko-0.
|
109
|
-
nkululeko-0.
|
110
|
-
nkululeko-0.
|
111
|
-
nkululeko-0.
|
112
|
-
nkululeko-0.
|
109
|
+
nkululeko/utils/util.py,sha256=eQkfd_3MO2JYis5QbROnCmhglQGkl4-F9TLCT1uiQH0,14514
|
110
|
+
nkululeko-0.88.0.dist-info/LICENSE,sha256=0zGP5B_W35yAcGfHPS18Q2B8UhvLRY3dQq1MhpsJU_U,1076
|
111
|
+
nkululeko-0.88.0.dist-info/METADATA,sha256=RTWqGxR2H8T7hM_h8PFAqnssBdfPxEjmB289vVMoEyo,38853
|
112
|
+
nkululeko-0.88.0.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
|
113
|
+
nkululeko-0.88.0.dist-info/top_level.txt,sha256=DPFNNSHPjUeVKj44dVANAjuVGRCC3MusJ08lc2a8xFA,10
|
114
|
+
nkululeko-0.88.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|