make_noiser.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. """This module inmplements some methods to artificialy noise the data
  2. """
  3. from typing import List, Dict
  4. from random import choices, sample, shuffle
  5. import copy
  6. import random
  7. random.seed(80)
  8. class Noise :
  9. """
  10. This class simulates noise in the data. Crucially,\
  11. noise can be made on three cases :\
  12. (1) The noise of phonemes order of a given sequence\
  13. by making the order of the sequence more aribitrary,\
  14. (2) Replacement of some phonemes of a given sequence\
  15. by arbitrary sampled phonemes from a vocabulary and\
  16. (3) By arbitrary interverting some sequences of two different speakers.
  17. Atributes
  18. ---------
  19. - phonemes_order_noise :
  20. Parameter for controling the degree of noise at the level\
  21. of phonemes order. See the point 1 mentioned above.
  22. - speakers_noise_values :
  23. Parameters for controling the degree of noise at the level\
  24. of speakers. See the point 3 mentioned above.
  25. - phonemes_noise_value :
  26. Parameter for controling the degree of noise at the level of phonemes.
  27. See the point 2 mentioned above.
  28. """
  29. def __init__(self,
  30. most_probable_phonemes,
  31. phonemes_order_noise_value=0.3,
  32. speakers_noise_values=(0.5, 0.5),
  33. phonemes_noise_value=0.5) :
  34. self.most_probable_phonemes = most_probable_phonemes
  35. self.phonemes_order_noise_value = phonemes_order_noise_value
  36. self.speakers_noise_values = speakers_noise_values
  37. self.phonemes_noise_value = phonemes_noise_value
  38. def order_noise(self, sequence: List[str]) -> str :
  39. """
  40. Making noise the order of the phonemes in a given sequence
  41. Parameters
  42. ----------
  43. - sequence : list
  44. The sequence for which the phonemes order must be noised.
  45. Returns
  46. -------
  47. - str :
  48. The sequence with the order of phonemes noised.
  49. """
  50. # number of phonemes to noise in the sequence = len(sequence) / nb_phonemes_to_noise
  51. phonemes_to_noise = round(len(sequence) * self.phonemes_order_noise_value)
  52. # sample nb_phonemes_to_noise positions in the sequence
  53. positions_sampled = list(sample(range(len(sequence)), k=phonemes_to_noise))
  54. copied_positions = copy.deepcopy(positions_sampled)
  55. shuffle(copied_positions)
  56. # change the positions of the sampled phonemes
  57. for original_position, new_position in zip(positions_sampled, copied_positions):
  58. sequence[original_position] = sequence[new_position]
  59. return " ".join(sequence)
  60. def phonemes_noise(self, sequence: List[str]) -> str :
  61. """
  62. Makinng noise the phonemes of the sequence by replacing\
  63. some phonemes of the sequence by arbitrary sampled phonemes\
  64. from the vocabulary.
  65. Parameters
  66. ----------
  67. - sequence : list
  68. The sequence for which the phonemes must be noised.
  69. Returns
  70. -------
  71. - str :
  72. The sequence with noised phonemes.
  73. """
  74. phonemes_to_noise = round(len(sequence) * self.phonemes_noise_value)
  75. indexes = choices(range(len(sequence)), k=phonemes_to_noise)
  76. # choose new phonemes only from the most probable phonemes.
  77. phonemes = choices(self.most_probable_phonemes, k=phonemes_to_noise)
  78. # and replace some indices of the sequence by those choosen phonemes
  79. for idx, phonemes in zip(indexes, phonemes) :
  80. sequence[idx] = phonemes
  81. return " ".join(sequence)
  82. def speakers_noise(self, speakers_sequences: Dict[str, set]) -> Dict[str, set] :
  83. """
  84. Making noise in the speaker's statements.
  85. Parameters
  86. ----------
  87. - speakers_sequences : dict
  88. Dictionary containing the utterances for each speaker.
  89. Returns
  90. -------
  91. - dict :
  92. The dictionary containing the few statements\
  93. interchanged between the two speakers.
  94. """
  95. first_speaker, second_speaker = "Target_Child", "Adult"
  96. noise_first_speaker, noise_second_speaker = self.speakers_noise_values
  97. speakers_sequences[second_speaker] = set(speakers_sequences[second_speaker])
  98. speakers_sequences[first_speaker] = set(speakers_sequences[first_speaker])
  99. # sample some percentage of utterances from each speaker
  100. sequences_to_noise_second_speaker = round(len(speakers_sequences[second_speaker]) * noise_second_speaker)
  101. sequences_to_noise_first_speaker = round(len(speakers_sequences[first_speaker]) * noise_first_speaker)
  102. sequences_noise_second_speaker = sample(list(speakers_sequences[second_speaker]), k=sequences_to_noise_second_speaker)
  103. sequences_noise_first_speaker = sample(list(speakers_sequences[first_speaker]), k=sequences_to_noise_first_speaker)
  104. # noise by interchanging sampled utterances
  105. speakers_sequences[second_speaker] -= set(sequences_noise_second_speaker)
  106. speakers_sequences[first_speaker] -= set(sequences_noise_first_speaker)
  107. speakers_sequences[second_speaker] |= set(sequences_noise_first_speaker)
  108. speakers_sequences[first_speaker] |= set(sequences_noise_second_speaker)
  109. # set to list
  110. speakers_sequences[first_speaker] = list(speakers_sequences[first_speaker])
  111. speakers_sequences[second_speaker] = list(speakers_sequences[second_speaker])
  112. return speakers_sequences
  113. def __call__(self, loaded_dataset: dict) -> dict:
  114. """
  115. Apply the three types of noise.
  116. Parameters
  117. ----------
  118. loaded_dataset : dict
  119. The dictionary containing the utterances for each family,\
  120. at each and for each speaker.
  121. Returns
  122. -------
  123. dict :
  124. The noised data.
  125. """
  126. for family in loaded_dataset :
  127. for age in loaded_dataset[family] :
  128. if "Adult" in loaded_dataset[family][age] :
  129. for idx, utterance in enumerate(loaded_dataset[family][age]["Adult"]) :
  130. splitted_utterance = utterance.split(" ")
  131. loaded_dataset[family][age]["Adult"][idx] = self.order_noise(splitted_utterance)
  132. loaded_dataset[family][age]["Adult"][idx] = self.phonemes_noise(splitted_utterance)
  133. if "Target_Child" in loaded_dataset[family][age] :
  134. for idx, utterance in enumerate(loaded_dataset[family][age]["Target_Child"]) :
  135. splitted_utterance = utterance.split(" ")
  136. loaded_dataset[family][age]["Target_Child"][idx] = self.order_noise(splitted_utterance)
  137. loaded_dataset[family][age]["Target_Child"][idx] = self.phonemes_noise(splitted_utterance)
  138. if("Target_Child" in loaded_dataset[family][age]
  139. and "Adult" in loaded_dataset[family][age]
  140. and all(self.speakers_noise_values)):
  141. noised_speaker = self.speakers_noise(loaded_dataset[family][age])
  142. loaded_dataset[family][age]["Target_Child"] = noised_speaker["Target_Child"]
  143. loaded_dataset[family][age]["Adult"] = noised_speaker["Adult"]
  144. return loaded_dataset