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

音频分类脚本中ESC50Data类无len()方法报错排查

问题:ESC50Data类无长度属性导致TypeError报错

问题场景

在Jupyter Notebook中运行PyTorch音频分类脚本,创建DataLoader时触发TypeError: object of type 'ESC50Data' has no len()错误。

原代码如下:

from torch.utils.data import Dataset, DataLoader

class ESC50Data(Dataset):
      def __init__(self, base, df, in_col, out_col):
        self.df = df
        self.data = []
        self.labels = []
        self.c2i={}
        self.i2c={}
        self.categories = sorted(df[out_col].unique())
        for i, category in enumerate(self.categories):
            self.c2i[category]=i
            self.i2c[i]=category
        for ind in tqdm(range(len(df))):
            row = df.iloc[ind]
            file_path = os.path.join(base,row[in_col])
            self.data.append(spec_to_image(get_melspectrogram(file_path))[np.newaxis,...])
            self.labels.append(self.c2i[row['category']])
            def __len__(self):
                                    return len(self.data)
            def __getitem__(self, idx):
                                                return self.data[idx], self.labels[idx]

train_data = ESC50Data('audio', train, 'filename', 'category')
valid_data = ESC50Data('audio', valid, 'filename', 'category')

train_loader = DataLoader(train_data, batch_size=16, shuffle=True)
valid_loader = DataLoader(valid_data, batch_size=16, shuffle=True)

报错堆栈:

TypeError                                 Traceback (most recent call last)
Input In [47], in <cell line: 1>()
----> 1 train_loader = DataLoader(train_data, batch_size=16, shuffle=True)
      2 valid_loader = DataLoader(valid_data, batch_size=16, shuffle=True)

File ~/opt/anaconda3/lib/python3.9/site-packages/torch/utils/data/dataloader.py:353, in DataLoader.__init__(self, dataset, batch_size, shuffle, sampler, batch_sampler, num_workers, collate_fn, pin_memory, drop_last, timeout, worker_init_fn, multiprocessing_context, generator, prefetch_factor, persistent_workers, pin_memory_device)
    351 else:  # map-style
    352     if shuffle:
---> 353         sampler = RandomSampler(dataset, generator=generator)  # type: ignore[arg-type]
    354     else:
    355         sampler = SequentialSampler(dataset)  # type: ignore[arg-type]

File ~/opt/anaconda3/lib/python3.9/site-packages/torch/utils/data/sampler.py:106, in RandomSampler.__init__(self, data_source, replacement, num_samples, generator)
    102 if not isinstance(self.replacement, bool):
    103     raise TypeError("replacement should be a boolean value, but got "
    104                     "replacement={}".format(self.replacement))
---> 106 if not isinstance(self.num_samples, int) or self.num_samples <= 0:
    107     raise ValueError("num_samples should be a positive integer "
    108                      "value, but got num_samples={}".format(self.num_samples))

File ~/opt/anaconda3/lib/python3.9/site-packages/torch/utils/data/sampler.py:114, in RandomSampler.num_samples(self)
    110 @property
    111 def num_samples(self) -> int:
    112     # dataset size might change at runtime
    113     if self._num_samples is None:
---> 114         return len(self.data_source)
    115     return self._num_samples

TypeError: object of type 'ESC50Data' has no len()

错误原因

核心问题是缩进错误:__len__和__getitem__方法被错误定义在__init__方法内部的for循环中,导致这两个方法不是ESC50Data类的成员方法,而是for循环内的局部函数。PyTorch的Dataset子类要求必须实现__len__和__getitem__作为类的公开方法,否则DataLoader无法获取数据集长度,从而触发报错。

修正后的代码

将__len__和__getitem__的缩进调整到与__init__同级,作为类的成员方法:

from torch.utils.data import Dataset, DataLoader

class ESC50Data(Dataset):
    def __init__(self, base, df, in_col, out_col):
        self.df = df
        self.data = []
        self.labels = []
        self.c2i={}
        self.i2c={}
        self.categories = sorted(df[out_col].unique())
        for i, category in enumerate(self.categories):
            self.c2i[category]=i
            self.i2c[i]=category
        for ind in tqdm(range(len(df))):
            row = df.iloc[ind]
            file_path = os.path.join(base,row[in_col])
            self.data.append(spec_to_image(get_melspectrogram(file_path))[np.newaxis,...])
            self.labels.append(self.c2i[row['category']])
    
    # 调整缩进,作为类方法
    def __len__(self):
        return len(self.data)
    
    # 调整缩进,作为类方法
    def __getitem__(self, idx):
        return self.data[idx], self.labels[idx]

train_data = ESC50Data('audio', train, 'filename', 'category')
valid_data = ESC50Data('audio', valid, 'filename', 'category')

train_loader = DataLoader(train_data, batch_size=16, shuffle=True)
valid_loader = DataLoader(valid_data, batch_size=16, shuffle=True)

内容的提问来源于stack exchange,提问作者Adil Hydari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 10:10:25