You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 04:50:14