使用STFT矩阵训练AutoEncoder遇ValueError的解决请求
问题与解决:STFT作为AutoEncoder输入的预处理错误
问题背景
作为音频处理与深度学习新手,尝试直接以STFT(不转换为频谱图)作为输入训练AutoEncoder,预处理时触发报错:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
相关代码如下:
import librosa import librosa.display import matplotlib.pyplot as plt import numpy as np import pandas as pd import IPython.display as ipd import soundfile as sf from scipy.io import wavfile import os import tensorflow as tf # path audio_dir='/content/drive/MyDrive/audio2/0' output_dir = '/content/drive/MyDrive/audio2/output' #convert wav to stft audio_list=[] stft=[] for file_name in os.listdir(audio_dir): if file_name.endswith('.wav'): file_path = os.path.join(audio_dir, file_name) y,sr = librosa.load(file_path, sr=16000) # y -> array time series (my_audio as np.array) y = np.array(y) stft_lib = np.abs(librosa.stft(y, n_fft=1024, hop_length=512, window='hann')) audio_list.append(y) stft.append(stft_lib ) #resize the stft then convert it to np.array resized_stft_list = [] # Define the target shape target_shape = (512, 64, 2) # Iterate over each STFT matrix in the list and resize it for stft in stft_list: resized_stft = np.resize(stft, target_shape) resized_stft_list.append(resized_stft) # Convert the resized STFT list to a NumPy array resized_stft_array = np.array(resized_stft_list) #split the data train_ratio = 0.8 train_stft, val_stft = train_test_split(resized_stft_array, train_size=train_ratio, random_state=42)
错误原因与修复步骤
1. 修复变量名冲突
代码中定义的STFT列表变量为stft,但后续循环错误使用了未定义的stft_list,同时循环变量stft覆盖了原列表变量,导致逻辑混乱。修改循环部分:
# 循环变量改用stft_matrix,避免覆盖原列表;遍历的是已定义的stft列表 for stft_matrix in stft: # 后续处理逻辑
2. 替换错误的形状调整方式
np.resize会通过重复/截断数据强制匹配目标形状,破坏STFT的频率-时序结构,同时强行将单通道STFT转为2通道的操作不合理。正确做法如下:
方式1:保留幅度谱,添加单通道维度(推荐)
先统一所有STFT的时间步长,再添加通道维度适配模型输入:
target_time_steps = 64 processed_stft = [] for stft_matrix in stft: freq_bins, time_steps = stft_matrix.shape # 截断或补零到目标时间步 if time_steps > target_time_steps: stft_processed = stft_matrix[:, :target_time_steps] else: pad_width = target_time_steps - time_steps stft_processed = np.pad(stft_matrix, ((0,0), (0, pad_width)), mode='constant') # 添加通道维度(适配CNN类模型的输入要求) stft_with_channel = np.expand_dims(stft_processed, axis=-1) processed_stft.append(stft_with_channel) resized_stft_array = np.array(processed_stft)
方式2:保留STFT实部+虚部作为2通道
如果确实需要2通道输入,不要强行用np.resize,而是保留STFT的复数信息拆分通道:
# 重新生成STFT时不要取绝对值,保留复数形式 stft=[] for file_name in os.listdir(audio_dir): if file_name.endswith('.wav'): file_path = os.path.join(audio_dir, file_name) y,sr = librosa.load(file_path, sr=16000) stft_lib = librosa.stft(y, n_fft=1024, hop_length=512, window='hann') # 拆分实部和虚部作为2通道 stft_2ch = np.stack([np.real(stft_lib), np.imag(stft_lib)], axis=-1) stft.append(stft_2ch) # 再统一时间步长 target_time_steps = 64 processed_stft = [] for stft_matrix in stft: freq_bins, time_steps, _ = stft_matrix.shape if time_steps > target_time_steps: stft_processed = stft_matrix[:, :target_time_steps, :] else: pad_width = target_time_steps - time_steps stft_processed = np.pad(stft_matrix, ((0,0), (0, pad_width), (0,0)), mode='constant') processed_stft.append(stft_processed) resized_stft_array = np.array(processed_stft)
3. 补充缺失的导入
代码使用了train_test_split但未导入,需添加:
from sklearn.model_selection import train_test_split
4. 匹配模型输入形状
确保AutoEncoder的输入层与预处理后的数据形状一致,例如处理后数据形状为(样本数, 513, 64, 1),输入层定义为:
input_layer = tf.keras.layers.Input(shape=(513, 64, 1))
内容的提问来源于stack exchange,提问作者chaima rebah
相关产品推荐
相关产品推荐

