Files
paddlepaddle--paddle/test/legacy_test/test_multiprocess_dataloader_dataset.py
T
2026-07-13 12:40:42 +08:00

474 lines
15 KiB
Python
Executable File

# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest
import numpy as np
from op_test import get_places
import paddle
from paddle import base
from paddle.io import (
ChainDataset,
ComposeDataset,
ConcatDataset,
DataLoader,
Dataset,
IterableDataset,
TensorDataset,
)
IMAGE_SIZE = 32
class RandomDataset(Dataset):
def __init__(self, sample_num):
self.sample_num = sample_num
def __len__(self):
return self.sample_num
def __getitem__(self, idx):
np.random.seed(idx)
image = np.random.random([IMAGE_SIZE]).astype('float32')
label = np.random.randint(0, 9, (1,)).astype('int64')
return image, label
class RandomIterableDataset(IterableDataset):
def __init__(self, sample_num):
self.sample_num = sample_num
def __iter__(self):
for i in range(self.sample_num):
np.random.seed(i)
image = np.random.random([IMAGE_SIZE]).astype('float32')
label = np.random.randint(0, 9, (1,)).astype('int64')
yield image, label
class TestTensorDataset(unittest.TestCase):
def run_main(self, num_workers, places):
paddle.seed(1)
place = paddle.CPUPlace()
with base.dygraph.guard(place):
input_np = np.random.random([16, 3, 4]).astype('float32')
input = paddle.to_tensor(input_np)
label_np = np.random.random([16, 1]).astype('int32')
label = paddle.to_tensor(label_np)
dataset = TensorDataset([input, label])
assert len(dataset) == 16
dataloader = DataLoader(
dataset,
places=place,
num_workers=num_workers,
batch_size=1,
drop_last=True,
)
for i, (input, label) in enumerate(dataloader()):
assert len(input) == 1
assert len(label) == 1
assert input.shape == [1, 3, 4]
assert label.shape == [1, 1]
assert isinstance(input, base.core.eager.Tensor)
assert isinstance(label, base.core.eager.Tensor)
np.testing.assert_allclose(input.numpy(), input_np[i])
np.testing.assert_allclose(label.numpy(), label_np[i])
def test_main(self):
for p in get_places():
self.run_main(num_workers=0, places=p)
class TestComposeDataset(unittest.TestCase):
def test_main(self):
paddle.seed(1)
dataset1 = RandomDataset(10)
dataset2 = RandomDataset(10)
dataset = ComposeDataset([dataset1, dataset2])
assert len(dataset) == 10
for i in range(len(dataset)):
input1, label1, input2, label2 = dataset[i]
input1_t, label1_t = dataset1[i]
input2_t, label2_t = dataset2[i]
np.testing.assert_allclose(input1, input1_t)
np.testing.assert_allclose(label1, label1_t)
np.testing.assert_allclose(input2, input2_t)
np.testing.assert_allclose(label2, label2_t)
class TestRandomSplitApi(unittest.TestCase):
def test_main(self):
paddle.seed(1)
dataset1, dataset2 = paddle.io.random_split(range(5), [1, 4])
self.assertTrue(len(dataset1) == 1)
self.assertTrue(len(dataset2) == 4)
elements_list = list(range(5))
for _, val in enumerate(dataset1):
elements_list.remove(val)
for _, val in enumerate(dataset2):
elements_list.remove(val)
self.assertTrue(len(elements_list) == 0)
class TestRandomSplitError(unittest.TestCase):
def test_errors(self):
paddle.seed(1)
self.assertRaises(ValueError, paddle.io.random_split, range(5), [3, 8])
self.assertRaises(ValueError, paddle.io.random_split, range(5), [8])
self.assertRaises(ValueError, paddle.io.random_split, range(5), [])
class TestSubsetDataset(unittest.TestCase):
def run_main(self, num_workers, places):
paddle.seed(1)
input_np = np.random.random([5, 3, 4]).astype('float32')
input = paddle.to_tensor(input_np)
label_np = np.random.random([5, 1]).astype('int32')
label = paddle.to_tensor(label_np)
dataset = TensorDataset([input, label])
even_subset = paddle.io.Subset(dataset, [0, 2, 4])
odd_subset = paddle.io.Subset(dataset, [1, 3])
assert len(dataset) == 5
def prepare_dataloader(dataset):
return DataLoader(
dataset,
places=places,
num_workers=num_workers,
batch_size=1,
drop_last=True,
)
dataloader = prepare_dataloader(dataset)
dataloader_even = prepare_dataloader(even_subset)
dataloader_odd = prepare_dataloader(odd_subset)
def assert_basic(input, label):
assert len(input) == 1
assert len(label) == 1
assert input.shape == [1, 3, 4]
assert label.shape == [1, 1]
assert isinstance(input, base.core.eager.Tensor)
assert isinstance(label, base.core.eager.Tensor)
elements_list = []
for _, (input, label) in enumerate(dataloader()):
assert_basic(input, label)
elements_list.append(label)
for _, (input, label) in enumerate(dataloader_even()):
assert_basic(input, label)
elements_list.remove(label)
odd_list = []
for _, (input, label) in enumerate(dataloader_odd()):
assert_basic(input, label)
odd_list.append(label)
self.assertEqual(odd_list, elements_list)
def test_main(self):
paddle.seed(1)
for p in get_places():
self.run_main(num_workers=0, places=p)
class TestChainDataset(unittest.TestCase):
def run_main(self, num_workers, places):
paddle.seed(1)
dataset1 = RandomIterableDataset(10)
dataset2 = RandomIterableDataset(10)
dataset = ChainDataset([dataset1, dataset2])
samples = []
for data in iter(dataset):
samples.append(data)
assert len(samples) == 20
idx = 0
for image, label in iter(dataset1):
np.testing.assert_allclose(image, samples[idx][0])
np.testing.assert_allclose(label, samples[idx][1])
idx += 1
for image, label in iter(dataset2):
np.testing.assert_allclose(image, samples[idx][0])
np.testing.assert_allclose(label, samples[idx][1])
idx += 1
def test_main(self):
for p in get_places():
self.run_main(num_workers=0, places=p)
class NumpyMixTensorDataset(Dataset):
def __init__(self, sample_num):
self.sample_num = sample_num
def __len__(self):
return self.sample_num
def __getitem__(self, idx):
np.random.seed(idx)
image = np.random.random([IMAGE_SIZE]).astype('float32')
label = np.random.randint(0, 9, (1,)).astype('int64')
return paddle.to_tensor(image, place=paddle.CPUPlace()), label
class TestNumpyMixTensorDataset(TestTensorDataset):
def run_main(self, num_workers, places):
paddle.seed(1)
place = paddle.CPUPlace()
with base.dygraph.guard(place):
dataset = NumpyMixTensorDataset(16)
assert len(dataset) == 16
dataloader = DataLoader(
dataset,
places=place,
num_workers=num_workers,
batch_size=1,
drop_last=True,
)
for i, (input, label) in enumerate(dataloader()):
assert len(input) == 1
assert len(label) == 1
assert input.shape == [1, IMAGE_SIZE]
assert label.shape == [1, 1]
assert isinstance(input, base.core.eager.Tensor)
assert isinstance(label, base.core.eager.Tensor)
class ComplexDataset(Dataset):
def __init__(self, sample_num):
self.sample_num = sample_num
def __len__(self):
return self.sample_num
def __getitem__(self, idx):
return (
3.1,
'abc',
paddle.to_tensor(
np.random.random([IMAGE_SIZE]).astype('float32'),
place=paddle.CPUPlace(),
),
[1, np.random.random([2]).astype('float32')],
{'a': 2.0, 'b': np.random.random([2]).astype('float32')},
)
class TestComplexDataset(unittest.TestCase):
def run_main(self, num_workers):
paddle.seed(1)
place = paddle.CPUPlace()
with base.dygraph.guard(place):
dataset = ComplexDataset(16)
assert len(dataset) == 16
dataloader = DataLoader(
dataset,
places=place,
num_workers=num_workers,
batch_size=2,
drop_last=True,
)
for i, data in enumerate(dataloader()):
assert len(data) == 5
# data[0]: collate 3.1
assert data[0].shape == [2]
assert isinstance(data[1], list)
# data[1]: collate 'abc'
assert len(data[1]) == 2
assert isinstance(data[1][0], str)
assert isinstance(data[1][1], str)
# data[2]: collate tensor
assert data[2].shape == [2, IMAGE_SIZE]
# data[3]: collate list
assert isinstance(data[3], list)
assert data[3][0].shape == [2]
assert data[3][1].shape == [2, 2]
# data[4]: collate dict
assert isinstance(data[4], dict)
assert data[4]['a'].shape == [2]
assert data[4]['b'].shape == [2, 2]
def test_main(self):
for num_workers in [0, 2]:
self.run_main(num_workers)
class SingleFieldDataset(Dataset):
def __init__(self, sample_num):
self.sample_num = sample_num
def __len__(self):
return self.sample_num
def __getitem__(self, idx):
return np.random.random((2, 3)).astype('float32')
class TestSingleFieldDataset(unittest.TestCase):
def init_dataset(self):
self.sample_num = 16
self.dataset = SingleFieldDataset(self.sample_num)
def run_main(self, num_workers):
paddle.seed(1)
place = paddle.CPUPlace()
with base.dygraph.guard(place):
self.init_dataset()
dataloader = DataLoader(
self.dataset,
places=place,
num_workers=num_workers,
batch_size=2,
drop_last=True,
)
for i, data in enumerate(dataloader()):
assert isinstance(data, base.core.eager.Tensor)
assert data.shape == [2, 2, 3]
def test_main(self):
for num_workers in [0, 2]:
self.run_main(num_workers)
class SingleFieldIterableDataset(IterableDataset):
def __init__(self, sample_num):
self.sample_num = sample_num
def __iter__(self):
for _ in range(self.sample_num):
yield np.random.random((2, 3)).astype('float32')
class TestSingleFieldIterableDataset(TestSingleFieldDataset):
def init_dataset(self):
self.sample_num = 16
self.dataset = SingleFieldIterableDataset(self.sample_num)
class TestDataLoaderGenerateStates(unittest.TestCase):
def setUp(self):
self.inputs = [(0, 1), (0, 2), (1, 3)]
self.outputs = [
[1835504127, 1731038949, 1320224556, 2330041505],
[2834126987, 2358157858, 1860244682, 1437227251],
[457190280, 2660306227, 859341110, 354512857],
]
def test_main(self):
from paddle.io.dataloader.worker import _generate_states
for inp, outp in zip(self.inputs, self.outputs):
out = _generate_states(*inp)
assert out == outp
class TestDatasetWithDropLast(unittest.TestCase):
def run_main(self, dataset, num_samples, batch_size):
for num_workers in [0, 1]:
for drop_last in [True, False]:
steps = (
num_samples + (1 - int(drop_last)) * (batch_size - 1)
) // batch_size
dataloader = DataLoader(
dataset,
batch_size=batch_size,
drop_last=drop_last,
num_workers=num_workers,
)
datas = []
for data in dataloader:
datas.append(data)
assert len(datas) == steps
def test_map_dataset(self):
dataset = RandomDataset(10)
self.run_main(dataset, 10, 3)
def test_iterable_dataset(self):
dataset = RandomIterableDataset(10)
self.run_main(dataset, 10, 3)
class TestConcatDataset(unittest.TestCase):
def run_main(self, num_workers, places):
result = ConcatDataset([[0], [1]])
self.assertEqual(2, len(result))
self.assertEqual(0, result[0])
self.assertEqual(1, result[1])
result = ConcatDataset([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]])
self.assertEqual(10, len(result))
self.assertEqual(0, result[0])
self.assertEqual(5, result[5])
result = ConcatDataset([[0, 1, 2, 3, 4], [], [5, 6, 7, 8, 9]])
self.assertEqual(10, len(result))
self.assertEqual(0, result[0])
self.assertEqual(5, result[5])
result = ConcatDataset([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]])
with self.assertRaises(IndexError):
result[11]
def test_main(self):
for p in get_places():
self.run_main(num_workers=0, places=p)
def test_iterable_dataset_err(self):
d1 = TensorDataset([paddle.rand((7, 3, 28, 28)), paddle.rand((7,))])
it1 = RandomIterableDataset(10)
it2 = RandomIterableDataset(10)
with self.assertRaisesRegex(
AssertionError, "does not support IterableDataset"
):
ConcatDataset([d1, it2, it1])
with self.assertRaisesRegex(
AssertionError, "does not support IterableDataset"
):
ConcatDataset([it2])
with self.assertRaisesRegex(
AssertionError, "does not support IterableDataset"
):
ConcatDataset([it1, d1])
if __name__ == '__main__':
unittest.main()