MMS-MSG เป็นเฟรมเวิร์กแบบแยกส่วนสูงและยืดหยุ่นสำหรับการสร้างการผสมคำพูด มันขยายรหัสฐานของฐานข้อมูล SMS-WSJ สำหรับการสร้างสัญญาณผสมเพื่อให้สามารถสร้างทั้งการผสมคำพูดสไตล์การประชุมและสัญญาณผสมที่สอดคล้องกับฐานข้อมูลผสมคำพูดแบบคลาสสิก
ข้อมูลการประชุมอธิบายการตั้งค่าที่มีพลวัตสูง ทั้งสภาพแวดล้อมที่มี MMS-MSG เราไม่ได้ตั้งเป้าหมายที่จะจัดทำฐานข้อมูลใหม่เดียว
แต่เราต้องการจัดเตรียมกรอบการทำงานที่สามารถปรับเปลี่ยนได้ซึ่งช่วยให้การสร้างต้นแบบและการประเมินผลของระบบการประชุมและระบบการถอดความในสภาพแวดล้อมที่มากที่สุด
แง่มุมหลักของ MMS-MSG คือการสร้างข้อมูลสไตล์การประชุม การประชุมถูกสร้างขึ้นในแบบแยกส่วน พารามิเตอร์ที่ปรับได้คือ:
กระบวนการสุ่มตัวอย่างเป็นแบบแยกส่วนเพื่อให้สามารถสร้างสถานการณ์หลายสถานการณ์ได้โดยการเปลี่ยนไปป์ไลน์การสุ่มตัวอย่างเล็กน้อย เราจัดเตรียมคลาสตัวอย่างเพื่อแสดงวิธีการใช้โมดูลเดียว หากไม่รองรับสถานการณ์โมดูลการสุ่มตัวอย่างใหม่สามารถนำไปใช้งานได้ง่ายเพื่อปรับ MMS-MSG ให้ตรงกับความต้องการของคุณ
กระบวนการจำลองข้อมูลของ MMS-MSG ถูกแบ่งออกเป็นการสุ่มตัวอย่างพารามิเตอร์และการสร้างข้อมูลจริง ผ่านสิ่งนี้เราสนับสนุนการสร้างข้อมูลตามความต้องการ ด้วยวิธีนี้จะต้องบันทึกข้อมูลต้นทางและพารามิเตอร์การประชุมเท่านั้นซึ่งจะช่วยให้การจำลองสถานการณ์การประชุมต่างๆในขณะที่ลดพื้นที่ดิสก์ที่จำเป็นให้น้อยที่สุด อย่างไรก็ตามเรายังสนับสนุนการสร้างข้อมูลการประชุมออฟไลน์หากบันทึกลงในฮาร์ดดิสก์เป็นสิ่งจำเป็นสำหรับเวิร์กโฟลว์ของคุณ
เราให้รหัสเพื่อสร้างการผสมคำพูดตามข้อกำหนดของฐานข้อมูลการแยกแหล่งที่ใช้ในปัจจุบันซึ่งคำพูดเดียวของลำโพงหลายตัวไม่ว่าจะซ้อนทับกันบางส่วนหรือทั้งหมด ด้วยการใช้ MMS-MSG เพื่อสร้างข้อมูลการฝึกอบรมสำหรับฐานข้อมูลเหล่านี้เราให้การสนับสนุนแบบดั้งเดิมของการผสมแบบไดนามิก
ฐานข้อมูลผสมคำพูดที่รองรับ:
วางแผน:
เครื่องกำเนิดส่วนผสมใช้ LAZY_DATASET ในขณะที่ฟังก์ชั่นหลักของ MMS_MSG สามารถใช้งานได้โดยไม่ต้องใช้ Lazy_Dataset แต่คุณสมบัติบางอย่าง (เช่นการผสมแบบไดนามิกและฐานข้อมูลที่เป็นนามธรรม) ไม่สามารถใช้ได้
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 )
รูทีนการปรับเปลี่ยนข้อมูลอื่น ๆ สามารถแมปกับ ds
ได้โดยตรงหลังจากโหลดตัวอย่าง
lazy_dataset.Dataset
สามารถเสียบเข้ากับ 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 )
ตัวอย่างอินพุตควรมีโครงสร้างนี้:
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)
}
หลังจากเลือกคำพูดสำหรับส่วนผสมตัวอย่างคำพูดเหล่านี้จะถูกทำให้เป็นมาตรฐานและ "collated" ซึ่งส่งผลให้โครงสร้างคล้ายกับสิ่งนี้:
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'
],
...
}
เริ่มต้นจากโครงสร้างดังกล่าวโมดูลการสุ่มตัวอย่างสามารถนำไปใช้เพื่อเติมตัวอย่างด้วยข้อมูลเพิ่มเติมเช่นการชดเชยหรือการปรับขนาดของคำพูด
คลาสฐานข้อมูลหรือคำจำกัดความมีไว้สำหรับสถานการณ์ทั่วไปสองสามสถานการณ์ใน mms_msg.databases
แต่ละคลาสฐานข้อมูลต้องกำหนดสองวิธี:
get_mixture_dataset
ซึ่งห่อหุ้มระยะ "การสุ่มตัวอย่าง" และสร้างท่อของโมดูลการสุ่มตัวอย่างและload_example
ซึ่งให้ขั้นตอน "การจำลอง" เช่นการโหลดและการผสมข้อมูลเสียงฐานข้อมูลพื้นฐาน (ปราศจากพารามิเตอร์) จะมีลักษณะเช่นนี้:
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 )
และสามารถสร้างอินสแตนซ์ด้วย
db = MyDatabase ( 'path/to/source/database.json' )
โครงสร้างของไปป์ไลน์การสุ่มตัวอย่างชุดข้อมูลอธิบายไว้ในส่วนถัดไป
นี่คือตัวอย่างของไปป์ไลน์การสุ่มตัวอย่างอย่างง่ายสำหรับชุดข้อมูลเดียว:
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 ))
กระบวนการสุ่มตัวอย่างเริ่มต้นด้วยการสร้าง "องค์ประกอบแหล่งที่มา" เช่นคำพูดการสุ่มตัวอย่าง (ฐาน) สำหรับแต่ละส่วนผสม สิ่งนี้ทำใน get_composition_dataset
ซึ่งใช้อัลกอริทึมการสุ่มตัวอย่างคล้ายกับ SMS-WSJ ที่ใช้คำพูดแต่ละครั้งจากฐานข้อมูลแหล่งที่มาบ่อยครั้ง
หลังจากนี้โมดูลการสุ่มตัวอย่างสามารถนำไปใช้เพื่อจำลองรูปแบบการพูดหรือสภาพแวดล้อมที่แตกต่างกัน ตัวอย่างข้างต้นตั้งค่าออฟเซ็ตทั้งหมดเป็นศูนย์ (เช่นคำพูดทั้งหมดเริ่มต้นที่จุดเริ่มต้นของส่วนผสม) ด้วย ConstantOffsetSampler
และตัวอย่างสเกลสุ่มที่มีสูงสุด 5dB กับ UniformScalingSampler
มีโมดูลการสุ่มตัวอย่างอื่น ๆ อีกมากมายรวมถึงหนึ่งที่จำลองรูปแบบการพูดสไตล์การประชุม ตัวอย่างสำหรับสิ่งนี้สามารถพบได้ในสมุดบันทึกนี้
ผสมใน mms_msg
ถูกสร้างขึ้นโดยใช้โมดูลการสุ่มตัวอย่างแต่ละรายการกับตัวอย่างหนึ่งหลังจากที่อื่น ๆ แต่ละโมดูลการสุ่มตัวอย่างมีการกำหนดอย่างสมบูรณ์เช่นเอาต์พุตของมันขึ้นอยู่กับพารามิเตอร์ไฮเปอร์พารามิเตอร์และตัวอย่างอินพุต แต่ไม่ได้รับอนุญาตให้รักษาสถานะที่ไม่แน่นอน นี่คือเพื่อให้แน่ใจว่าการทำซ้ำ: การสุ่มตัวอย่างไม่ได้ขึ้นอยู่กับลำดับที่สร้างส่วนผสมจำนวนหรือลำดับที่ใช้โมดูล
โมดูลการสุ่มตัวอย่างเป็นแบบเรียกได้ที่ได้รับส่วนผสม (กลาง) เป็นพจนานุกรมปรับเปลี่ยนและส่งคืน โมดูลการสุ่มตัวอย่างพื้นฐานที่ใช้เป็นฟังก์ชั่นที่ไม่มีพารามิเตอร์ไฮเปอร์พารามิเตอร์อาจมีลักษณะเช่นนี้:
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
ส่วนสำคัญคือ mms_msg.sampling.utils.rng.get_rng_example
มันส่งคืนวัตถุ np.random.Generator
ที่เริ่มต้นด้วยเมล็ดที่คำนวณจากข้อมูลพื้นฐานจากพจนานุกรมตัวอย่าง (ตัวอย่าง-ID และชุดข้อมูล) และสตริงเมล็ดเพิ่มเติม ซึ่งหมายความว่าตัวเลขสุ่มที่สร้างขึ้นในโมดูลมีค่าเท่ากันทุกครั้งที่โมดูลถูกนำไปใช้กับตัวอย่างอินพุตเดียวกัน
หากโมดูลการสุ่มตัวอย่างของคุณมีพารามิเตอร์ hyperparameters เราขอแนะนำ dataclass แช่แข็งเพื่อให้แน่ใจว่าไม่สามารถเปลี่ยนแปลงได้:
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
ตัวอย่างที่เป็นประโยชน์มากขึ้นได้รับในสมุดบันทึกนี้
MMS-MSG ถูกเสนอในสิ่งพิมพ์ต่อไปนี้:
@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} } ,
} ```