鱼C论坛

 找回密码
 立即注册
查看: 313|回复: 9

不使用droplast=true如何保证所有样本都被预测

[复制链接]
发表于 2024-11-7 16:58:34 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
总的样本数不能被batchsize整除,最后一个batch又想保留要怎么写代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-11-7 16:58:49 | 显示全部楼层
在处理深度学习任务时,通常会使用小批量(batch)处理数据,`drop_last=True` 意味着在样本数不能被批量大小整除的情况下舍弃最后一批数据。要确保所有样本都参与预测而不舍弃最后的批次,你可以采取以下方法:

1. **手动处理最后一个批次**:
   可以在循环过程中手动处理最后一个批次数据,而不是使用 `drop_last=True`。这种方式需要在循环结束后,再次处理未形成完整批次的剩余样本。

2. **DataLoader默认行为**:
   如果你在使用 PyTorch 的 `DataLoader` ,默认情况下 `drop_last=False`,所以只需要确保不设置 `drop_last=True` 即可。

3. **示例代码**:
   以下是一个简单示例,展示如何确保所有样本都被预测:

  
  1. import torch
  2.    from torch.utils.data import DataLoader, TensorDataset

  3.    # 创建一些示例数据
  4.    data = torch.arange(0, 23).float().reshape(-1, 1)
  5.    dataset = TensorDataset(data)

  6.    # 定义 DataLoader
  7.    batch_size = 5
  8.    dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=False)

  9.    # 遍历 DataLoader
  10.    for inputs in dataloader:
  11.        inputs = inputs[0]  # 取出实际数据(因为DataLoader返回的是一个tuple)
  12.        # 在这里进行您的模型预测,比如:
  13.        predictions = inputs * 2  # 示例操作
  14.        print(predictions)
复制代码


在这个例子中,只需确保 `drop_last=False`(默认)即可自动处理最后一个不完整的批次。这样你就可以在模型中处理所有的样本,不会有数据被丢弃。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-11-7 17:06:03 | 显示全部楼层
FishC 发表于 2024-11-7 16:58
在处理深度学习任务时,通常会使用小批量(batch)处理数据,`drop_last=True` 意味着在样本数不能被批量大 ...
  1. pd.concat([result.astype(np.float32),y_valid],axis=1)#两个数组合并成一个dataframe
复制代码


有报错
  1. ---------------------------------------------------------------------------
  2. TypeError                                 Traceback (most recent call last)
  3. Cell In[83], line 1
  4. ----> 1 pd.concat([result.values,y_valid],axis=1)#两个数组合并成一个dataframe

  5. File /opt/conda/lib/python3.10/site-packages/pandas/core/reshape/concat.py:382, in concat(objs, axis, join, ignore_index, keys, levels, names, verify_integrity, sort, copy)
  6.     379 elif copy and using_copy_on_write():
  7.     380     copy = False
  8. --> 382 op = _Concatenator(
  9.     383     objs,
  10.     384     axis=axis,
  11.     385     ignore_index=ignore_index,
  12.     386     join=join,
  13.     387     keys=keys,
  14.     388     levels=levels,
  15.     389     names=names,
  16.     390     verify_integrity=verify_integrity,
  17.     391     copy=copy,
  18.     392     sort=sort,
  19.     393 )
  20.     395 return op.get_result()

  21. File /opt/conda/lib/python3.10/site-packages/pandas/core/reshape/concat.py:448, in _Concatenator.__init__(self, objs, axis, join, keys, levels, names, ignore_index, verify_integrity, copy, sort)
  22.     445 objs, keys = self._clean_keys_and_objs(objs, keys)
  23.     447 # figure out what our result ndim is going to be
  24. --> 448 ndims = self._get_ndims(objs)
  25.     449 sample, objs = self._get_sample_object(objs, ndims, keys, names, levels)
  26.     451 # Standardize axis parameter to int

  27. File /opt/conda/lib/python3.10/site-packages/pandas/core/reshape/concat.py:489, in _Concatenator._get_ndims(self, objs)
  28.     484     if not isinstance(obj, (ABCSeries, ABCDataFrame)):
  29.     485         msg = (
  30.     486             f"cannot concatenate object of type '{type(obj)}'; "
  31.     487             "only Series and DataFrame objs are valid"
  32.     488         )
  33. --> 489         raise TypeError(msg)
  34.     491     ndims.add(obj.ndim)
  35.     492 return ndims

  36. TypeError: cannot concatenate object of type '<class 'builtin_function_or_method'>'; only Series and DataFrame objs are valid
复制代码


result是一个张量,如何转化成series
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-7 17:06:15 | 显示全部楼层
Terence888 发表于 2024-11-07 17:06
pd.concat(,axis=1)#两个数组合并成一个dataframe

...


报错信息表示在使用 `pd.concat()` 时,输入参数不正确或者不完整。要将两个数组合并成一个 DataFrame,首先需要确保它们是合法的 pandas 对象(如 Series 或 DataFrame)。如果你目前有两个 NumPy 数组或者 PyTorch 张量,可以先将它们转换为 pandas 对象。

这里是你可以参考的步骤:

1. **转换张量到 NumPy 数组(如果你有的是 PyTorch 张量):**

  1. import torch

  2. # 示例张量
  3. tensor1 = torch.tensor([1, 2, 3])
  4. tensor2 = torch.tensor([4, 5, 6])

  5. # 转换为 NumPy 数组
  6. array1 = tensor1.numpy()
  7. array2 = tensor2.numpy()
复制代码


2. **将 NumPy 数组转换为 Pandas Series:**

  1. import pandas as pd

  2. # 转换为 Pandas Series
  3. series1 = pd.Series(array1)
  4. series2 = pd.Series(array2)
复制代码


3. **使用 `pd.concat()` 合并:**

  1. # 合并为 DataFrame
  2. result_df = pd.concat([series1, series2], axis=1)
  3. print(result_df)
复制代码


注意,`pd.concat()` 的第一个参数应该是一个可以迭代的对象(如列表),包含需要合并的 pandas 对象。如果你有多个 Series 或 DataFrame,它们都应以列表的形式提供。

确保你为 `pd.concat()` 提供了正确的输入类型。如果结果仍然是一个张量,转换步骤应成功无误地将其转为 Series。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-11-7 17:07:20 | 显示全部楼层
FishC 发表于 2024-11-7 17:06
报错信息表示在使用 `pd.concat()` 时,输入参数不正确或者不完整。要将两个数组合并成一个 DataFrame ...
  1. ---------------------------------------------------------------------------
  2. TypeError                                 Traceback (most recent call last)
  3. Cell In[85], line 1
  4. ----> 1 pd.concat([result.numpy(),y_valid],axis=1)#两个数组合并成一个dataframe

  5. File /opt/conda/lib/python3.10/site-packages/pandas/core/reshape/concat.py:382, in concat(objs, axis, join, ignore_index, keys, levels, names, verify_integrity, sort, copy)
  6.     379 elif copy and using_copy_on_write():
  7.     380     copy = False
  8. --> 382 op = _Concatenator(
  9.     383     objs,
  10.     384     axis=axis,
  11.     385     ignore_index=ignore_index,
  12.     386     join=join,
  13.     387     keys=keys,
  14.     388     levels=levels,
  15.     389     names=names,
  16.     390     verify_integrity=verify_integrity,
  17.     391     copy=copy,
  18.     392     sort=sort,
  19.     393 )
  20.     395 return op.get_result()

  21. File /opt/conda/lib/python3.10/site-packages/pandas/core/reshape/concat.py:448, in _Concatenator.__init__(self, objs, axis, join, keys, levels, names, ignore_index, verify_integrity, copy, sort)
  22.     445 objs, keys = self._clean_keys_and_objs(objs, keys)
  23.     447 # figure out what our result ndim is going to be
  24. --> 448 ndims = self._get_ndims(objs)
  25.     449 sample, objs = self._get_sample_object(objs, ndims, keys, names, levels)
  26.     451 # Standardize axis parameter to int

  27. File /opt/conda/lib/python3.10/site-packages/pandas/core/reshape/concat.py:489, in _Concatenator._get_ndims(self, objs)
  28.     484     if not isinstance(obj, (ABCSeries, ABCDataFrame)):
  29.     485         msg = (
  30.     486             f"cannot concatenate object of type '{type(obj)}'; "
  31.     487             "only Series and DataFrame objs are valid"
  32.     488         )
  33. --> 489         raise TypeError(msg)
  34.     491     ndims.add(obj.ndim)
  35.     492 return ndims

  36. TypeError: cannot concatenate object of type '<class 'numpy.ndarray'>'; only Series and DataFrame objs are valid
复制代码


还是报错
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-7 17:07:48 | 显示全部楼层
Terence888 发表于 2024-11-07 17:07
-------------------------------------------------- ...


根据报错信息,你在调用 `pd.concat()` 时没有传入任何对象,`pd.concat()` 的第一个参数应该是一个可迭代对象,通常是一个包含多个 Series 或 DataFrame 的列表。下面是将两个数组(或张量)合并为一个 DataFrame 的完整步骤:

1. **确保输入有效:**

假设你有两个数组:

  1. import numpy as np

  2. # 示例数组
  3. array1 = np.array([1, 2, 3])
  4. array2 = np.array([4, 5, 6])
复制代码


2. **将 NumPy 数组转换为 Pandas Series:**

  1. import pandas as pd

  2. # 将数组转换为 Pandas Series
  3. series1 = pd.Series(array1)
  4. series2 = pd.Series(array2)
复制代码


3. **使用 `pd.concat()` 合并这些 Series:**

  1. # 合并为 DataFrame
  2. result_df = pd.concat([series1, series2], axis=1)

  3. # 打印结果
  4. print(result_df)
复制代码


在 `pd.concat()` 函数调用时,第一个参数需要是一个列表,包含你希望合并的各个对象(如 Series 或 DataFrame)。在上面的例子中,`[series1, series2]` 是一个包含两个 Pandas Series 的列表,然后通过指定 `axis=1` 来水平合并它们形成一个 DataFrame。

确保你将数据放入列表中并传递给 `pd.concat()`,这样可以避免之前的错误。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-11-7 17:09:11 | 显示全部楼层
FishC 发表于 2024-11-7 17:07
根据报错信息,你在调用 `pd.concat()` 时没有传入任何对象,`pd.concat()` 的第一个参数应该是一个可 ...
  1. pd.concat([result.numpy(),y_valid],axis=1)#两个数组合并成一个dataframe
复制代码

concat里面是一个列表,没法将result转化成series数组
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-7 17:21:20 | 显示全部楼层
Terence888 发表于 2024-11-07 17:09
pd.concat(,axis=1)#两个数组合并成一个dataframe
co ...


在你的描述中,你想将两个数组合并成一个 `DataFrame`,并且 `pd.concat()` 的第一个参数需要是个列表,但在代码中并没有具体给出这两个数组的内容。如果你已经有两个结果数组或者 Series,需要将它们合并成一个 `DataFrame`,可以按照以下方法操作:

假设有两个数组或 Series:

  1. import numpy as np
  2. import pandas as pd

  3. # 假设这两个是要合并的数组
  4. array1 = np.array([1, 2, 3])
  5. array2 = np.array([4, 5, 6])

  6. # 将 NumPy 数组转换为 Pandas Series,保留索引
  7. series1 = pd.Series(array1)
  8. series2 = pd.Series(array2)

  9. # 使用 pd.concat 将它们水平合并成一个 DataFrame
  10. result_df = pd.concat([series1, series2], axis=1)

  11. print(result_df)
复制代码


在这个例子中,我们首先将 NumPy 数组转换为 Pandas `Series`,然后利用 `pd.concat()` 合并成一个 `DataFrame`。关键在于将这两个 `Series` 放入一个列表中,然后通过 `pd.concat()` 的 `axis=1` 参数来水平合并它们。

如果你的输入数据已经是 Pandas 的 `Series` 或者它们在一个列表中,则直接使用 `pd.concat()` 合并即可。确保 `pd.concat()` 的参数是一个包含所有待合并对象的列表,这是关键所在。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-11-7 17:33:32 | 显示全部楼层
FishC 发表于 2024-11-7 17:21
在你的描述中,你想将两个数组合并成一个 `DataFrame`,并且 `pd.concat()` 的第一个参数需要是个列表 ...
  1. from torch.utils.data import random_split

  2. train_size = int(0.8 * len(train_dataset)) # train:valid = 8:2
  3. valid_size = len(train_dataset) - train_size

  4. train_dataset,valid_dataset = random_split(train_dataset,[train_size,valid_size])
  5. print(f'{len(train_dataset)} train samples')
  6. print(f'{len(valid_dataset)} valid samples')
  7. print(f'{len(test_dataset)} test samples')
复制代码
  1. from torch.utils.data import DataLoader

  2. train_dataloader = DataLoader(train_dataset,batch_size=8,shuffle=True,pin_memory=True)#锁页内存(pin_memory)能够保持与GPU进行高速传输,在训练时加快数据的读取
  3. valid_dataloader = DataLoader(valid_dataset,batch_size=8,shuffle=False,pin_memory=True)

  4. #collate_fn用于自定义数据加载和批处理的方式
复制代码
  1. pre_valid = inference(model,valid_dataloader)
复制代码

为什么模型输出结果的第一维变成了229,而不是总的样本数量
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-7 17:33:47 | 显示全部楼层
Terence888 发表于 2024-11-07 17:33
from torch.utils.data import random_split

train ...


输出结果的维度和总的样本数量不匹配可能有多种原因。我们可以逐步检查:

1. **数据集分割**:确保输入到 `random_split()` 函数的 `train_dataset` 是你期望的完整数据集。确认 `train_size` 和 `valid_size` 的计算是否正确。

2. **模型推断**:`inference()` 函数的实现会影响输出的维度。确保 `inference()` 函数返回的结果是你想要的格式。通常,输出的维度与输入数据的批大小和模型具体实现有关。

3. **检查 `DataLoader` 和模型的工作方式**:
   - `DataLoader` 分批处理数据,因此输出的维度可能受到批大小的影响。确保在 `inference()` 过程中,正确拼接这些批次的结果。
   - 例如,如果在模型推断过程中使用了 `torch.cat()` 或类似的方法拼接批次输出,检查是否在批次之间确实合并所需的所有张量。

4. **批次和填充**:如果样本数量不是批大小的整数倍,可能会导致最后一个批次的大小与其他批次不同。确认输出与样本数量最终是通过批次正确处理的。

可以尝试一个简单的调试步骤,明确各个组件的维度和形状,确保它们在整个数据流和模型处理中能够产生所需的输出:

  1. # 打印 DataLoader 输出
  2. for batch in valid_dataloader:
  3.     print(batch.shape)  # 打印每个批次的尺寸

  4. # 在 inference 函数中,打印模型输出
  5. def inference(model, dataloader):
  6.     model.eval()
  7.     outputs = []
  8.     for data in dataloader:
  9.         output = model(data)
  10.         print(output.shape)  # 调试打印
  11.         outputs.append(output)
  12.     return torch.cat(outputs)  # 确保所有输出连接在一起
复制代码


通过检查以上各个部分的维度,可以更容易定位问题所在。如果这些建议没有解决问题,请提供更多上下文和代码细节以便更为精确的排查。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-18 17:11

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表