Я создал пользовательские классы, которые хотят использовать с конвейерами scikit-learn и Feature-Unions.
Каждый класс принимает в качестве входных данных фрейм данных с 2 столбцами: 0, 1
Каждая строка в первом столбце является массивом пустых чисел, а каждая строка во второй строке является числом.
Учитывая эти два входа, я создал статическую функцию, которая вычисляет для каждой строки значений кадра данных 40.
Так что, если исходный кадр данных имеетформа 100 x 2, вывод должен быть 100 x 40.
Я использовал модули BaseEstimator и TransformerMixin для простой обработки методов fit_transform.
Когда я вызываю метод fit_transform, я получаю следующую ошибку:
ValueError: Форма переданных значений (288, 40), индексы подразумевают (288, 2)
class MelFrequencyCepstralCoefficientsCalculator(BaseEstimator, TransformerMixin):
"""outputs Mel-frequency cepstral coefficients"""
def __init__(self):
"""
"""
@staticmethod
def calculate_coef(file_array: np.array,
sample_rate):
"""
:param file_array:
:param sample_rate:
:return:
"""
# mfcc: Mel-frequency cepstral coefficients to each row
# this output is an array of shape (40, )
mfccs = np.mean(librosa.feature.mfcc(y=file_array,
sr=sample_rate,
n_mfcc=40).T, axis=0)
return mfccs
def transform(self, X, y=None) -> np.array:
print('Calculating Mel-frequency cepstral coefficients')
res = X.progress_apply(lambda row: self.calculate_coef(row[0], row[1]), axis=1).values
print('Output shape: {}'.format(res.shape))
return res
def fit(self, X, y=None):
"""Returns `self` unless something different happens in train and test"""
return self
mfccs = MelFrequencyCepstralCoefficientsCalculator()
x_val = mfccs.fit_transform(x_val_raw)
Разве я не могу иметь собственный класс, который создает более одного объекта в конвейере sklearn?
PS: progress_appy допустим.Я использую модуль tqdm, который расширяет apply , чтобы иметь индикатор выполнения для каждого вычисления
Обходной путь, который намного медленнее, но работает, следующий:
def transform(self, X: pd.DataFrame, y=None) -> np.array:
"""
:param X:
:param y:
:return:
"""
print('Calculating Mel-frequency cepstral coefficients')
# res = X.apply(lambda row: self.calculate_coef(row[0], row[1]), axis=1)
features = np.empty((0, 40))
rows = X.iterrows()
for row in tqdm(rows):
ext_features = self.calculate_coef(row[1][0], row[1][1])
features = np.vstack([features, ext_features])
print('Output shape: {}'.format(features.shape))
return features