O MMS-MSG é uma estrutura altamente modular e flexível para a geração de misturas de fala. Ele estende a base de código do banco de dados SMS-WSJ para a geração de sinais de mistura para poder gerar misturas de fala em estilo de reunião e sinais de mistura correspondentes aos bancos de dados clássicos da mistura de fala.
Os dados de reunião descrevem uma configuração altamente dinâmica. Tanto o ambiente com o MMS-MSG, não pretendemos fornecer um único banco de dados.
Em vez disso, queremos fornecer uma estrutura adaptável que permita a prototipagem e a avaliação da reunião do sistema de procesação e transcrição no maior número possível de ambientes.
O aspecto central do MMS-MSG é a geração de dados de estilo de reunião. As reuniões são geradas de maneira modular. Os parâmetros ajustáveis são:
O processo de amostragem é modularizado, para que muitos cenários possam ser criados alterando ligeiramente o pipeline de amostragem. Fornecemos classes de exemplo para mostrar como os módulos únicos são usados. Se um cenário não for suportado, novos módulos de amostragem podem ser facilmente implementados para adaptar o MMS-MSG aos seus requisitos.
O processo de simulação de dados do MMS-MSG é dividido na amostragem de parâmetros e na geração de dados real. Com isso, apoiamos a geração de dados sob demanda. Dessa forma, apenas os dados de origem e os parâmetros da reunião precisam ser salvos, permitindo a simulação de vários cenários de reunião, minimizando o espaço de disco necessário. No entanto, também apoiamos a geração offline dos dados de atender aos dados se salvá -los no disco rígido for necessário para o seu fluxo de trabalho.
Fornecemos código para gerar misturas de fala de acordo com as especificações de bancos de dados de separação de origem atualmente usados, onde enunciados únicos de vários alto -falantes, parcial ou totalmente se sobrepõem. Ao usar o MMS-MSG para gerar dados de treinamento para esses bancos de dados, oferecemos um suporte nativo à mistura dinâmica.
Bancos de dados de mistura de fala suportados:
Planejado:
O gerador de mistura usa LAZY_Dataset. Embora a funcionalidade principal do MMS_MSG possa ser usada sem LAZY_Dataset, alguns recursos (como a mixagem dinâmica e a abstração do banco de dados) não estão disponíveis na época.
from mms_msg . databases . classical . full_overlap import WSJ2Mix
from mms_msg . sampling . utils import collate_fn
db = WSJ2Mix ()
# Get a train dataset with dynamic mixing
# This dataset only emits the metadata of the mixtures, it doesn't load
# the data yet
ds = db . get_dataset ( 'train_si284_rng' )
# The data can be loaded by mapping a database's load_example function
ds = ds . map ( db . load_example )
# Other dataset modifications (see lazy_dataset doc)
ds = ds . shuffle ( reshuffle = True )
ds = ds . batch ( batch_size = 8 ). map ( collate_fn )
# ...
# Parallelize data loading with lazy_dataset
ds = ds . prefetch ( num_workers = 8 , buffer_size = 16 )
# The dataset can now be used in any training loop
for example in ds :
# ... do fancy stuff with the example.
# The loaded audio data is in example['audio_data']
print ( example )
Quaisquer outras rotinas de modificação de dados podem ser mapeadas para ds
diretamente após o carregamento do exemplo.
Um lazy_dataset.Dataset
pode ser conectado a uma torch.utils.data.DataLoader
:
from mms_msg . databases . classical . full_overlap import WSJ2Mix
db = WSJ2Mix ()
ds = db . get_dataset ( 'train_si284_rng' ). map ( db . load_example )
# Parallelize data loading with torch.utils.data.DataLoader
from torch . utils . data import DataLoader
loader = DataLoader ( ds , batch_size = 8 , shuffle = True , num_workers = 8 )
for example in loader :
print ( example )
Os exemplos de entrada devem ter esta estrutura:
example = {
'audio_path' : {
'observation' : 'single_speaker_recording.wav'
},
'speaker_id' : 'A' ,
'num_samples' : 1234 , # Number of samples of the observation file
# 'num_samples': {'observation': 1234} # Alernative, if other audios are present
'dataset' : 'test' , # The input dataset name
'example_id' : 'asdf1234' , # Unique ID of this example. Optional if the input data is passes as a dict
'scenario' : 'cafe-asdf1234' , # (Optional) If provided, mms_msg makes sure that all examples of the same speaker in a mixture share the same scenario
# ... (any additional keys)
}
Depois de selecionar enunciados para uma mistura, esses exemplos de enunciado são normalizados e "colados", o que resulta em uma estrutura semelhante a esta:
example = {
'audio_path' : {
'original_source' : [
'source1.wav' ,
'source2.wav' ,
],
},
'speaker_id' : [
'A' , 'B'
],
'num_samples' : { # The structure under some keys mirrors the structure in 'audio_path'
'original_source' : [
1234 , 4321
]
},
'source_id' : [ # Reference to the source examples this mixture was created from
'asdf1234' , 'asdf1235'
],
...
}
A partir de tal estrutura, os módulos de amostragem podem ser aplicados para preencher o exemplo com mais informações, por exemplo, compensações ou escala dos enunciados.
Classes ou definições de banco de dados são fornecidas para alguns cenários comuns em mms_msg.databases
. Cada classe de banco de dados deve definir dois métodos:
get_mixture_dataset
, que encapsula o estágio de "amostragem" e cria um pipeline de módulos de amostragem eload_example
, que fornece o estágio de "simulação", ou seja, carregando e misturando os dados de áudio.Um banco de dados básico (livre de parâmetros) ficaria assim:
from mms_msg . databases . database import MMSMSGDatabase
from lazy_dataset . database import JsonDatabase
import mms_msg
class MyDatabase ( JsonDatabase , MMSMSGDatabase ):
def get_mixture_dataset ( self , name , rng ):
ds = mms_msg . sampling . source_composition . get_composition_dataset (
input_dataset = super (). get_dataset ( name ),
num_speakers = 2 ,
rng = rng ,
)
ds = ds . map ( mms_msg . sampling . pattern . classical . ConstantOffsetSampler ( 8000 ))
ds = ds . map ( mms_msg . sampling . environment . scaling . ConstantScalingSampler ( 0 ))
return ds
def load_example ( self , example ):
return mms_msg . simulation . anechoic . anechoic_scenario_map_fn ( example )
e pode ser instanciado com
db = MyDatabase ( 'path/to/source/database.json' )
A estrutura do pipeline de amostragem do conjunto de dados é descrita na próxima seção.
Este é um exemplo de um pipeline de amostragem simples para um único conjunto de dados:
import mms_msg
input_ds = ... # Get source utterance examples from somewhere
# Compute a composition of base examples. This makes sure that the speaker distribution
# in the mixtures is equal to the speaker distribution in the original database.
ds = mms_msg . sampling . source_composition . get_composition_dataset ( input_dataset = input_ds , num_speakers = 2 )
# If required: Offset the utterances
ds = ds . map ( mms_msg . sampling . pattern . classical . ConstantOffsetSampler ( 0 ))
# If required: Add log_weights to simulate volume differences
ds = ds . map ( mms_msg . sampling . environment . scaling . UniformScalingSampler ( max_weight = 5 ))
O processo de amostragem sempre começa com a criação de uma "composição da fonte", ou seja, enunciados de amostragem (base) para cada mistura. Isso é feito em get_composition_dataset
, que implementa um algoritmo de amostragem semelhante ao SMS-WSJ que usa cada enunciada do banco de dados de origem igualmente.
Depois disso, os módulos de amostragem podem ser aplicados para simular diferentes padrões ou ambientes de fala. O exemplo acima define todas as compensações a zero (ou seja, todas as declarações começam no início da mistura) com o ConstantOffsetSampler
e amostras de uma escala aleatória com um máximo de 5dB com o UniformScalingSampler
.
Muitos outros módulos de amostragem estão disponíveis, incluindo um que simula padrões de fala em estilo de reunião. Exemplos para isso podem ser encontrados neste caderno.
As misturas em mms_msg
são criadas aplicando módulos de amostragem individuais a um exemplo um após o outro. Cada módulo de amostragem é totalmente determinístico, ou seja, sua saída depende apenas de seus hiperparâmetros e do exemplo de entrada, mas não tem permissão para manter um estado mutável. Isso é para garantir a reprodutibilidade: a amostragem não depende da ordem em que as misturas são geradas, o número ou ordem em que os módulos são aplicados.
Um módulo de amostragem é um chamável que recebe uma mistura (intermediária) como um dicionário, modifica -a e o retorna. Um módulo de amostragem básico, implementado como uma função sem hiperparâmetros, poderia parecer assim:
import mms_msg
def my_sampling_module ( example : dict ) -> dict :
# Get a deterministic random number generator based on the input example
# and an additional seed string. The seed string ensures that the RNGs
# differ between different sampling modules
rng = mms_msg . sampling . utils . rng . get_rng_example ( example , 'my_sampler' )
# Sample whatever based on RNG and possibly the contents of example
example [ 'my_random_number' ] = rng . random ()
return example
Uma parte importante é a função mms_msg.sampling.utils.rng.get_rng_example
. Ele retorna um objeto np.random.Generator
, que é inicializado com uma semente calculada a partir de informações básicas do exemplo de dicionário (exemplo-ID e DataSet) e uma sequência de sementes adicional. Isso significa que os números aleatórios gerados em um módulo são iguais toda vez que o módulo é aplicado ao mesmo exemplo de entrada.
Se o seu módulo de amostragem tiver hiperparâmetros, recomendamos um dataclass congelado para garantir a imutabilidade:
import mms_msg
from dataclasses import dataclass
@ dataclass ( frozen = True )
class MySamplingModule :
size : int = 42
def __call__ ( self , example ):
rng = mms_msg . sampling . utils . rng . get_rng_example ( example , 'my_sampler' )
# Sample whatever based on RNG and possibly the contents of example
example [ 'my_random_number' ] = rng . random ( self . size )
return example
Um exemplo mais prático é dado neste caderno.
MMS-MSG foi proposto na seguinte publicação:
@inproceedings { cordlandwehr2022mms_msg ,
title = { MMS-MSG: A Multi-purpose Multi-Speaker Mixture Signal Generator } ,
author = { Tobias Cord-Landwehr and Thilo von Neumann and Christoph Boeddeker and Reinhold Haeb-Umbach } ,
year = { 2022 } ,
booktitle = { International Workshop on Acoustic Signal Enhancement (IWAENC) } ,
publisher = { {IEEE} } ,
} ```