We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Sampler should be seeded lazily
## 🐛 Bug

After #63026 is landed, the generator for Sampler is attached to the instance, which helps to serialize the state of Sampler. But, it brings a problem that it will prevent Sampler's generator being seeded before each epoch.

## To Reproduce

Check https://github.com/pytorch/pytorch/pull/63026#issuecomment-902234490

User would expect same result for the sampler without specifying generator input when set seed for each epoch.
```py
sampler = RandomSampler(ds)
torch.manual_seed(0)
l1 = list(sampler)
torch.manual_seed(0)
l2 = list(sampler)
# Expect same
assert l1 == l2
```


cc @SsnL @VitalyFedyunin @ejguan @NivekT

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `torch/utils/data/sampler.py`
Content:
```
1 import torch
2 from torch import Tensor
3 
4 from typing import Iterator, Optional, Sequence, List, TypeVar, Generic, Sized
5 
6 T_co = TypeVar('T_co', covariant=True)
7 
8 class Sampler(Generic[T_co]):
9     r"""Base class for all Samplers.
10 
11     Every Sampler subclass has to provide an :meth:`__iter__` method, providing a
12     way to iterate over indices of dataset elements, and a :meth:`__len__` method
13     that returns the length of the returned iterators.
14 
15     .. note:: The :meth:`__len__` method isn't strictly required by
16               :class:`~torch.utils.data.DataLoader`, but is expected in any
17               calculation involving the length of a :class:`~torch.utils.data.DataLoader`.
18     """
19 
20     def __init__(self, data_source: Optional[Sized]) -> None:
21         pass
22 
23     def __iter__(self) -> Iterator[T_co]:
24         raise NotImplementedError
25 
26     # NOTE [ Lack of Default `__len__` in Python Abstract Base Classes ]
27     #
28     # Many times we have an abstract class representing a collection/iterable of
29     # data, e.g., `torch.utils.data.Sampler`, with its subclasses optionally
30     # implementing a `__len__` method. In such cases, we must make sure to not
31     # provide a default implementation, because both straightforward default
32     # implementations have their issues:
33     #
34     #   + `return NotImplemented`:
35     #     Calling `len(subclass_instance)` raises:
36     #       TypeError: 'NotImplementedType' object cannot be interpreted as an integer
37     #
38     #   + `raise NotImplementedError()`:
39     #     This prevents triggering some fallback behavior. E.g., the built-in
40     #     `list(X)` tries to call `len(X)` first, and executes a different code
41     #     path if the method is not found or `NotImplemented` is returned, while
42     #     raising an `NotImplementedError` will propagate and and make the call
43     #     fail where it could have use `__iter__` to complete the call.
44     #
45     # Thus, the only two sensible things to do are
46     #
47     #   + **not** provide a default `__len__`.
48     #
49     #   + raise a `TypeError` instead, which is what Python uses when users call
50     #     a method that is not defined on an object.
51     #     (@ssnl verifies that this works on at least Python 3.7.)
52 
53 
54 class SequentialSampler(Sampler[int]):
55     r"""Samples elements sequentially, always in the same order.
56 
57     Args:
58         data_source (Dataset): dataset to sample from
59     """
60     data_source: Sized
61 
62     def __init__(self, data_source: Sized) -> None:
63         self.data_source = data_source
64 
65     def __iter__(self) -> Iterator[int]:
66         return iter(range(len(self.data_source)))
67 
68     def __len__(self) -> int:
69         return len(self.data_source)
70 
71 
72 class RandomSampler(Sampler[int]):
73     r"""Samples elements randomly. If without replacement, then sample from a shuffled dataset.
74     If with replacement, then user can specify :attr:`num_samples` to draw.
75 
76     Args:
77         data_source (Dataset): dataset to sample from
78         replacement (bool): samples are drawn on-demand with replacement if ``True``, default=``False``
79         num_samples (int): number of samples to draw, default=`len(dataset)`. This argument
80             is supposed to be specified only when `replacement` is ``True``.
81         generator (Generator): Generator used in sampling.
82     """
83     data_source: Sized
84     replacement: bool
85 
86     def __init__(self, data_source: Sized, replacement: bool = False,
87                  num_samples: Optional[int] = None, generator=None) -> None:
88         self.data_source = data_source
89         self.replacement = replacement
90         self._num_samples = num_samples
91         self.generator = generator
92 
93         if not isinstance(self.replacement, bool):
94             raise TypeError("replacement should be a boolean value, but got "
95                             "replacement={}".format(self.replacement))
96 
97         if self._num_samples is not None and not replacement:
98             raise ValueError("With replacement=False, num_samples should not be specified, "
99                              "since a random permute will be performed.")
100 
101         if not isinstance(self.num_samples, int) or self.num_samples <= 0:
102             raise ValueError("num_samples should be a positive integer "
103                              "value, but got num_samples={}".format(self.num_samples))
104 
105     @property
106     def num_samples(self) -> int:
107         # dataset size might change at runtime
108         if self._num_samples is None:
109             return len(self.data_source)
110         return self._num_samples
111 
112     def __iter__(self) -> Iterator[int]:
113         n = len(self.data_source)
114         if self.generator is None:
115             self.generator = torch.Generator()
116             self.generator.manual_seed(int(torch.empty((), dtype=torch.int64).random_().item()))
117 
118         if self.replacement:
119             for _ in range(self.num_samples // 32):
120                 yield from torch.randint(high=n, size=(32,), dtype=torch.int64, generator=self.generator).tolist()
121             yield from torch.randint(high=n, size=(self.num_samples % 32,), dtype=torch.int64, generator=self.generator).tolist()
122         else:
123             yield from torch.randperm(n, generator=self.generator).tolist()
124 
125     def __len__(self) -> int:
126         return self.num_samples
127 
128 
129 class SubsetRandomSampler(Sampler[int]):
130     r"""Samples elements randomly from a given list of indices, without replacement.
131 
132     Args:
133         indices (sequence): a sequence of indices
134         generator (Generator): Generator used in sampling.
135     """
136     indices: Sequence[int]
137 
138     def __init__(self, indices: Sequence[int], generator=None) -> None:
139         self.indices = indices
140         self.generator = generator
141 
142     def __iter__(self) -> Iterator[int]:
143         return (self.indices[i] for i in torch.randperm(len(self.indices), generator=self.generator))
144 
145     def __len__(self) -> int:
146         return len(self.indices)
147 
148 
149 class WeightedRandomSampler(Sampler[int]):
150     r"""Samples elements from ``[0,..,len(weights)-1]`` with given probabilities (weights).
151 
152     Args:
153         weights (sequence)   : a sequence of weights, not necessary summing up to one
154         num_samples (int): number of samples to draw
155         replacement (bool): if ``True``, samples are drawn with replacement.
156             If not, they are drawn without replacement, which means that when a
157             sample index is drawn for a row, it cannot be drawn again for that row.
158         generator (Generator): Generator used in sampling.
159 
160     Example:
161         >>> list(WeightedRandomSampler([0.1, 0.9, 0.4, 0.7, 3.0, 0.6], 5, replacement=True))
162         [4, 4, 1, 4, 5]
163         >>> list(WeightedRandomSampler([0.9, 0.4, 0.05, 0.2, 0.3, 0.1], 5, replacement=False))
164         [0, 1, 4, 3, 2]
165     """
166     weights: Tensor
167     num_samples: int
168     replacement: bool
169 
170     def __init__(self, weights: Sequence[float], num_samples: int,
171                  replacement: bool = True, generator=None) -> None:
172         if not isinstance(num_samples, int) or isinstance(num_samples, bool) or \
173                 num_samples <= 0:
174             raise ValueError("num_samples should be a positive integer "
175                              "value, but got num_samples={}".format(num_samples))
176         if not isinstance(replacement, bool):
177             raise ValueError("replacement should be a boolean value, but got "
178                              "replacement={}".format(replacement))
179         self.weights = torch.as_tensor(weights, dtype=torch.double)
180         self.num_samples = num_samples
181         self.replacement = replacement
182         self.generator = generator
183 
184     def __iter__(self) -> Iterator[int]:
185         rand_tensor = torch.multinomial(self.weights, self.num_samples, self.replacement, generator=self.generator)
186         return iter(rand_tensor.tolist())
187 
188     def __len__(self) -> int:
189         return self.num_samples
190 
191 
192 class BatchSampler(Sampler[List[int]]):
193     r"""Wraps another sampler to yield a mini-batch of indices.
194 
195     Args:
196         sampler (Sampler or Iterable): Base sampler. Can be any iterable object
197         batch_size (int): Size of mini-batch.
198         drop_last (bool): If ``True``, the sampler will drop the last batch if
199             its size would be less than ``batch_size``
200 
201     Example:
202         >>> list(BatchSampler(SequentialSampler(range(10)), batch_size=3, drop_last=False))
203         [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
204         >>> list(BatchSampler(SequentialSampler(range(10)), batch_size=3, drop_last=True))
205         [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
206     """
207 
208     def __init__(self, sampler: Sampler[int], batch_size: int, drop_last: bool) -> None:
209         # Since collections.abc.Iterable does not check for `__getitem__`, which
210         # is one way for an object to be an iterable, we don't do an `isinstance`
211         # check here.
212         if not isinstance(batch_size, int) or isinstance(batch_size, bool) or \
213                 batch_size <= 0:
214             raise ValueError("batch_size should be a positive integer value, "
215                              "but got batch_size={}".format(batch_size))
216         if not isinstance(drop_last, bool):
217             raise ValueError("drop_last should be a boolean value, but got "
218                              "drop_last={}".format(drop_last))
219         self.sampler = sampler
220         self.batch_size = batch_size
221         self.drop_last = drop_last
222 
223     def __iter__(self) -> Iterator[List[int]]:
224         batch = []
225         for idx in self.sampler:
226             batch.append(idx)
227             if len(batch) == self.batch_size:
228                 yield batch
229                 batch = []
230         if len(batch) > 0 and not self.drop_last:
231             yield batch
232 
233     def __len__(self) -> int:
234         # Can only be called if self.sampler has __len__ implemented
235         # We cannot enforce this condition, so we turn off typechecking for the
236         # implementation below.
237         # Somewhat related: see NOTE [ Lack of Default `__len__` in Python Abstract Base Classes ]
238         if self.drop_last:
239             return len(self.sampler) // self.batch_size  # type: ignore[arg-type]
240         else:
241             return (len(self.sampler) + self.batch_size - 1) // self.batch_size  # type: ignore[arg-type]
242
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/torch/utils/data/sampler.py b/torch/utils/data/sampler.py
--- a/torch/utils/data/sampler.py
+++ b/torch/utils/data/sampler.py
@@ -112,15 +112,18 @@
     def __iter__(self) -> Iterator[int]:
         n = len(self.data_source)
         if self.generator is None:
-            self.generator = torch.Generator()
-            self.generator.manual_seed(int(torch.empty((), dtype=torch.int64).random_().item()))
+            seed = int(torch.empty((), dtype=torch.int64).random_().item())
+            generator = torch.Generator()
+            generator.manual_seed(seed)
+        else:
+            generator = self.generator
 
         if self.replacement:
             for _ in range(self.num_samples // 32):
-                yield from torch.randint(high=n, size=(32,), dtype=torch.int64, generator=self.generator).tolist()
-            yield from torch.randint(high=n, size=(self.num_samples % 32,), dtype=torch.int64, generator=self.generator).tolist()
+                yield from torch.randint(high=n, size=(32,), dtype=torch.int64, generator=generator).tolist()
+            yield from torch.randint(high=n, size=(self.num_samples % 32,), dtype=torch.int64, generator=generator).tolist()
         else:
-            yield from torch.randperm(n, generator=self.generator).tolist()
+            yield from torch.randperm(n, generator=generator).tolist()
 
     def __len__(self) -> int:
         return self.num_samples
@@ -140,7 +143,8 @@
         self.generator = generator
 
     def __iter__(self) -> Iterator[int]:
-        return (self.indices[i] for i in torch.randperm(len(self.indices), generator=self.generator))
+        for i in torch.randperm(len(self.indices), generator=self.generator):
+            yield self.indices[i]
 
     def __len__(self) -> int:
         return len(self.indices)
@@ -183,7 +187,7 @@
 
     def __iter__(self) -> Iterator[int]:
         rand_tensor = torch.multinomial(self.weights, self.num_samples, self.replacement, generator=self.generator)
-        return iter(rand_tensor.tolist())
+        yield from iter(rand_tensor.tolist())
 
     def __len__(self) -> int:
         return self.num_samples

{"golden_diff": "diff --git a/torch/utils/data/sampler.py b/torch/utils/data/sampler.py\n--- a/torch/utils/data/sampler.py\n+++ b/torch/utils/data/sampler.py\n@@ -112,15 +112,18 @@\n     def __iter__(self) -> Iterator[int]:\n         n = len(self.data_source)\n         if self.generator is None:\n-            self.generator = torch.Generator()\n-            self.generator.manual_seed(int(torch.empty((), dtype=torch.int64).random_().item()))\n+            seed = int(torch.empty((), dtype=torch.int64).random_().item())\n+            generator = torch.Generator()\n+            generator.manual_seed(seed)\n+        else:\n+            generator = self.generator\n \n         if self.replacement:\n             for _ in range(self.num_samples // 32):\n-                yield from torch.randint(high=n, size=(32,), dtype=torch.int64, generator=self.generator).tolist()\n-            yield from torch.randint(high=n, size=(self.num_samples % 32,), dtype=torch.int64, generator=self.generator).tolist()\n+                yield from torch.randint(high=n, size=(32,), dtype=torch.int64, generator=generator).tolist()\n+            yield from torch.randint(high=n, size=(self.num_samples % 32,), dtype=torch.int64, generator=generator).tolist()\n         else:\n-            yield from torch.randperm(n, generator=self.generator).tolist()\n+            yield from torch.randperm(n, generator=generator).tolist()\n \n     def __len__(self) -> int:\n         return self.num_samples\n@@ -140,7 +143,8 @@\n         self.generator = generator\n \n     def __iter__(self) -> Iterator[int]:\n-        return (self.indices[i] for i in torch.randperm(len(self.indices), generator=self.generator))\n+        for i in torch.randperm(len(self.indices), generator=self.generator):\n+            yield self.indices[i]\n \n     def __len__(self) -> int:\n         return len(self.indices)\n@@ -183,7 +187,7 @@\n \n     def __iter__(self) -> Iterator[int]:\n         rand_tensor = torch.multinomial(self.weights, self.num_samples, self.replacement, generator=self.generator)\n-        return iter(rand_tensor.tolist())\n+        yield from iter(rand_tensor.tolist())\n \n     def __len__(self) -> int:\n         return self.num_samples\n", "issue": "Sampler should be seeded lazily\n## \ud83d\udc1b Bug\r\n\r\nAfter #63026 is landed, the generator for Sampler is attached to the instance, which helps to serialize the state of Sampler. But, it brings a problem that it will prevent Sampler's generator being seeded before each epoch.\r\n\r\n## To Reproduce\r\n\r\nCheck https://github.com/pytorch/pytorch/pull/63026#issuecomment-902234490\r\n\r\nUser would expect same result for the sampler without specifying generator input when set seed for each epoch.\r\n```py\r\nsampler = RandomSampler(ds)\r\ntorch.manual_seed(0)\r\nl1 = list(sampler)\r\ntorch.manual_seed(0)\r\nl2 = list(sampler)\r\n# Expect same\r\nassert l1 == l2\r\n```\r\n\r\n\r\ncc @SsnL @VitalyFedyunin @ejguan @NivekT\n", "before_files": [{"content": "import torch\nfrom torch import Tensor\n\nfrom typing import Iterator, Optional, Sequence, List, TypeVar, Generic, Sized\n\nT_co = TypeVar('T_co', covariant=True)\n\nclass Sampler(Generic[T_co]):\n    r\"\"\"Base class for all Samplers.\n\n    Every Sampler subclass has to provide an :meth:`__iter__` method, providing a\n    way to iterate over indices of dataset elements, and a :meth:`__len__` method\n    that returns the length of the returned iterators.\n\n    .. note:: The :meth:`__len__` method isn't strictly required by\n              :class:`~torch.utils.data.DataLoader`, but is expected in any\n              calculation involving the length of a :class:`~torch.utils.data.DataLoader`.\n    \"\"\"\n\n    def __init__(self, data_source: Optional[Sized]) -> None:\n        pass\n\n    def __iter__(self) -> Iterator[T_co]:\n        raise NotImplementedError\n\n    # NOTE [ Lack of Default `__len__` in Python Abstract Base Classes ]\n    #\n    # Many times we have an abstract class representing a collection/iterable of\n    # data, e.g., `torch.utils.data.Sampler`, with its subclasses optionally\n    # implementing a `__len__` method. In such cases, we must make sure to not\n    # provide a default implementation, because both straightforward default\n    # implementations have their issues:\n    #\n    #   + `return NotImplemented`:\n    #     Calling `len(subclass_instance)` raises:\n    #       TypeError: 'NotImplementedType' object cannot be interpreted as an integer\n    #\n    #   + `raise NotImplementedError()`:\n    #     This prevents triggering some fallback behavior. E.g., the built-in\n    #     `list(X)` tries to call `len(X)` first, and executes a different code\n    #     path if the method is not found or `NotImplemented` is returned, while\n    #     raising an `NotImplementedError` will propagate and and make the call\n    #     fail where it could have use `__iter__` to complete the call.\n    #\n    # Thus, the only two sensible things to do are\n    #\n    #   + **not** provide a default `__len__`.\n    #\n    #   + raise a `TypeError` instead, which is what Python uses when users call\n    #     a method that is not defined on an object.\n    #     (@ssnl verifies that this works on at least Python 3.7.)\n\n\nclass SequentialSampler(Sampler[int]):\n    r\"\"\"Samples elements sequentially, always in the same order.\n\n    Args:\n        data_source (Dataset): dataset to sample from\n    \"\"\"\n    data_source: Sized\n\n    def __init__(self, data_source: Sized) -> None:\n        self.data_source = data_source\n\n    def __iter__(self) -> Iterator[int]:\n        return iter(range(len(self.data_source)))\n\n    def __len__(self) -> int:\n        return len(self.data_source)\n\n\nclass RandomSampler(Sampler[int]):\n    r\"\"\"Samples elements randomly. If without replacement, then sample from a shuffled dataset.\n    If with replacement, then user can specify :attr:`num_samples` to draw.\n\n    Args:\n        data_source (Dataset): dataset to sample from\n        replacement (bool): samples are drawn on-demand with replacement if ``True``, default=``False``\n        num_samples (int): number of samples to draw, default=`len(dataset)`. This argument\n            is supposed to be specified only when `replacement` is ``True``.\n        generator (Generator): Generator used in sampling.\n    \"\"\"\n    data_source: Sized\n    replacement: bool\n\n    def __init__(self, data_source: Sized, replacement: bool = False,\n                 num_samples: Optional[int] = None, generator=None) -> None:\n        self.data_source = data_source\n        self.replacement = replacement\n        self._num_samples = num_samples\n        self.generator = generator\n\n        if not isinstance(self.replacement, bool):\n            raise TypeError(\"replacement should be a boolean value, but got \"\n                            \"replacement={}\".format(self.replacement))\n\n        if self._num_samples is not None and not replacement:\n            raise ValueError(\"With replacement=False, num_samples should not be specified, \"\n                             \"since a random permute will be performed.\")\n\n        if not isinstance(self.num_samples, int) or self.num_samples <= 0:\n            raise ValueError(\"num_samples should be a positive integer \"\n                             \"value, but got num_samples={}\".format(self.num_samples))\n\n    @property\n    def num_samples(self) -> int:\n        # dataset size might change at runtime\n        if self._num_samples is None:\n            return len(self.data_source)\n        return self._num_samples\n\n    def __iter__(self) -> Iterator[int]:\n        n = len(self.data_source)\n        if self.generator is None:\n            self.generator = torch.Generator()\n            self.generator.manual_seed(int(torch.empty((), dtype=torch.int64).random_().item()))\n\n        if self.replacement:\n            for _ in range(self.num_samples // 32):\n                yield from torch.randint(high=n, size=(32,), dtype=torch.int64, generator=self.generator).tolist()\n            yield from torch.randint(high=n, size=(self.num_samples % 32,), dtype=torch.int64, generator=self.generator).tolist()\n        else:\n            yield from torch.randperm(n, generator=self.generator).tolist()\n\n    def __len__(self) -> int:\n        return self.num_samples\n\n\nclass SubsetRandomSampler(Sampler[int]):\n    r\"\"\"Samples elements randomly from a given list of indices, without replacement.\n\n    Args:\n        indices (sequence): a sequence of indices\n        generator (Generator): Generator used in sampling.\n    \"\"\"\n    indices: Sequence[int]\n\n    def __init__(self, indices: Sequence[int], generator=None) -> None:\n        self.indices = indices\n        self.generator = generator\n\n    def __iter__(self) -> Iterator[int]:\n        return (self.indices[i] for i in torch.randperm(len(self.indices), generator=self.generator))\n\n    def __len__(self) -> int:\n        return len(self.indices)\n\n\nclass WeightedRandomSampler(Sampler[int]):\n    r\"\"\"Samples elements from ``[0,..,len(weights)-1]`` with given probabilities (weights).\n\n    Args:\n        weights (sequence)   : a sequence of weights, not necessary summing up to one\n        num_samples (int): number of samples to draw\n        replacement (bool): if ``True``, samples are drawn with replacement.\n            If not, they are drawn without replacement, which means that when a\n            sample index is drawn for a row, it cannot be drawn again for that row.\n        generator (Generator): Generator used in sampling.\n\n    Example:\n        >>> list(WeightedRandomSampler([0.1, 0.9, 0.4, 0.7, 3.0, 0.6], 5, replacement=True))\n        [4, 4, 1, 4, 5]\n        >>> list(WeightedRandomSampler([0.9, 0.4, 0.05, 0.2, 0.3, 0.1], 5, replacement=False))\n        [0, 1, 4, 3, 2]\n    \"\"\"\n    weights: Tensor\n    num_samples: int\n    replacement: bool\n\n    def __init__(self, weights: Sequence[float], num_samples: int,\n                 replacement: bool = True, generator=None) -> None:\n        if not isinstance(num_samples, int) or isinstance(num_samples, bool) or \\\n                num_samples <= 0:\n            raise ValueError(\"num_samples should be a positive integer \"\n                             \"value, but got num_samples={}\".format(num_samples))\n        if not isinstance(replacement, bool):\n            raise ValueError(\"replacement should be a boolean value, but got \"\n                             \"replacement={}\".format(replacement))\n        self.weights = torch.as_tensor(weights, dtype=torch.double)\n        self.num_samples = num_samples\n        self.replacement = replacement\n        self.generator = generator\n\n    def __iter__(self) -> Iterator[int]:\n        rand_tensor = torch.multinomial(self.weights, self.num_samples, self.replacement, generator=self.generator)\n        return iter(rand_tensor.tolist())\n\n    def __len__(self) -> int:\n        return self.num_samples\n\n\nclass BatchSampler(Sampler[List[int]]):\n    r\"\"\"Wraps another sampler to yield a mini-batch of indices.\n\n    Args:\n        sampler (Sampler or Iterable): Base sampler. Can be any iterable object\n        batch_size (int): Size of mini-batch.\n        drop_last (bool): If ``True``, the sampler will drop the last batch if\n            its size would be less than ``batch_size``\n\n    Example:\n        >>> list(BatchSampler(SequentialSampler(range(10)), batch_size=3, drop_last=False))\n        [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]\n        >>> list(BatchSampler(SequentialSampler(range(10)), batch_size=3, drop_last=True))\n        [[0, 1, 2], [3, 4, 5], [6, 7, 8]]\n    \"\"\"\n\n    def __init__(self, sampler: Sampler[int], batch_size: int, drop_last: bool) -> None:\n        # Since collections.abc.Iterable does not check for `__getitem__`, which\n        # is one way for an object to be an iterable, we don't do an `isinstance`\n        # check here.\n        if not isinstance(batch_size, int) or isinstance(batch_size, bool) or \\\n                batch_size <= 0:\n            raise ValueError(\"batch_size should be a positive integer value, \"\n                             \"but got batch_size={}\".format(batch_size))\n        if not isinstance(drop_last, bool):\n            raise ValueError(\"drop_last should be a boolean value, but got \"\n                             \"drop_last={}\".format(drop_last))\n        self.sampler = sampler\n        self.batch_size = batch_size\n        self.drop_last = drop_last\n\n    def __iter__(self) -> Iterator[List[int]]:\n        batch = []\n        for idx in self.sampler:\n            batch.append(idx)\n            if len(batch) == self.batch_size:\n                yield batch\n                batch = []\n        if len(batch) > 0 and not self.drop_last:\n            yield batch\n\n    def __len__(self) -> int:\n        # Can only be called if self.sampler has __len__ implemented\n        # We cannot enforce this condition, so we turn off typechecking for the\n        # implementation below.\n        # Somewhat related: see NOTE [ Lack of Default `__len__` in Python Abstract Base Classes ]\n        if self.drop_last:\n            return len(self.sampler) // self.batch_size  # type: ignore[arg-type]\n        else:\n            return (len(self.sampler) + self.batch_size - 1) // self.batch_size  # type: ignore[arg-type]\n", "path": "torch/utils/data/sampler.py"}], "after_files": [{"content": "import torch\nfrom torch import Tensor\n\nfrom typing import Iterator, Optional, Sequence, List, TypeVar, Generic, Sized\n\nT_co = TypeVar('T_co', covariant=True)\n\nclass Sampler(Generic[T_co]):\n    r\"\"\"Base class for all Samplers.\n\n    Every Sampler subclass has to provide an :meth:`__iter__` method, providing a\n    way to iterate over indices of dataset elements, and a :meth:`__len__` method\n    that returns the length of the returned iterators.\n\n    .. note:: The :meth:`__len__` method isn't strictly required by\n              :class:`~torch.utils.data.DataLoader`, but is expected in any\n              calculation involving the length of a :class:`~torch.utils.data.DataLoader`.\n    \"\"\"\n\n    def __init__(self, data_source: Optional[Sized]) -> None:\n        pass\n\n    def __iter__(self) -> Iterator[T_co]:\n        raise NotImplementedError\n\n    # NOTE [ Lack of Default `__len__` in Python Abstract Base Classes ]\n    #\n    # Many times we have an abstract class representing a collection/iterable of\n    # data, e.g., `torch.utils.data.Sampler`, with its subclasses optionally\n    # implementing a `__len__` method. In such cases, we must make sure to not\n    # provide a default implementation, because both straightforward default\n    # implementations have their issues:\n    #\n    #   + `return NotImplemented`:\n    #     Calling `len(subclass_instance)` raises:\n    #       TypeError: 'NotImplementedType' object cannot be interpreted as an integer\n    #\n    #   + `raise NotImplementedError()`:\n    #     This prevents triggering some fallback behavior. E.g., the built-in\n    #     `list(X)` tries to call `len(X)` first, and executes a different code\n    #     path if the method is not found or `NotImplemented` is returned, while\n    #     raising an `NotImplementedError` will propagate and and make the call\n    #     fail where it could have use `__iter__` to complete the call.\n    #\n    # Thus, the only two sensible things to do are\n    #\n    #   + **not** provide a default `__len__`.\n    #\n    #   + raise a `TypeError` instead, which is what Python uses when users call\n    #     a method that is not defined on an object.\n    #     (@ssnl verifies that this works on at least Python 3.7.)\n\n\nclass SequentialSampler(Sampler[int]):\n    r\"\"\"Samples elements sequentially, always in the same order.\n\n    Args:\n        data_source (Dataset): dataset to sample from\n    \"\"\"\n    data_source: Sized\n\n    def __init__(self, data_source: Sized) -> None:\n        self.data_source = data_source\n\n    def __iter__(self) -> Iterator[int]:\n        return iter(range(len(self.data_source)))\n\n    def __len__(self) -> int:\n        return len(self.data_source)\n\n\nclass RandomSampler(Sampler[int]):\n    r\"\"\"Samples elements randomly. If without replacement, then sample from a shuffled dataset.\n    If with replacement, then user can specify :attr:`num_samples` to draw.\n\n    Args:\n        data_source (Dataset): dataset to sample from\n        replacement (bool): samples are drawn on-demand with replacement if ``True``, default=``False``\n        num_samples (int): number of samples to draw, default=`len(dataset)`. This argument\n            is supposed to be specified only when `replacement` is ``True``.\n        generator (Generator): Generator used in sampling.\n    \"\"\"\n    data_source: Sized\n    replacement: bool\n\n    def __init__(self, data_source: Sized, replacement: bool = False,\n                 num_samples: Optional[int] = None, generator=None) -> None:\n        self.data_source = data_source\n        self.replacement = replacement\n        self._num_samples = num_samples\n        self.generator = generator\n\n        if not isinstance(self.replacement, bool):\n            raise TypeError(\"replacement should be a boolean value, but got \"\n                            \"replacement={}\".format(self.replacement))\n\n        if self._num_samples is not None and not replacement:\n            raise ValueError(\"With replacement=False, num_samples should not be specified, \"\n                             \"since a random permute will be performed.\")\n\n        if not isinstance(self.num_samples, int) or self.num_samples <= 0:\n            raise ValueError(\"num_samples should be a positive integer \"\n                             \"value, but got num_samples={}\".format(self.num_samples))\n\n    @property\n    def num_samples(self) -> int:\n        # dataset size might change at runtime\n        if self._num_samples is None:\n            return len(self.data_source)\n        return self._num_samples\n\n    def __iter__(self) -> Iterator[int]:\n        n = len(self.data_source)\n        if self.generator is None:\n            seed = int(torch.empty((), dtype=torch.int64).random_().item())\n            generator = torch.Generator()\n            generator.manual_seed(seed)\n        else:\n            generator = self.generator\n\n        if self.replacement:\n            for _ in range(self.num_samples // 32):\n                yield from torch.randint(high=n, size=(32,), dtype=torch.int64, generator=generator).tolist()\n            yield from torch.randint(high=n, size=(self.num_samples % 32,), dtype=torch.int64, generator=generator).tolist()\n        else:\n            yield from torch.randperm(n, generator=generator).tolist()\n\n    def __len__(self) -> int:\n        return self.num_samples\n\n\nclass SubsetRandomSampler(Sampler[int]):\n    r\"\"\"Samples elements randomly from a given list of indices, without replacement.\n\n    Args:\n        indices (sequence): a sequence of indices\n        generator (Generator): Generator used in sampling.\n    \"\"\"\n    indices: Sequence[int]\n\n    def __init__(self, indices: Sequence[int], generator=None) -> None:\n        self.indices = indices\n        self.generator = generator\n\n    def __iter__(self) -> Iterator[int]:\n        for i in torch.randperm(len(self.indices), generator=self.generator):\n            yield self.indices[i]\n\n    def __len__(self) -> int:\n        return len(self.indices)\n\n\nclass WeightedRandomSampler(Sampler[int]):\n    r\"\"\"Samples elements from ``[0,..,len(weights)-1]`` with given probabilities (weights).\n\n    Args:\n        weights (sequence)   : a sequence of weights, not necessary summing up to one\n        num_samples (int): number of samples to draw\n        replacement (bool): if ``True``, samples are drawn with replacement.\n            If not, they are drawn without replacement, which means that when a\n            sample index is drawn for a row, it cannot be drawn again for that row.\n        generator (Generator): Generator used in sampling.\n\n    Example:\n        >>> list(WeightedRandomSampler([0.1, 0.9, 0.4, 0.7, 3.0, 0.6], 5, replacement=True))\n        [4, 4, 1, 4, 5]\n        >>> list(WeightedRandomSampler([0.9, 0.4, 0.05, 0.2, 0.3, 0.1], 5, replacement=False))\n        [0, 1, 4, 3, 2]\n    \"\"\"\n    weights: Tensor\n    num_samples: int\n    replacement: bool\n\n    def __init__(self, weights: Sequence[float], num_samples: int,\n                 replacement: bool = True, generator=None) -> None:\n        if not isinstance(num_samples, int) or isinstance(num_samples, bool) or \\\n                num_samples <= 0:\n            raise ValueError(\"num_samples should be a positive integer \"\n                             \"value, but got num_samples={}\".format(num_samples))\n        if not isinstance(replacement, bool):\n            raise ValueError(\"replacement should be a boolean value, but got \"\n                             \"replacement={}\".format(replacement))\n        self.weights = torch.as_tensor(weights, dtype=torch.double)\n        self.num_samples = num_samples\n        self.replacement = replacement\n        self.generator = generator\n\n    def __iter__(self) -> Iterator[int]:\n        rand_tensor = torch.multinomial(self.weights, self.num_samples, self.replacement, generator=self.generator)\n        yield from iter(rand_tensor.tolist())\n\n    def __len__(self) -> int:\n        return self.num_samples\n\n\nclass BatchSampler(Sampler[List[int]]):\n    r\"\"\"Wraps another sampler to yield a mini-batch of indices.\n\n    Args:\n        sampler (Sampler or Iterable): Base sampler. Can be any iterable object\n        batch_size (int): Size of mini-batch.\n        drop_last (bool): If ``True``, the sampler will drop the last batch if\n            its size would be less than ``batch_size``\n\n    Example:\n        >>> list(BatchSampler(SequentialSampler(range(10)), batch_size=3, drop_last=False))\n        [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]\n        >>> list(BatchSampler(SequentialSampler(range(10)), batch_size=3, drop_last=True))\n        [[0, 1, 2], [3, 4, 5], [6, 7, 8]]\n    \"\"\"\n\n    def __init__(self, sampler: Sampler[int], batch_size: int, drop_last: bool) -> None:\n        # Since collections.abc.Iterable does not check for `__getitem__`, which\n        # is one way for an object to be an iterable, we don't do an `isinstance`\n        # check here.\n        if not isinstance(batch_size, int) or isinstance(batch_size, bool) or \\\n                batch_size <= 0:\n            raise ValueError(\"batch_size should be a positive integer value, \"\n                             \"but got batch_size={}\".format(batch_size))\n        if not isinstance(drop_last, bool):\n            raise ValueError(\"drop_last should be a boolean value, but got \"\n                             \"drop_last={}\".format(drop_last))\n        self.sampler = sampler\n        self.batch_size = batch_size\n        self.drop_last = drop_last\n\n    def __iter__(self) -> Iterator[List[int]]:\n        batch = []\n        for idx in self.sampler:\n            batch.append(idx)\n            if len(batch) == self.batch_size:\n                yield batch\n                batch = []\n        if len(batch) > 0 and not self.drop_last:\n            yield batch\n\n    def __len__(self) -> int:\n        # Can only be called if self.sampler has __len__ implemented\n        # We cannot enforce this condition, so we turn off typechecking for the\n        # implementation below.\n        # Somewhat related: see NOTE [ Lack of Default `__len__` in Python Abstract Base Classes ]\n        if self.drop_last:\n            return len(self.sampler) // self.batch_size  # type: ignore[arg-type]\n        else:\n            return (len(self.sampler) + self.batch_size - 1) // self.batch_size  # type: ignore[arg-type]\n", "path": "torch/utils/data/sampler.py"}]}