Pytorch:小批量过拟合:调试

Posted

技术标签:

【中文标题】Pytorch:小批量过拟合:调试【英文标题】:Pytorch: Overfitting on a small batch: Debugging 【发布时间】:2021-01-16 11:12:54 【问题描述】:

我正在构建一个多类图像分类器。 有一个调试技巧可以对单个批次进行过拟合,以检查程序中是否存在更深层次的错误。 如何以一种可移植的格式设计代码? 一种艰巨且不明智的方法是为小批量构建一个保留训练/测试文件夹,其中测试类由 2 个分布组成 - 可见数据和不可见数据,如果模型在可见数据上表现更好而在不可见数据上表现不佳,那么我们可以得出结论,我们的网络没有任何更深层次的结构性错误。 但是,这似乎不是一种智能和便携的方式,并且必须解决所有问题。

目前,我有一个数据集类,我在其中以以下方式对 train/dev/test 中的数据进行分区 -

def split_equal_into_val_test(csv_file=None, stratify_colname='y',
                              frac_train=0.6, frac_val=0.15, frac_test=0.25,
                              ):
    """
    Split a Pandas dataframe into three subsets (train, val, and test).

    Following fractional ratios provided by the user, where val and
    test set have the same number of each classes while train set have
    the remaining number of left classes
    Parameters
    ----------
    csv_file : Input data csv file to be passed
    stratify_colname : str
        The name of the column that will be used for stratification. Usually
        this column would be for the label.
    frac_train : float
    frac_val   : float
    frac_test  : float
        The ratios with which the dataframe will be split into train, val, and
        test data. The values should be expressed as float fractions and should
        sum to 1.0.
    random_state : int, None, or RandomStateInstance
        Value to be passed to train_test_split().

    Returns
    -------
    df_train, df_val, df_test :
        Dataframes containing the three splits.

    """
    df = pd.read_csv(csv_file).iloc[:, 1:]

    if frac_train + frac_val + frac_test != 1.0:
        raise ValueError('fractions %f, %f, %f do not add up to 1.0' %
                         (frac_train, frac_val, frac_test))

    if stratify_colname not in df.columns:
        raise ValueError('%s is not a column in the dataframe' %
                         (stratify_colname))

    df_input = df

    no_of_classes = 4
    sfact = int((0.1*len(df))/no_of_classes)

    # Shuffling the data frame
    df_input = df_input.sample(frac=1)


    df_temp_1 = df_input[df_input['labels'] == 1][:sfact]
    df_temp_2 = df_input[df_input['labels'] == 2][:sfact]
    df_temp_3 = df_input[df_input['labels'] == 3][:sfact]
    df_temp_4 = df_input[df_input['labels'] == 4][:sfact]

    dev_test_df = pd.concat([df_temp_1, df_temp_2, df_temp_3, df_temp_4])
    dev_test_y = dev_test_df['labels']
    # Split the temp dataframe into val and test dataframes.
    df_val, df_test, dev_Y, test_Y = train_test_split(
        dev_test_df, dev_test_y,
        stratify=dev_test_y,
        test_size=0.5,
        )


    df_train = df[~df['img'].isin(dev_test_df['img'])]

    assert len(df_input) == len(df_train) + len(df_val) + len(df_test)

    return df_train, df_val, df_test

def train_val_to_ids(train, val, test, stratify_columns='labels'): # noqa
    """
    Convert the stratified dataset in the form of dictionary : partition['train] and labels.

    To generate the parallel code according to https://stanford.edu/~shervine/blog/pytorch-how-to-generate-data-parallel
    Parameters
    -----------
    csv_file : Input data csv file to be passed
    stratify_columns : The label column

    Returns
    -----------
    partition, labels:
        partition dictionary containing train and validation ids and label dictionary containing ids and their labels # noqa

    """
    train_list, val_list, test_list = train['img'].to_list(), val['img'].to_list(), test['img'].to_list() # noqa
    partition = "train_set": train_list,
                 "val_set": val_list,
                 
    labels = dict(zip(train.img, train.labels))
    labels.update(dict(zip(val.img, val.labels)))
    return partition, labels

P.S - 我了解 PyTorch 闪电,并且知道它们具有可以轻松使用的过度拟合功能,但我不想转向 PyTorch 闪电。

【问题讨论】:

便携是什么意思?为什么不只训练 20 个样本,直到您的模型达到 100% 成功(无论您的指标如何) 如何限制代码只训练 20 个样本,而不创建另一个数据集文件夹。 【参考方案1】:

我不知道它会如何便携,但我使用的一个技巧是修改Dataset 中的__len__ 函数。

如果我修改它来自

def __len__(self):
    return len(self.data_list)

def __len__(self):
    return 20

它只会输出数据集中的前 20 个元素(不管 shuffle)。您只需要更改一行代码,其余的应该都可以正常工作,所以我认为它非常整洁。

【讨论】:

感谢您的回答。这是否会为训练集和开发集提供相同的元素,因为如果我们提供不同的开发集和训练集,那么您不认为如果模型在开发集上表现不佳,那么它也可能由于各种其他原因而发生。 我的意思是发现网络运行正常(没有任何更深层次的结构错误),它必须在不同的开发中表现不佳,并且在训练集中遇到的相同元素上也表现出色。为此,开发集应包含这两种元素的组合。 @Mark 我不同意“必须在不同的开发人员上表现不佳”。对于调试,我们只需要对一小组数据进行过拟合。我们甚至不需要在这里设置“dev”。 @Mark 应该可以达到非常高的准确率(或者非常低的损失)。 好的,我明白了。我把事情复杂化了。我刚刚通过了 train loader 也代替了 valid loader 并且还通过了您对限制 len 功能的建议性更改。我设法发现我的网络有一个错误。谢谢。

以上是关于Pytorch:小批量过拟合:调试的主要内容,如果未能解决你的问题,请参考以下文章

Pytorch Note24 防止过拟合

Pytorch vs. Keras:Pytorch 模型严重过拟合

过拟合&欠拟合 || 深度学习 || Pytorch || 动手学深度学习11 || 跟李沐学AI

PyTorch学习(十三)过拟合

模型选择 + 过拟合和欠拟合 动手学深度学习v2 pytorch

翻译: 4.4. 模型选择Model Selection欠拟合Underfitting和过拟合Overfitting pytorch