uisrnn.utils

Utils for UIS-RNN.

  1# Copyright 2018 Google LLC
  2#
  3# Licensed under the Apache License, Version 2.0 (the "License");
  4# you may not use this file except in compliance with the License.
  5# You may obtain a copy of the License at
  6#
  7#     https://www.apache.org/licenses/LICENSE-2.0
  8#
  9# Unless required by applicable law or agreed to in writing, software
 10# distributed under the License is distributed on an "AS IS" BASIS,
 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12# See the License for the specific language governing permissions and
 13# limitations under the License.
 14"""Utils for UIS-RNN."""
 15
 16import random
 17import string
 18
 19import numpy as np
 20import torch
 21from torch import autograd
 22
 23
 24class Logger:
 25  """A class for printing logging information to screen."""
 26
 27  def __init__(self, verbosity):
 28    self._verbosity = verbosity
 29
 30  def print(self, level, message):
 31    """Print a message if level is not higher than verbosity.
 32
 33    Args:
 34      level: the level of this message, smaller value means more important
 35      message: the message to be printed
 36    """
 37    if level <= self._verbosity:
 38      print(message)
 39
 40
 41def generate_random_string(length=6):
 42  """Generate a random string of upper case letters and digits.
 43
 44  Args:
 45    length: length of the generated string
 46
 47  Returns:
 48    the generated string
 49  """
 50  return ''.join([
 51      random.choice(string.ascii_uppercase + string.digits)
 52      for _ in range(length)])
 53
 54
 55def enforce_cluster_id_uniqueness(cluster_ids):
 56  """Enforce uniqueness of cluster id across sequences.
 57
 58  Args:
 59    cluster_ids: a list of 1-dim list/numpy.ndarray of strings
 60
 61  Returns:
 62    a new list with same length of cluster_ids
 63
 64  Raises:
 65    TypeError: if cluster_ids or its element has wrong type
 66  """
 67  if not isinstance(cluster_ids, list):
 68    raise TypeError('cluster_ids must be a list')
 69  new_cluster_ids = []
 70  for cluster_id in cluster_ids:
 71    sequence_id = generate_random_string()
 72    if isinstance(cluster_id, np.ndarray):
 73      cluster_id = cluster_id.tolist()
 74    if not isinstance(cluster_id, list):
 75      raise TypeError('Elements of cluster_ids must be list or numpy.ndarray')
 76    new_cluster_id = ['_'.join([sequence_id, s]) for s in cluster_id]
 77    new_cluster_ids.append(new_cluster_id)
 78  return new_cluster_ids
 79
 80
 81def concatenate_training_data(train_sequences, train_cluster_ids,
 82                              enforce_uniqueness=True, shuffle=True):
 83  """Concatenate training data.
 84
 85  Args:
 86    train_sequences: a list of 2-dim numpy arrays to be concatenated
 87    train_cluster_ids: a list of 1-dim list/numpy.ndarray of strings
 88    enforce_uniqueness: a boolean indicated whether we should enfore uniqueness
 89      to train_cluster_ids
 90    shuffle: whether to randomly shuffle input order
 91
 92  Returns:
 93    concatenated_train_sequence: a 2-dim numpy array
 94    concatenated_train_cluster_id: a list of strings
 95
 96  Raises:
 97    TypeError: if input has wrong type
 98    ValueError: if sizes/dimensions of input or their elements are incorrect
 99  """
100  # check input
101  if not isinstance(train_sequences, list) or not isinstance(
102      train_cluster_ids, list):
103    raise TypeError('train_sequences and train_cluster_ids must be lists')
104  if len(train_sequences) != len(train_cluster_ids):
105    raise ValueError(
106        'train_sequences and train_cluster_ids must have same size')
107  train_cluster_ids = [
108      x.tolist() if isinstance(x, np.ndarray) else x
109      for x in train_cluster_ids]
110  global_observation_dim = None
111  for i, (train_sequence, train_cluster_id) in enumerate(
112      zip(train_sequences, train_cluster_ids)):
113    train_length, observation_dim = train_sequence.shape
114    if i == 0:
115      global_observation_dim = observation_dim
116    elif global_observation_dim != observation_dim:
117      raise ValueError(
118          'train_sequences must have consistent observation dimension')
119    if not isinstance(train_cluster_id, list):
120      raise TypeError(
121          'Elements of train_cluster_ids must be list or numpy.ndarray')
122    if len(train_cluster_id) != train_length:
123      raise ValueError(
124          'Each train_sequence and its train_cluster_id must have same length')
125
126  # enforce uniqueness
127  if enforce_uniqueness:
128    train_cluster_ids = enforce_cluster_id_uniqueness(train_cluster_ids)
129
130  # random shuffle
131  if shuffle:
132    zipped_input = list(zip(train_sequences, train_cluster_ids))
133    random.shuffle(zipped_input)
134    train_sequences, train_cluster_ids = zip(*zipped_input)
135
136  # concatenate
137  concatenated_train_sequence = np.concatenate(train_sequences, axis=0)
138  concatenated_train_cluster_id = [x for train_cluster_id in train_cluster_ids
139                                   for x in train_cluster_id]
140  return concatenated_train_sequence, concatenated_train_cluster_id
141
142
143def sample_permuted_segments(index_sequence, number_samples):
144  """Sample sequences with permuted blocks.
145
146  Args:
147    index_sequence: (integer array, size: L)
148      - subsequence index
149      For example, index_sequence = [1,2,6,10,11,12].
150    number_samples: (integer)
151      - number of subsampled block-preserving permuted sequences.
152      For example, number_samples = 5
153
154  Returns:
155    sampled_index_sequences: (a list of numpy arrays) - a list of subsampled
156      block-preserving permuted sequences. For example,
157    ```
158    sampled_index_sequences =
159    [[10,11,12,1,2,6],
160     [6,1,2,10,11,12],
161     [1,2,10,11,12,6],
162     [6,1,2,10,11,12],
163     [1,2,6,10,11,12]]
164    ```
165      The length of "sampled_index_sequences" is "number_samples".
166  """
167  segments = []
168  if len(index_sequence) == 1:
169    segments.append(index_sequence)
170  else:
171    prev = 0
172    for i in range(len(index_sequence) - 1):
173      if index_sequence[i + 1] != index_sequence[i] + 1:
174        segments.append(index_sequence[prev:(i + 1)])
175        prev = i + 1
176      if i + 1 == len(index_sequence) - 1:
177        segments.append(index_sequence[prev:])
178  # sample permutations
179  sampled_index_sequences = []
180  for _ in range(number_samples):
181    segments_array = []
182    permutation = np.random.permutation(len(segments))
183    for permutation_item in permutation:
184      segments_array.append(segments[permutation_item])
185    sampled_index_sequences.append(np.concatenate(segments_array))
186  return sampled_index_sequences
187
188
189def resize_sequence(sequence, cluster_id, num_permutations=None):
190  """Resize sequences for packing and batching.
191
192  Args:
193    sequence: (real numpy matrix, size: seq_len*obs_size) - observed sequence
194    cluster_id: (numpy vector, size: seq_len) - cluster indicator sequence
195    num_permutations: int - Number of permutations per utterance sampled.
196
197  Returns:
198    sub_sequences: A list of numpy array, with obsevation vector from the same
199      cluster in the same list.
200    seq_lengths: The length of each cluster (+1).
201  """
202  # merge sub-sequences that belong to a single cluster to a single sequence
203  unique_id = np.unique(cluster_id)
204  sub_sequences = []
205  seq_lengths = []
206  if num_permutations and num_permutations > 1:
207    for i in unique_id:
208      idx_set = np.where(cluster_id == i)[0]
209      sampled_idx_sets = sample_permuted_segments(idx_set, num_permutations)
210      for j in range(num_permutations):
211        sub_sequences.append(sequence[sampled_idx_sets[j], :])
212        seq_lengths.append(len(idx_set) + 1)
213  else:
214    for i in unique_id:
215      idx_set = np.where(cluster_id == i)
216      sub_sequences.append(sequence[idx_set, :][0])
217      seq_lengths.append(len(idx_set[0]) + 1)
218  return sub_sequences, seq_lengths
219
220
221def pack_sequence(
222    sub_sequences, seq_lengths, batch_size, observation_dim, device):
223  """Pack sequences for training.
224
225  Args:
226    sub_sequences: A list of numpy array, with obsevation vector from the same
227      cluster in the same list.
228    seq_lengths: The length of each cluster (+1).
229    batch_size: int or None - Run batch learning if batch_size is None. Else,
230      run online learning with specified batch size.
231    observation_dim: int - dimension for observation vectors
232    device: str - Your device. E.g., `cuda:0` or `cpu`.
233
234  Returns:
235    packed_rnn_input: (PackedSequence object) packed rnn input
236    rnn_truth: ground truth
237  """
238  num_clusters = len(seq_lengths)
239  sorted_seq_lengths = np.sort(seq_lengths)[::-1]
240  permute_index = np.argsort(seq_lengths)[::-1]
241
242  if batch_size is None:
243    rnn_input = np.zeros((sorted_seq_lengths[0],
244                          num_clusters,
245                          observation_dim))
246    for i in range(num_clusters):
247      rnn_input[1:sorted_seq_lengths[i], i,
248                :] = sub_sequences[permute_index[i]]
249    rnn_input = autograd.Variable(
250        torch.from_numpy(rnn_input).float()).to(device)
251    packed_rnn_input = torch.nn.utils.rnn.pack_padded_sequence(
252        rnn_input, sorted_seq_lengths, batch_first=False)
253  else:
254    mini_batch = np.sort(np.random.choice(num_clusters, batch_size))
255    rnn_input = np.zeros((sorted_seq_lengths[mini_batch[0]],
256                          batch_size,
257                          observation_dim))
258    for i in range(batch_size):
259      rnn_input[1:sorted_seq_lengths[mini_batch[i]],
260                i, :] = sub_sequences[permute_index[mini_batch[i]]]
261    rnn_input = autograd.Variable(
262        torch.from_numpy(rnn_input).float()).to(device)
263    packed_rnn_input = torch.nn.utils.rnn.pack_padded_sequence(
264        rnn_input, sorted_seq_lengths[mini_batch], batch_first=False)
265  # ground truth is the shifted input
266  rnn_truth = rnn_input[1:, :, :]
267  return packed_rnn_input, rnn_truth
268
269
270def output_result(model_args, training_args, test_record):
271  """Produce a string to summarize the experiment."""
272  accuracy_array, _ = zip(*test_record)
273  total_accuracy = np.mean(accuracy_array)
274  output_string = """
275Config:
276  sigma_alpha: {}
277  sigma_beta: {}
278  crp_alpha: {}
279  learning rate: {}
280  regularization: {}
281  batch size: {}
282
283Performance:
284  averaged accuracy: {:.6f}
285  accuracy numbers for all testing sequences:
286  """.strip().format(
287      training_args.sigma_alpha,
288      training_args.sigma_beta,
289      model_args.crp_alpha,
290      training_args.learning_rate,
291      training_args.regularization_weight,
292      training_args.batch_size,
293      total_accuracy)
294  for accuracy in accuracy_array:
295    output_string += '\n    {:.6f}'.format(accuracy)
296  output_string += '\n' + '=' * 80 + '\n'
297  filename = 'layer_{}_{}_{:.1f}_result.txt'.format(
298      model_args.rnn_hidden_size,
299      model_args.rnn_depth, model_args.rnn_dropout)
300  with open(filename, 'a') as file_object:
301    file_object.write(output_string)
302  return output_string
303
304
305def estimate_transition_bias(cluster_ids, smooth=1):
306  """Estimate the transition bias.
307
308  Args:
309    cluster_id: Either a list of cluster indicator sequences, or a single
310      concatenated sequence. The former is strongly preferred, since the
311      transition_bias estimated from the latter will be inaccurate.
312    smooth: int or float - Smoothing coefficient, avoids -inf value in np.log
313      in the case of a sequence with a single speaker and division by 0 in the
314      case of empty sequences. Using a small value for smooth decreases the
315      bias in the calculation of transition_bias but can also lead to underflow
316      in some remote cases, larger values are safer but less accurate.
317
318  Returns:
319    bias: Flipping coin head probability.
320    bias_denominator: The denominator of the bias, used for multiple calls to
321      fit().
322  """
323  transit_num = smooth
324  bias_denominator = 2 * smooth
325  for cluster_id_seq in cluster_ids:
326    for entry in range(len(cluster_id_seq) - 1):
327      transit_num += (cluster_id_seq[entry] != cluster_id_seq[entry + 1])
328      bias_denominator += 1
329  bias = transit_num / bias_denominator
330  return bias, bias_denominator
class Logger:
25class Logger:
26  """A class for printing logging information to screen."""
27
28  def __init__(self, verbosity):
29    self._verbosity = verbosity
30
31  def print(self, level, message):
32    """Print a message if level is not higher than verbosity.
33
34    Args:
35      level: the level of this message, smaller value means more important
36      message: the message to be printed
37    """
38    if level <= self._verbosity:
39      print(message)

A class for printing logging information to screen.

Logger(verbosity)
28  def __init__(self, verbosity):
29    self._verbosity = verbosity
def print(self, level, message):
31  def print(self, level, message):
32    """Print a message if level is not higher than verbosity.
33
34    Args:
35      level: the level of this message, smaller value means more important
36      message: the message to be printed
37    """
38    if level <= self._verbosity:
39      print(message)

Print a message if level is not higher than verbosity.

Args: level: the level of this message, smaller value means more important message: the message to be printed

def generate_random_string(length=6):
42def generate_random_string(length=6):
43  """Generate a random string of upper case letters and digits.
44
45  Args:
46    length: length of the generated string
47
48  Returns:
49    the generated string
50  """
51  return ''.join([
52      random.choice(string.ascii_uppercase + string.digits)
53      for _ in range(length)])

Generate a random string of upper case letters and digits.

Args: length: length of the generated string

Returns: the generated string

def enforce_cluster_id_uniqueness(cluster_ids):
56def enforce_cluster_id_uniqueness(cluster_ids):
57  """Enforce uniqueness of cluster id across sequences.
58
59  Args:
60    cluster_ids: a list of 1-dim list/numpy.ndarray of strings
61
62  Returns:
63    a new list with same length of cluster_ids
64
65  Raises:
66    TypeError: if cluster_ids or its element has wrong type
67  """
68  if not isinstance(cluster_ids, list):
69    raise TypeError('cluster_ids must be a list')
70  new_cluster_ids = []
71  for cluster_id in cluster_ids:
72    sequence_id = generate_random_string()
73    if isinstance(cluster_id, np.ndarray):
74      cluster_id = cluster_id.tolist()
75    if not isinstance(cluster_id, list):
76      raise TypeError('Elements of cluster_ids must be list or numpy.ndarray')
77    new_cluster_id = ['_'.join([sequence_id, s]) for s in cluster_id]
78    new_cluster_ids.append(new_cluster_id)
79  return new_cluster_ids

Enforce uniqueness of cluster id across sequences.

Args: cluster_ids: a list of 1-dim list/numpy.ndarray of strings

Returns: a new list with same length of cluster_ids

Raises: TypeError: if cluster_ids or its element has wrong type

def concatenate_training_data( train_sequences, train_cluster_ids, enforce_uniqueness=True, shuffle=True):
 82def concatenate_training_data(train_sequences, train_cluster_ids,
 83                              enforce_uniqueness=True, shuffle=True):
 84  """Concatenate training data.
 85
 86  Args:
 87    train_sequences: a list of 2-dim numpy arrays to be concatenated
 88    train_cluster_ids: a list of 1-dim list/numpy.ndarray of strings
 89    enforce_uniqueness: a boolean indicated whether we should enfore uniqueness
 90      to train_cluster_ids
 91    shuffle: whether to randomly shuffle input order
 92
 93  Returns:
 94    concatenated_train_sequence: a 2-dim numpy array
 95    concatenated_train_cluster_id: a list of strings
 96
 97  Raises:
 98    TypeError: if input has wrong type
 99    ValueError: if sizes/dimensions of input or their elements are incorrect
100  """
101  # check input
102  if not isinstance(train_sequences, list) or not isinstance(
103      train_cluster_ids, list):
104    raise TypeError('train_sequences and train_cluster_ids must be lists')
105  if len(train_sequences) != len(train_cluster_ids):
106    raise ValueError(
107        'train_sequences and train_cluster_ids must have same size')
108  train_cluster_ids = [
109      x.tolist() if isinstance(x, np.ndarray) else x
110      for x in train_cluster_ids]
111  global_observation_dim = None
112  for i, (train_sequence, train_cluster_id) in enumerate(
113      zip(train_sequences, train_cluster_ids)):
114    train_length, observation_dim = train_sequence.shape
115    if i == 0:
116      global_observation_dim = observation_dim
117    elif global_observation_dim != observation_dim:
118      raise ValueError(
119          'train_sequences must have consistent observation dimension')
120    if not isinstance(train_cluster_id, list):
121      raise TypeError(
122          'Elements of train_cluster_ids must be list or numpy.ndarray')
123    if len(train_cluster_id) != train_length:
124      raise ValueError(
125          'Each train_sequence and its train_cluster_id must have same length')
126
127  # enforce uniqueness
128  if enforce_uniqueness:
129    train_cluster_ids = enforce_cluster_id_uniqueness(train_cluster_ids)
130
131  # random shuffle
132  if shuffle:
133    zipped_input = list(zip(train_sequences, train_cluster_ids))
134    random.shuffle(zipped_input)
135    train_sequences, train_cluster_ids = zip(*zipped_input)
136
137  # concatenate
138  concatenated_train_sequence = np.concatenate(train_sequences, axis=0)
139  concatenated_train_cluster_id = [x for train_cluster_id in train_cluster_ids
140                                   for x in train_cluster_id]
141  return concatenated_train_sequence, concatenated_train_cluster_id

Concatenate training data.

Args: train_sequences: a list of 2-dim numpy arrays to be concatenated train_cluster_ids: a list of 1-dim list/numpy.ndarray of strings enforce_uniqueness: a boolean indicated whether we should enfore uniqueness to train_cluster_ids shuffle: whether to randomly shuffle input order

Returns: concatenated_train_sequence: a 2-dim numpy array concatenated_train_cluster_id: a list of strings

Raises: TypeError: if input has wrong type ValueError: if sizes/dimensions of input or their elements are incorrect

def sample_permuted_segments(index_sequence, number_samples):
144def sample_permuted_segments(index_sequence, number_samples):
145  """Sample sequences with permuted blocks.
146
147  Args:
148    index_sequence: (integer array, size: L)
149      - subsequence index
150      For example, index_sequence = [1,2,6,10,11,12].
151    number_samples: (integer)
152      - number of subsampled block-preserving permuted sequences.
153      For example, number_samples = 5
154
155  Returns:
156    sampled_index_sequences: (a list of numpy arrays) - a list of subsampled
157      block-preserving permuted sequences. For example,
158    ```
159    sampled_index_sequences =
160    [[10,11,12,1,2,6],
161     [6,1,2,10,11,12],
162     [1,2,10,11,12,6],
163     [6,1,2,10,11,12],
164     [1,2,6,10,11,12]]
165    ```
166      The length of "sampled_index_sequences" is "number_samples".
167  """
168  segments = []
169  if len(index_sequence) == 1:
170    segments.append(index_sequence)
171  else:
172    prev = 0
173    for i in range(len(index_sequence) - 1):
174      if index_sequence[i + 1] != index_sequence[i] + 1:
175        segments.append(index_sequence[prev:(i + 1)])
176        prev = i + 1
177      if i + 1 == len(index_sequence) - 1:
178        segments.append(index_sequence[prev:])
179  # sample permutations
180  sampled_index_sequences = []
181  for _ in range(number_samples):
182    segments_array = []
183    permutation = np.random.permutation(len(segments))
184    for permutation_item in permutation:
185      segments_array.append(segments[permutation_item])
186    sampled_index_sequences.append(np.concatenate(segments_array))
187  return sampled_index_sequences

Sample sequences with permuted blocks.

Args: index_sequence: (integer array, size: L) - subsequence index For example, index_sequence = [1,2,6,10,11,12]. number_samples: (integer) - number of subsampled block-preserving permuted sequences. For example, number_samples = 5

Returns: sampled_index_sequences: (a list of numpy arrays) - a list of subsampled block-preserving permuted sequences. For example,

sampled_index_sequences =
[[10,11,12,1,2,6],
 [6,1,2,10,11,12],
 [1,2,10,11,12,6],
 [6,1,2,10,11,12],
 [1,2,6,10,11,12]]
The length of "sampled_index_sequences" is "number_samples".

def resize_sequence(sequence, cluster_id, num_permutations=None):
190def resize_sequence(sequence, cluster_id, num_permutations=None):
191  """Resize sequences for packing and batching.
192
193  Args:
194    sequence: (real numpy matrix, size: seq_len*obs_size) - observed sequence
195    cluster_id: (numpy vector, size: seq_len) - cluster indicator sequence
196    num_permutations: int - Number of permutations per utterance sampled.
197
198  Returns:
199    sub_sequences: A list of numpy array, with obsevation vector from the same
200      cluster in the same list.
201    seq_lengths: The length of each cluster (+1).
202  """
203  # merge sub-sequences that belong to a single cluster to a single sequence
204  unique_id = np.unique(cluster_id)
205  sub_sequences = []
206  seq_lengths = []
207  if num_permutations and num_permutations > 1:
208    for i in unique_id:
209      idx_set = np.where(cluster_id == i)[0]
210      sampled_idx_sets = sample_permuted_segments(idx_set, num_permutations)
211      for j in range(num_permutations):
212        sub_sequences.append(sequence[sampled_idx_sets[j], :])
213        seq_lengths.append(len(idx_set) + 1)
214  else:
215    for i in unique_id:
216      idx_set = np.where(cluster_id == i)
217      sub_sequences.append(sequence[idx_set, :][0])
218      seq_lengths.append(len(idx_set[0]) + 1)
219  return sub_sequences, seq_lengths

Resize sequences for packing and batching.

Args: sequence: (real numpy matrix, size: seq_len*obs_size) - observed sequence cluster_id: (numpy vector, size: seq_len) - cluster indicator sequence num_permutations: int - Number of permutations per utterance sampled.

Returns: sub_sequences: A list of numpy array, with obsevation vector from the same cluster in the same list. seq_lengths: The length of each cluster (+1).

def pack_sequence(sub_sequences, seq_lengths, batch_size, observation_dim, device):
222def pack_sequence(
223    sub_sequences, seq_lengths, batch_size, observation_dim, device):
224  """Pack sequences for training.
225
226  Args:
227    sub_sequences: A list of numpy array, with obsevation vector from the same
228      cluster in the same list.
229    seq_lengths: The length of each cluster (+1).
230    batch_size: int or None - Run batch learning if batch_size is None. Else,
231      run online learning with specified batch size.
232    observation_dim: int - dimension for observation vectors
233    device: str - Your device. E.g., `cuda:0` or `cpu`.
234
235  Returns:
236    packed_rnn_input: (PackedSequence object) packed rnn input
237    rnn_truth: ground truth
238  """
239  num_clusters = len(seq_lengths)
240  sorted_seq_lengths = np.sort(seq_lengths)[::-1]
241  permute_index = np.argsort(seq_lengths)[::-1]
242
243  if batch_size is None:
244    rnn_input = np.zeros((sorted_seq_lengths[0],
245                          num_clusters,
246                          observation_dim))
247    for i in range(num_clusters):
248      rnn_input[1:sorted_seq_lengths[i], i,
249                :] = sub_sequences[permute_index[i]]
250    rnn_input = autograd.Variable(
251        torch.from_numpy(rnn_input).float()).to(device)
252    packed_rnn_input = torch.nn.utils.rnn.pack_padded_sequence(
253        rnn_input, sorted_seq_lengths, batch_first=False)
254  else:
255    mini_batch = np.sort(np.random.choice(num_clusters, batch_size))
256    rnn_input = np.zeros((sorted_seq_lengths[mini_batch[0]],
257                          batch_size,
258                          observation_dim))
259    for i in range(batch_size):
260      rnn_input[1:sorted_seq_lengths[mini_batch[i]],
261                i, :] = sub_sequences[permute_index[mini_batch[i]]]
262    rnn_input = autograd.Variable(
263        torch.from_numpy(rnn_input).float()).to(device)
264    packed_rnn_input = torch.nn.utils.rnn.pack_padded_sequence(
265        rnn_input, sorted_seq_lengths[mini_batch], batch_first=False)
266  # ground truth is the shifted input
267  rnn_truth = rnn_input[1:, :, :]
268  return packed_rnn_input, rnn_truth

Pack sequences for training.

Args: sub_sequences: A list of numpy array, with obsevation vector from the same cluster in the same list. seq_lengths: The length of each cluster (+1). batch_size: int or None - Run batch learning if batch_size is None. Else, run online learning with specified batch size. observation_dim: int - dimension for observation vectors device: str - Your device. E.g., cuda:0 or cpu.

Returns: packed_rnn_input: (PackedSequence object) packed rnn input rnn_truth: ground truth

def output_result(model_args, training_args, test_record):
271def output_result(model_args, training_args, test_record):
272  """Produce a string to summarize the experiment."""
273  accuracy_array, _ = zip(*test_record)
274  total_accuracy = np.mean(accuracy_array)
275  output_string = """
276Config:
277  sigma_alpha: {}
278  sigma_beta: {}
279  crp_alpha: {}
280  learning rate: {}
281  regularization: {}
282  batch size: {}
283
284Performance:
285  averaged accuracy: {:.6f}
286  accuracy numbers for all testing sequences:
287  """.strip().format(
288      training_args.sigma_alpha,
289      training_args.sigma_beta,
290      model_args.crp_alpha,
291      training_args.learning_rate,
292      training_args.regularization_weight,
293      training_args.batch_size,
294      total_accuracy)
295  for accuracy in accuracy_array:
296    output_string += '\n    {:.6f}'.format(accuracy)
297  output_string += '\n' + '=' * 80 + '\n'
298  filename = 'layer_{}_{}_{:.1f}_result.txt'.format(
299      model_args.rnn_hidden_size,
300      model_args.rnn_depth, model_args.rnn_dropout)
301  with open(filename, 'a') as file_object:
302    file_object.write(output_string)
303  return output_string

Produce a string to summarize the experiment.

def estimate_transition_bias(cluster_ids, smooth=1):
306def estimate_transition_bias(cluster_ids, smooth=1):
307  """Estimate the transition bias.
308
309  Args:
310    cluster_id: Either a list of cluster indicator sequences, or a single
311      concatenated sequence. The former is strongly preferred, since the
312      transition_bias estimated from the latter will be inaccurate.
313    smooth: int or float - Smoothing coefficient, avoids -inf value in np.log
314      in the case of a sequence with a single speaker and division by 0 in the
315      case of empty sequences. Using a small value for smooth decreases the
316      bias in the calculation of transition_bias but can also lead to underflow
317      in some remote cases, larger values are safer but less accurate.
318
319  Returns:
320    bias: Flipping coin head probability.
321    bias_denominator: The denominator of the bias, used for multiple calls to
322      fit().
323  """
324  transit_num = smooth
325  bias_denominator = 2 * smooth
326  for cluster_id_seq in cluster_ids:
327    for entry in range(len(cluster_id_seq) - 1):
328      transit_num += (cluster_id_seq[entry] != cluster_id_seq[entry + 1])
329      bias_denominator += 1
330  bias = transit_num / bias_denominator
331  return bias, bias_denominator

Estimate the transition bias.

Args: cluster_id: Either a list of cluster indicator sequences, or a single concatenated sequence. The former is strongly preferred, since the transition_bias estimated from the latter will be inaccurate. smooth: int or float - Smoothing coefficient, avoids -inf value in np.log in the case of a sequence with a single speaker and division by 0 in the case of empty sequences. Using a small value for smooth decreases the bias in the calculation of transition_bias but can also lead to underflow in some remote cases, larger values are safer but less accurate.

Returns: bias: Flipping coin head probability. bias_denominator: The denominator of the bias, used for multiple calls to fit().