We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Question on chunk shift in ChunkIterFactory.build_iter()
In the code, shift width is calculated as a ratio of utterance length as follows:
S = int(L * self.chunk_shift_ratio)

Shouldn't shift width be calculated as a ratio of chunk length like below ?
S = int(W * self.chunk_shift_ratio)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `espnet2/iterators/chunk_iter_factory.py`
Content:
```
1 import logging
2 from typing import Any
3 from typing import Dict
4 from typing import Iterator
5 from typing import List
6 from typing import Sequence
7 from typing import Tuple
8 from typing import Union
9 
10 import numpy as np
11 import torch
12 from typeguard import check_argument_types
13 
14 from espnet2.iterators.abs_iter_factory import AbsIterFactory
15 from espnet2.iterators.sequence_iter_factory import SequenceIterFactory
16 from espnet2.samplers.abs_sampler import AbsSampler
17 
18 
19 class ChunkIterFactory(AbsIterFactory):
20     """Creates chunks from a sequence
21 
22     Examples:
23         >>> batches = [["id1"], ["id2"], ...]
24         >>> batch_size = 128
25         >>> chunk_length = 1000
26         >>> iter_factory = ChunkIterFactory(dataset, batches, batch_size, chunk_length)
27         >>> it = iter_factory.build_iter(epoch)
28         >>> for ids, batch in it:
29         ...     ...
30 
31     - The number of mini-batches are varied in each epochs and
32       we can't get the number in advance
33       because IterFactory doesn't be given to the length information.
34     - Since the first reason, "num_iters_per_epoch" can't be implemented
35       for this iterator. Instead of it, "num_samples_per_epoch" is implemented.
36 
37     """
38 
39     def __init__(
40         self,
41         dataset,
42         batch_size: int,
43         batches: Union[AbsSampler, Sequence[Sequence[Any]]],
44         chunk_length: Union[int, str],
45         chunk_shift_ratio: float = 0.5,
46         num_cache_chunks: int = 1024,
47         num_samples_per_epoch: int = None,
48         seed: int = 0,
49         shuffle: bool = False,
50         num_workers: int = 0,
51         collate_fn=None,
52         pin_memory: bool = False,
53     ):
54         assert check_argument_types()
55         assert all(len(x) == 1 for x in batches), "batch-size must be 1"
56 
57         self.per_sample_iter_factory = SequenceIterFactory(
58             dataset=dataset,
59             batches=batches,
60             num_iters_per_epoch=num_samples_per_epoch,
61             seed=seed,
62             shuffle=shuffle,
63             num_workers=num_workers,
64             collate_fn=collate_fn,
65             pin_memory=pin_memory,
66         )
67 
68         self.num_cache_chunks = max(num_cache_chunks, batch_size)
69         if isinstance(chunk_length, str):
70             if len(chunk_length) == 0:
71                 raise ValueError("e.g. 5,8 or 3-5: but got empty string")
72 
73             self.chunk_lengths = []
74             for x in chunk_length.split(","):
75                 try:
76                     sps = list(map(int, x.split("-")))
77                 except ValueError:
78                     raise ValueError(f"e.g. 5,8 or 3-5: but got {chunk_length}")
79 
80                 if len(sps) > 2:
81                     raise ValueError(f"e.g. 5,8 or 3-5: but got {chunk_length}")
82                 elif len(sps) == 2:
83                     # Append all numbers between the range into the candidates
84                     self.chunk_lengths += list(range(sps[0], sps[1] + 1))
85                 else:
86                     self.chunk_lengths += [sps[0]]
87         else:
88             # Single candidates: Fixed chunk length
89             self.chunk_lengths = [chunk_length]
90 
91         self.chunk_shift_ratio = chunk_shift_ratio
92         self.batch_size = batch_size
93         self.seed = seed
94         self.shuffle = shuffle
95 
96     def build_iter(
97         self,
98         epoch: int,
99         shuffle: bool = None,
100     ) -> Iterator[Tuple[List[str], Dict[str, torch.Tensor]]]:
101         per_sample_loader = self.per_sample_iter_factory.build_iter(epoch, shuffle)
102 
103         if shuffle is None:
104             shuffle = self.shuffle
105         state = np.random.RandomState(epoch + self.seed)
106 
107         # NOTE(kamo):
108         #   This iterator supports multiple chunk lengths and
109         #   keep chunks for each lenghts here until collecting specified numbers
110         cache_chunks_dict = {}
111         cache_id_list_dict = {}
112         for ids, batch in per_sample_loader:
113             # Must be per-sample-loader
114             assert len(ids) == 1, f"Must be per-sample-loader: {len(ids)}"
115             assert all(len(x) == 1 for x in batch.values())
116 
117             # Get keys of sequence data
118             sequence_keys = []
119             for key in batch:
120                 if key + "_lengths" in batch:
121                     sequence_keys.append(key)
122             # Remove lengths data and get the first sample
123             batch = {k: v[0] for k, v in batch.items() if not k.endswith("_lengths")}
124             id_ = ids[0]
125 
126             for key in sequence_keys:
127                 if len(batch[key]) != len(batch[sequence_keys[0]]):
128                     raise RuntimeError(
129                         f"All sequences must has same length: "
130                         f"{len(batch[key])} != {len(batch[sequence_keys[0]])}"
131                     )
132 
133             L = len(batch[sequence_keys[0]])
134             # Select chunk length
135             chunk_lengths = [lg for lg in self.chunk_lengths if lg < L]
136             if len(chunk_lengths) == 0:
137                 logging.warning(
138                     f"The length of '{id_}' is {L}, but it is shorter than "
139                     f"any candidates of chunk-length: {self.chunk_lengths}"
140                 )
141                 continue
142 
143             W = int(state.choice(chunk_lengths, 1))
144             cache_id_list = cache_id_list_dict.setdefault(W, [])
145             cache_chunks = cache_chunks_dict.setdefault(W, {})
146 
147             # Shift width to the next chunk
148             S = int(L * self.chunk_shift_ratio)
149             # Number of chunks
150             N = (L - W) // S + 1
151             if shuffle:
152                 Z = state.randint(0, (L - W) % S + 1)
153             else:
154                 Z = 0
155 
156             # Split a sequence into chunks.
157             # Note that the marginal frames divided by chunk length are discarded
158             for k, v in batch.items():
159                 if k not in cache_chunks:
160                     cache_chunks[k] = []
161                 if k in sequence_keys:
162                     # Shift chunks with overlapped length for data augmentation
163                     cache_chunks[k] += [v[Z + i * S : Z + i * S + W] for i in range(N)]
164                 else:
165                     # If not sequence, use whole data instead of chunk
166                     cache_chunks[k] += [v for _ in range(N)]
167             cache_id_list += [id_ for _ in range(N)]
168 
169             if len(cache_id_list) > self.num_cache_chunks:
170                 cache_id_list, cache_chunks = yield from self._generate_mini_batches(
171                     cache_id_list,
172                     cache_chunks,
173                     shuffle,
174                     state,
175                 )
176 
177             cache_id_list_dict[W] = cache_id_list
178             cache_chunks_dict[W] = cache_chunks
179 
180         else:
181             for W in cache_id_list_dict:
182                 cache_id_list = cache_id_list_dict.setdefault(W, [])
183                 cache_chunks = cache_chunks_dict.setdefault(W, {})
184 
185                 yield from self._generate_mini_batches(
186                     cache_id_list,
187                     cache_chunks,
188                     shuffle,
189                     state,
190                 )
191 
192     def _generate_mini_batches(
193         self,
194         id_list: List[str],
195         batches: Dict[str, List[torch.Tensor]],
196         shuffle: bool,
197         state: np.random.RandomState,
198     ):
199         if shuffle:
200             indices = np.arange(0, len(id_list))
201             state.shuffle(indices)
202             batches = {k: [v[i] for i in indices] for k, v in batches.items()}
203             id_list = [id_list[i] for i in indices]
204 
205         bs = self.batch_size
206         while len(id_list) >= bs:
207             # Make mini-batch and yield
208             yield (
209                 id_list[:bs],
210                 {k: torch.stack(v[:bs], 0) for k, v in batches.items()},
211             )
212             id_list = id_list[bs:]
213             batches = {k: v[bs:] for k, v in batches.items()}
214 
215         return id_list, batches
216
```
--- 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/espnet2/iterators/chunk_iter_factory.py b/espnet2/iterators/chunk_iter_factory.py
--- a/espnet2/iterators/chunk_iter_factory.py
+++ b/espnet2/iterators/chunk_iter_factory.py
@@ -145,7 +145,7 @@
             cache_chunks = cache_chunks_dict.setdefault(W, {})
 
             # Shift width to the next chunk
-            S = int(L * self.chunk_shift_ratio)
+            S = int(W * self.chunk_shift_ratio)
             # Number of chunks
             N = (L - W) // S + 1
             if shuffle:

{"golden_diff": "diff --git a/espnet2/iterators/chunk_iter_factory.py b/espnet2/iterators/chunk_iter_factory.py\n--- a/espnet2/iterators/chunk_iter_factory.py\n+++ b/espnet2/iterators/chunk_iter_factory.py\n@@ -145,7 +145,7 @@\n             cache_chunks = cache_chunks_dict.setdefault(W, {})\n \n             # Shift width to the next chunk\n-            S = int(L * self.chunk_shift_ratio)\n+            S = int(W * self.chunk_shift_ratio)\n             # Number of chunks\n             N = (L - W) // S + 1\n             if shuffle:\n", "issue": "Question on chunk shift in ChunkIterFactory.build_iter()\nIn the code, shift width is calculated as a ratio of utterance length as follows:\r\nS = int(L * self.chunk_shift_ratio)\r\n\r\nShouldn't shift width be calculated as a ratio of chunk length like below ?\r\nS = int(W * self.chunk_shift_ratio)\r\n\n", "before_files": [{"content": "import logging\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Iterator\nfrom typing import List\nfrom typing import Sequence\nfrom typing import Tuple\nfrom typing import Union\n\nimport numpy as np\nimport torch\nfrom typeguard import check_argument_types\n\nfrom espnet2.iterators.abs_iter_factory import AbsIterFactory\nfrom espnet2.iterators.sequence_iter_factory import SequenceIterFactory\nfrom espnet2.samplers.abs_sampler import AbsSampler\n\n\nclass ChunkIterFactory(AbsIterFactory):\n    \"\"\"Creates chunks from a sequence\n\n    Examples:\n        >>> batches = [[\"id1\"], [\"id2\"], ...]\n        >>> batch_size = 128\n        >>> chunk_length = 1000\n        >>> iter_factory = ChunkIterFactory(dataset, batches, batch_size, chunk_length)\n        >>> it = iter_factory.build_iter(epoch)\n        >>> for ids, batch in it:\n        ...     ...\n\n    - The number of mini-batches are varied in each epochs and\n      we can't get the number in advance\n      because IterFactory doesn't be given to the length information.\n    - Since the first reason, \"num_iters_per_epoch\" can't be implemented\n      for this iterator. Instead of it, \"num_samples_per_epoch\" is implemented.\n\n    \"\"\"\n\n    def __init__(\n        self,\n        dataset,\n        batch_size: int,\n        batches: Union[AbsSampler, Sequence[Sequence[Any]]],\n        chunk_length: Union[int, str],\n        chunk_shift_ratio: float = 0.5,\n        num_cache_chunks: int = 1024,\n        num_samples_per_epoch: int = None,\n        seed: int = 0,\n        shuffle: bool = False,\n        num_workers: int = 0,\n        collate_fn=None,\n        pin_memory: bool = False,\n    ):\n        assert check_argument_types()\n        assert all(len(x) == 1 for x in batches), \"batch-size must be 1\"\n\n        self.per_sample_iter_factory = SequenceIterFactory(\n            dataset=dataset,\n            batches=batches,\n            num_iters_per_epoch=num_samples_per_epoch,\n            seed=seed,\n            shuffle=shuffle,\n            num_workers=num_workers,\n            collate_fn=collate_fn,\n            pin_memory=pin_memory,\n        )\n\n        self.num_cache_chunks = max(num_cache_chunks, batch_size)\n        if isinstance(chunk_length, str):\n            if len(chunk_length) == 0:\n                raise ValueError(\"e.g. 5,8 or 3-5: but got empty string\")\n\n            self.chunk_lengths = []\n            for x in chunk_length.split(\",\"):\n                try:\n                    sps = list(map(int, x.split(\"-\")))\n                except ValueError:\n                    raise ValueError(f\"e.g. 5,8 or 3-5: but got {chunk_length}\")\n\n                if len(sps) > 2:\n                    raise ValueError(f\"e.g. 5,8 or 3-5: but got {chunk_length}\")\n                elif len(sps) == 2:\n                    # Append all numbers between the range into the candidates\n                    self.chunk_lengths += list(range(sps[0], sps[1] + 1))\n                else:\n                    self.chunk_lengths += [sps[0]]\n        else:\n            # Single candidates: Fixed chunk length\n            self.chunk_lengths = [chunk_length]\n\n        self.chunk_shift_ratio = chunk_shift_ratio\n        self.batch_size = batch_size\n        self.seed = seed\n        self.shuffle = shuffle\n\n    def build_iter(\n        self,\n        epoch: int,\n        shuffle: bool = None,\n    ) -> Iterator[Tuple[List[str], Dict[str, torch.Tensor]]]:\n        per_sample_loader = self.per_sample_iter_factory.build_iter(epoch, shuffle)\n\n        if shuffle is None:\n            shuffle = self.shuffle\n        state = np.random.RandomState(epoch + self.seed)\n\n        # NOTE(kamo):\n        #   This iterator supports multiple chunk lengths and\n        #   keep chunks for each lenghts here until collecting specified numbers\n        cache_chunks_dict = {}\n        cache_id_list_dict = {}\n        for ids, batch in per_sample_loader:\n            # Must be per-sample-loader\n            assert len(ids) == 1, f\"Must be per-sample-loader: {len(ids)}\"\n            assert all(len(x) == 1 for x in batch.values())\n\n            # Get keys of sequence data\n            sequence_keys = []\n            for key in batch:\n                if key + \"_lengths\" in batch:\n                    sequence_keys.append(key)\n            # Remove lengths data and get the first sample\n            batch = {k: v[0] for k, v in batch.items() if not k.endswith(\"_lengths\")}\n            id_ = ids[0]\n\n            for key in sequence_keys:\n                if len(batch[key]) != len(batch[sequence_keys[0]]):\n                    raise RuntimeError(\n                        f\"All sequences must has same length: \"\n                        f\"{len(batch[key])} != {len(batch[sequence_keys[0]])}\"\n                    )\n\n            L = len(batch[sequence_keys[0]])\n            # Select chunk length\n            chunk_lengths = [lg for lg in self.chunk_lengths if lg < L]\n            if len(chunk_lengths) == 0:\n                logging.warning(\n                    f\"The length of '{id_}' is {L}, but it is shorter than \"\n                    f\"any candidates of chunk-length: {self.chunk_lengths}\"\n                )\n                continue\n\n            W = int(state.choice(chunk_lengths, 1))\n            cache_id_list = cache_id_list_dict.setdefault(W, [])\n            cache_chunks = cache_chunks_dict.setdefault(W, {})\n\n            # Shift width to the next chunk\n            S = int(L * self.chunk_shift_ratio)\n            # Number of chunks\n            N = (L - W) // S + 1\n            if shuffle:\n                Z = state.randint(0, (L - W) % S + 1)\n            else:\n                Z = 0\n\n            # Split a sequence into chunks.\n            # Note that the marginal frames divided by chunk length are discarded\n            for k, v in batch.items():\n                if k not in cache_chunks:\n                    cache_chunks[k] = []\n                if k in sequence_keys:\n                    # Shift chunks with overlapped length for data augmentation\n                    cache_chunks[k] += [v[Z + i * S : Z + i * S + W] for i in range(N)]\n                else:\n                    # If not sequence, use whole data instead of chunk\n                    cache_chunks[k] += [v for _ in range(N)]\n            cache_id_list += [id_ for _ in range(N)]\n\n            if len(cache_id_list) > self.num_cache_chunks:\n                cache_id_list, cache_chunks = yield from self._generate_mini_batches(\n                    cache_id_list,\n                    cache_chunks,\n                    shuffle,\n                    state,\n                )\n\n            cache_id_list_dict[W] = cache_id_list\n            cache_chunks_dict[W] = cache_chunks\n\n        else:\n            for W in cache_id_list_dict:\n                cache_id_list = cache_id_list_dict.setdefault(W, [])\n                cache_chunks = cache_chunks_dict.setdefault(W, {})\n\n                yield from self._generate_mini_batches(\n                    cache_id_list,\n                    cache_chunks,\n                    shuffle,\n                    state,\n                )\n\n    def _generate_mini_batches(\n        self,\n        id_list: List[str],\n        batches: Dict[str, List[torch.Tensor]],\n        shuffle: bool,\n        state: np.random.RandomState,\n    ):\n        if shuffle:\n            indices = np.arange(0, len(id_list))\n            state.shuffle(indices)\n            batches = {k: [v[i] for i in indices] for k, v in batches.items()}\n            id_list = [id_list[i] for i in indices]\n\n        bs = self.batch_size\n        while len(id_list) >= bs:\n            # Make mini-batch and yield\n            yield (\n                id_list[:bs],\n                {k: torch.stack(v[:bs], 0) for k, v in batches.items()},\n            )\n            id_list = id_list[bs:]\n            batches = {k: v[bs:] for k, v in batches.items()}\n\n        return id_list, batches\n", "path": "espnet2/iterators/chunk_iter_factory.py"}], "after_files": [{"content": "import logging\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Iterator\nfrom typing import List\nfrom typing import Sequence\nfrom typing import Tuple\nfrom typing import Union\n\nimport numpy as np\nimport torch\nfrom typeguard import check_argument_types\n\nfrom espnet2.iterators.abs_iter_factory import AbsIterFactory\nfrom espnet2.iterators.sequence_iter_factory import SequenceIterFactory\nfrom espnet2.samplers.abs_sampler import AbsSampler\n\n\nclass ChunkIterFactory(AbsIterFactory):\n    \"\"\"Creates chunks from a sequence\n\n    Examples:\n        >>> batches = [[\"id1\"], [\"id2\"], ...]\n        >>> batch_size = 128\n        >>> chunk_length = 1000\n        >>> iter_factory = ChunkIterFactory(dataset, batches, batch_size, chunk_length)\n        >>> it = iter_factory.build_iter(epoch)\n        >>> for ids, batch in it:\n        ...     ...\n\n    - The number of mini-batches are varied in each epochs and\n      we can't get the number in advance\n      because IterFactory doesn't be given to the length information.\n    - Since the first reason, \"num_iters_per_epoch\" can't be implemented\n      for this iterator. Instead of it, \"num_samples_per_epoch\" is implemented.\n\n    \"\"\"\n\n    def __init__(\n        self,\n        dataset,\n        batch_size: int,\n        batches: Union[AbsSampler, Sequence[Sequence[Any]]],\n        chunk_length: Union[int, str],\n        chunk_shift_ratio: float = 0.5,\n        num_cache_chunks: int = 1024,\n        num_samples_per_epoch: int = None,\n        seed: int = 0,\n        shuffle: bool = False,\n        num_workers: int = 0,\n        collate_fn=None,\n        pin_memory: bool = False,\n    ):\n        assert check_argument_types()\n        assert all(len(x) == 1 for x in batches), \"batch-size must be 1\"\n\n        self.per_sample_iter_factory = SequenceIterFactory(\n            dataset=dataset,\n            batches=batches,\n            num_iters_per_epoch=num_samples_per_epoch,\n            seed=seed,\n            shuffle=shuffle,\n            num_workers=num_workers,\n            collate_fn=collate_fn,\n            pin_memory=pin_memory,\n        )\n\n        self.num_cache_chunks = max(num_cache_chunks, batch_size)\n        if isinstance(chunk_length, str):\n            if len(chunk_length) == 0:\n                raise ValueError(\"e.g. 5,8 or 3-5: but got empty string\")\n\n            self.chunk_lengths = []\n            for x in chunk_length.split(\",\"):\n                try:\n                    sps = list(map(int, x.split(\"-\")))\n                except ValueError:\n                    raise ValueError(f\"e.g. 5,8 or 3-5: but got {chunk_length}\")\n\n                if len(sps) > 2:\n                    raise ValueError(f\"e.g. 5,8 or 3-5: but got {chunk_length}\")\n                elif len(sps) == 2:\n                    # Append all numbers between the range into the candidates\n                    self.chunk_lengths += list(range(sps[0], sps[1] + 1))\n                else:\n                    self.chunk_lengths += [sps[0]]\n        else:\n            # Single candidates: Fixed chunk length\n            self.chunk_lengths = [chunk_length]\n\n        self.chunk_shift_ratio = chunk_shift_ratio\n        self.batch_size = batch_size\n        self.seed = seed\n        self.shuffle = shuffle\n\n    def build_iter(\n        self,\n        epoch: int,\n        shuffle: bool = None,\n    ) -> Iterator[Tuple[List[str], Dict[str, torch.Tensor]]]:\n        per_sample_loader = self.per_sample_iter_factory.build_iter(epoch, shuffle)\n\n        if shuffle is None:\n            shuffle = self.shuffle\n        state = np.random.RandomState(epoch + self.seed)\n\n        # NOTE(kamo):\n        #   This iterator supports multiple chunk lengths and\n        #   keep chunks for each lenghts here until collecting specified numbers\n        cache_chunks_dict = {}\n        cache_id_list_dict = {}\n        for ids, batch in per_sample_loader:\n            # Must be per-sample-loader\n            assert len(ids) == 1, f\"Must be per-sample-loader: {len(ids)}\"\n            assert all(len(x) == 1 for x in batch.values())\n\n            # Get keys of sequence data\n            sequence_keys = []\n            for key in batch:\n                if key + \"_lengths\" in batch:\n                    sequence_keys.append(key)\n            # Remove lengths data and get the first sample\n            batch = {k: v[0] for k, v in batch.items() if not k.endswith(\"_lengths\")}\n            id_ = ids[0]\n\n            for key in sequence_keys:\n                if len(batch[key]) != len(batch[sequence_keys[0]]):\n                    raise RuntimeError(\n                        f\"All sequences must has same length: \"\n                        f\"{len(batch[key])} != {len(batch[sequence_keys[0]])}\"\n                    )\n\n            L = len(batch[sequence_keys[0]])\n            # Select chunk length\n            chunk_lengths = [lg for lg in self.chunk_lengths if lg < L]\n            if len(chunk_lengths) == 0:\n                logging.warning(\n                    f\"The length of '{id_}' is {L}, but it is shorter than \"\n                    f\"any candidates of chunk-length: {self.chunk_lengths}\"\n                )\n                continue\n\n            W = int(state.choice(chunk_lengths, 1))\n            cache_id_list = cache_id_list_dict.setdefault(W, [])\n            cache_chunks = cache_chunks_dict.setdefault(W, {})\n\n            # Shift width to the next chunk\n            S = int(W * self.chunk_shift_ratio)\n            # Number of chunks\n            N = (L - W) // S + 1\n            if shuffle:\n                Z = state.randint(0, (L - W) % S + 1)\n            else:\n                Z = 0\n\n            # Split a sequence into chunks.\n            # Note that the marginal frames divided by chunk length are discarded\n            for k, v in batch.items():\n                if k not in cache_chunks:\n                    cache_chunks[k] = []\n                if k in sequence_keys:\n                    # Shift chunks with overlapped length for data augmentation\n                    cache_chunks[k] += [v[Z + i * S : Z + i * S + W] for i in range(N)]\n                else:\n                    # If not sequence, use whole data instead of chunk\n                    cache_chunks[k] += [v for _ in range(N)]\n            cache_id_list += [id_ for _ in range(N)]\n\n            if len(cache_id_list) > self.num_cache_chunks:\n                cache_id_list, cache_chunks = yield from self._generate_mini_batches(\n                    cache_id_list,\n                    cache_chunks,\n                    shuffle,\n                    state,\n                )\n\n            cache_id_list_dict[W] = cache_id_list\n            cache_chunks_dict[W] = cache_chunks\n\n        else:\n            for W in cache_id_list_dict:\n                cache_id_list = cache_id_list_dict.setdefault(W, [])\n                cache_chunks = cache_chunks_dict.setdefault(W, {})\n\n                yield from self._generate_mini_batches(\n                    cache_id_list,\n                    cache_chunks,\n                    shuffle,\n                    state,\n                )\n\n    def _generate_mini_batches(\n        self,\n        id_list: List[str],\n        batches: Dict[str, List[torch.Tensor]],\n        shuffle: bool,\n        state: np.random.RandomState,\n    ):\n        if shuffle:\n            indices = np.arange(0, len(id_list))\n            state.shuffle(indices)\n            batches = {k: [v[i] for i in indices] for k, v in batches.items()}\n            id_list = [id_list[i] for i in indices]\n\n        bs = self.batch_size\n        while len(id_list) >= bs:\n            # Make mini-batch and yield\n            yield (\n                id_list[:bs],\n                {k: torch.stack(v[:bs], 0) for k, v in batches.items()},\n            )\n            id_list = id_list[bs:]\n            batches = {k: v[bs:] for k, v in batches.items()}\n\n        return id_list, batches\n", "path": "espnet2/iterators/chunk_iter_factory.py"}]}