我创建了要与scikit-learn管道和Feature-Unions一起使用的自定义类。
每个类都将一个包含两列的数据帧作为输入:0、1
第一列中的每一行都是一个numpy数组,第二行中的每一行都是一个数字。
鉴于这两个输入,我创建了一个静态函数,用于计算数据帧40个值的每一行。
因此,如果原始数据帧的形状为100 x 2,则输出应为100 x40。
我已经使用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 有效。我正在使用扩展 apply 的tqdm模块,以便为每个计算提供进度条
以下是较慢但可行的解决方法:
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