Get a random batch of data from the specified bucket, prepare for step. To feed data in step(..) it must be a list of batch-major vectors, while data here contains single length-major cases. So the main logic of this function is to re-index data cases to be in the proper format for feed
(self, data, bucket_id)
| 257 | return None, outputs[0], outputs[1:] # No gradient norm, loss, outputs. |
| 258 | |
| 259 | def get_batch(self, data, bucket_id): |
| 260 | """Get a random batch of data from the specified bucket, prepare for step. |
| 261 | |
| 262 | To feed data in step(..) it must be a list of batch-major vectors, while |
| 263 | data here contains single length-major cases. So the main logic of this |
| 264 | function is to re-index data cases to be in the proper format for feeding. |
| 265 | |
| 266 | Args: |
| 267 | data: a tuple of size len(self.buckets) in which each element contains |
| 268 | lists of pairs of input and output data that we use to create a batch. |
| 269 | bucket_id: integer, which bucket to get the batch for. |
| 270 | |
| 271 | Returns: |
| 272 | The triple (encoder_inputs, decoder_inputs, target_weights) for |
| 273 | the constructed batch that has the proper format to call step(...) later. |
| 274 | """ |
| 275 | encoder_size, decoder_size = self.buckets[bucket_id] |
| 276 | encoder_inputs, decoder_inputs = [], [] |
| 277 | |
| 278 | # Get a random batch of encoder and decoder inputs from data, |
| 279 | # pad them if needed, reverse encoder inputs and add GO to decoder. |
| 280 | for _ in xrange(self.batch_size): |
| 281 | encoder_input, decoder_input = random.choice(data[bucket_id]) |
| 282 | |
| 283 | # Encoder inputs are padded and then reversed. |
| 284 | encoder_pad = [data_utils.PAD_ID] * (encoder_size - len(encoder_input)) |
| 285 | encoder_inputs.append(list(reversed(encoder_input + encoder_pad))) |
| 286 | |
| 287 | # Decoder inputs get an extra "GO" symbol, and are padded then. |
| 288 | decoder_pad_size = decoder_size - len(decoder_input) - 1 |
| 289 | decoder_inputs.append([data_utils.GO_ID] + decoder_input + |
| 290 | [data_utils.PAD_ID] * decoder_pad_size) |
| 291 | |
| 292 | # Now we create batch-major vectors from the data selected above. |
| 293 | batch_encoder_inputs, batch_decoder_inputs, batch_weights = [], [], [] |
| 294 | |
| 295 | # Batch encoder inputs are just re-indexed encoder_inputs. |
| 296 | for length_idx in xrange(encoder_size): |
| 297 | batch_encoder_inputs.append( |
| 298 | np.array([encoder_inputs[batch_idx][length_idx] |
| 299 | for batch_idx in xrange(self.batch_size)], dtype=np.int32)) |
| 300 | |
| 301 | # Batch decoder inputs are re-indexed decoder_inputs, we create weights. |
| 302 | for length_idx in xrange(decoder_size): |
| 303 | batch_decoder_inputs.append( |
| 304 | np.array([decoder_inputs[batch_idx][length_idx] |
| 305 | for batch_idx in xrange(self.batch_size)], dtype=np.int32)) |
| 306 | |
| 307 | # Create target_weights to be 0 for targets that are padding. |
| 308 | batch_weight = np.ones(self.batch_size, dtype=np.float32) |
| 309 | for batch_idx in xrange(self.batch_size): |
| 310 | # We set weight to 0 if the corresponding target is a PAD symbol. |
| 311 | # The corresponding target is decoder_input shifted by 1 forward. |
| 312 | if length_idx < decoder_size - 1: |
| 313 | target = decoder_inputs[batch_idx][length_idx + 1] |
| 314 | if length_idx == decoder_size - 1 or target == data_utils.PAD_ID: |
| 315 | batch_weight[batch_idx] = 0.0 |
| 316 | batch_weights.append(batch_weight) |