diff --git a/.gitignore b/.gitignore index 7f799eb95949484aa2c7cc39f3754666cb755c53..60d04541123f9b22473c1d54f12462c185d82f3e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ ENV/ env/ .venv/ .ENV/ - # Python IDEs .idea/ .vscode/ @@ -29,6 +28,17 @@ tensorboard_logs/ .DS_Store Thumbs.db +# PyCharm files +*.iml +.idea/ + +# Coverage and testing tools +.coverage +nosetests.xml +coverage.xml +*.cover +*.log + # Compiled extension modules *.so *.dylib @@ -40,3 +50,9 @@ cython_debug/ # Other custom ignore rules *.bak *.swp + +.ruff_cache/ + +# Model checkpoints (downloaded at runtime) +ckpts/ +.gradio/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..fa27918c7f99e4a535474ccd1cdf373d61568a96 --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ +Creative Commons Attribution 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution 4.0 International Public License ("Public License"). +To the extent this Public License may be interpreted as a contract, +You are granted the Licensed Rights in consideration of Your acceptance +of these terms and conditions, and the Licensor grants You such rights +in consideration of benefits the Licensor receives from making +the Licensed Material available under these terms and conditions. + +You are free to: +- Share — copy and redistribute the material in any medium or format +- Adapt — remix, transform, and build upon the material for any purpose, even commercially. + +Under the following terms: +- Attribution — You must give appropriate credit, provide a link to the license, + and indicate if changes were made. You may do so in any reasonable manner, + but not in any way that suggests the licensor endorses you or your use. + +No additional restrictions — You may not apply legal terms or +technological measures that legally restrict others from doing +anything the license permits. + +Full license text: https://creativecommons.org/licenses/by/4.0/legalcode diff --git a/README.md b/README.md index 1226698e846d0b1075807e6d462d7d4fd4d52976..73e2ea25d25b6a59b8dea745afe2ed524917d6d5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ --- title: SongFormer -emoji: "\U0001F3B5" +emoji: "🎵" colorFrom: blue colorTo: indigo sdk: gradio @@ -40,6 +40,8 @@ Chunbo Hao*, Ruibin Yuan*, Jixun Yao, Qixin Deng, SongFormer is a music structure analysis framework that leverages multi-resolution self-supervised representations and heterogeneous supervision, accompanied by the large-scale multilingual dataset SongFormDB and the high-quality benchmark SongFormBench to foster fair and reproducible research. +**This Space offers two modes:** analyze a *Single File* with downloadable results (JSON / MSA / CSV / plot / ZIP), or use the *Batch* tab to process multiple files with live per-file status, a combined ZIP (downloadable mid-run), and a per-file inspector with audio playback. Runs on ZeroGPU — each analyzed file consumes daily GPU quota. +  ## Citation diff --git a/app.py b/app.py index 6ccb841afdb46489f25de5c16dcb057f39da2e66..c63d4d3766899298b0d0edea86789a58a609cd5a 100644 --- a/app.py +++ b/app.py @@ -1,30 +1,9 @@ import os import sys -current_file = os.path.abspath(__file__) -current_dir = os.path.dirname(current_file) - -songformer_path = os.path.join(current_dir, "src", "SongFormer") -if os.path.exists(songformer_path): - os.chdir(songformer_path) -else: - print(f"The target working directory does not exist: {songformer_path}") - -working_dir = os.getcwd() - -third_party_path = os.path.join(current_dir, "src", "third_party") -if os.path.exists(third_party_path): - sys.path.insert(0, third_party_path) -sys.path.insert(0, working_dir) - -musicfm_paths = [ - os.path.join(current_dir, "src"), - os.path.join(current_dir, "third_party"), - os.path.join(current_dir, "src", "SongFormer"), -] -for path in musicfm_paths: - if os.path.exists(path): - sys.path.insert(0, path) +os.chdir(os.path.join("src", "SongFormer")) +sys.path.append(os.path.join("..", "third_party")) +sys.path.append(".") # monkey patch to fix issues in msaf import scipy @@ -39,7 +18,8 @@ import json import math import importlib import matplotlib -matplotlib.use('Agg') + +matplotlib.use("Agg") # non-interactive backend: safe for rendering plots off the main thread import matplotlib.pyplot as plt import matplotlib.ticker as ticker from pathlib import Path @@ -51,6 +31,11 @@ from musicfm.model.musicfm_25hz import MusicFM25Hz from postprocessing.functional import postprocess_functional_structure from dataset.label2id import DATASET_ID_ALLOWED_LABEL_IDS, DATASET_LABEL_TO_DATASET_ID from utils.fetch_pretrained import download_all + +import export_utils + +# ZeroGPU (Hugging Face Spaces). Preinstalled on the Space; this branch +# is Space-only and never runs locally. import spaces # Constants @@ -69,6 +54,23 @@ msa_model = None device = None +def get_device(): + """Select the best available device: MPS (Apple Silicon), CUDA, or CPU.""" + if torch.cuda.is_available(): + return torch.device("cuda") + if hasattr(torch.backends, "mps") and torch.backends.mps.is_available(): + return torch.device("mps") + return torch.device("cpu") + + +def clear_device_cache(device): + """Clear GPU memory cache for the given device type.""" + if device.type == "cuda": + torch.cuda.empty_cache() + elif device.type == "mps": + torch.mps.empty_cache() + + def load_checkpoint(checkpoint_path, device=None): """Load checkpoint from path""" if device is None: @@ -90,7 +92,7 @@ def initialize_models(model_name: str, checkpoint: str, config_path: str): global muq_model, musicfm_model, msa_model, device # Set device - device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + device = get_device() # Load MuQ muq_model = MuQ.from_pretrained("OpenMuQ/MuQ-large-msd-iter") @@ -123,17 +125,26 @@ def initialize_models(model_name: str, checkpoint: str, config_path: str): return hp -@spaces.GPU(duration=300) +def _gpu_duration(audio_path, win_size=420, hop_size=420, num_classes=128): + """Estimate GPU seconds for one file (ZeroGPU dynamic duration). + + Conservative: 30s base + 0.2s per audio second, clamped to [60, 300]. + Tune the constants from observed Space timings. + """ + try: + audio_secs = librosa.get_duration(path=audio_path) + except Exception: + return 120 + return int(min(300, max(60, 30 + 0.2 * audio_secs))) + + +@spaces.GPU(duration=_gpu_duration) def process_audio(audio_path, win_size=420, hop_size=420, num_classes=128): """Process audio file and return structure analysis results""" global muq_model, musicfm_model, msa_model, device if muq_model is None: - hp = initialize_models( - model_name="SongFormer", - checkpoint="SongFormer.safetensors", - config_path="SongFormer.yaml", - ) + hp = initialize_models() else: hp = OmegaConf.load(os.path.join("configs", "SongFormer.yaml")) @@ -180,14 +191,14 @@ def process_audio(audio_path, win_size=420, hop_size=420, num_classes=128): muq_output = muq_model(audio_seg.unsqueeze(0), output_hidden_states=True) muq_embd_420s = muq_output["hidden_states"][10] del muq_output - torch.cuda.empty_cache() + clear_device_cache(device) _, musicfm_hidden_states = musicfm_model.get_predictions( audio_seg.unsqueeze(0) ) musicfm_embd_420s = musicfm_hidden_states[10] del musicfm_hidden_states - torch.cuda.empty_cache() + clear_device_cache(device) # Process 30-second segments wraped_muq_embd_30s = [] @@ -211,14 +222,14 @@ def process_audio(audio_path, win_size=420, hop_size=420, num_classes=128): output_hidden_states=True, )["hidden_states"][10] ) - torch.cuda.empty_cache() + clear_device_cache(device) wraped_musicfm_embd_30s.append( musicfm_model.get_predictions( audio[start_idx_30s:end_idx_30s].unsqueeze(0) )[1][10] ) - torch.cuda.empty_cache() + clear_device_cache(device) if wraped_muq_embd_30s: wraped_muq_embd_30s = torch.concatenate(wraped_muq_embd_30s, dim=1) @@ -325,6 +336,7 @@ def create_visualization( logits, msa_output, label_num=8, frame_rates=AFTER_DOWNSAMPLING_FRAME_RATES ): """Create visualization plot""" + # Assume ID_TO_LABEL mapping exists try: from dataset.label2id import ID_TO_LABEL except: @@ -420,48 +432,241 @@ def rule_post_processing(msa_list): return result +def analyze_one(audio_file, out_dir, stem=None): + """Run the full per-file analysis pipeline and write export files. + + Shared by the single-file and batch handlers so the two paths cannot + drift. Returns (segments, json_str, msa_str, fig, export_paths). The + caller owns the returned figure (single-file displays it via gr.Plot; + batch saves+closes it); on a write failure the figure is closed here + before re-raising so it never leaks. + """ + logits, msa_output = process_audio(audio_file) + # Apply rule-based post-processing, if not needed, use in cli infer + msa_output = rule_post_processing(msa_output) + segments = format_as_segments(msa_output) + msa_str = format_as_msa(msa_output) + json_str = format_as_json(segments) + fig = create_visualization(logits, msa_output) + try: + export_paths = export_utils.write_exports( + audio_file, segments, json_str, msa_str, fig, out_dir, stem=stem + ) + except Exception: + plt.close(fig) + raise + return segments, json_str, msa_str, fig, export_paths + + def process_and_analyze(audio_file): """Main processing function""" - def format_time(t: float) -> str: - minutes = int(t // 60) - seconds = t % 60 - return f"{minutes:02d}:{seconds:06.3f}" - if audio_file is None: - return None, "", "", None + return None, "", "", None, None, None, None, None, None try: - # Process audio - logits, msa_output = process_audio(audio_file) - # Apply rule-based post-processing - msa_output = rule_post_processing(msa_output) - # Format outputs - segments = format_as_segments(msa_output) - msa_format = format_as_msa(msa_output) - json_format = format_as_json(segments) + # Shared pipeline; exports land in a fresh per-run temp directory + # (stale runs are swept automatically by the bootstrap). + out_dir = export_utils.new_run_dir() + segments, json_format, msa_format, fig, export_paths = analyze_one( + audio_file, out_dir + ) # Create table data - table_data = [ - [ - f"{float(seg['start']):.2f} ({format_time(float(seg['start']))})", - f"{float(seg['end']):.2f} ({format_time(float(seg['end']))})", - seg["label"], - ] - for seg in segments - ] + table_data = export_utils.segments_to_table(segments) - # Create visualization - fig = create_visualization(logits, msa_output) - - return table_data, json_format, msa_format, fig + zip_path = os.path.join( + out_dir, export_utils.stem_of(audio_file) + "_songformer.zip" + ) + export_utils.make_zip(list(export_paths.values()), zip_path) + + return ( + table_data, + json_format, + msa_format, + fig, + export_paths["json"], + export_paths["msa"], + export_paths["csv"], + export_paths["png"], + zip_path, + ) except Exception as e: import traceback error_msg = f"Error: {str(e)}\n{traceback.format_exc()}" - print(error_msg) - return None, "", error_msg, None + print(error_msg) # 在命令行输出完整错误 + return None, "", error_msg, None, None, None, None, None, None + + +def process_batch(files): + """Analyze multiple files sequentially, yielding live status. + + The status table itself is the progress display: every file is listed + as queued upfront, flips to processing, then to done/failed. Dropdown + choices update as files finish so completed results can be inspected + while the rest of the batch is still running. + + Outputs (per yield): status rows, ZIP download update, file-selector + update, per-file results dict (for the detail viewer). + """ + if not files: + yield ( + [["(no files uploaded)", "", "", ""]], + gr.update(value=None), + gr.update(choices=[], value=None), + {}, + ) + return + + run_dir = export_utils.new_run_dir() + bundle = os.path.join(run_dir, "bundle") + os.makedirs(bundle, exist_ok=True) + + # De-duplicate stems upfront so same-named uploads don't overwrite each + # other and the queued list shows the final names. + used_stems = set() + queue = [] + for audio_file in files: + base = export_utils.stem_of(audio_file) + stem = base + n = 2 + while stem in used_stems: + stem = f"{base}_{n}" + n += 1 + used_stems.add(stem) + queue.append((audio_file, stem)) + + status_rows = [[stem, "⏳ queued", "", ""] for _, stem in queue] + results = {} + zipped_count = 0 # how many files the on-disk ZIP actually contains + zip_path = os.path.join(run_dir, "songformer_batch.zip") + + def _rebuild_bundle_zip(): + """Rewrite manifests and atomically swap in an updated ZIP. + + Called after each completed file so the download button always + serves "everything so far". os.replace is atomic, so a click can + never observe a half-written archive. The (stem, segments) pairs + are derived from `results` — the single source of truth. + """ + named = [(s, r["segments"]) for s, r in results.items()] + with open( + os.path.join(bundle, "summary.csv"), "w", encoding="utf-8", newline="" + ) as f: + f.write(export_utils.segments_to_combined_csv(named)) + with open( + os.path.join(bundle, "combined.json"), "w", encoding="utf-8" + ) as f: + f.write(export_utils.combined_json(named)) + part = zip_path + ".part" + export_utils.zip_dir(bundle, part) + os.replace(part, zip_path) + + # List every file as queued; clear any previous run's results + yield ( + status_rows, + gr.update(value=None, interactive=False, label="⬇️ Download all (ZIP)"), + gr.update(choices=[], value=None), + {}, + ) + + for idx, (audio_file, stem) in enumerate(queue): + status_rows[idx] = [stem, "🔄 processing…", "", ""] + yield status_rows, gr.update(), gr.update(), results + try: + file_dir = os.path.join(bundle, stem) + os.makedirs(file_dir, exist_ok=True) + segments, json_str, msa_str, fig, paths = analyze_one( + audio_file, file_dir, stem=stem + ) + plt.close(fig) + duration = ( + export_utils.format_time(float(segments[-1]["end"])) + if segments + else "" + ) + status_rows[idx] = [stem, "✅", len(segments), duration] + results[stem] = { + "segments": segments, + "json": json_str, + "msa": msa_str, + "png": paths["png"], + "audio": audio_file, + } + except Exception as e: + import traceback + + print(f"Batch error for {stem}:\n{traceback.format_exc()}") + status_rows[idx] = [stem, "❌ " + str(e)[:80], 0, ""] + # ZeroGPU quota exhausted: every remaining file would fail the + # same way, so skip them. (Message heuristic — ZeroGPU does not + # document a stable exception class.) + if "quota" in str(e).lower(): + for j in range(idx + 1, len(queue)): + status_rows[j] = [queue[j][1], "⏭️ skipped (GPU quota)", "", ""] + yield ( + status_rows, + gr.update(), + gr.update(choices=list(results.keys())), + results, + ) + break + else: + # A ZIP rebuild failure must NOT mark the analyzed file as + # failed: its exports exist and the next successful rebuild + # will include it (pairs derive from `results`). + try: + # Keep the ZIP downloadable mid-run with everything so far + _rebuild_bundle_zip() + zipped_count = len(results) + except Exception: + import traceback + + print(f"ZIP rebuild error after {stem}:\n{traceback.format_exc()}") + if zipped_count: + zip_update = gr.update( + value=zip_path, + interactive=True, + label=f"⬇️ Download all (ZIP) — {zipped_count}/{len(queue)} files", + ) + else: + zip_update = gr.update() + # Completed files become inspectable while the batch continues + yield status_rows, zip_update, gr.update(choices=list(results.keys())), results + + # Manifests + ZIP were rebuilt incrementally per file; just normalize + # the button label now that the batch is complete. The button is only + # active if at least one rebuild actually produced a ZIP on disk. + yield ( + status_rows, + gr.update( + value=zip_path if zipped_count else None, + interactive=bool(zipped_count), + label="⬇️ Download all (ZIP)", + ), + gr.update(choices=list(results.keys())), + results, + ) + + +def on_select_file(stem, results): + """Render a previously-computed file's result in the batch detail viewer.""" + # A selection can race an in-flight batch iteration under rare scheduler + # timings (choices reach the browser just before the state lands); the + # guard degrades to an empty view, recoverable by re-selecting. + results = results or {} + if not stem or stem not in results: + return None, "", "", None, None + r = results[stem] + return ( + export_utils.segments_to_table(r["segments"]), + r["json"], + r["msa"], + r["png"], + r.get("audio"), + ) # Create Gradio interface @@ -503,78 +708,173 @@ with gr.Blocks( # Links gr.HTML("""
""") + with gr.Tabs(): + with gr.Tab("Single File"): + # Main input area + with gr.Row(): + with gr.Column(scale=3): + audio_input = gr.Audio( + label="Upload Audio File", type="filepath", elem_id="audio-input" + ) - # Main input area - with gr.Row(): - with gr.Column(scale=3): - audio_input = gr.Audio( - label="Upload Audio File", type="filepath", elem_id="audio-input" - ) + with gr.Column(scale=1): + gr.Markdown("### 📌 Examples") + gr.Examples( + examples=[ + ["examples/BC_5cd6a6.mp3"], + ["examples/BC_282ece.mp3"], + ["examples/BHX_0158_letitrock.wav"], + ["examples/BHX_0374_drunkonyou.wav"], + ], + inputs=[audio_input], + label="Click to load example", + ) - with gr.Column(scale=1): - gr.Markdown("### Examples") - gr.Examples( - examples=[ - ["examples/BC_5cd6a6.mp3"], - ["examples/BC_282ece.mp3"], - ["examples/BHX_0158_letitrock.wav"], - ["examples/BHX_0374_drunkonyou.wav"], - ], - inputs=[audio_input], - label="Click to load example", - ) + # Analyze button + with gr.Row(): + analyze_btn = gr.Button( + "🚀 Analyze Music Structure", variant="primary", scale=1 + ) - # Analyze button - with gr.Row(): - analyze_btn = gr.Button( - "Analyze Music Structure", variant="primary", scale=1 - ) + # Results display area + with gr.Row(): + with gr.Column(scale=13): + segments_table = gr.Dataframe( + headers=["Start / s (m:s.ms)", "End / s (m:s.ms)", "Label"], + label="Detected Music Segments", + interactive=False, + elem_id="result-table", + ) + with gr.Column(scale=8): + with gr.Row(): + with gr.Accordion("📄 JSON Output", open=False): + json_output = gr.Textbox( + label="JSON Format", + lines=15, + max_lines=20, + interactive=False, + show_copy_button=True, + ) + with gr.Row(): + with gr.Accordion("📋 MSA Text Output", open=False): + msa_output = gr.Textbox( + label="MSA Format", + lines=15, + max_lines=20, + interactive=False, + show_copy_button=True, + ) + + # Visualization plot + with gr.Row(): + plot_output = gr.Plot(label="Activation Curves Visualization") - # Results display area - with gr.Row(): - with gr.Column(scale=13): - segments_table = gr.Dataframe( - headers=["Start / s (m:s.ms)", "End / s (m:s.ms)", "Label"], - label="Detected Music Segments", - interactive=False, - elem_id="result-table", + # Export / download buttons (populated after analysis) + with gr.Row(): + download_json_btn = gr.DownloadButton("⬇️ JSON") + download_msa_btn = gr.DownloadButton("⬇️ MSA (.txt)") + download_csv_btn = gr.DownloadButton("⬇️ CSV") + download_png_btn = gr.DownloadButton("⬇️ Plot (.png)") + download_zip_btn = gr.DownloadButton( + "⬇️ Download all (ZIP)", variant="primary" + ) + + with gr.Tab("Batch"): + gr.Markdown( + "Upload multiple audio files, analyze them sequentially, " + "and download all results as a single ZIP.\n\n" + "*This Space runs on ZeroGPU: each file consumes your daily " + "GPU quota (2–40 min depending on account tier). The ZIP " + "below always contains everything analyzed so far.*" ) - with gr.Column(scale=8): with gr.Row(): - with gr.Accordion("JSON Output", open=False): - json_output = gr.Textbox( - label="JSON Format", - lines=15, - max_lines=20, - interactive=False, - show_copy_button=True, + with gr.Column(scale=3): + batch_files = gr.File( + label="Upload Audio Files", + file_count="multiple", + type="filepath", ) + with gr.Column(scale=1): + batch_analyze_btn = gr.Button( + "🚀 Analyze Batch", variant="primary" + ) + batch_zip_btn = gr.DownloadButton( + "⬇️ Download all (ZIP)", variant="primary", interactive=False + ) + with gr.Row(): + batch_status = gr.Dataframe( + headers=["File", "Status", "Segments", "Duration"], + label="Batch Status", + interactive=False, + ) + batch_results_state = gr.State({}) + gr.Markdown("### Inspect a file") with gr.Row(): - with gr.Accordion("MSA Text Output", open=False): - msa_output = gr.Textbox( - label="MSA Format", - lines=15, - max_lines=20, + with gr.Column(scale=1): + batch_file_selector = gr.Dropdown( + label="Processed File", choices=[], interactive=True + ) + with gr.Column(scale=2): + batch_detail_audio = gr.Audio( + label="Listen", type="filepath", interactive=False + ) + with gr.Row(): + with gr.Column(scale=13): + batch_detail_table = gr.Dataframe( + headers=["Start / s (m:s.ms)", "End / s (m:s.ms)", "Label"], + label="Detected Music Segments", interactive=False, - show_copy_button=True, ) - - # Visualization plot - with gr.Row(): - plot_output = gr.Plot(label="Activation Curves Visualization") + with gr.Column(scale=8): + with gr.Row(): + with gr.Accordion("📄 JSON Output", open=False): + batch_detail_json = gr.Textbox( + label="JSON Format", + lines=15, + max_lines=20, + interactive=False, + show_copy_button=True, + ) + with gr.Row(): + with gr.Accordion("📋 MSA Text Output", open=False): + batch_detail_msa = gr.Textbox( + label="MSA Format", + lines=15, + max_lines=20, + interactive=False, + show_copy_button=True, + ) + with gr.Row(): + batch_detail_plot = gr.Image(label="Activation Curves Visualization") gr.HTML("""
MuQ & MuQ-MuLan
-
-
-
-This is the official repository for the paper *"**MuQ**: Self-Supervised **Mu**sic Representation Learning
- with Mel Residual Vector **Q**uantization"*.
-
-In this repo, the following models are released:
-
-- **MuQ**: A large music foundation model pre-trained via Self-Supervised Learning (SSL), achieving SOTA in various MIR tasks.
-- **MuQ-MuLan**: A music-text joint embedding model trained via contrastive learning, supporting both English and Chinese texts.
-
-## Overview
-
-We develop the **MuQ** for music SSL. MuQ applys our proposed Mel-RVQ as quantitative targets and achieves SOTA performance on many music understanding (or MIR) tasks.
-
-We also construct the **MuQ-MuLan**, a CLIP-like model trained by contrastive learning, which jointly represents music and text into embeddings.
-
-For more details, please refer to our [paper](https://arxiv.org/abs/2501.01108).
-
-
-
-
-
-
-## Model Checkpoints
-
-| Model Name | Parameters | Data | HuggingFace🤗 |
-| ----------- | --- | --- | ----------- |
-| MuQ | ~300M | MSD dataset | [OpenMuQ/MuQ-large-msd-iter](https://huggingface.co/OpenMuQ/MuQ-large-msd-iter) |
-| MuQ-MuLan | ~700M | music-text pairs | [OpenMuQ/MuQ-MuLan-large](https://huggingface.co/OpenMuQ/MuQ-MuLan-large) |
-
-**Note**: Please note that the open-sourced MuQ was trained on the Million Song Dataset. Due to differences in dataset size, the open-sourced model may not achieve the same level of performance as reported in the paper. The training recipes can be found [here](./src/recipes).
-
-## License
-
-The code in this repository is released under the MIT license as found in the [LICENSE](LICENSE) file.
-
-The model weights (MuQ-large-msd-iter, MuQ-MuLan-large) in this repository are released under the CC-BY-NC 4.0 license, as detailed in the [LICENSE_weights](LICENSE_weights) file.
-
-## Citation
-
-```
-@article{zhu2025muq,
- title={MuQ: Self-Supervised Music Representation Learning with Mel Residual Vector Quantization},
- author={Haina Zhu and Yizhi Zhou and Hangting Chen and Jianwei Yu and Ziyang Ma and Rongzhi Gu and Yi Luo and Wei Tan and Xie Chen},
- journal={arXiv preprint arXiv:2501.01108},
- year={2025}
-}
-```
-
-## Acknowledgement
-
-We borrow many codes from the following repositories:
-- [lucidrains/musiclm-pytorch](https://github.com/lucidrains/musiclm-pytorch)
-- [minzwon/musicfm](https://github.com/minzwon/musicfm)
-
-
-Also, we are especially grateful to the awesome [MARBLE-Benchmark](https://github.com/a43992899/MARBLE-Benchmark).
diff --git a/src/third_party/MuQ/images/muq-logo.jpeg b/src/third_party/MuQ/images/muq-logo.jpeg
deleted file mode 100644
index 37cd1531747f00a00d001e43946f012053a15146..0000000000000000000000000000000000000000
Binary files a/src/third_party/MuQ/images/muq-logo.jpeg and /dev/null differ
diff --git a/src/third_party/MuQ/images/radar.jpg b/src/third_party/MuQ/images/radar.jpg
deleted file mode 100644
index ebcd9823c610b60fb7e7f9085758bbd067e9de91..0000000000000000000000000000000000000000
Binary files a/src/third_party/MuQ/images/radar.jpg and /dev/null differ
diff --git a/src/third_party/MuQ/images/tab-marble.jpg b/src/third_party/MuQ/images/tab-marble.jpg
deleted file mode 100644
index 5d85812cd86a6776f1cda603bc53fa2f0c9b697d..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/images/tab-marble.jpg
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:d7287c7741b06062fb5cb57b10149c9138cbb56ad3eabef7e3b957ea32db1639
-size 263577
diff --git a/src/third_party/MuQ/images/tab-mulan.png b/src/third_party/MuQ/images/tab-mulan.png
deleted file mode 100644
index 1c28074d4e3f9983474f04ca31de14ac204ff8e4..0000000000000000000000000000000000000000
Binary files a/src/third_party/MuQ/images/tab-mulan.png and /dev/null differ
diff --git a/src/third_party/MuQ/images/tagging.jpg b/src/third_party/MuQ/images/tagging.jpg
deleted file mode 100644
index d89179798e6fb4b6c54421390d43beb086675006..0000000000000000000000000000000000000000
Binary files a/src/third_party/MuQ/images/tagging.jpg and /dev/null differ
diff --git a/src/third_party/MuQ/requirements.txt b/src/third_party/MuQ/requirements.txt
deleted file mode 100644
index 21619ff79263184ec409ffac46ff7967d6ec4160..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/requirements.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-einops
-librosa
-nnAudio
-numpy
-soundfile
-torch
-torchaudio
-tqdm
-transformers
-easydict
-x_clip
\ No newline at end of file
diff --git a/src/third_party/MuQ/setup.py b/src/third_party/MuQ/setup.py
deleted file mode 100644
index 1006570f10a897f88b59a4e92cdb869c1299a34e..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/setup.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from setuptools import setup, find_packages
-
-setup(
- name='muq', # Name of the package
- version='0.1.0', # Version of the package
- packages=find_packages(where='src'), # Automatically discover packages under the 'src' directory
- package_dir={'': 'src'}, # Specify the root directory for packages as 'src'
- include_package_data=True, # Include additional files, such as static files
- install_requires=[ # List of dependencies
- "einops",
- "librosa",
- "nnAudio",
- "numpy",
- "soundfile",
- "torch",
- "torchaudio",
- "tqdm",
- "transformers",
- "easydict",
- "x_clip",
- ],
- author='Haina Zhu', # Author name
- author_email='juhayna@qq.com', # Author email address
- description='MuQ: A deep learning model for music and text', # Short description of the package
- long_description=open('README.md', encoding='utf-8').read(), # Long description from the README file
- long_description_content_type='text/markdown', # Format of the long description (Markdown)
- url='https://github.com/tencent-ailab/MuQ', # Project URL
- classifiers=[
- 'Programming Language :: Python :: 3', # Python 3 support
- 'License :: OSI Approved :: MIT License', # License type
- 'Operating System :: OS Independent', # Supports all operating systems
- ],
- python_requires='>=3.8', # Supported Python version
-)
diff --git a/src/third_party/MuQ/src/muq/__init__.py b/src/third_party/MuQ/src/muq/__init__.py
deleted file mode 100644
index 7575a352fcd9af16c791d2ce5dae3dfe72521b6f..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/muq/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from .muq import MuQ, MuQConfig
-from .muq_mulan import MuQMuLan, MuQMuLanConfig
\ No newline at end of file
diff --git a/src/third_party/MuQ/src/muq/muq/__init__.py b/src/third_party/MuQ/src/muq/muq/__init__.py
deleted file mode 100644
index 40a3cb62132cb3b3628b977c2a13563b78fe59c1..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/muq/muq/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .muq import MuQConfig, MuQ
\ No newline at end of file
diff --git a/src/third_party/MuQ/src/muq/muq/models/__init__.py b/src/third_party/MuQ/src/muq/muq/models/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/src/third_party/MuQ/src/muq/muq/models/muq_model.py b/src/third_party/MuQ/src/muq/muq/models/muq_model.py
deleted file mode 100644
index cd40397376cd25960909619aff68fdc3846d02d9..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/muq/muq/models/muq_model.py
+++ /dev/null
@@ -1,366 +0,0 @@
-import json
-import random
-import torch
-from torch import nn
-from einops import rearrange
-import os
-from easydict import EasyDict
-
-from ..modules.random_quantizer import RandomProjectionQuantizer
-from ..modules.features import MelSTFT
-from ..modules.conv import Conv2dSubsampling
-
-class MuQModel(nn.Module):
-
- def __init__(
- self,
- num_codebooks=1,
- codebook_dim=16,
- codebook_size=4096,
- features=["melspec_2048"],
- hop_length=240,
- n_mels=128,
- conv_dim=512,
- encoder_dim=1024,
- encoder_depth=12,
- mask_hop=0.4,
- mask_prob=0.6,
- is_flash=False,
- stat=dict(),
- w2v2_config=dict(),
- use_rvq_target=False,
- use_vq_target=False,
- use_encodec_target=False,
- rvq_ckpt_path=None,
- recon_loss_ratio=None,
- label_rate=25,
- rvq_n_codebooks=8,
- rvq_multi_layer_num=1,
- ):
- super().__init__()
-
- # global variables
- self.hop_length = hop_length
- self.mask_hop = mask_hop
- self.mask_prob = mask_prob
- self.num_codebooks = num_codebooks
- self.codebook_size = codebook_size
- self.features = features
- self.recon_loss_ratio = recon_loss_ratio
- self.n_fold = int(100//label_rate)
- self.label_rate = label_rate
-
- # load feature mean / std stats
- self.stat = stat
-
- # feature extractor
- self.preprocessor_melspec_2048 = MelSTFT(
- n_fft=2048, hop_length=hop_length, is_db=True
- )
-
- # random quantizer
- self.use_rvq_target = use_rvq_target
- self.use_vq_target = use_vq_target
- self.use_encodec_target = use_encodec_target
-
- seed = 142
- if self.use_rvq_like_target:
- if use_rvq_target:
- from ..modules.rvq import ResidualVectorQuantize
-
- inp_dim = 128*self.n_fold
- self.rvq = ResidualVectorQuantize(
- input_dim = inp_dim,
- n_codebooks = rvq_n_codebooks,
- codebook_size = 1024,
- codebook_dim = 16,
- quantizer_dropout = 0.0,
- use_multi_layer_num = rvq_multi_layer_num,
- )
- elif use_vq_target:
- from ..modules.rvq import VectorQuantize
-
- self.rvq = VectorQuantize(
- input_dim = 128*self.n_fold,
- codebook_size = 1024,
- codebook_dim = 8,
- stale_tolerance = 1000,
- mfcc_clustering = False
- )
- elif use_encodec_target:
- from encodec import EncodecModel
- self.rvq = EncodecModel.encodec_model_24khz()
- self.rvq.set_target_bandwidth(6.0)
- for param in self.rvq.parameters():
- param.requires_grad = False
-
- if rvq_ckpt_path is not None and os.path.exists(rvq_ckpt_path):
- state_dict = torch.load(rvq_ckpt_path, map_location="cpu")
- self.rvq.load_state_dict(state_dict)
- else:
- pass
- # print(f'Checkpoint for rvq `{rvq_ckpt_path}` not found. Using random initialization.')
- else:
- for feature in self.features:
- for i in range(num_codebooks):
- setattr(
- self,
- f"quantizer_{feature}", # _{i}
- RandomProjectionQuantizer(
- n_mels * self.n_fold, codebook_dim, codebook_size, seed=seed + i
- ),
- )
-
- # two residual convolution layers + one projection layer
- strides_factory = {
- 4: [2, 2],
- 2: [2, 1]
- }
- self.conv = Conv2dSubsampling(
- 1, conv_dim, encoder_dim, strides=strides_factory.get(self.n_fold), n_bands=n_mels
- )
-
- # Conformer
- if is_flash:
- from modules.flash_conformer import (
- Wav2Vec2ConformerEncoder,
- Wav2Vec2ConformerConfig,
- )
- else:
- from transformers.models.wav2vec2_conformer.modeling_wav2vec2_conformer import (
- Wav2Vec2ConformerEncoder,
- Wav2Vec2ConformerConfig,
- )
- config = EasyDict(w2v2_config)
- config.num_hidden_layers = encoder_depth
- config.hidden_size = encoder_dim
-
- self.conformer = Wav2Vec2ConformerEncoder(config)
-
- self.linear = nn.Linear(encoder_dim, codebook_size) # projection layer
-
- # reconstruct melspec
- if self.recon_loss_ratio is not None and self.recon_loss_ratio > 0:
- self.recon_proj = nn.Linear(encoder_dim, n_mels * self.n_fold)
- self.recon_loss = nn.MSELoss()
-
- # loss function
- self.loss = nn.CrossEntropyLoss()
-
- # cls token (used for sequence classification)
- random.seed(seed)
- self.cls_token = nn.Parameter(torch.randn(encoder_dim))
-
-
- @property
- def use_rvq_like_target(self):
- return self.use_rvq_target or self.use_vq_target or self.use_encodec_target
-
- def masking(self, x, attention_mask=None):
- """random masking of 400ms with given probability"""
- mx = x.clone()
- b, t = mx.shape
- len_masking_raw = int(24000 * self.mask_hop)
- len_masking_token = int(24000 / self.hop_length / 2 / 2 * self.mask_hop)
-
- # get random mask indices
- start_indices = torch.rand(b, t // len_masking_raw) < self.mask_prob
- time_domain_masked_indices = torch.nonzero(
- start_indices.repeat_interleave(len_masking_raw, dim=1)
- )
- token_domain_masked_indices = torch.nonzero(
- start_indices.repeat_interleave(len_masking_token, dim=1)
- )
-
- # mask with random values
- masking_noise = (
- torch.randn(time_domain_masked_indices.shape[0], dtype=x.dtype) * 0.1
- ) # 0 mean 0.1 std
- mx[tuple(time_domain_masked_indices.t())] = masking_noise.to(x.device)
-
- return mx, token_domain_masked_indices
-
-
- @torch.no_grad()
- def preprocessing(self, x, features):
- """extract classic audio features"""
- # check precision
- if x.dtype == torch.float16 or x.dtype == torch.bfloat16:
- precision = 16
- else:
- precision = 32
-
- out = {}
- for key in features:
- layer = getattr(self, "preprocessor_%s" % key)
- layer.to(x.device)
- dtype = x.dtype
- out[key] = layer(x.float())[..., :-1]
- if precision == 16:
- out[key] = out[key].half()
- if out[key].dtype != dtype:
- out[key].to(dtype=dtype)
- return out
-
- def encoder(self, x, *, attention_mask=None, is_features_only=False):
- """2-layer conv + w2v-conformer"""
- x = self.conv(x)
- mask_indices = None
- if attention_mask is None:
- out = self.conformer(x, output_hidden_states=True)
- else:
- attention_mask = attention_mask.bool()
- skip_n = int(attention_mask.size(-1) / x.size(1))
- attention_mask = attention_mask[:, ::skip_n]
- attention_mask = attention_mask[:, :x.size(1)]
- out = self.conformer(x, attention_mask=attention_mask, output_hidden_states=True)
- hidden_emb = out["hidden_states"]
- last_emb = out["last_hidden_state"]
- logits = self.linear(last_emb)
- interval = self.codebook_size
- logits = {
- key: logits[:, :, i * interval : (i + 1) * interval]
- for i, key in enumerate(self.features)
- }
- return logits, hidden_emb, mask_indices
-
- @torch.no_grad()
- def normalize(self, x):
- """normalize the input audio to have zero mean unit variance"""
- for key in x.keys():
- x[key] = (x[key] - self.stat["%s_mean" % key]) / self.stat["%s_std" % key]
- return x
-
- @torch.no_grad()
- def rearrange(self, x):
- """rearrange the batch to flatten every 4 steps"""
- for key in x.keys():
- if key == "chromagram":
- x[key] = rearrange(x[key], "b f t -> b t f")
- else:
- x[key] = rearrange(x[key], "b f (t s) -> b t (s f)", s=self.n_fold)
- return x
-
- def get_rvq_codes(self, inp, raw_wav):
- if self.use_rvq_target:
- quantized_prompt_embeds, codes, _, commitment_loss, codebook_loss, rvq_usage = self.rvq(inp)
- return codes
- if self.use_vq_target:
- quantized_prompt_embeds, commitment_loss, codebook_loss, codes, _ = self.rvq(inp)
- return codes.unsqueeze(1)
- if self.use_encodec_target:
- encoded_frames = self.rvq.encode(raw_wav.unsqueeze(1)) #list, B,[ 8,T ]
- codes = torch.cat([encoded[0].detach() for encoded in encoded_frames], dim=-1)
- if self.label_rate == 25:
- codes = codes[:, :, ::3]
- return codes
-
- @torch.no_grad()
- def tokenize(self, x, raw_wav):
- out = {}
- for key in x.keys():
- if self.use_rvq_like_target:
- self.rvq.eval()
- inp = x[key].permute((0, 2, 1))
- codes = self.get_rvq_codes(inp, raw_wav)
- out[key] = torch.cat([codes[:, idx, ...] for idx in range(int(self.codebook_size//1024))], dim=-1)
- else:
- layer = getattr(self, "quantizer_%s" % key)
- out[key] = layer(x[key])
- return out
-
- def get_targets(self, x, label=None):
- if self.use_encodec_target:
- raw_x = x.clone()
- else:
- raw_x = None
- x = self.preprocessing(x, features=self.features)
- x = self.normalize(x)
- x = self.rearrange(x)
- melspec = x['melspec_2048']
- if label is None:
- # Use labels from Mel-RVQ
- target_tokens = self.tokenize(x, raw_x)
- else:
- # Use labels pre-extracted for iteration training
- target_tokens = {'melspec_2048': rearrange(label, "b n s -> b (n s)").long()}
- return target_tokens, melspec
-
- def get_predictions(self, x, *, mask=None, attention_mask=None, return_new_mask=False, is_features_only=False):
- # preprocessing
- x = self.preprocessing(x, features=["melspec_2048"])
- x = self.normalize(x)
-
- # encoding
- logits, hidden_emb, new_mask = self.encoder(x["melspec_2048"], attention_mask=attention_mask, is_features_only=is_features_only)
-
- if return_new_mask:
- return logits, hidden_emb, mask if new_mask is None else new_mask
- else:
- return logits, hidden_emb
-
- def get_latent(self, x, layer_ix=12):
- _, hidden_states = self.get_predictions(x)
- emb = hidden_states[layer_ix]
- return emb
-
- def compute_nce(self, x, pos, negs):
- neg_is_pos = (pos == negs).all(-1)
- pos = pos.unsqueeze(0)
- targets = torch.cat([pos, negs], dim=0)
-
- logits = torch.cosine_similarity(x.float(), targets.float(), dim=-1).type_as(x)
- logits /= 0.1
- if neg_is_pos.any():
- logits[1:][neg_is_pos] = float("-inf")
- logits = logits.transpose(0, 1)
- return logits
-
- def get_loss(self, logits, target_tokens, masked_indices):
- losses = {}
- accuracies = {}
- for key in logits.keys():
- if not self.use_rvq_like_target:
- masked_logits = logits[key][tuple(masked_indices.t())]
- masked_tokens = target_tokens[key][tuple(masked_indices.t())]
- else:
- Batch, SeqLen, N_Codebook_x_CodebookSize = logits[key].shape
- Batch, N_Codebook_x_SeqLen = target_tokens[key].shape
- N_Codebook = int(N_Codebook_x_SeqLen // SeqLen)
- target_tokens[key] = rearrange(target_tokens[key], "b (n s) -> b s n", n=N_Codebook) # Batch, SeqLen=750, N_Codebook=4
- masked_logits = logits[key][tuple(masked_indices.t())]
- masked_tokens = target_tokens[key][tuple(masked_indices.t())]
- masked_logits = rearrange(masked_logits, "b (n c) -> (b n) c", n=N_Codebook)
- masked_tokens = rearrange(masked_tokens, "b n -> (b n)", n=N_Codebook)
-
- losses[key] = self.loss(masked_logits, masked_tokens)
- accuracies[key] = (
- torch.sum(masked_logits.argmax(-1) == masked_tokens)
- / masked_tokens.numel()
- )
- return losses, accuracies
-
- def get_recon_loss(self, last_hidden_emb, melspec, masked_indices):
- pred_melspec = self.recon_proj(last_hidden_emb[tuple(masked_indices.t())])
- target_melspec = melspec[tuple(masked_indices.t())]
- recon_loss = self.recon_loss(pred_melspec, target_melspec)
- return recon_loss
-
- def forward(self, x, attention_mask=None, label=None):
- dtype = x.dtype
- # get target feature tokens
- target_tokens, melspec = self.get_targets(x, label=label)
-
- # masking
- x, masked_indices = self.masking(x, attention_mask=attention_mask)
-
- # forward
- logits, hidden_emb, masked_indices = self.get_predictions(x, mask=masked_indices, attention_mask=attention_mask, return_new_mask=True)
-
- # get loss
- losses, accuracies = self.get_loss(logits, target_tokens, masked_indices)
-
- if self.recon_loss_ratio:
- losses["recon_loss"] = self.get_recon_loss(hidden_emb[-1], melspec, masked_indices) * self.recon_loss_ratio
-
- return logits, hidden_emb, losses, accuracies
diff --git a/src/third_party/MuQ/src/muq/muq/modules/__init__.py b/src/third_party/MuQ/src/muq/muq/modules/__init__.py
deleted file mode 100644
index 139597f9cb07c5d48bed18984ec4747f4b4f3438..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/muq/muq/modules/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/src/third_party/MuQ/src/muq/muq/modules/conv.py b/src/third_party/MuQ/src/muq/muq/modules/conv.py
deleted file mode 100644
index 4e4695371474a19789b77b3668d01e0f430f11a1..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/muq/muq/modules/conv.py
+++ /dev/null
@@ -1,77 +0,0 @@
-from torch import nn
-from einops import rearrange
-
-
-class Res2dModule(nn.Module):
- def __init__(self, idim, odim, stride=(2, 2)):
- super(Res2dModule, self).__init__()
- self.conv1 = nn.Conv2d(idim, odim, 3, padding=1, stride=stride)
- self.bn1 = nn.BatchNorm2d(odim)
- self.conv2 = nn.Conv2d(odim, odim, 3, padding=1)
- self.bn2 = nn.BatchNorm2d(odim)
- self.relu = nn.ReLU()
-
- # residual
- self.diff = False
- if (idim != odim) or (stride[0] > 1):
- self.conv3 = nn.Conv2d(idim, odim, 3, padding=1, stride=stride)
- self.bn3 = nn.BatchNorm2d(odim)
- self.diff = True
-
- def forward(self, x):
- out = self.bn2(self.conv2(self.relu(self.bn1(self.conv1(x)))))
- if self.diff:
- x = self.bn3(self.conv3(x))
- out = x + out
- out = self.relu(out)
- return out
-
-
-class Conv2dSubsampling(nn.Module):
- """Convolutional 2D subsampling (to 1/4 length).
-
- Args:
- idim (int): Input dimension.
- hdim (int): Hidden dimension.
- odim (int): Output dimension.
- strides (list): Sizes of strides.
- n_bands (int): Number of frequency bands.
- """
-
- def __init__(self, idim, hdim, odim, strides=[2, 2], n_bands=64):
- """Construct an Conv2dSubsampling object."""
- super(Conv2dSubsampling, self).__init__()
-
- self.conv = nn.Sequential(
- Res2dModule(idim, hdim, (2, strides[0])),
- Res2dModule(hdim, hdim, (2, strides[1])),
- )
- self.linear = nn.Linear(hdim * n_bands // 2 // 2, odim)
-
- def forward(self, x):
- """Subsample x.
-
- Args:
- x (torch.Tensor): Input tensor (#batch, idim, time).
-
- Returns:
- torch.Tensor: Subsampled tensor (#batch, time', odim),
- where time' = time // 4.
- """
-
- if x.dim() == 3:
- x = x.unsqueeze(1) # (b, c, f, t)
- x = self.conv(x)
- x = rearrange(x, "b c f t -> b t (c f)")
- x = self.linear(x)
- return x
-
-if __name__ == '__main__':
- import torch
- conv_dim, encoder_dim = 512, 1024
- conv = Conv2dSubsampling(
- 1, conv_dim, encoder_dim, strides=[2, 1], n_bands=128
- )
- inp = torch.randn((1, 128, 3000))
- out = conv(inp)
- print(out.shape)
\ No newline at end of file
diff --git a/src/third_party/MuQ/src/muq/muq/modules/features.py b/src/third_party/MuQ/src/muq/muq/modules/features.py
deleted file mode 100644
index 8c206ae569b5b0d2d770ae4ab533ed45add81eb8..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/muq/muq/modules/features.py
+++ /dev/null
@@ -1,37 +0,0 @@
-import torchaudio
-from torch import nn
-import torch
-
-
-class MelSTFT:
- def __init__(
- self,
- sample_rate=24000,
- n_fft=2048,
- hop_length=240,
- n_mels=128,
- is_db=False,
- ):
- super(MelSTFT, self).__init__()
-
- # spectrogram
- self.mel_stft = torchaudio.transforms.MelSpectrogram(
- sample_rate=sample_rate, n_fft=n_fft, hop_length=hop_length, n_mels=n_mels
- )
-
- # amplitude to decibel
- self.is_db = is_db
- if is_db:
- self.amplitude_to_db = torchaudio.transforms.AmplitudeToDB()
-
- def __call__(self, waveform):
- if self.is_db:
- return self.amplitude_to_db(self.mel_stft(waveform))
- else:
- return self.mel_stft(waveform)
-
- def to(self, device):
- self.mel_stft = self.mel_stft.to(device)
- if self.is_db:
- self.amplitude_to_db = self.amplitude_to_db.to(device)
- return self
diff --git a/src/third_party/MuQ/src/muq/muq/modules/flash_conformer.py b/src/third_party/MuQ/src/muq/muq/modules/flash_conformer.py
deleted file mode 100644
index 89012c476c27973748e2cee914dae3b400348465..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/muq/muq/modules/flash_conformer.py
+++ /dev/null
@@ -1,2114 +0,0 @@
-# coding=utf-8
-# Copyright 2022 The Fairseq Authors and the HuggingFace Inc. team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-""" PyTorch Wav2Vec2-Conformer model."""
-
-import math
-from dataclasses import dataclass
-from typing import Optional, Tuple, Union
-
-import numpy as np
-import torch
-import torch.utils.checkpoint
-from torch import nn
-from torch.nn import CrossEntropyLoss
-from torch.nn import functional as F
-
-from transformers.activations import ACT2FN
-from transformers.deepspeed import is_deepspeed_zero3_enabled
-from transformers.modeling_outputs import (
- BaseModelOutput,
- CausalLMOutput,
- SequenceClassifierOutput,
- TokenClassifierOutput,
- Wav2Vec2BaseModelOutput,
- XVectorOutput,
-)
-from transformers.modeling_utils import PreTrainedModel
-from transformers.utils import (
- ModelOutput,
- add_code_sample_docstrings,
- add_start_docstrings,
- add_start_docstrings_to_model_forward,
- logging,
- replace_return_docstrings,
-)
-from transformers.models.wav2vec2_conformer.configuration_wav2vec2_conformer import Wav2Vec2ConformerConfig
-
-
-logger = logging.get_logger(__name__)
-
-
-_HIDDEN_STATES_START_POSITION = 2
-
-# General docstring
-_CONFIG_FOR_DOC = "Wav2Vec2ConformerConfig"
-
-# Base docstring
-_CHECKPOINT_FOR_DOC = "facebook/wav2vec2-conformer-rope-large-960h-ft"
-_EXPECTED_OUTPUT_SHAPE = [1, 292, 1024]
-
-# CTC docstring
-_CTC_EXPECTED_OUTPUT = "'MISTER QUILTER IS THE APOSTLE OF THE MIDDLE CLASSES AND WE ARE GLAD TO WELCOME HIS GOSPEL'"
-_CTC_EXPECTED_LOSS = 64.21
-
-
-WAV2VEC2_CONFORMER_PRETRAINED_MODEL_ARCHIVE_LIST = [
- "facebook/wav2vec2-conformer-rel-pos-large",
- # See all Wav2Vec2Conformer models at https://huggingface.co/models?filter=wav2vec2-conformer
-]
-
-
-@dataclass
-# Copied from transformers.models.wav2vec2.modeling_wav2vec2.Wav2Vec2ForPreTrainingOutput with Wav2Vec2->Wav2Vec2Conformer
-class Wav2Vec2ConformerForPreTrainingOutput(ModelOutput):
- """
- Output type of [`Wav2Vec2ConformerForPreTraining`], with potential hidden states and attentions.
-
- Args:
- loss (*optional*, returned when `sample_negative_indices` are passed, `torch.FloatTensor` of shape `(1,)`):
- Total loss as the sum of the contrastive loss (L_m) and the diversity loss (L_d) as stated in the [official
- paper](https://arxiv.org/pdf/2006.11477.pdf) . (classification) loss.
- projected_states (`torch.FloatTensor` of shape `(batch_size, sequence_length, config.proj_codevector_dim)`):
- Hidden-states of the model projected to *config.proj_codevector_dim* that can be used to predict the masked
- projected quantized states.
- projected_quantized_states (`torch.FloatTensor` of shape `(batch_size, sequence_length, config.proj_codevector_dim)`):
- Quantized extracted feature vectors projected to *config.proj_codevector_dim* representing the positive
- target vectors for contrastive loss.
- hidden_states (`tuple(torch.FloatTensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
- Tuple of `torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer) of
- shape `(batch_size, sequence_length, hidden_size)`.
-
- Hidden-states of the model at the output of each layer plus the initial embedding outputs.
- attentions (`tuple(torch.FloatTensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
- Tuple of `torch.FloatTensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
- sequence_length)`.
-
- Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
- heads.
- contrastive_loss (*optional*, returned when `sample_negative_indices` are passed, `torch.FloatTensor` of shape `(1,)`):
- The contrastive loss (L_m) as stated in the [official paper](https://arxiv.org/pdf/2006.11477.pdf) .
- diversity_loss (*optional*, returned when `sample_negative_indices` are passed, `torch.FloatTensor` of shape `(1,)`):
- The diversity loss (L_d) as stated in the [official paper](https://arxiv.org/pdf/2006.11477.pdf) .
- """
-
- loss: Optional[torch.FloatTensor] = None
- projected_states: torch.FloatTensor = None
- projected_quantized_states: torch.FloatTensor = None
- codevector_perplexity: torch.FloatTensor = None
- hidden_states: Optional[Tuple[torch.FloatTensor]] = None
- attentions: Optional[Tuple[torch.FloatTensor]] = None
- contrastive_loss: Optional[torch.FloatTensor] = None
- diversity_loss: Optional[torch.FloatTensor] = None
-
-
-# Copied from transformers.models.wav2vec2.modeling_wav2vec2._compute_mask_indices
-def _compute_mask_indices(
- shape: Tuple[int, int],
- mask_prob: float,
- mask_length: int,
- attention_mask: Optional[torch.LongTensor] = None,
- min_masks: int = 0,
-) -> np.ndarray:
- """
- Computes random mask spans for a given shape. Used to implement [SpecAugment: A Simple Data Augmentation Method for
- ASR](https://arxiv.org/abs/1904.08779). Note that this method is not optimized to run on TPU and should be run on
- CPU as part of the preprocessing during training.
-
- Args:
- shape: The shape for which to compute masks. This should be of a tuple of size 2 where
- the first element is the batch size and the second element is the length of the axis to span.
- mask_prob: The percentage of the whole axis (between 0 and 1) which will be masked. The number of
- independently generated mask spans of length `mask_length` is computed by
- `mask_prob*shape[1]/mask_length`. Note that due to overlaps, `mask_prob` is an upper bound and the
- actual percentage will be smaller.
- mask_length: size of the mask
- min_masks: minimum number of masked spans
- attention_mask: A (right-padded) attention mask which independently shortens the feature axis of
- each batch dimension.
- """
- batch_size, sequence_length = shape
-
- if mask_length < 1:
- raise ValueError("`mask_length` has to be bigger than 0.")
-
- if mask_length > sequence_length:
- raise ValueError(
- f"`mask_length` has to be smaller than `sequence_length`, but got `mask_length`: {mask_length}"
- f" and `sequence_length`: {sequence_length}`"
- )
-
- # epsilon is used for probabilistic rounding
- epsilon = np.random.rand(1).item()
-
- def compute_num_masked_span(input_length):
- """Given input length, compute how many spans should be masked"""
- num_masked_span = int(mask_prob * input_length / mask_length + epsilon)
- num_masked_span = max(num_masked_span, min_masks)
-
- # make sure num masked span <= sequence_length
- if num_masked_span * mask_length > sequence_length:
- num_masked_span = sequence_length // mask_length
-
- # make sure num_masked span is also <= input_length - (mask_length - 1)
- if input_length - (mask_length - 1) < num_masked_span:
- num_masked_span = max(input_length - (mask_length - 1), 0)
-
- return num_masked_span
-
- # compute number of masked spans in batch
- input_lengths = (
- attention_mask.sum(-1).detach().tolist()
- if attention_mask is not None
- else [sequence_length for _ in range(batch_size)]
- )
-
- # SpecAugment mask to fill
- spec_aug_mask = np.zeros((batch_size, sequence_length), dtype=bool)
- spec_aug_mask_idxs = []
-
- max_num_masked_span = compute_num_masked_span(sequence_length)
-
- if max_num_masked_span == 0:
- return spec_aug_mask
-
- for input_length in input_lengths:
- # compute num of masked spans for this input
- num_masked_span = compute_num_masked_span(input_length)
-
- # get random indices to mask
- spec_aug_mask_idx = np.random.choice(
- np.arange(input_length - (mask_length - 1)), num_masked_span, replace=False
- )
-
- # pick first sampled index that will serve as a dummy index to pad vector
- # to ensure same dimension for all batches due to probabilistic rounding
- # Picking first sample just pads those vectors twice.
- if len(spec_aug_mask_idx) == 0:
- # this case can only happen if `input_length` is strictly smaller then
- # `sequence_length` in which case the last token has to be a padding
- # token which we can use as a dummy mask id
- dummy_mask_idx = sequence_length - 1
- else:
- dummy_mask_idx = spec_aug_mask_idx[0]
-
- spec_aug_mask_idx = np.concatenate(
- [spec_aug_mask_idx, np.ones(max_num_masked_span - num_masked_span, dtype=np.int32) * dummy_mask_idx]
- )
- spec_aug_mask_idxs.append(spec_aug_mask_idx)
-
- spec_aug_mask_idxs = np.array(spec_aug_mask_idxs)
-
- # expand masked indices to masked spans
- spec_aug_mask_idxs = np.broadcast_to(
- spec_aug_mask_idxs[:, :, None], (batch_size, max_num_masked_span, mask_length)
- )
- spec_aug_mask_idxs = spec_aug_mask_idxs.reshape(batch_size, max_num_masked_span * mask_length)
-
- # add offset to the starting indexes so that indexes now create a span
- offsets = np.arange(mask_length)[None, None, :]
- offsets = np.broadcast_to(offsets, (batch_size, max_num_masked_span, mask_length)).reshape(
- batch_size, max_num_masked_span * mask_length
- )
- spec_aug_mask_idxs = spec_aug_mask_idxs + offsets
-
- # ensure that we cannot have indices larger than sequence_length
- if spec_aug_mask_idxs.max() > sequence_length - 1:
- spec_aug_mask_idxs[spec_aug_mask_idxs > sequence_length - 1] = sequence_length - 1
-
- # scatter indices to mask
- np.put_along_axis(spec_aug_mask, spec_aug_mask_idxs, 1, -1)
-
- return spec_aug_mask
-
-
-# Copied from transformers.models.wav2vec2.modeling_wav2vec2._sample_negative_indices
-def _sample_negative_indices(
- features_shape: Tuple, num_negatives: int, mask_time_indices: Optional[np.ndarray] = None
-):
- """
- Sample `num_negatives` vectors from feature vectors.
- """
- batch_size, sequence_length = features_shape
-
- # generate indices of the positive vectors themselves, repeat them `num_negatives` times
- sequence_length_range = np.arange(sequence_length)
-
- # get `num_negatives` random vector indices from the same utterance
- sampled_negative_indices = np.zeros(shape=(batch_size, sequence_length, num_negatives), dtype=np.int32)
-
- mask_time_indices = (
- mask_time_indices.astype(bool) if mask_time_indices is not None else np.ones(features_shape, dtype=bool)
- )
-
- for batch_idx in range(batch_size):
- high = mask_time_indices[batch_idx].sum() - 1
- mapped_masked_indices = sequence_length_range[mask_time_indices[batch_idx]]
-
- feature_indices = np.broadcast_to(np.arange(high + 1)[:, None], (high + 1, num_negatives))
- sampled_indices = np.random.randint(0, high, size=(high + 1, num_negatives))
- # avoid sampling the same positive vector, but keep the distribution uniform
- sampled_indices[sampled_indices >= feature_indices] += 1
-
- # remap to actual indices
- sampled_negative_indices[batch_idx][mask_time_indices[batch_idx]] = mapped_masked_indices[sampled_indices]
-
- # correct for batch size
- sampled_negative_indices[batch_idx] += batch_idx * sequence_length
-
- return sampled_negative_indices
-
-
-# Copied from transformers.models.wav2vec2.modeling_wav2vec2.Wav2Vec2NoLayerNormConvLayer with Wav2Vec2->Wav2Vec2Conformer
-class Wav2Vec2ConformerNoLayerNormConvLayer(nn.Module):
- def __init__(self, config, layer_id=0):
- super().__init__()
- self.in_conv_dim = config.conv_dim[layer_id - 1] if layer_id > 0 else 1
- self.out_conv_dim = config.conv_dim[layer_id]
-
- self.conv = nn.Conv1d(
- self.in_conv_dim,
- self.out_conv_dim,
- kernel_size=config.conv_kernel[layer_id],
- stride=config.conv_stride[layer_id],
- bias=config.conv_bias,
- )
- self.activation = ACT2FN[config.feat_extract_activation]
-
- def forward(self, hidden_states):
- hidden_states = self.conv(hidden_states)
- hidden_states = self.activation(hidden_states)
- return hidden_states
-
-
-# Copied from transformers.models.wav2vec2.modeling_wav2vec2.Wav2Vec2LayerNormConvLayer with Wav2Vec2->Wav2Vec2Conformer
-class Wav2Vec2ConformerLayerNormConvLayer(nn.Module):
- def __init__(self, config, layer_id=0):
- super().__init__()
- self.in_conv_dim = config.conv_dim[layer_id - 1] if layer_id > 0 else 1
- self.out_conv_dim = config.conv_dim[layer_id]
-
- self.conv = nn.Conv1d(
- self.in_conv_dim,
- self.out_conv_dim,
- kernel_size=config.conv_kernel[layer_id],
- stride=config.conv_stride[layer_id],
- bias=config.conv_bias,
- )
- self.layer_norm = nn.LayerNorm(self.out_conv_dim, elementwise_affine=True)
- self.activation = ACT2FN[config.feat_extract_activation]
-
- def forward(self, hidden_states):
- hidden_states = self.conv(hidden_states)
-
- hidden_states = hidden_states.transpose(-2, -1)
- hidden_states = self.layer_norm(hidden_states)
- hidden_states = hidden_states.transpose(-2, -1)
-
- hidden_states = self.activation(hidden_states)
- return hidden_states
-
-
-# Copied from transformers.models.wav2vec2.modeling_wav2vec2.Wav2Vec2GroupNormConvLayer with Wav2Vec2->Wav2Vec2Conformer
-class Wav2Vec2ConformerGroupNormConvLayer(nn.Module):
- def __init__(self, config, layer_id=0):
- super().__init__()
- self.in_conv_dim = config.conv_dim[layer_id - 1] if layer_id > 0 else 1
- self.out_conv_dim = config.conv_dim[layer_id]
-
- self.conv = nn.Conv1d(
- self.in_conv_dim,
- self.out_conv_dim,
- kernel_size=config.conv_kernel[layer_id],
- stride=config.conv_stride[layer_id],
- bias=config.conv_bias,
- )
- self.activation = ACT2FN[config.feat_extract_activation]
-
- self.layer_norm = nn.GroupNorm(num_groups=self.out_conv_dim, num_channels=self.out_conv_dim, affine=True)
-
- def forward(self, hidden_states):
- hidden_states = self.conv(hidden_states)
- hidden_states = self.layer_norm(hidden_states)
- hidden_states = self.activation(hidden_states)
- return hidden_states
-
-
-# Copied from transformers.models.wav2vec2.modeling_wav2vec2.Wav2Vec2PositionalConvEmbedding with Wav2Vec2->Wav2Vec2Conformer
-class Wav2Vec2ConformerPositionalConvEmbedding(nn.Module):
- def __init__(self, config):
- super().__init__()
- self.conv = nn.Conv1d(
- config.hidden_size,
- config.hidden_size,
- kernel_size=config.num_conv_pos_embeddings,
- padding=config.num_conv_pos_embeddings // 2,
- groups=config.num_conv_pos_embedding_groups,
- )
-
- if is_deepspeed_zero3_enabled():
- import deepspeed
-
- with deepspeed.zero.GatheredParameters(self.conv.weight, modifier_rank=0):
- self.conv = nn.utils.weight_norm(self.conv, name="weight", dim=2)
- deepspeed.zero.register_external_parameter(self, self.conv.weight_v)
- deepspeed.zero.register_external_parameter(self, self.conv.weight_g)
- else:
- self.conv = nn.utils.weight_norm(self.conv, name="weight", dim=2)
-
- self.padding = Wav2Vec2ConformerSamePadLayer(config.num_conv_pos_embeddings)
- self.activation = ACT2FN[config.feat_extract_activation]
-
- def forward(self, hidden_states):
- hidden_states = hidden_states.transpose(1, 2)
-
- hidden_states = self.conv(hidden_states)
- hidden_states = self.padding(hidden_states)
- hidden_states = self.activation(hidden_states)
-
- hidden_states = hidden_states.transpose(1, 2)
- return hidden_states
-
-
-class Wav2Vec2ConformerRotaryPositionalEmbedding(nn.Module):
- """Rotary positional embedding
- Reference : https://blog.eleuther.ai/rotary-embeddings/ Paper: https://arxiv.org/pdf/2104.09864.pdf
- """
-
- def __init__(self, config):
- super().__init__()
- dim = config.hidden_size // config.num_attention_heads
- base = config.rotary_embedding_base
-
- inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))
- self.register_buffer("inv_freq", inv_freq)
- self.cached_sequence_length = None
- self.cached_rotary_positional_embedding = None
-
- def forward(self, hidden_states):
- sequence_length = hidden_states.shape[1]
-
- if sequence_length == self.cached_sequence_length and self.cached_rotary_positional_embedding is not None:
- return self.cached_rotary_positional_embedding
-
- self.cached_sequence_length = sequence_length
- time_stamps = torch.arange(sequence_length).type_as(self.inv_freq)
- freqs = torch.einsum("i,j->ij", time_stamps, self.inv_freq)
- embeddings = torch.cat((freqs, freqs), dim=-1)
-
- cos_embeddings = embeddings.cos()[:, None, None, :]
- sin_embeddings = embeddings.sin()[:, None, None, :]
- self.cached_rotary_positional_embedding = torch.stack([cos_embeddings, sin_embeddings])
- return self.cached_rotary_positional_embedding
-
-
-class Wav2Vec2ConformerRelPositionalEmbedding(nn.Module):
- """Relative positional encoding module."""
-
- def __init__(self, config):
- super().__init__()
- self.max_len = config.max_source_positions
- self.d_model = config.hidden_size
- self.pe = None
- self.extend_pe(torch.tensor(0.0).expand(1, self.max_len))
-
- def extend_pe(self, x):
- # Reset the positional encodings
- if self.pe is not None:
- # self.pe contains both positive and negative parts
- # the length of self.pe is 2 * input_len - 1
- if self.pe.size(1) >= x.size(1) * 2 - 1:
- if self.pe.dtype != x.dtype or self.pe.device != x.device:
- self.pe = self.pe.to(dtype=x.dtype, device=x.device)
- return
- # Suppose `i` is the position of query vector and `j` is the
- # position of key vector. We use positive relative positions when keys
- # are to the left (i>j) and negative relative positions otherwise (i- -* **Convolutional Neural Networks (CNN)** - + [Language Modeling with Gated Convolutional Networks (Dauphin et al., 2017)](examples/language_model/conv_lm/README.md) - + [Convolutional Sequence to Sequence Learning (Gehring et al., 2017)](examples/conv_seq2seq/README.md) - + [Classical Structured Prediction Losses for Sequence to Sequence Learning (Edunov et al., 2018)](https://github.com/pytorch/fairseq/tree/classic_seqlevel) - + [Hierarchical Neural Story Generation (Fan et al., 2018)](examples/stories/README.md) - + [wav2vec: Unsupervised Pre-training for Speech Recognition (Schneider et al., 2019)](examples/wav2vec/README.md) -* **LightConv and DynamicConv models** - + [Pay Less Attention with Lightweight and Dynamic Convolutions (Wu et al., 2019)](examples/pay_less_attention_paper/README.md) -* **Long Short-Term Memory (LSTM) networks** - + Effective Approaches to Attention-based Neural Machine Translation (Luong et al., 2015) -* **Transformer (self-attention) networks** - + Attention Is All You Need (Vaswani et al., 2017) - + [Scaling Neural Machine Translation (Ott et al., 2018)](examples/scaling_nmt/README.md) - + [Understanding Back-Translation at Scale (Edunov et al., 2018)](examples/backtranslation/README.md) - + [Adaptive Input Representations for Neural Language Modeling (Baevski and Auli, 2018)](examples/language_model/README.adaptive_inputs.md) - + [Lexically constrained decoding with dynamic beam allocation (Post & Vilar, 2018)](examples/constrained_decoding/README.md) - + [Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context (Dai et al., 2019)](examples/truncated_bptt/README.md) - + [Adaptive Attention Span in Transformers (Sukhbaatar et al., 2019)](examples/adaptive_span/README.md) - + [Mixture Models for Diverse Machine Translation: Tricks of the Trade (Shen et al., 2019)](examples/translation_moe/README.md) - + [RoBERTa: A Robustly Optimized BERT Pretraining Approach (Liu et al., 2019)](examples/roberta/README.md) - + [Facebook FAIR's WMT19 News Translation Task Submission (Ng et al., 2019)](examples/wmt19/README.md) - + [Jointly Learning to Align and Translate with Transformer Models (Garg et al., 2019)](examples/joint_alignment_translation/README.md ) - + [Multilingual Denoising Pre-training for Neural Machine Translation (Liu et at., 2020)](examples/mbart/README.md) - + [Neural Machine Translation with Byte-Level Subwords (Wang et al., 2020)](examples/byte_level_bpe/README.md) - + [Unsupervised Quality Estimation for Neural Machine Translation (Fomicheva et al., 2020)](examples/unsupervised_quality_estimation/README.md) - + [wav2vec 2.0: A Framework for Self-Supervised Learning of Speech Representations (Baevski et al., 2020)](examples/wav2vec/README.md) - + [Generating Medical Reports from Patient-Doctor Conversations Using Sequence-to-Sequence Models (Enarvi et al., 2020)](examples/pointer_generator/README.md) - + [Linformer: Self-Attention with Linear Complexity (Wang et al., 2020)](examples/linformer/README.md) - + [Cross-lingual Retrieval for Iterative Self-Supervised Training (Tran et al., 2020)](examples/criss/README.md) - + [Deep Transformers with Latent Depth (Li et al., 2020)](examples/latent_depth/README.md) - + [Unsupervised Cross-lingual Representation Learning for Speech Recognition (Conneau et al., 2020)](https://arxiv.org/abs/2006.13979) - + [Self-training and Pre-training are Complementary for Speech Recognition (Xu et al., 2020)](https://arxiv.org/abs/2010.11430) - + [Robust wav2vec 2.0: Analyzing Domain Shift in Self-Supervised Pre-Training (Hsu, et al., 2021)](https://arxiv.org/abs/2104.01027) - + [Unsupervised Speech Recognition (Baevski, et al., 2021)](https://arxiv.org/abs/2105.11084) - + [Simple and Effective Zero-shot Cross-lingual Phoneme Recognition (Xu et al., 2021)](https://arxiv.org/abs/2109.11680) - + [VideoCLIP: Contrastive Pre-training for Zero-shot Video-Text Understanding (Xu et. al., 2021)](https://arxiv.org/pdf/2109.14084.pdf) - + [VLM: Task-agnostic Video-Language Model Pre-training for Video Understanding (Xu et. al., 2021)](https://aclanthology.org/2021.findings-acl.370.pdf) - + [NormFormer: Improved Transformer Pretraining with Extra Normalization (Shleifer et. al, 2021)](examples/normformer/README.md) -* **Non-autoregressive Transformers** - + Non-Autoregressive Neural Machine Translation (Gu et al., 2017) - + Deterministic Non-Autoregressive Neural Sequence Modeling by Iterative Refinement (Lee et al. 2018) - + Insertion Transformer: Flexible Sequence Generation via Insertion Operations (Stern et al. 2019) - + Mask-Predict: Parallel Decoding of Conditional Masked Language Models (Ghazvininejad et al., 2019) - + [Levenshtein Transformer (Gu et al., 2019)](examples/nonautoregressive_translation/README.md) -* **Finetuning** - + [Better Fine-Tuning by Reducing Representational Collapse (Aghajanyan et al. 2020)](examples/rxf/README.md) - -
- -* September 2020: [Added Linformer code](examples/linformer/README.md) -* September 2020: [Added pointer-generator networks](examples/pointer_generator/README.md) -* August 2020: [Added lexically constrained decoding](examples/constrained_decoding/README.md) -* August 2020: [wav2vec2 models and code released](examples/wav2vec/README.md) -* July 2020: [Unsupervised Quality Estimation code released](examples/unsupervised_quality_estimation/README.md) -* May 2020: [Follow fairseq on Twitter](https://twitter.com/fairseq) -* April 2020: [Monotonic Multihead Attention code released](examples/simultaneous_translation/README.md) -* April 2020: [Quant-Noise code released](examples/quant_noise/README.md) -* April 2020: [Initial model parallel support and 11B parameters unidirectional LM released](examples/megatron_11b/README.md) -* March 2020: [Byte-level BPE code released](examples/byte_level_bpe/README.md) -* February 2020: [mBART model and code released](examples/mbart/README.md) -* February 2020: [Added tutorial for back-translation](https://github.com/pytorch/fairseq/tree/main/examples/backtranslation#training-your-own-model-wmt18-english-german) -* December 2019: [fairseq 0.9.0 released](https://github.com/pytorch/fairseq/releases/tag/v0.9.0) -* November 2019: [VizSeq released (a visual analysis toolkit for evaluating fairseq models)](https://facebookresearch.github.io/vizseq/docs/getting_started/fairseq_example) -* November 2019: [CamemBERT model and code released](examples/camembert/README.md) -* November 2019: [BART model and code released](examples/bart/README.md) -* November 2019: [XLM-R models and code released](examples/xlmr/README.md) -* September 2019: [Nonautoregressive translation code released](examples/nonautoregressive_translation/README.md) -* August 2019: [WMT'19 models released](examples/wmt19/README.md) -* July 2019: fairseq relicensed under MIT license -* July 2019: [RoBERTa models and code released](examples/roberta/README.md) -* June 2019: [wav2vec models and code released](examples/wav2vec/README.md) - -
-
-VLM is a masked language model style pre-training using only one encoder with masked modality model (MMM) for retrieval/generation/sequence labeling style tasks.
-
-
-
-### News
-[Oct. 2021] Initial release of implementation for the following papers:
-[VideoCLIP: Contrastive Pre-training for Zero-shot Video-Text Understanding](https://arxiv.org/pdf/2109.14084.pdf) (Xu et. al., EMNLP 2021)
-[VLM: Task-agnostic Video-Language Model Pre-training for Video Understanding](https://aclanthology.org/2021.findings-acl.370.pdf) (Xu et. al., ACL Findings 2021)
-
-
-### Installation
-We aim to minimize the dependency of this repo on other packages.
-We use fairseq as the main trainer (no models/datasets dependency on fairseq. We will support other trainer in future):
-```
-git clone https://github.com/pytorch/fairseq
-cd fairseq
-pip install -e . # also optionally follow fairseq README for apex installation for fp16 training.
-export MKL_THREADING_LAYER=GNU # fairseq may need this for numpy.
-```
-
-Then install this toolkit:
-```
-cd examples/MMPT # MMPT can be in any folder, not necessarily under fairseq/examples.
-pip install -e .
-```
-
-The code is developed under Python=3.8.8, Pytorch=1.8, cuda=11.0 with fairseq=1.0.0a0+af0389f and tested under Python=3.8.8 pytorch=1.9 cuda=11.0 fairseq=1.0.0a0+8e7bc73 during code release.
-Most models require `transformers==3.4` for API compatibility `pip install transformers==3.4`.
-In addition, some downstream tasks may need `conda install pandas`.
-
-
-### Usage
-#### Download Checkpoints
-We use pre-trained [S3D](https://github.com/antoine77340/S3D_HowTo100M) for video feature extraction. Please place the models as `pretrained_models/s3d_dict.npy` and `pretrained_models/s3d_howto100m.pth`.
-
-Download VideoCLIP checkpoint `https://dl.fbaipublicfiles.com/MMPT/retri/videoclip/checkpoint_best.pt` to `runs/retri/videoclip` or VLM checkpoint `https://dl.fbaipublicfiles.com/MMPT/mtm/vlm/checkpoint_best.pt` to `runs/mtm/vlm`.
-
-#### Demo of Inference
-run `python locallaunch.py projects/retri/videoclip.yaml --dryrun` to get all `.yaml`s for VideoCLIP.
-
-```python
-import torch
-
-from mmpt.models import MMPTModel
-
-
-model, tokenizer, aligner = MMPTModel.from_pretrained(
- "projects/retri/videoclip/how2.yaml")
-
-model.eval()
-
-
-# B, T, FPS, H, W, C (VideoCLIP is trained on 30 fps of s3d)
-video_frames = torch.randn(1, 2, 30, 224, 224, 3)
-caps, cmasks = aligner._build_text_seq(
- tokenizer("some text", add_special_tokens=False)["input_ids"]
-)
-
-caps, cmasks = caps[None, :], cmasks[None, :] # bsz=1
-
-with torch.no_grad():
- output = model(video_frames, caps, cmasks, return_score=True)
-print(output["score"]) # dot-product
-```
-
-#### Data Preparation
-See [dataset](DATASET.md) for each dataset.
-
-#### Global Config for Training Pipeline
-We organize a global config file for a training/testing pipeline under projects (see a detailed [explanation](CONFIG.md)). For example, VideoCLIP in `projects/retri/videoclip.yaml` and VLM is in `projects/mtm/vlm.yaml`.
-
-We wrap all cmds into `locallaunch.py` and `mmpt_cli/localjob.py`. You can check concrete cmds by `--dryrun` and then drop it for actual run.
-
-First, run `python locallaunch.py projects/retri/videoclip.yaml --dryrun` will generate configs for all configs of pre-training, zero-shot evaluation, fine-tuning and testing, for VideoCLIP under `projects/retri/videoclip`.
-
-Then each (either training or evaluation) process will be configed by a concrete config file (we save all complex arguments into the concrete config file for reproducibility, including fairseq args). For example, run zero-shot evaluation on youcook,
-```
-python locallaunch.py projects/retri/videoclip/test_youcook_zs.yaml --jobtype local_predict # zero-shot evaluation.
-python locallaunch.py projects/retri/videoclip/youcook_videoclip.yaml --jobtype local_single --dryrun # fine-tuning: use --dryrun to check cmds and drop it to make an actual run; local_small will run on two gpus (as in paper).
-python locallaunch.py projects/retri/videoclip/test_youcook_videoclip.yaml --jobtype local_predict # testing on fine-tuned model.
-```
-
-Pretraining can be run as:
-```
-python locallaunch.py projects/retri/videoclip/how2.yaml --jobtype local_single --dryrun # check then drop dryrun; paper is ran on local_big as 8 gpus.
-```
-You may need to change `--jobtype`, check/extend `LocalJob` in `mmpt_cli/localjob.py` for multi-gpu/multi-node pre-training.
-
-The detailed instructions of pretraining and fine-tuning can be found at [pretraining instruction](pretraining.md) and [finetuning instruction](endtask.md).
-
-
-### Development
-Several components of this toolkit can be re-used for future research (and also our ongoing research).
-
-#### Framework Wrapper
-We currently only support fairseq, but most components can be easily fit into other frameworks like huggingface. This repo is a `--user-dir` of fairseq with fairseq wrapper. For example, `mmpt/tasks` includes a `FairseqMMTTask`, which manages `mmpt/datasets` with `FairseqDataset`, `mmpt/models` with `FairseqModel`, `mmpt/losses` with `FairseqCriterion`.
-
-#### Processors
-**Multi**modal research introduces the complexity on modality alignment from different input sources to losses. Inspired by [MMF](https://github.com/facebookresearch/mmf), this toolkit leverages `mmpt/processors` to handle various needs of data preprocessing and loading, **alleviating** the needs of multiple `torch.data.utils.Dataset` (that can be tricky for ablation study).
-Processors can also be decoupled from `torch.data.utils.Dataset` for offline preprocessing instead of on-the-fly data preprocessing.
-
-We decouple a `mmpt.MMDataset` as 3 types of processors: `MetaProcessor`, `VideoProcessor`, `TextProcessor` and `Aligner`. They can be configed in `dataset` field of a config file (e.g., see `projects/task/how2.yaml`).
-`MetaProcessor` is used to load the meta data about a dataset, aka, all video_ids of how2 dataset.
-`VideoProcessor` is used to load the video features about a dataset. For example, S3D features for each second of a video.
-`TextProcessor` is used to load the text (feature). For example, BERT pre-tokenized text clips for how2 dataset (with `start`s, `end`s of timestamps and `cap` for `token_ids`).
-`Aligner` is the core class for different baselines that prepares the training data. For example, sampling a clip, masking tokens for MLM, etc.
-
-#### Performance-tuned Components
-To speed up pre-training, this toolkit uses sharded features stored in mmaped numpy, backed by `ShardedTensor` in `mmpt/utils/shardedtensor.py` (adopted from MARGE paper). This reduces the loads of IO for multi-GPU training without loading all features for a video into the memory each time and `ShardedTensor` ensure features are stored in continuous disk space for near random access. This is used for both How2 video features and texts in `mmpt/processors/how2processor.py`.
-
-
-### Citation
-If this codebase is useful for your work, please cite the following papers:
-
-```BibTeX
-@inproceedings{xu-etal-2021-videoclip,
- title = "{VideoCLIP}: Contrastive Pre-training for\\Zero-shot Video-Text Understanding",
- author = "Xu, Hu and
- Ghosh, Gargi and
- Huang, Po-Yao and
- Okhonko, Dmytro and
- Aghajanyan, Armen and
- Metze, Florian and
- Zettlemoyer, Luke and
- Feichtenhofer, Christoph",
- booktitle = "Proceedings of the 2021 Conference on Empirical Methods in Natural Language Processing (EMNLP)",
- month = nov,
- year = "2021",
- address = "Online",
- publisher = "Association for Computational Linguistics",
-}
-
-@inproceedings{xu-etal-2021-vlm,
- title = "{VLM}: Task-agnostic Video-Language Model Pre-training for Video Understanding",
- author = "Xu, Hu and
- Ghosh, Gargi and
- Huang, Po-Yao and
- Arora, Prahal and
- Aminzadeh, Masoumeh and
- Feichtenhofer, Christoph and
- Metze, Florian and
- Zettlemoyer, Luke",
- booktitle = "Findings of the Association for Computational Linguistics: ACL-IJCNLP 2021",
- month = aug,
- year = "2021",
- address = "Online",
- publisher = "Association for Computational Linguistics",
- url = "https://aclanthology.org/2021.findings-acl.370",
- doi = "10.18653/v1/2021.findings-acl.370",
- pages = "4227--4239",
-}
-```
-
-### Bug Reports
-This repo is in its initial stage, welcome bug reports to huxu@fb.com
-
-### Copyright
-The majority of Multimodal Pre-training (MMPT) is licensed under CC-BY-NC, however portions of the project are available under separate license terms: Evaluation Codes/Models: Howto100M and HuggingFace Transformers are licensed under the Apache2.0 license; COIN and NLG-eval are licensed under the MIT license; CrossTask is licensed under the BSD-3; DiDeMo is licensed under the BSD-2 license.
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/endtask.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/endtask.md
deleted file mode 100644
index 7690955327283ded4b37857a4a7b78463e0eb0f8..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/endtask.md
+++ /dev/null
@@ -1,41 +0,0 @@
-# Zero-shot Transfer and Finetuning
-
-(If you are new to the ideas of `mmpt.processors`, see [README](README.md) first.)
-All finetuning datasets (specifically `processors`) are defined in `mmpt.processors.dsprocessor`.
-Given the complexity of different types of finetuning tasks, each task may have their own meta/video/text/aligner processors and `mmpt/evaluators/{Predictor,Metric}`.
-
-### Tasks
-
-Currently, we support 5 end datasets: `MSRVTT`, `Youcook`, `COIN`, `Crosstask` and `DiDeMo` with the following tasks:
-text-video retrieval: `MSRVTT`, `Youcook`, `DiDeMo`;
-video captioning: `Youcook`;
-Video Question and Answering: `MSRVTT-QA`.
-
-To add your own dataset, you can specify the corresponding processors and config them in the `dataset` field of a config file, such as `projects/task/vtt.yaml`.
-
-### Zero-shot Transfer (no Training)
-Zero-shot transfer will run the pre-trained model (e.g., VideoCLIP) directly on testing data. Configs with pattern: `projects/task/*_zs_*.yaml` are dedicated for zero-shot transfer.
-
-### Fine-tuning
-
-The training of a downstream task is similar to pretraining, execept you may need to specify the `restore_file` in `fairseq.checkpoint` and reset optimizers, see `projects/task/ft.yaml` that is included by `projects/task/vtt.yaml`.
-
-We typically do finetuning on 2 gpus (`local_small`).
-
-### Testing
-For each finetuning dataset, you may need to specify a testing config, similar to `projects/task/test_vtt.yaml`.
-
-We define `mmpt.evaluators.Predictor` for different types of prediction. For example, `MSRVTT` and `Youcook` are video-retrieval tasks and expecting to use `RetrievalPredictor`. You may need to define your new type of predictors and specify that in `predictor` field of a testing config.
-
-Each task may also have their own metric for evaluation. This can be created in `mmpt.evaluators.Metric` and specified in the `metric` field of a testing config.
-
-Launching a testing is as simple as training by specifying the path of a testing config:
-```python locallaunch.py projects/mfmmlm/test_vtt.yaml```
-Testing will be launched locally by default since prediction is computationally less expensive.
-
-### Third-party Libraries
-We list the following finetuning tasks that require third-party libraries.
-
-Youcook captioning: `https://github.com/Maluuba/nlg-eval`
-
-CrossTask: `https://github.com/DmZhukov/CrossTask`'s `dp` under `third-party/CrossTask` (`python setup.py build_ext --inplace`)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/locallaunch.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/locallaunch.py
deleted file mode 100644
index e20fd816fa3bed8b1af8f6a4d1a07ccb69a1fffa..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/locallaunch.py
+++ /dev/null
@@ -1,148 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-import argparse
-import os
-
-from omegaconf import OmegaConf
-
-from mmpt.utils import recursive_config, overwrite_dir
-from mmpt_cli.localjob import LocalJob
-
-
-class JobLauncher(object):
- JOB_CONFIG = {
- "local": LocalJob,
- }
-
- def __init__(self, yaml_file):
- self.yaml_file = yaml_file
- job_key = "local"
-
- if yaml_file.endswith(".yaml"):
- config = recursive_config(yaml_file)
- if config.task_type is not None:
- job_key = config.task_type.split("_")[0]
- else:
- raise ValueError("unknown extension of job file:", yaml_file)
- self.job_key = job_key
-
- def __call__(self, job_type=None, dryrun=False):
- if job_type is not None:
- self.job_key = job_type.split("_")[0]
- print("[JobLauncher] job_key", self.job_key)
- job = JobLauncher.JOB_CONFIG[self.job_key](
- self.yaml_file, job_type=job_type, dryrun=dryrun)
- return job.submit()
-
-
-class Pipeline(object):
- """a job that loads yaml config."""
-
- def __init__(self, fn):
- """
- load a yaml config of a job and save generated configs as yaml for each task.
- return: a list of files to run as specified by `run_task`.
- """
- if fn.endswith(".py"):
- # a python command.
- self.backend = "python"
- self.run_yamls = [fn]
- return
-
- job_config = recursive_config(fn)
- if job_config.base_dir is None: # single file job config.
- self.run_yamls = [fn]
- return
-
- self.project_dir = os.path.join("projects", job_config.project_dir)
- self.run_dir = os.path.join("runs", job_config.project_dir)
-
- if job_config.run_task is not None:
- run_yamls = []
- for stage in job_config.run_task:
- # each stage can have multiple tasks running in parallel.
- if OmegaConf.is_list(stage):
- stage_yamls = []
- for task_file in stage:
- stage_yamls.append(
- os.path.join(self.project_dir, task_file))
- run_yamls.append(stage_yamls)
- else:
- run_yamls.append(os.path.join(self.project_dir, stage))
- self.run_yamls = run_yamls
- configs_to_save = self._overwrite_task(job_config)
- self._save_configs(configs_to_save)
-
- def __getitem__(self, idx):
- yaml_files = self.run_yamls[idx]
- if isinstance(yaml_files, list):
- return [JobLauncher(yaml_file) for yaml_file in yaml_files]
- return [JobLauncher(yaml_files)]
-
- def __len__(self):
- return len(self.run_yamls)
-
- def _save_configs(self, configs_to_save: dict):
- # save
- os.makedirs(self.project_dir, exist_ok=True)
- for config_file in configs_to_save:
- config = configs_to_save[config_file]
- print("saving", config_file)
- OmegaConf.save(config=config, f=config_file)
-
- def _overwrite_task(self, job_config):
- configs_to_save = {}
- self.base_project_dir = os.path.join("projects", job_config.base_dir)
- self.base_run_dir = os.path.join("runs", job_config.base_dir)
-
- for config_sets in job_config.task_group:
- overwrite_config = job_config.task_group[config_sets]
- if (
- overwrite_config.task_list is None
- or len(overwrite_config.task_list) == 0
- ):
- print(
- "[warning]",
- job_config.task_group,
- "has no task_list specified.")
- # we don't want this added to a final config.
- task_list = overwrite_config.pop("task_list", None)
- for config_file in task_list:
- config_file_path = os.path.join(
- self.base_project_dir, config_file)
- config = recursive_config(config_file_path)
- # overwrite it.
- if overwrite_config:
- config = OmegaConf.merge(config, overwrite_config)
- overwrite_dir(config, self.run_dir, basedir=self.base_run_dir)
- save_file_path = os.path.join(self.project_dir, config_file)
- configs_to_save[save_file_path] = config
- return configs_to_save
-
-
-def main(args):
- job_type = args.jobtype if args.jobtype else None
- # parse multiple pipelines.
- pipelines = [Pipeline(fn) for fn in args.yamls.split(",")]
-
- for pipe_id, pipeline in enumerate(pipelines):
- if not hasattr(pipeline, "project_dir"):
- for job in pipeline[0]:
- job(job_type=job_type, dryrun=args.dryrun)
-
-
-if __name__ == "__main__":
- parser = argparse.ArgumentParser()
- parser.add_argument("yamls", type=str)
- parser.add_argument(
- "--dryrun",
- action="store_true",
- help="run config and prepare to submit without launch the job.",
- )
- parser.add_argument(
- "--jobtype", type=str, default="",
- help="force to run jobs as specified.")
- args = parser.parse_args()
- main(args)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/__init__.py
deleted file mode 100644
index 6ff86ddd5ce0c454281e6568c628bd3c49ea5024..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/__init__.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-try:
- # fairseq user dir
- from .datasets import FairseqMMDataset
- from .losses import FairseqCriterion
- from .models import FairseqMMModel
- from .tasks import FairseqMMTask
-except ImportError:
- pass
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/datasets/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/datasets/__init__.py
deleted file mode 100644
index 2578235e1771fdc7e6fcfb66a519cbe891d7e254..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/datasets/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-from .mmdataset import *
-
-try:
- from .fairseqmmdataset import *
-except ImportError:
- pass
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/datasets/fairseqmmdataset.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/datasets/fairseqmmdataset.py
deleted file mode 100644
index 02c49141db69c44663bd438b947c268d06f8aa2b..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/datasets/fairseqmmdataset.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-"""
-TODO (huxu): fairseq wrapper class for all dataset you defined: mostly MMDataset.
-"""
-
-from collections import OrderedDict
-
-from torch.utils.data import Dataset
-from torch.utils.data.dataloader import default_collate
-from fairseq.data import FairseqDataset, data_utils
-
-
-class FairseqMMDataset(FairseqDataset):
- """
- A wrapper class for MMDataset for fairseq.
- """
-
- def __init__(self, mmdataset):
- if not isinstance(mmdataset, Dataset):
- raise TypeError("mmdataset must be of type `torch.utils.data.dataset`.")
- self.mmdataset = mmdataset
-
- def set_epoch(self, epoch, **unused):
- super().set_epoch(epoch)
- self.epoch = epoch
-
- def __getitem__(self, idx):
- with data_utils.numpy_seed(43211, self.epoch, idx):
- return self.mmdataset[idx]
-
- def __len__(self):
- return len(self.mmdataset)
-
- def collater(self, samples):
- if hasattr(self.mmdataset, "collator"):
- return self.mmdataset.collator(samples)
- if len(samples) == 0:
- return {}
- if isinstance(samples[0], dict):
- batch = OrderedDict()
- for key in samples[0]:
- if samples[0][key] is not None:
- batch[key] = default_collate([sample[key] for sample in samples])
- return batch
- else:
- return default_collate(samples)
-
- def size(self, index):
- """dummy implementation: we don't use --max-tokens"""
- return 1
-
- def num_tokens(self, index):
- """dummy implementation: we don't use --max-tokens"""
- return 1
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/datasets/mmdataset.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/datasets/mmdataset.py
deleted file mode 100644
index 3d07283f917a430a8d9b1226c8fa6ab71450e8a9..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/datasets/mmdataset.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import torch
-
-from collections import OrderedDict
-
-from torch.utils.data import Dataset
-from torch.utils.data.dataloader import default_collate
-
-from ..utils import set_seed
-
-
-class MMDataset(Dataset):
- """
- A generic multi-modal dataset.
- Args:
- `meta_processor`: a meta processor,
- handling loading meta data and return video_id and text_id.
- `video_processor`: a video processor,
- handling e.g., decoding, loading .np files.
- `text_processor`: a text processor,
- handling e.g., tokenization.
- `aligner`: combine the video and text feature
- as one training example.
- """
-
- def __init__(
- self,
- meta_processor,
- video_processor,
- text_processor,
- align_processor,
- ):
- self.split = meta_processor.split
- self.meta_processor = meta_processor
- self.video_processor = video_processor
- self.text_processor = text_processor
- self.align_processor = align_processor
-
- def __len__(self):
- return len(self.meta_processor)
-
- def __getitem__(self, idx):
- if self.split == "test":
- set_seed(idx)
- video_id, text_id = self.meta_processor[idx]
- video_feature = self.video_processor(video_id)
- text_feature = self.text_processor(text_id)
- output = self.align_processor(video_id, video_feature, text_feature)
- # TODO (huxu): the following is for debug purpose.
- output.update({"idx": idx})
- return output
-
- def collater(self, samples):
- """This collator is deprecated.
- set self.collator = MMDataset.collater.
- see collator in FairseqMMDataset.
- """
-
- if len(samples) == 0:
- return {}
- if isinstance(samples[0], dict):
- batch = OrderedDict()
- for key in samples[0]:
- if samples[0][key] is not None:
- batch[key] = default_collate(
- [sample[key] for sample in samples])
- # if torch.is_tensor(batch[key]):
- # print(key, batch[key].size())
- # else:
- # print(key, len(batch[key]))
- return batch
- else:
- return default_collate(samples)
-
- def print_example(self, output):
- print("[one example]", output["video_id"])
- if (
- hasattr(self.align_processor, "subsampling")
- and self.align_processor.subsampling is not None
- and self.align_processor.subsampling > 1
- ):
- for key in output:
- if torch.is_tensor(output[key]):
- output[key] = output[key][0]
-
- # search tokenizer to translate ids back.
- tokenizer = None
- if hasattr(self.text_processor, "tokenizer"):
- tokenizer = self.text_processor.tokenizer
- elif hasattr(self.align_processor, "tokenizer"):
- tokenizer = self.align_processor.tokenizer
- if tokenizer is not None:
- caps = output["caps"].tolist()
- if isinstance(caps[0], list):
- caps = caps[0]
- print("caps", tokenizer.decode(caps))
- print("caps", tokenizer.convert_ids_to_tokens(caps))
-
- for key, value in output.items():
- if torch.is_tensor(value):
- if len(value.size()) >= 3: # attention_mask.
- print(key, value.size())
- print(key, "first", value[0, :, :])
- print(key, "last", value[-1, :, :])
- else:
- print(key, value)
- print("[end of one example]")
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/evaluators/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/evaluators/__init__.py
deleted file mode 100644
index 2d06b9d7974db251143025124468f48cd230e89a..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/evaluators/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-from .metric import *
-from .evaluator import *
-
-
-# experimental.
-try:
- from .expmetric import *
-except ImportError:
- pass
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/evaluators/evaluator.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/evaluators/evaluator.py
deleted file mode 100644
index 94d9c5ec9a6e84434dbced8d5647754c5a571570..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/evaluators/evaluator.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-import os
-import glob
-import numpy as np
-
-from . import metric as metric_path
-from . import predictor as predictor_path
-
-
-class Evaluator(object):
- """
- perform evaluation on a single (downstream) task.
- make this both offline and online.
- TODO(huxu) saving evaluation results.
- """
-
- def __init__(self, config, eval_dataloader=None):
- if config.metric is None:
- raise ValueError("config.metric is", config.metric)
- metric_cls = getattr(metric_path, config.metric)
- self.metric = metric_cls(config)
- if config.predictor is None:
- raise ValueError("config.predictor is", config.predictor)
- predictor_cls = getattr(predictor_path, config.predictor)
- self.predictor = predictor_cls(config)
- self.eval_dataloader = eval_dataloader
-
- def __call__(self):
- try:
- print(self.predictor.pred_dir)
- for pred_file in glob.glob(
- self.predictor.pred_dir + "/*_merged.npy"):
- outputs = np.load(pred_file)
- results = self.metric.compute_metrics(outputs)
- self.metric.print_computed_metrics(results)
-
- outputs = np.load(os.path.join(
- self.predictor.pred_dir, "merged.npy"))
- results = self.metric.compute_metrics(outputs)
- return {"results": results, "metric": self.metric}
- except FileNotFoundError:
- print("\n[missing]", self.predictor.pred_dir)
- return {}
-
- def evaluate(self, model, eval_dataloader=None, output_file="merged"):
- if eval_dataloader is None:
- eval_dataloader = self.eval_dataloader
- outputs = self.predictor.predict_loop(
- model, eval_dataloader, output_file)
- results = self.metric.compute_metrics(**outputs)
- return results
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/evaluators/metric.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/evaluators/metric.py
deleted file mode 100644
index 163724bb250cb1b7057b3fa4d75a9fafa9c181f5..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/evaluators/metric.py
+++ /dev/null
@@ -1,313 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import numpy as np
-import json
-
-
-class Metric(object):
- def __init__(self, config, metric_names):
- self.metric_names = metric_names
-
- def best_metric(self, metric):
- return metric[self.metric_names[0]]
-
- def save_metrics(self, fn, metrics):
- with open(fn, "w") as fw:
- json.dump(fw, metrics)
-
- def print_computed_metrics(self, metrics):
- raise NotImplementedError
-
-
-class RetrievalMetric(Metric):
- """
- this is modified from `howto100m/metrics.py`.
- History of changes:
- refactor as a class.
- add metric_key in __init__
- """
-
- def __init__(self, config, metric_names=["R1", "R5", "R10", "MR"]):
- super().__init__(config, metric_names)
- self.error = False # TODO(huxu): add to config to print error.
-
- def compute_metrics(self, outputs, texts, **kwargs):
- x = outputs
- sx = np.sort(-x, axis=1)
- d = np.diag(-x)
- d = d[:, np.newaxis]
- ind = sx - d
- ind = np.where(ind == 0)
- ind = ind[1]
- metrics = {}
- metrics["R1"] = float(np.sum(ind == 0)) / len(ind)
- metrics["R5"] = float(np.sum(ind < 5)) / len(ind)
- metrics["R10"] = float(np.sum(ind < 10)) / len(ind)
- metrics["MR"] = np.median(ind) + 1
-
- max_idx = np.argmax(outputs, axis=1)
- if self.error:
- # print top-20 errors.
- error = []
- for ex_idx in range(20):
- error.append((texts[ex_idx], texts[max_idx[ex_idx]]))
- metrics["error"] = error
- return metrics
-
- def print_computed_metrics(self, metrics):
- r1 = metrics["R1"]
- r5 = metrics["R5"]
- r10 = metrics["R10"]
- mr = metrics["MR"]
- print(
- "R@1: {:.4f} - R@5: {:.4f} - R@10: {:.4f} - Median R: {}".format(
- r1, r5, r10, mr
- )
- )
- if "error" in metrics:
- print(metrics["error"])
-
-
-class DiDeMoMetric(Metric):
- """
- History of changes:
- python 2.x to python 3.x.
- merge utils.py into eval to save one file.
- reference: https://github.com/LisaAnne/LocalizingMoments/blob/master/utils/eval.py
- Code to evaluate your results on the DiDeMo dataset.
- """
- def __init__(self, config, metric_names=["rank1", "rank5", "miou"]):
- super().__init__(config, metric_names)
-
- def compute_metrics(self, outputs, targets, **kwargs):
- assert len(outputs) == len(targets)
- rank1, rank5, miou = self._eval_predictions(outputs, targets)
- metrics = {
- "rank1": rank1,
- "rank5": rank5,
- "miou": miou
- }
- return metrics
-
- def print_computed_metrics(self, metrics):
- rank1 = metrics["rank1"]
- rank5 = metrics["rank5"]
- miou = metrics["miou"]
- # print("Average rank@1: %f" % rank1)
- # print("Average rank@5: %f" % rank5)
- # print("Average iou: %f" % miou)
-
- print(
- "Average rank@1: {:.4f} Average rank@5: {:.4f} Average iou: {:.4f}".format(
- rank1, rank5, miou
- )
- )
-
- def _iou(self, pred, gt):
- intersection = max(0, min(pred[1], gt[1]) + 1 - max(pred[0], gt[0]))
- union = max(pred[1], gt[1]) + 1 - min(pred[0], gt[0])
- return float(intersection)/union
-
- def _rank(self, pred, gt):
- return pred.index(tuple(gt)) + 1
-
- def _eval_predictions(self, segments, data):
- '''
- Inputs:
- segments: For each item in the ground truth data, rank possible video segments given the description and video.
- In DiDeMo, there are 21 posible moments extracted for each video so the list of video segments will be of length 21.
- The first video segment should be the video segment that best corresponds to the text query.
- There are 4180 sentence in the validation data, so when evaluating a model on the val dataset,
- segments should be a list of lenght 4180, and each item in segments should be a list of length 21.
- data: ground truth data
- '''
- average_ranks = []
- average_iou = []
- for s, d in zip(segments, data):
- pred = s[0]
- ious = [self._iou(pred, t) for t in d['times']]
- average_iou.append(np.mean(np.sort(ious)[-3:]))
- ranks = [self._rank(s, t) for t in d['times'] if tuple(t) in s] # if t in s] is added for s, e not in prediction.
- average_ranks.append(np.mean(np.sort(ranks)[:3]))
- rank1 = np.sum(np.array(average_ranks) <= 1)/float(len(average_ranks))
- rank5 = np.sum(np.array(average_ranks) <= 5)/float(len(average_ranks))
- miou = np.mean(average_iou)
-
- # print("Average rank@1: %f" % rank1)
- # print("Average rank@5: %f" % rank5)
- # print("Average iou: %f" % miou)
- return rank1, rank5, miou
-
-
-class NLGMetric(Metric):
- def __init__(
- self,
- config,
- metric_names=[
- "Bleu_1", "Bleu_2", "Bleu_3", "Bleu_4",
- "METEOR", "ROUGE_L", "CIDEr"
- ]
- ):
- super().__init__(config, metric_names)
- # please install NLGEval from `https://github.com/Maluuba/nlg-eval`
- from nlgeval import NLGEval
- self.nlg = NLGEval()
-
- def compute_metrics(self, outputs, targets, **kwargs):
- return self.nlg.compute_metrics(
- hyp_list=outputs, ref_list=targets)
-
- def print_computed_metrics(self, metrics):
- Bleu_1 = metrics["Bleu_1"]
- Bleu_2 = metrics["Bleu_2"]
- Bleu_3 = metrics["Bleu_3"]
- Bleu_4 = metrics["Bleu_4"]
- METEOR = metrics["METEOR"]
- ROUGE_L = metrics["ROUGE_L"]
- CIDEr = metrics["CIDEr"]
-
- print(
- "Bleu_1: {:.4f} - Bleu_2: {:.4f} - Bleu_3: {:.4f} - Bleu_4: {:.4f} - METEOR: {:.4f} - ROUGE_L: {:.4f} - CIDEr: {:.4f}".format(
- Bleu_1, Bleu_2, Bleu_3, Bleu_4, METEOR, ROUGE_L, CIDEr
- )
- )
-
-
-class QAMetric(Metric):
- def __init__(
- self,
- config,
- metric_names=["acc"]
- ):
- super().__init__(config, metric_names)
-
- def compute_metrics(self, outputs, targets, **kwargs):
- from sklearn.metrics import accuracy_score
- return {"acc": accuracy_score(targets, outputs)}
-
- def print_computed_metrics(self, metrics):
- print("acc: {:.4f}".format(metrics["acc"]))
-
-
-class COINActionSegmentationMetric(Metric):
- """
- COIN dataset listed 3 repos for Action Segmentation.
- Action Sets, NeuralNetwork-Viterbi, TCFPN-ISBA.
- The first and second are the same.
- https://github.com/alexanderrichard/action-sets/blob/master/eval.py
-
- Future reference for the third:
- `https://github.com/Zephyr-D/TCFPN-ISBA/blob/master/utils/metrics.py`
- """
- def __init__(self, config, metric_name=["frame_acc"]):
- super().__init__(config, metric_name)
-
- def compute_metrics(self, outputs, targets):
- n_frames = 0
- n_errors = 0
- n_errors = sum(outputs != targets)
- n_frames = len(targets)
- return {"frame_acc": 1.0 - float(n_errors) / n_frames}
-
- def print_computed_metrics(self, metrics):
- fa = metrics["frame_acc"]
- print("frame accuracy:", fa)
-
-
-class CrossTaskMetric(Metric):
- def __init__(self, config, metric_names=["recall"]):
- super().__init__(config, metric_names)
-
- def compute_metrics(self, outputs, targets, **kwargs):
- """refactored from line 166:
- https://github.com/DmZhukov/CrossTask/blob/master/train.py"""
-
- recalls = self._get_recalls(Y_true=targets, Y_pred=outputs)
- results = {}
- for task, rec in recalls.items():
- results[str(task)] = rec
-
- avg_recall = np.mean(list(recalls.values()))
- results["recall"] = avg_recall
- return results
-
- def print_computed_metrics(self, metrics):
- print('Recall: {0:0.3f}'.format(metrics["recall"]))
- for task in metrics:
- if task != "recall":
- print('Task {0}. Recall = {1:0.3f}'.format(
- task, metrics[task]))
-
- def _get_recalls(self, Y_true, Y_pred):
- """refactored from
- https://github.com/DmZhukov/CrossTask/blob/master/train.py"""
-
- step_match = {task: 0 for task in Y_true.keys()}
- step_total = {task: 0 for task in Y_true.keys()}
- for task, ys_true in Y_true.items():
- ys_pred = Y_pred[task]
- for vid in set(ys_pred.keys()).intersection(set(ys_true.keys())):
- y_true = ys_true[vid]
- y_pred = ys_pred[vid]
- step_total[task] += (y_true.sum(axis=0) > 0).sum()
- step_match[task] += (y_true*y_pred).sum()
- recalls = {
- task: step_match[task] / n for task, n in step_total.items()}
- return recalls
-
-
-class ActionRecognitionMetric(Metric):
- def __init__(
- self,
- config,
- metric_names=["acc", "acc_splits", "r1_splits", "r5_splits", "r10_splits"]
- ):
- super().__init__(config, metric_names)
-
- def compute_metrics(self, outputs, targets, splits, **kwargs):
- all_video_embd = outputs
- labels = targets
- split1, split2, split3 = splits
- accs = []
- r1s = []
- r5s = []
- r10s = []
- for split in range(3):
- if split == 0:
- s = split1
- elif split == 1:
- s = split2
- else:
- s = split3
-
- X_pred = all_video_embd[np.where(s == 2)[0]]
- label_test = labels[np.where(s == 2)[0]]
- logits = X_pred
- X_pred = np.argmax(X_pred, axis=1)
- acc = np.sum(X_pred == label_test) / float(len(X_pred))
- accs.append(acc)
- # compute recall.
- sorted_pred = (-logits).argsort(axis=-1)
- label_test_sp = label_test.reshape(-1, 1)
-
- r1 = np.mean((sorted_pred[:, :1] == label_test_sp).sum(axis=1), axis=0)
- r5 = np.mean((sorted_pred[:, :5] == label_test_sp).sum(axis=1), axis=0)
- r10 = np.mean((sorted_pred[:, :10] == label_test_sp).sum(axis=1), axis=0)
- r1s.append(r1)
- r5s.append(r5)
- r10s.append(r10)
-
- return {"acc": accs[0], "acc_splits": accs, "r1_splits": r1s, "r5_splits": r5s, "r10_splits": r10s}
-
- def print_computed_metrics(self, metrics):
- for split, acc in enumerate(metrics["acc_splits"]):
- print("Top 1 accuracy on split {}: {}; r1 {}; r5 {}; r10 {}".format(
- split + 1, acc,
- metrics["r1_splits"][split],
- metrics["r5_splits"][split],
- metrics["r10_splits"][split],
- )
- )
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/evaluators/predictor.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/evaluators/predictor.py
deleted file mode 100644
index 2ffef6ab474a7a275d90784250d04222bd6dc70f..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/evaluators/predictor.py
+++ /dev/null
@@ -1,595 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-import os
-import random
-import json
-import numpy as np
-import torch
-import pickle
-import math
-
-from tqdm import tqdm
-
-
-class Predictor(object):
- """this base class is used to save predictions to disk
- (and being called by a evaluator later).
- Predictor has minimum support of single gpu prediction.
- """
- def __init__(self, config):
- self.pred_dir = None # on-the-fly eval does not save the results.
- if hasattr(config, "eval") and config.eval is not None:
- self.pred_dir = config.eval.save_path
- os.makedirs(self.pred_dir, exist_ok=True)
-
- def __call__(self, outputs):
- """extract the prediction and save it."""
- raise NotImplementedError
-
- def predict_loop(self, model, eval_dataloader, output_file=None):
- """on-the-fly prediction on a single gpu."""
- self.full_scores = []
- model.eval()
- model = model.to(0)
- with torch.no_grad():
- for data in eval_dataloader:
- data = self.to_ctx(data)
- outputs = model(**data)
- outputs.update(data)
- self(outputs)
- return self.finalize(output_file)
-
- def finalize(self, output_file):
- pass
-
- def to_ctx(self, data, ctx=0, dtype=None):
- if isinstance(data, dict):
- for key in data:
- if torch.is_tensor(data[key]):
- if dtype is not None and data[key].dtype == torch.float32:
- data[key] = data[key].to(dtype)
- data[key] = data[key].to(ctx)
- return data
- else:
- raise ValueError("non-dict type of batch is not supported yet.")
-
-
-class NLGPredictor(Predictor):
- """Predicting Text from MMFusion models."""
- """TODO: make a context."""
- def __init__(self, config):
- super().__init__(config)
- from transformers import AutoTokenizer
-
- self.tokenizer = AutoTokenizer.from_pretrained(
- config.dataset.bert_name,
- bos_token="[CLS]", eos_token="[SEP]")
- self.bos_token_id = self.tokenizer.bos_token_id
- self.eos_token_id = self.tokenizer.eos_token_id
-
- def predict_loop(self, model, eval_dataloader, output_file=None):
- """TODO: refactor base classes."""
- ctx = 0
- outputs = {"outputs": [], "targets": [[]]}
- model.eval()
- model = model.to(ctx)
- with torch.no_grad():
- for data in tqdm(eval_dataloader):
- data = self.to_ctx(data, ctx)
- self(data, model, outputs)
- return self.finalize(outputs, output_file)
-
- def __call__(self, data, model, outputs):
- data.update({
- "bos_token_id": self.bos_token_id,
- "eos_token_id": self.eos_token_id
- })
-
- output = model.generate(**data)
- assert len(output) == len(data["ref"])
- for idx, _output in enumerate(output):
- generated_text = self.tokenizer.decode(
- _output, skip_special_tokens=True)
- if generated_text == "":
- generated_text = "none"
- outputs["outputs"].append(generated_text)
- outputs["targets"][0].append(data["ref"][idx])
- if random.random() < 0.001:
- print("_output", _output)
- print("generated_text", generated_text)
- print("ref", data["ref"][idx])
-
- def finalize(self, outputs, output_file=None):
- if output_file is not None:
- with open(os.path.join(
- self.pred_dir, output_file + ".json"), "w") as fw:
- json.dump(outputs, fw, indent=4)
- return outputs
-
-
-class RetrievalPredictor(Predictor):
- """generated `pooled_video` and `pooled_text`."""
- def __init__(self, config):
- super().__init__(config)
- from transformers import AutoTokenizer
- self.tokenizer = AutoTokenizer.from_pretrained(
- config.dataset.bert_name)
-
- def predict_loop(
- self,
- model,
- eval_dataloader,
- output_file="retrieval.npy"
- ):
- """on-the-fly prediction on a single gpu."""
- full_scores = []
- texts = []
- model.eval()
- model = model.cuda()
- with torch.no_grad():
- for data in eval_dataloader:
- # convert to dict.
- if not isinstance(data, dict):
- data = {
- "caps": data[0],
- "cmasks": data[1],
- "vfeats": data[2],
- "vmasks": data[3],
- "video_id": data[4]
- }
- data = self.to_ctx(data)
- outputs = model(**data)
- outputs.update(data)
- self(outputs, full_scores)
- for _cap in data["caps"]:
- texts.append(
- self.tokenizer.decode(_cap, skip_special_tokens=True)
- )
-
- return self.finalize(full_scores, texts, output_file)
-
- def __call__(self, sample, full_scores):
- scores = self._get_pooled_outputs(sample)
- self._append_scores(scores, full_scores)
-
- def finalize(self, full_scores, texts, output_file=None):
- outputs = self._aggregate_scores(full_scores)
- if output_file is not None:
- np.save(os.path.join(self.pred_dir, output_file + ".npy"), outputs)
- return {"outputs": outputs, "texts": texts}
-
- def _get_pooled_outputs(self, outputs):
- if "pooled_video" in outputs:
- return outputs["pooled_video"], outputs["pooled_text"]
- else:
- raise ValueError("unknown format of outputs.")
-
- def _append_scores(self, scores, full_scores):
- assert len(scores) == 2
- if len(full_scores) == 0:
- full_scores.append([])
- full_scores.append([])
- full_scores[0].append(scores[0].cpu().detach().numpy())
- full_scores[1].append(scores[1].cpu().detach().numpy())
-
- def _aggregate_scores(self, scores):
- assert len(scores) == 2
- video_hidden = np.concatenate(scores[0], axis=0)
- text_hidden = np.concatenate(scores[1], axis=0)
- # clear up.
- self.full_scores = []
- return np.matmul(text_hidden, video_hidden.T)
-
-
-class QAPredictor(Predictor):
- """generated `pooled_video` and `pooled_text`."""
- def __init__(self, config):
- super().__init__(config)
- """predictor maintains scores and aggregate them."""
-
- def predict_loop(self, model, eval_dataloader, output_file="qa.npy"):
- """on-the-fly prediction on a single gpu."""
- self.full_scores = []
- model.eval()
- model = model.cuda()
- with torch.no_grad():
- for data in eval_dataloader:
- # reshape ans and dup video 5 times.
- v_len = data["vfeats"].size(1)
- hidden_size = data["vfeats"].size(2)
- data["vfeats"] = data["vfeats"].unsqueeze(1).repeat(1, 5, 1, 1).view(-1, v_len, hidden_size)
- data["vmasks"] = data["vmasks"].unsqueeze(1).repeat(1, 5, 1).view(-1, v_len)
-
- t_len = data["caps"].size(-1)
- data["caps"] = data["caps"].view(-1, t_len)
- data["cmasks"] = data["cmasks"].view(-1, t_len)
-
- data = self.to_ctx(data)
- outputs = model(**data)
- outputs.update(data)
- self(outputs)
- return self.finalize(output_file)
-
- def __call__(self, sample):
- hidden_size = sample["pooled_video"].size(-1)
- pooled_video = sample["pooled_video"].view(-1, 5, hidden_size)
- pooled_text = sample["pooled_text"].view(-1, 5, hidden_size)
- scores = torch.bmm(pooled_video, pooled_text.transpose(2, 1))
- scores = scores.argmax(-1)
- self._append_scores(scores[:, 0], sample["answers"], self.full_scores)
-
- def finalize(self, output_file=None):
- outputs, targets = self._aggregate_scores(self.full_scores)
- if output_file is not None:
- np.save(os.path.join(self.pred_dir, output_file + ".npy"), outputs)
- return {"outputs": outputs, "targets": targets}
-
- def _append_scores(self, scores, answers, full_scores):
- if len(full_scores) == 0:
- full_scores.append([])
- full_scores.append([])
- full_scores[0].append(scores.cpu().detach().numpy())
- full_scores[1].append(answers.cpu().detach().numpy())
-
- def _aggregate_scores(self, scores):
- assert len(scores) == 2
- outputs = np.concatenate(scores[0], axis=0)
- targets = np.concatenate(scores[1], axis=0)
- # clear up.
- self.full_scores = []
- return outputs, targets
-
-
-class CrossTaskPredictor(Predictor):
- """
- CrossTaskPredictor needs to compute the average of logits
- for overlapped sliding-window.
- """
- def __init__(self, config):
- super().__init__(config)
- self.lsm = torch.nn.LogSoftmax(dim=1)
- self.max_video_len = config.dataset.max_video_len
- self.sliding_window = config.dataset.sliding_window
- self.sliding_window_size = config.dataset.sliding_window_size
- self.annotation_path = config.dataset.annotation_path
-
- def predict_loop(self, model, eval_dataloader, output_file="result.pkl"):
- """refactored from line 144:
- https://github.com/DmZhukov/CrossTask/blob/master/train.py
- """
- ctx = 0
- model.eval()
- model = model.to(ctx)
- # this is not a loss but just compute neg_log_prob.
- Y_pred = {}
- Y_true = {}
- with torch.no_grad():
- for batch in eval_dataloader:
- self(batch, model, Y_pred, Y_true)
- return self.finalize(Y_pred, Y_true, output_file)
-
- def __call__(self, sample, model, Y_pred, Y_true):
- # please install dp from `https://github.com/DmZhukov/CrossTask`
- from dp import dp
- vid, task = sample['video_id'][0], sample['task'][0]
- sample = self.to_ctx(sample)
- # compute the average logits over sliding windows.
- output = model(**sample)
- batch_logits = output["logits"].cpu()
-
- video_len = sample["video_len"][0]
-
- # the following version is slow.
- logits = torch.zeros((video_len, batch_logits.size(1)))
- logits_counts = torch.zeros((video_len, 1), dtype=torch.long)
- # use the same loop as aligner to recover.
- batch_logit_idx = 0
- for window_start in range(0, video_len, self.sliding_window):
- video_end = min(video_len - window_start, self.sliding_window_size)
- logits[window_start: window_start + video_end] += batch_logits[
- batch_logit_idx: batch_logit_idx + video_end]
- batch_logit_idx += video_end
- logits_counts[window_start: window_start + video_end] += torch.ones((video_end, 1), dtype=torch.long)
-
- if (video_len - window_start) <= self.sliding_window_size:
- break
-
- logits /= logits_counts
- assert logits.size() == (video_len, batch_logits.size(1)), "{}, {}".format(logits.size(), video_len)
-
- O = self.lsm(logits)
- y = np.zeros(O.size(), dtype=np.float32)
- dp(y, -O.detach().cpu().numpy())
- if task not in Y_pred:
- Y_pred[task] = {}
- Y_pred[task][vid] = y
- annot_path = os.path.join(
- self.annotation_path, task+'_'+vid+'.csv')
- if os.path.exists(annot_path):
- if task not in Y_true:
- Y_true[task] = {}
- Y_true[task][vid] = self._read_assignment(
- *y.shape, annot_path)
-
- def finalize(self, Y_pred, Y_true, output_file=None):
- if output_file is not None:
- with open(
- os.path.join(self.pred_dir, output_file + ".pkl"),
- "wb") as fw:
- pickle.dump(
- {"Y_pred": Y_pred, "Y_true": Y_true}, fw,
- protocol=pickle.HIGHEST_PROTOCOL)
- return {"outputs": Y_pred, "targets": Y_true}
-
- def _read_assignment(self, T, K, path):
- """
- refactored from https://github.com/DmZhukov/CrossTask/blob/master/data.py
- Howto interpret contraints on loss that is going to be minimized:
- lambd is a big number;
- self.lambd * C is a big number for all valid position (csv stores invalids)
-
- def forward(self, O, Y, C):
- return (Y*(self.lambd * C - self.lsm(O))).mean(dim=0).sum()
-
- This will load the csv file and fill-in the step col from start to end rows.
- """
-
- Y = np.zeros([T, K], dtype=np.uint8)
- with open(path, 'r') as f:
- for line in f:
- step, start, end = line.strip().split(',')
- start = int(math.floor(float(start)))
- end = int(math.ceil(float(end)))
- step = int(step) - 1
- Y[start:end, step] = 1
- return Y
-
-
-class COINPredictor(Predictor):
- """
- COINPredictor is similar to CrossTask on sliding windows.
- """
- def __init__(self, config):
- super().__init__(config)
- self.max_video_len = config.dataset.max_video_len
- self.sliding_window = config.dataset.sliding_window
- self.sliding_window_size = config.dataset.sliding_window_size
-
- def predict_loop(self, model, eval_dataloader, output_file="result.pkl"):
- """refactored from line 144:
- https://github.com/DmZhukov/CrossTask/blob/master/train.py
- """
- ctx = 0
- model.eval()
- model = model.to(ctx)
- # this is not a loss but just compute neg_log_prob.
- Y_pred = []
- Y_true = []
- with torch.no_grad():
- for batch in eval_dataloader:
- self(batch, model, Y_pred, Y_true)
- return self.finalize(Y_pred, Y_true, output_file)
-
- def __call__(self, sample, model, Y_pred, Y_true):
- sample = self.to_ctx(sample)
- # compute the average logits over sliding windows.
- output = model(**sample)
- logits = self._merge_windows(sample, output)
- Y_pred.append(logits.argmax(dim=1))
- Y_true.append(sample["video_targets"].squeeze(0).cpu())
-
- def _merge_windows(self, sample, output):
- targets = sample["targets"].reshape(-1).cpu()
- valid_mask = targets != -100
- targets = targets[valid_mask]
- batch_logits = output["logits"].cpu()
- batch_logits = batch_logits.reshape(-1, batch_logits.size(-1))
- batch_logits = batch_logits[valid_mask]
-
- video_len = sample["video_len"][0]
-
- # the following version is slow.
- logits = torch.zeros((video_len, batch_logits.size(1)))
- logits_counts = torch.zeros((video_len, 1), dtype=torch.long)
- # use the same loop as aligner to recover.
- batch_logit_idx = 0
- for window_start in range(0, video_len, self.sliding_window):
- video_end = min(video_len - window_start, self.sliding_window_size)
- logits[window_start: window_start + video_end] += batch_logits[
- batch_logit_idx: batch_logit_idx + video_end]
- batch_logit_idx += video_end
- logits_counts[window_start: window_start + video_end] += torch.ones((video_end, 1), dtype=torch.long)
- if (video_len - window_start) <= self.sliding_window_size:
- break
- logits /= logits_counts
- assert logits.size() == (video_len, batch_logits.size(1)), "{}, {}".format(logits.size(), video_len)
- return logits
-
- def finalize(self, Y_pred, Y_true, output_file=None):
- Y_pred = torch.cat(Y_pred, dim=0).numpy()
- Y_true = torch.cat(Y_true, dim=0).numpy()
- assert len(Y_pred) == len(Y_true)
-
- error_mask = Y_pred != Y_true
- print("sample error", Y_pred[error_mask][:10], Y_true[error_mask][:10])
- print("sample error", Y_pred[error_mask][10:20], Y_true[error_mask][10:20])
-
- if output_file is not None:
- with open(
- os.path.join(self.pred_dir, output_file + ".pkl"),
- "wb") as fw:
- pickle.dump(
- {"Y_pred": Y_pred, "Y_true": Y_true}, fw,
- protocol=pickle.HIGHEST_PROTOCOL)
- return {"outputs": Y_pred, "targets": Y_true}
-
-
-class COINZSPredictor(COINPredictor):
- """
- COINZSPredictor for COIN zero-shot prediction.
- """
-
- def __init__(self, config):
- super().__init__(config)
- self.dataset_config = config.dataset
-
- def predict_loop(self, model, eval_dataloader, output_file="result.pkl"):
- """refactored from line 144:
- https://github.com/DmZhukov/CrossTask/blob/master/train.py
- """
- ctx = 0
- model.eval()
- model = model.to(ctx)
-
- with torch.no_grad():
- outputs = eval_dataloader.dataset.meta_processor.meta_text_labels(
- self.dataset_config)
- outputs = self.to_ctx(outputs, ctx)
- label_hidden_states = model.forward_text(**outputs).cpu()
- label_sim = label_hidden_states @ label_hidden_states.t()
- num_labels = label_sim.size(0)
- eye_mask = ~torch.eye(num_labels, dtype=torch.bool)
- label_sim = label_sim.masked_select(eye_mask).view(num_labels, num_labels - 1)
- lbd = label_sim.max()
-
- # this is not a loss but just compute neg_log_prob.
- Y_pred = []
- Y_true = []
- with torch.no_grad():
- for batch in eval_dataloader:
- self(batch, label_hidden_states, model, lbd, Y_pred, Y_true)
- return self.finalize(Y_pred, Y_true, output_file)
-
- def reshape_subsample(self, sample):
- for key in sample:
- if torch.is_tensor(sample[key]):
- sample[key] = self.flat_subsample(sample[key])
- return sample
-
- def flat_subsample(self, tensor):
- if len(tensor.size()) > 1 and tensor.size(0) == 1:
- tensor = tensor.squeeze(0)
- return tensor
-
- def __call__(self, sample, label_hidden_states, model, lbd, Y_pred, Y_true):
- sample = self.reshape_subsample(sample)
- sample = self.to_ctx(sample)
- # compute the average logits over sliding windows.
- sample["output_hidden_states"] = True
- video_outputs = model.forward_video(**sample).cpu()
- output = {"logits": video_outputs[:, 1:sample["vmasks"].size(1)+1] @ label_hidden_states.t()}
- logits = self._merge_windows(sample, output)
- # logic of zero-shot for sequence labeling.
- logits_argmax = logits.argmax(dim=1) + 1 # 0 is "O" label.
- logits_max = logits.max(dim=1)[0]
-
- pred = torch.zeros_like(logits_argmax)
- label_select = logits_max > lbd # 73 or 74
- pred[label_select] = logits_argmax[label_select]
-
- Y_pred.append(pred)
- Y_true.append(sample["video_targets"].squeeze(0).cpu())
-
- def finalize(self, Y_pred, Y_true, output_file=None):
- Y_pred = torch.cat(Y_pred, dim=0).numpy()
- Y_true = torch.cat(Y_true, dim=0).numpy()
- assert len(Y_pred) == len(Y_true)
-
- error_mask = Y_pred != Y_true
- print("sample error", Y_pred[error_mask][:10], Y_true[error_mask][:10])
- print("sample error", Y_pred[error_mask][10:20], Y_true[error_mask][10:20])
-
- if output_file is not None:
- with open(
- os.path.join(self.pred_dir, output_file + ".pkl"),
- "wb") as fw:
- pickle.dump(
- {"Y_pred": Y_pred, "Y_true": Y_true}, fw,
- protocol=pickle.HIGHEST_PROTOCOL)
- return {"outputs": Y_pred, "targets": Y_true}
-
-
-class DiDeMoPredictor(Predictor):
- """reference: https://github.com/LisaAnne/LocalizingMoments/blob/master/utils/eval.py
- https://github.com/LisaAnne/LocalizingMoments/blob/master/utils/data_processing.py
- """
- def __init__(self, config):
- super().__init__(config)
- # load targets.
- with open(config.dataset.test_path) as data_file:
- self.test_data = json.load(data_file)
-
- def predict_loop(self, model, eval_dataloader, output_file="didemo.npy"):
- """
- TODO: two solutions here.
- """
- import itertools
- # 21 chunks.
- self.possible_segments = [(0,0), (1,1), (2,2), (3,3), (4,4), (5,5)]
- for i in itertools.combinations(range(6), 2):
- self.possible_segments.append(i)
- # pick segments from a video.
-
- """on-the-fly prediction on a single gpu."""
- self.full_scores = []
- model.eval()
- model = model.cuda()
- with torch.no_grad():
- for data in eval_dataloader:
- # TODO special forwarding logic here.
- data = self.to_ctx(data)
- data["output_hidden_states"] = True
- hidden_video = model.forward_video(**data)
- data["output_hidden_states"] = False
- pooled_text = model.forward_text(**data)
- outputs = {
- "hidden_video": hidden_video,
- "pooled_text": pooled_text
- }
- outputs.update(data)
- self(outputs)
- return self.finalize(output_file)
-
- def __call__(self, sample):
- # TODO: make an index select from self.possible_segments.
- hidden_video = sample["hidden_video"]
- pooled_text = sample["pooled_text"]
- vmasks = sample["vmasks"]
- # probably maintain valid results here.
-
- hidden_video = hidden_video[:, 1:-1, :]
- # probably maintain valid results here.
- pooled_video = []
- for s, e in self.possible_segments:
- pooled_video.append(
- torch.mean(
- hidden_video[:, int(s*5):int((e+1)*5), :],
- dim=1, keepdim=True)
- )
- pooled_video = torch.cat(pooled_video, dim=1)
- scores = torch.bmm(
- pooled_video, pooled_text.unsqueeze(-1)).squeeze(-1).cpu()
-
- ranks = scores.argsort(dim=-1, descending=True)
-
- for batch_idx, rank in enumerate(ranks):
- rank_of_moment = []
- for m_idx, moment in enumerate(rank):
- s, e = self.possible_segments[moment.item()]
- if torch.any(
- vmasks[batch_idx, int(s*5):int((e+1)*5)]
- ):
- rank_of_moment.append((s, e))
- self.full_scores.append(rank_of_moment)
-
- def finalize(self, output_file=None):
- outputs = self._aggregate_scores(self.full_scores)
- if output_file is not None:
- np.save(os.path.join(self.pred_dir, output_file + ".npy"), outputs)
- return {"outputs": outputs, "targets": self.test_data}
-
- def _aggregate_scores(self, scores):
- self.full_scores = []
- return scores
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/losses/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/losses/__init__.py
deleted file mode 100644
index 8dc32c96d2d8aed25c59e69e9d9a2ff24a9a2a47..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/losses/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-from .loss import *
-from .nce import *
-
-try:
- from .fairseqmmloss import *
-except ImportError:
- pass
-
-try:
- from .expnce import *
-except ImportError:
- pass
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/losses/fairseqmmloss.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/losses/fairseqmmloss.py
deleted file mode 100644
index a95e5ecf45d90098c1719487bb9a11c36be7c507..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/losses/fairseqmmloss.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-"""
-TODO (huxu): a general fairseq criterion for all your pre-defined losses.
-"""
-
-from fairseq.criterions import FairseqCriterion, register_criterion
-from fairseq.logging import metrics
-
-
-@register_criterion("mmloss")
-class MMCriterion(FairseqCriterion):
- def __init__(self, task):
- super().__init__(task)
- # TODO (huxu): wrap forward call of loss_fn and eval_fn into task.
- self.mmtask = task.mmtask
-
- def forward(self, model, sample):
- """Compute the loss for the given sample.
- Returns a tuple with three elements:
- 1) the loss
- 2) the sample size, which is used as the denominator for the gradient
- 3) logging outputs to display while training
- """
- outputs = self.mmtask(model, sample)
-
- loss, loss_scalar, max_len, batch_size, sample_size = (
- outputs["loss"],
- outputs["loss_scalar"],
- outputs["max_len"],
- outputs["batch_size"],
- outputs["sample_size"],
- )
-
- logging_output = {
- "loss": loss_scalar,
- "ntokens": max_len * batch_size, # dummy report.
- "nsentences": batch_size, # dummy report.
- "sample_size": sample_size,
- }
-
- return loss, 1, logging_output
-
- @staticmethod
- def reduce_metrics(logging_outputs) -> None:
- """Aggregate logging outputs from data parallel training."""
- """since we use NCE, our actual batch_size is 1 per GPU.
- Then we take the mean of each worker."""
- loss_sum = sum(log.get("loss", 0.0) for log in logging_outputs)
- sample_size = sum(log.get("sample_size", 0) for log in logging_outputs)
- metrics.log_scalar("loss", loss_sum / sample_size, round=3)
-
- @staticmethod
- def logging_outputs_can_be_summed() -> bool:
- """
- Whether the logging outputs returned by `forward` can be summed
- across workers prior to calling `reduce_metrics`. Setting this
- to True will improves distributed training speed.
- """
- return True
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/losses/loss.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/losses/loss.py
deleted file mode 100644
index 99c05d067edac220f9e53080f09f0b40d7dc1e8d..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/losses/loss.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# Copyright (c) Facebook, Inc. All Rights Reserved
-
-import torch
-
-from torch import nn
-
-
-class Loss(object):
- def __call__(self, *args, **kwargs):
- raise NotImplementedError
-
-
-# Dummy Loss for testing.
-class DummyLoss(Loss):
- def __init__(self):
- self.loss = nn.CrossEntropyLoss()
-
- def __call__(self, logits, targets, **kwargs):
- return self.loss(logits, targets)
-
-
-class DummyK400Loss(Loss):
- """dummy k400 loss for MViT."""
- def __init__(self):
- self.loss = nn.CrossEntropyLoss()
-
- def __call__(self, logits, targets, **kwargs):
- return self.loss(
- logits, torch.randint(0, 400, (logits.size(0),), device=logits.device))
-
-
-class CrossEntropy(Loss):
- def __init__(self):
- self.loss = nn.CrossEntropyLoss()
-
- def __call__(self, logits, targets, **kwargs):
- return self.loss(logits.reshape(-1, logits.size(-1)), targets.reshape(-1))
-
-
-class ArgmaxCrossEntropy(Loss):
- def __init__(self):
- self.loss = nn.CrossEntropyLoss()
-
- def __call__(self, logits, targets, **kwargs):
- return self.loss(logits, targets.argmax(dim=1))
-
-
-class BCE(Loss):
- def __init__(self):
- self.loss = nn.BCEWithLogitsLoss()
-
- def __call__(self, logits, targets, **kwargs):
- targets = targets.squeeze(0)
- return self.loss(logits, targets)
-
-
-class NLGLoss(Loss):
- def __init__(self):
- self.loss = nn.CrossEntropyLoss()
-
- def __call__(self, logits, text_label, **kwargs):
- targets = text_label[text_label != -100]
- return self.loss(logits, targets)
-
-
-class MSE(Loss):
- def __init__(self):
- self.loss = nn.MSELoss()
-
- def __call__(self, logits, targets, **kwargs):
- return self.loss(logits, targets)
-
-
-class L1(Loss):
- def __init__(self):
- self.loss = nn.L1Loss()
-
- def __call__(self, logits, targets, **kwargs):
- return self.loss(logits, targets)
-
-
-class SmoothL1(Loss):
- def __init__(self):
- self.loss = nn.SmoothL1Loss()
-
- def __call__(self, logits, targets, **kwargs):
- return self.loss(logits, targets)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/losses/nce.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/losses/nce.py
deleted file mode 100644
index ed7be8d372e371bb0e0d6166f76e01d3466d2306..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/losses/nce.py
+++ /dev/null
@@ -1,156 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-"""
-softmax-based NCE loss, used by this project.
-"""
-
-import torch
-
-from torch import nn
-
-from .loss import Loss
-
-
-class NCE(Loss):
- def __init__(self):
- # TODO (huxu): define temperature.
- self.loss = nn.CrossEntropyLoss()
-
- def __call__(self, align_scores, **kargs):
- # note: we reuse the same shape as cls head in BERT (batch_size, 2)
- # but NCE only needs one logits.
- # (so we drop all weights in the second neg logits.)
- align_scores = align_scores[:, :1]
- # duplicate negative examples
- batch_size = align_scores.size(0) // 2
- pos_scores = align_scores[:batch_size]
- neg_scores = align_scores[batch_size:].view(1, batch_size).repeat(
- batch_size, 1)
- scores = torch.cat([pos_scores, neg_scores], dim=1)
- return self.loss(
- scores,
- torch.zeros(
- (batch_size,),
- dtype=torch.long,
- device=align_scores.device),
- )
-
-
-class T2VContraLoss(Loss):
- """NCE for MM joint space, on softmax text2video matrix.
- """
- def __init__(self):
- # TODO (huxu): define temperature.
- self.loss = nn.CrossEntropyLoss()
-
- def __call__(self, pooled_video, pooled_text, **kargs):
- batch_size = pooled_video.size(0)
- logits = torch.mm(pooled_text, pooled_video.transpose(1, 0))
- targets = torch.arange(
- batch_size,
- dtype=torch.long,
- device=pooled_video.device)
- return self.loss(logits, targets)
-
-
-class V2TContraLoss(Loss):
- """NCE for MM joint space, with softmax on video2text matrix."""
-
- def __init__(self):
- # TODO (huxu): define temperature.
- self.loss = nn.CrossEntropyLoss()
-
- def __call__(self, pooled_video, pooled_text, **kargs):
- batch_size = pooled_video.size(0)
- logits = torch.mm(pooled_video, pooled_text.transpose(1, 0))
- targets = torch.arange(
- batch_size,
- dtype=torch.long,
- device=pooled_video.device)
- return self.loss(logits, targets)
-
-
-class MMContraLoss(Loss):
- def __init__(self):
- self.loss = nn.CrossEntropyLoss()
-
- def __call__(self, pooled_video, pooled_text, **kwargs):
- logits_per_video = pooled_video @ pooled_text.t()
- logits_per_text = pooled_text @ pooled_video.t()
-
- targets = torch.arange(
- pooled_video.size(0),
- dtype=torch.long,
- device=pooled_video.device)
- loss_video = self.loss(logits_per_video, targets)
- loss_text = self.loss(logits_per_text, targets)
- return loss_video + loss_text
-
-
-class MTM(Loss):
- """Combination of MFM and MLM."""
-
- def __init__(self):
- self.loss = nn.CrossEntropyLoss()
-
- def __call__(
- self,
- video_logits,
- text_logits,
- video_label,
- text_label,
- **kwargs
- ):
- text_logits = torch.cat([
- text_logits,
- torch.zeros(
- (text_logits.size(0), 1), device=text_logits.device)
- ], dim=1)
- vt_logits = torch.cat([video_logits, text_logits], dim=0)
- # loss for video.
- video_label = torch.zeros(
- (video_logits.size(0),),
- dtype=torch.long,
- device=video_logits.device
- )
-
- # loss for text.
- text_label = text_label.reshape(-1)
- labels_mask = text_label != -100
- selected_text_label = text_label[labels_mask]
-
- vt_label = torch.cat([video_label, selected_text_label], dim=0)
- return self.loss(vt_logits, vt_label)
-
-
-class MFMMLM(Loss):
- """Combination of MFM and MLM."""
-
- def __init__(self):
- self.loss = nn.CrossEntropyLoss()
-
- def __call__(
- self,
- video_logits,
- text_logits,
- video_label,
- text_label,
- **kwargs
- ):
- # loss for video.
- video_label = torch.zeros(
- (video_logits.size(0),),
- dtype=torch.long,
- device=video_logits.device
- )
- masked_frame_loss = self.loss(video_logits, video_label)
-
- # loss for text.
- text_label = text_label.reshape(-1)
- labels_mask = text_label != -100
- selected_text_label = text_label[labels_mask]
- masked_lm_loss = self.loss(text_logits, selected_text_label)
- return masked_frame_loss + masked_lm_loss
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/models/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/models/__init__.py
deleted file mode 100644
index 825250cd007f5e072b6c9d2376445b955a7aa71e..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/models/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-from .mmfusion import *
-from .transformermodel import *
-from .mmfusionnlg import *
-
-try:
- from .fairseqmmmodel import *
-except ImportError:
- pass
-
-try:
- from .expmmfusion import *
-except ImportError:
- pass
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/models/fairseqmmmodel.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/models/fairseqmmmodel.py
deleted file mode 100644
index b7dd643693dee8cfc20ca77d6cea798d07eaf15a..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/models/fairseqmmmodel.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-from fairseq.models import (
- BaseFairseqModel,
- register_model,
- register_model_architecture
-)
-
-
-@register_model("mmmodel")
-class FairseqMMModel(BaseFairseqModel):
- """a fairseq wrapper of model built by `task`."""
-
- @classmethod
- def build_model(cls, args, task):
- return FairseqMMModel(task.mmtask.model)
-
- def __init__(self, mmmodel):
- super().__init__()
- self.mmmodel = mmmodel
-
- def forward(self, *args, **kwargs):
- return self.mmmodel(*args, **kwargs)
-
- def upgrade_state_dict_named(self, state_dict, name):
-
- super().upgrade_state_dict_named(state_dict, name)
-
- keys_to_delete = []
-
- for key in state_dict:
- if key not in self.state_dict():
- keys_to_delete.append(key)
- for key in keys_to_delete:
- print("[INFO]", key, "not used anymore.")
- del state_dict[key]
-
- # copy any newly defined parameters.
- for key in self.state_dict():
- if key not in state_dict:
- print("[INFO] adding", key)
- state_dict[key] = self.state_dict()[key]
-
-
-# a dummy arch, we config the model.
-@register_model_architecture("mmmodel", "mmarch")
-def mmarch(args):
- pass
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/models/mmfusion.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/models/mmfusion.py
deleted file mode 100644
index 2509e26b67b467c3b18c76630881e66cf334a350..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/models/mmfusion.py
+++ /dev/null
@@ -1,926 +0,0 @@
-# coding=utf-8
-# Copyright 2018 The Google AI Language Team Authors and The HuggingFace Inc. team.
-# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# Copyright (c) Facebook, Inc. All Rights Reserved
-
-
-import torch
-
-from torch import nn
-
-try:
- from transformers import AutoConfig, AutoTokenizer
-except ImportError:
- pass
-
-from . import transformermodel
-
-
-class MMPTModel(nn.Module):
- """An e2e wrapper of inference model.
- """
- @classmethod
- def from_pretrained(cls, config, checkpoint="checkpoint_best.pt"):
- import os
- from ..utils import recursive_config
- from ..tasks import Task
- config = recursive_config(config)
- mmtask = Task.config_task(config)
- checkpoint_path = os.path.join(config.eval.save_path, checkpoint)
- mmtask.build_model(checkpoint=checkpoint_path)
- # TODO(huxu): make the video encoder configurable.
- from ..processors.models.s3dg import S3D
- video_encoder = S3D('pretrained_models/s3d_dict.npy', 512)
- video_encoder.load_state_dict(
- torch.load('pretrained_models/s3d_howto100m.pth'))
- from transformers import AutoTokenizer
- tokenizer = AutoTokenizer.from_pretrained(
- config.dataset.bert_name, use_fast=config.dataset.use_fast
- )
- from ..processors import Aligner
- aligner = Aligner(config.dataset)
- return (
- MMPTModel(config, mmtask.model, video_encoder),
- tokenizer,
- aligner
- )
-
- def __init__(self, config, model, video_encoder, **kwargs):
- super().__init__()
- self.max_video_len = config.dataset.max_video_len
- self.video_encoder = video_encoder
- self.model = model
-
- def forward(self, video_frames, caps, cmasks, return_score=False):
- bsz = video_frames.size(0)
- assert bsz == 1, "only bsz=1 is supported now."
- seq_len = video_frames.size(1)
- video_frames = video_frames.view(-1, *video_frames.size()[2:])
- vfeats = self.video_encoder(video_frames.permute(0, 4, 1, 2, 3))
- vfeats = vfeats['video_embedding']
- vfeats = vfeats.view(bsz, seq_len, vfeats.size(-1))
- padding = torch.zeros(
- bsz, self.max_video_len - seq_len, vfeats.size(-1))
- vfeats = torch.cat([vfeats, padding], dim=1)
- vmasks = torch.cat([
- torch.ones((bsz, seq_len), dtype=torch.bool),
- torch.zeros((bsz, self.max_video_len - seq_len), dtype=torch.bool)
- ],
- dim=1
- )
- output = self.model(caps, cmasks, vfeats, vmasks)
- if return_score:
- output = {"score": torch.bmm(
- output["pooled_video"][:, None, :],
- output["pooled_text"][:, :, None]
- ).squeeze(-1).squeeze(-1)}
- return output
-
-
-class MMFusion(nn.Module):
- """a MMPT wrapper class for MMBert style models.
- TODO: move isolated mask to a subclass.
- """
- def __init__(self, config, **kwargs):
- super().__init__()
- transformer_config = AutoConfig.from_pretrained(
- config.dataset.bert_name)
- self.hidden_size = transformer_config.hidden_size
- self.is_train = False
- if config.dataset.train_path is not None:
- self.is_train = True
- # 0 means no iso; 1-12 means iso up to that layer.
- self.num_hidden_layers = transformer_config.num_hidden_layers
- self.last_iso_layer = 0
- if config.dataset.num_iso_layer is not None:
- self.last_iso_layer = config.dataset.num_iso_layer - 1 + 1
-
- if config.model.mm_encoder_cls is not None:
- mm_encoder_cls = getattr(transformermodel, config.model.mm_encoder_cls)
- model_config = AutoConfig.from_pretrained(config.dataset.bert_name)
- model_config.max_video_len = config.dataset.max_video_len
- # TODO: a general way to add parameter for a model.
- model_config.use_seg_emb = config.model.use_seg_emb
- self.mm_encoder = mm_encoder_cls.from_pretrained(
- config.dataset.bert_name, config=model_config)
- elif config.model.video_encoder_cls is not None\
- and config.model.text_encoder_cls is not None:
- video_encoder_cls = getattr(transformermodel, config.model.video_encoder_cls)
- model_config = AutoConfig.from_pretrained(config.dataset.bert_name)
- model_config.max_video_len = config.dataset.max_video_len
- # TODO: make each model a set of config class.
- if hasattr(model_config, "num_layers"):
- model_config.num_layers = config.model.num_hidden_video_layers
- else:
- model_config.num_hidden_layers = config.model.num_hidden_video_layers
- self.video_encoder = video_encoder_cls.from_pretrained(
- config.dataset.bert_name, config=model_config)
- # exact same NLP model from Huggingface.
- text_encoder_cls = getattr(transformermodel, config.model.text_encoder_cls)
- self.text_encoder = text_encoder_cls.from_pretrained(
- config.dataset.bert_name)
- else:
- raise ValueError("the encoder must be either MM or two backbones.")
-
- def forward(
- self,
- caps,
- cmasks,
- vfeats,
- vmasks,
- **kwargs
- ):
- raise NotImplementedError(
- "Please derive MMFusion module."
- )
-
- def _mm_on_the_fly(
- self,
- cmasks,
- vmasks,
- attention_mask
- ):
- """helper function for mask, seg_ids and token_type_ids."""
- if attention_mask is None:
- attention_mask = self._mm_attention_mask(cmasks, vmasks)
-
- """
- 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
- | first sequence | second sequence |
- """
- token_type_ids = torch.cat(
- [
- torch.zeros(
- (vmasks.size(0), vmasks.size(1) + 2),
- dtype=torch.long,
- device=vmasks.device,
- ),
- torch.ones(
- (cmasks.size(0), cmasks.size(1) - 2),
- dtype=torch.long,
- device=cmasks.device,
- ),
- ],
- dim=1,
- )
- return attention_mask, token_type_ids
-
- def _mm_attention_mask(self, cmasks, vmasks):
- assert cmasks.size(0) == vmasks.size(0), "{}, {}, {}, {}".format(
- str(cmasks.size()),
- str(vmasks.size()),
- str(cmasks.size(0)),
- str(vmasks.size(0)),
- )
-
- mm_mask = torch.cat([cmasks[:, :1], vmasks, cmasks[:, 1:]], dim=1)
- if self.last_iso_layer == 0:
- # hard attention mask.
- return mm_mask
- else:
- # a gpu iso mask; 0 : num_iso_layer is isolated;
- # num_iso_layer: are MM-fused.
- # make an iso layer
- batch_size = cmasks.size(0)
- iso_mask = self._make_iso_mask(batch_size, cmasks, vmasks)
- mm_mask = mm_mask[:, None, :].repeat(1, mm_mask.size(-1), 1)
- iso_mm_masks = []
- # hard attention mask.
- iso_mask = iso_mask[:, None, :, :].repeat(
- 1, self.last_iso_layer, 1, 1)
- iso_mm_masks.append(iso_mask)
- if self.last_iso_layer < self.num_hidden_layers:
- mm_mask = mm_mask[:, None, :, :].repeat(
- 1, self.num_hidden_layers - self.last_iso_layer, 1, 1
- )
- iso_mm_masks.append(mm_mask)
- iso_mm_masks = torch.cat(iso_mm_masks, dim=1)
- return iso_mm_masks
-
- def _make_iso_mask(self, batch_size, cmasks, vmasks):
- cls_self_mask = torch.cat(
- [
- torch.ones(
- (batch_size, 1), dtype=torch.bool, device=cmasks.device),
- torch.zeros(
- (batch_size, cmasks.size(1) + vmasks.size(1) - 1),
- dtype=torch.bool, device=cmasks.device)
- ], dim=1)
-
- iso_video_mask = torch.cat(
- [
- # [CLS] is not used.
- torch.zeros(
- (batch_size, 1), dtype=torch.bool, device=cmasks.device
- ),
- vmasks,
- # assume to be 1.
- cmasks[:, 1:2],
- # 2 means [CLS] + [SEP]
- torch.zeros(
- (batch_size, cmasks.size(1) - 2),
- dtype=torch.bool,
- device=cmasks.device,
- ),
- ],
- dim=1,
- )
- iso_text_mask = torch.cat(
- [
- torch.zeros(
- (batch_size, 2 + vmasks.size(1)),
- dtype=torch.bool,
- device=cmasks.device,
- ), # [CLS] is not used.
- cmasks[:, 2:], # assume to be 1.
- ],
- dim=1,
- )
- cls_self_mask = cls_self_mask[:, None, :]
- iso_video_mask = iso_video_mask[:, None, :].repeat(
- 1, vmasks.size(1) + 1, 1)
- iso_text_mask = iso_text_mask[:, None, :].repeat(
- 1, cmasks.size(1) - 2, 1)
- return torch.cat([cls_self_mask, iso_video_mask, iso_text_mask], dim=1)
-
- def _pooling_vt_layer(
- self,
- layered_sequence_output,
- cmasks,
- vmasks
- ):
- layer_idx = self.last_iso_layer \
- if self.last_iso_layer > 0 else self.num_hidden_layers
- hidden_state = layered_sequence_output[layer_idx]
- # also output pooled_video and pooled_text.
- batch_size = cmasks.size(0)
- # pool the modality.
- text_offset = vmasks.size(1) + 2 # [CLS] + [SEP]
- # video tokens + [SEP]
- video_outputs = hidden_state[:, 1:text_offset]
- video_attention_mask = torch.cat(
- [
- vmasks,
- torch.ones(
- (batch_size, 1), dtype=torch.bool, device=vmasks.device),
- ],
- dim=1,
- )
- assert video_outputs.size(1) == video_attention_mask.size(1)
- pooled_video = torch.sum(
- video_outputs * video_attention_mask.unsqueeze(-1), dim=1
- ) / video_attention_mask.sum(1, keepdim=True)
- # pooled_video = torch.mean(video_outputs[0], dim=1)
-
- # text tokens + [SEP]
- text_attention_mask = cmasks[:, 2:]
- text_outputs = hidden_state[:, text_offset:]
- assert text_outputs.size(1) == text_attention_mask.size(1)
- pooled_text = torch.sum(
- text_outputs * text_attention_mask.unsqueeze(-1), dim=1
- ) / text_attention_mask.sum(1, keepdim=True)
- return pooled_video, pooled_text
-
-
-class MMFusionMFMMLM(MMFusion):
- """forward function for MFM and MLM."""
- def forward(
- self,
- caps,
- cmasks,
- vfeats,
- vmasks,
- attention_mask=None,
- video_label=None,
- text_label=None,
- **kwargs
- ):
- output_hidden_states = False if self.is_train else True
-
- target_vfeats, non_masked_frame_mask = None, None
- if video_label is not None:
- target_vfeats = vfeats.masked_select(
- video_label.unsqueeze(-1)).view(
- -1, vfeats.size(-1)
- )
- # mask video token.
- vfeats[video_label] = 0.0
- non_masked_frame_mask = vmasks.clone()
- non_masked_frame_mask[video_label] = False
-
- attention_mask, token_type_ids = self._mm_on_the_fly(
- cmasks, vmasks, attention_mask)
-
- outputs = self.mm_encoder(
- input_ids=caps,
- input_video_embeds=vfeats,
- attention_mask=attention_mask,
- token_type_ids=token_type_ids,
- masked_frame_labels=video_label,
- target_video_hidden_states=target_vfeats,
- non_masked_frame_mask=non_masked_frame_mask,
- masked_lm_labels=text_label,
- output_hidden_states=output_hidden_states,
- )
-
- video_logits, text_logits = outputs[0], outputs[1]
-
- if self.is_train: # return earlier for training.
- return {
- "video_logits": video_logits,
- "text_logits": text_logits,
- }
-
- pooled_video, pooled_text = self._pooling_vt_layer(
- outputs[2], cmasks, vmasks)
- return {"pooled_video": pooled_video, "pooled_text": pooled_text}
-
-
-class MMFusionMTM(MMFusionMFMMLM):
- def __init__(self, config, **kwargs):
- super().__init__(config)
- """
- For reproducibility:
- self.mm_encoder will be initialized then discarded.
- """
- from .transformermodel import MMBertForMTM
- model_config = AutoConfig.from_pretrained(config.dataset.bert_name)
- model_config.max_video_len = config.dataset.max_video_len
- model_config.use_seg_emb = config.model.use_seg_emb
- self.mm_encoder = MMBertForMTM.from_pretrained(
- config.dataset.bert_name, config=model_config)
-
-
-class MMFusionShare(MMFusion):
- """A retrival wrapper using mm_encoder as both video/text backbone.
- TODO: move formally.
- """
- def forward(
- self,
- caps,
- cmasks,
- vfeats,
- vmasks,
- attention_mask=None,
- video_label=None,
- text_label=None,
- output_hidden_states=False,
- **kwargs
- ):
- pooled_video = self.forward_video(
- vfeats,
- vmasks,
- caps,
- cmasks,
- output_hidden_states
- )
-
- pooled_text = self.forward_text(
- caps,
- cmasks,
- output_hidden_states
- )
-
- return {"pooled_video": pooled_video, "pooled_text": pooled_text}
-
- def forward_video(
- self,
- vfeats,
- vmasks,
- caps,
- cmasks,
- output_hidden_states=False,
- **kwargs
- ):
- input_ids = caps[:, :2]
-
- attention_mask = torch.cat([
- cmasks[:, :1],
- vmasks,
- cmasks[:, 1:2]
- ], dim=1)
-
- token_type_ids = torch.zeros(
- (vmasks.size(0), vmasks.size(1) + 2),
- dtype=torch.long,
- device=vmasks.device)
-
- outputs = self.mm_encoder(
- input_ids=input_ids,
- input_video_embeds=vfeats,
- attention_mask=attention_mask,
- token_type_ids=token_type_ids,
- output_hidden_states=True
- )
- video_outputs = outputs[0]
-
- if output_hidden_states:
- return video_outputs
-
- batch_size = cmasks.size(0)
-
- video_attention_mask = torch.cat(
- [
- torch.zeros(
- (batch_size, 1), dtype=torch.bool, device=vmasks.device),
- vmasks,
- torch.ones(
- (batch_size, 1), dtype=torch.bool, device=vmasks.device),
- ],
- dim=1,
- )
- assert video_outputs.size(1) == video_attention_mask.size(1)
-
- video_attention_mask = video_attention_mask.type(video_outputs.dtype) \
- / video_attention_mask.sum(1, keepdim=True)
-
- pooled_video = torch.bmm(
- video_outputs.transpose(2, 1),
- video_attention_mask.unsqueeze(2)
- ).squeeze(-1)
- return pooled_video # video_outputs
-
- def forward_text(
- self,
- caps,
- cmasks,
- output_hidden_states=False,
- **kwargs
- ):
- input_ids = torch.cat([
- caps[:, :1], caps[:, 2:],
- ], dim=1)
-
- attention_mask = torch.cat([
- cmasks[:, :1],
- cmasks[:, 2:]
- ], dim=1)
-
- token_type_ids = torch.cat([
- torch.zeros(
- (cmasks.size(0), 1),
- dtype=torch.long,
- device=cmasks.device),
- torch.ones(
- (cmasks.size(0), cmasks.size(1) - 2),
- dtype=torch.long,
- device=cmasks.device)
- ], dim=1)
-
- outputs = self.mm_encoder(
- input_ids=input_ids,
- input_video_embeds=None,
- attention_mask=attention_mask,
- token_type_ids=token_type_ids,
- output_hidden_states=True
- )
- text_outputs = outputs[0]
-
- if output_hidden_states:
- return text_outputs
-
- batch_size = caps.size(0)
- # text tokens + [SEP]
- text_attention_mask = torch.cat([
- torch.zeros(
- (batch_size, 1), dtype=torch.bool, device=cmasks.device),
- cmasks[:, 2:]
- ], dim=1)
-
- assert text_outputs.size(1) == text_attention_mask.size(1)
-
- text_attention_mask = text_attention_mask.type(text_outputs.dtype) \
- / text_attention_mask.sum(1, keepdim=True)
-
- pooled_text = torch.bmm(
- text_outputs.transpose(2, 1),
- text_attention_mask.unsqueeze(2)
- ).squeeze(-1)
- return pooled_text # text_outputs
-
-
-class MMFusionSeparate(MMFusionShare):
- def forward_video(
- self,
- vfeats,
- vmasks,
- caps,
- cmasks,
- output_hidden_states=False,
- **kwargs
- ):
- input_ids = caps[:, :2]
-
- attention_mask = torch.cat([
- cmasks[:, :1],
- vmasks,
- cmasks[:, 1:2]
- ], dim=1)
-
- token_type_ids = torch.zeros(
- (vmasks.size(0), vmasks.size(1) + 2),
- dtype=torch.long,
- device=vmasks.device)
-
- outputs = self.video_encoder(
- input_ids=input_ids,
- input_video_embeds=vfeats,
- attention_mask=attention_mask,
- token_type_ids=token_type_ids,
- output_hidden_states=True
- )
- video_outputs = outputs[0]
-
- if output_hidden_states:
- return video_outputs
-
- batch_size = cmasks.size(0)
-
- video_attention_mask = torch.cat(
- [
- torch.zeros(
- (batch_size, 1), dtype=torch.bool, device=vmasks.device),
- vmasks,
- torch.ones(
- (batch_size, 1), dtype=torch.bool, device=vmasks.device),
- ],
- dim=1,
- )
- assert video_outputs.size(1) == video_attention_mask.size(1)
-
- video_attention_mask = video_attention_mask.type(video_outputs.dtype) \
- / video_attention_mask.sum(1, keepdim=True)
-
- pooled_video = torch.bmm(
- video_outputs.transpose(2, 1),
- video_attention_mask.unsqueeze(2)
- ).squeeze(-1)
- return pooled_video # video_outputs
-
- def forward_text(
- self,
- caps,
- cmasks,
- output_hidden_states=False,
- **kwargs
- ):
- input_ids = torch.cat([
- caps[:, :1], caps[:, 2:],
- ], dim=1)
-
- attention_mask = torch.cat([
- cmasks[:, :1],
- cmasks[:, 2:]
- ], dim=1)
- # different from sharing, we use all-0 type.
- token_type_ids = torch.zeros(
- (cmasks.size(0), cmasks.size(1) - 1),
- dtype=torch.long,
- device=cmasks.device)
-
- outputs = self.text_encoder(
- input_ids=input_ids,
- attention_mask=attention_mask,
- token_type_ids=token_type_ids,
- output_hidden_states=True
- )
- text_outputs = outputs[0]
-
- if output_hidden_states:
- return text_outputs
-
- batch_size = caps.size(0)
- # text tokens + [SEP]
- text_attention_mask = torch.cat([
- torch.zeros(
- (batch_size, 1), dtype=torch.bool, device=cmasks.device),
- cmasks[:, 2:]
- ], dim=1)
-
- assert text_outputs.size(1) == text_attention_mask.size(1)
-
- text_attention_mask = text_attention_mask.type(text_outputs.dtype) \
- / text_attention_mask.sum(1, keepdim=True)
-
- pooled_text = torch.bmm(
- text_outputs.transpose(2, 1),
- text_attention_mask.unsqueeze(2)
- ).squeeze(-1)
- return pooled_text # text_outputs
-
-
-class MMFusionJoint(MMFusion):
- """fine-tuning wrapper for retrival task."""
-
- def forward(
- self,
- caps,
- cmasks,
- vfeats,
- vmasks,
- attention_mask=None,
- video_label=None,
- text_label=None,
- **kwargs
- ):
- # TODO (huxu): other ways to do negative examples; move the following
- # into your criterion forward.
- output_hidden_states = True
-
- attention_mask, token_type_ids = self._mm_on_the_fly(
- cmasks, vmasks, attention_mask)
-
- separate_forward_split = (
- None if self.is_train else vmasks.size(1) + 2
- ) # [CLS] + [SEP]
-
- outputs = self.mm_encoder(
- input_ids=caps,
- input_video_embeds=vfeats,
- attention_mask=attention_mask,
- token_type_ids=token_type_ids,
- output_hidden_states=output_hidden_states,
- separate_forward_split=separate_forward_split,
- )
-
- pooled_video, pooled_text = self._pooling_vt_layer(
- outputs[2], cmasks, vmasks)
- return {"pooled_video": pooled_video, "pooled_text": pooled_text}
-
-
-class MMFusionActionSegmentation(MMFusion):
- """Fine-tuning wrapper for action segmentation.
- TODO: rename this for VLM.
- """
- def forward(
- self,
- caps,
- cmasks,
- vfeats,
- vmasks,
- attention_mask=None,
- **kwargs
- ):
- # ActionLocalization assume of batch_size=1, squeeze it.
- caps = caps.view(-1, caps.size(-1))
- cmasks = cmasks.view(-1, cmasks.size(-1))
- vfeats = vfeats.view(-1, vfeats.size(2), vfeats.size(3))
- vmasks = vmasks.view(-1, vmasks.size(-1))
-
- # this may not cover all shapes of attention_mask.
- attention_mask = attention_mask.view(
- -1, attention_mask.size(2), attention_mask.size(3)) \
- if attention_mask is not None else None
-
- # TODO (huxu): other ways to do negative examples; move the following
- # into your criterion forward.
- output_hidden_states = True
-
- # video forwarding, text is dummy; never use attention_mask.
- attention_mask, token_type_ids = self._mm_on_the_fly(
- cmasks, vmasks, attention_mask)
-
- logits = self.mm_encoder(
- input_ids=caps,
- input_video_embeds=vfeats,
- attention_mask=attention_mask,
- token_type_ids=token_type_ids,
- output_hidden_states=output_hidden_states,
- )
- return {"logits": logits[0][:, 1:vmasks.size(1)+1]}
-
-
-class MMFusionActionLocalization(MMFusion):
- """fine-tuning model for retrival task."""
-
- def __init__(self, config, **kwargs):
- super().__init__(config)
- tokenizer = AutoTokenizer.from_pretrained(
- config.dataset.bert_name)
- self.cls_token_id = tokenizer.cls_token_id
- self.sep_token_id = tokenizer.sep_token_id
- self.pad_token_id = tokenizer.pad_token_id
-
- def forward(
- self,
- caps,
- cmasks,
- vfeats,
- vmasks,
- attention_mask=None,
- **kwargs
- ):
- # ActionLocalization assume of batch_size=1, squeeze it.
- caps = caps.squeeze(0)
- cmasks = cmasks.squeeze(0)
- vfeats = vfeats.squeeze(0)
- vmasks = vmasks.squeeze(0)
- attention_mask = attention_mask.squeeze(0) if attention_mask is not None else None
-
- # TODO (huxu): other ways to do negative examples; move the following
- # into your criterion forward.
- output_hidden_states = True
-
- # a len1 dummy video token.
- dummy_vfeats = torch.zeros(
- (caps.size(0), 1, vfeats.size(-1)), device=vfeats.device, dtype=vfeats.dtype)
- dummy_vmasks = torch.ones(
- (caps.size(0), 1), dtype=torch.bool,
- device=vfeats.device)
-
- dummy_caps = torch.LongTensor(
- [[self.cls_token_id, self.sep_token_id,
- self.pad_token_id, self.sep_token_id]],
- ).to(caps.device).repeat(vfeats.size(0), 1)
- dummy_cmasks = torch.BoolTensor(
- [[0, 1, 0, 1]] # pad are valid for attention.
- ).to(caps.device).repeat(vfeats.size(0), 1)
-
- # video forwarding, text is dummy; never use attention_mask.
- attention_mask, token_type_ids = self._mm_on_the_fly(
- dummy_cmasks, vmasks, None)
-
- outputs = self.mm_encoder(
- input_ids=dummy_caps,
- input_video_embeds=vfeats,
- attention_mask=attention_mask,
- token_type_ids=token_type_ids,
- output_hidden_states=output_hidden_states,
- )
-
- layer_idx = self.last_iso_layer \
- if self.last_iso_layer > 0 else self.num_hidden_layers
-
- video_seq = outputs[2][layer_idx][:, 1:vmasks.size(1)+1].masked_select(
- vmasks.unsqueeze(-1)
- ).view(-1, self.hidden_size)
-
- # text forwarding, video is dummy
- attention_mask, token_type_ids = self._mm_on_the_fly(
- cmasks, dummy_vmasks, None)
-
- outputs = self.mm_encoder(
- input_ids=caps,
- input_video_embeds=dummy_vfeats,
- attention_mask=attention_mask,
- token_type_ids=token_type_ids,
- output_hidden_states=output_hidden_states,
- )
-
- _, pooled_text = self._pooling_vt_layer(
- outputs[2], cmasks, dummy_vmasks)
- # this line is not right.
- logits = torch.mm(video_seq, pooled_text.transpose(1, 0))
- return {"logits": logits}
-
-
-# --------------- MMFusionSeparate for end tasks ---------------
-
-class MMFusionSeparateActionSegmentation(MMFusionSeparate):
- """Fine-tuning wrapper for action segmentation."""
- def forward(
- self,
- caps,
- cmasks,
- vfeats,
- vmasks,
- attention_mask=None,
- **kwargs
- ):
- # ActionLocalization assume of batch_size=1, squeeze it.
- caps = caps.view(-1, caps.size(-1))
- cmasks = cmasks.view(-1, cmasks.size(-1))
- vfeats = vfeats.view(-1, vfeats.size(2), vfeats.size(3))
- vmasks = vmasks.view(-1, vmasks.size(-1))
- logits = self.forward_video(
- vfeats,
- vmasks,
- caps,
- cmasks,
- output_hidden_states=True
- )
- return {"logits": logits[:, 1:vmasks.size(1)+1]}
-
-
-class MMFusionSeparateActionLocalization(MMFusionSeparate):
- def __init__(self, config, **kwargs):
- super().__init__(config)
- tokenizer = AutoTokenizer.from_pretrained(
- config.dataset.bert_name)
- self.cls_token_id = tokenizer.cls_token_id
- self.sep_token_id = tokenizer.sep_token_id
- self.pad_token_id = tokenizer.pad_token_id
-
- def forward(
- self,
- caps,
- cmasks,
- vfeats,
- vmasks,
- **kwargs
- ):
- # ActionLocalization assume of batch_size=1, squeeze it.
- caps = caps.squeeze(0)
- cmasks = cmasks.squeeze(0)
- vfeats = vfeats.squeeze(0)
- vmasks = vmasks.squeeze(0)
-
- # TODO (huxu): other ways to do negative examples; move the following
- # into your criterion forward.
- dummy_caps = torch.LongTensor(
- [[self.cls_token_id, self.sep_token_id,
- self.pad_token_id, self.sep_token_id]],
- ).to(caps.device).repeat(vfeats.size(0), 1)
- dummy_cmasks = torch.BoolTensor(
- [[0, 1, 0, 1]] # pad are valid for attention.
- ).to(caps.device).repeat(vfeats.size(0), 1)
-
- outputs = self.forward_video(
- vfeats,
- vmasks,
- dummy_caps,
- dummy_cmasks,
- output_hidden_states=True
- )
-
- video_seq = outputs[:, 1:vmasks.size(1)+1].masked_select(
- vmasks.unsqueeze(-1)
- ).view(-1, self.hidden_size)
-
- pooled_text = self.forward_text(
- caps,
- cmasks,
- output_hidden_states=False
- )
-
- # this line is not right.
- logits = torch.mm(video_seq, pooled_text.transpose(1, 0))
- return {"logits": logits}
-
-
-class MMFusionShareActionLocalization(MMFusionShare):
- def __init__(self, config, **kwargs):
- super().__init__(config)
- tokenizer = AutoTokenizer.from_pretrained(
- config.dataset.bert_name)
- self.cls_token_id = tokenizer.cls_token_id
- self.sep_token_id = tokenizer.sep_token_id
- self.pad_token_id = tokenizer.pad_token_id
-
- def forward(
- self,
- caps,
- cmasks,
- vfeats,
- vmasks,
- **kwargs
- ):
- # ActionLocalization assume of batch_size=1, squeeze it.
- caps = caps.squeeze(0)
- cmasks = cmasks.squeeze(0)
- vfeats = vfeats.squeeze(0)
- vmasks = vmasks.squeeze(0)
-
- # TODO (huxu): other ways to do negative examples; move the following
- # into your criterion forward.
- dummy_caps = torch.LongTensor(
- [[self.cls_token_id, self.sep_token_id,
- self.pad_token_id, self.sep_token_id]],
- ).to(caps.device).repeat(vfeats.size(0), 1)
- dummy_cmasks = torch.BoolTensor(
- [[0, 1, 0, 1]] # pad are valid for attention.
- ).to(caps.device).repeat(vfeats.size(0), 1)
-
- outputs = self.forward_video(
- vfeats,
- vmasks,
- dummy_caps,
- dummy_cmasks,
- output_hidden_states=True
- )
-
- video_seq = outputs[:, 1:vmasks.size(1)+1].masked_select(
- vmasks.unsqueeze(-1)
- ).view(-1, self.hidden_size)
-
- pooled_text = self.forward_text(
- caps,
- cmasks,
- output_hidden_states=False
- )
-
- # this line is not right.
- logits = torch.mm(video_seq, pooled_text.transpose(1, 0))
- return {"logits": logits}
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/models/mmfusionnlg.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/models/mmfusionnlg.py
deleted file mode 100644
index 9207e77dab3025d7a26efcce0795183de1d34fc7..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/MMPT/mmpt/models/mmfusionnlg.py
+++ /dev/null
@@ -1,999 +0,0 @@
-# coding=utf-8
-# Copyright 2018 The Google AI Language Team Authors, Facebook AI Research authors and The HuggingFace Inc. team.
-# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# Copyright (c) Facebook, Inc. All Rights Reserved
-
-
-import torch
-
-from torch.nn import functional as F
-
-from typing import Optional, Iterable
-
-try:
- from transformers import BertPreTrainedModel
- from transformers.modeling_bert import BertOnlyMLMHead
-
- from transformers.file_utils import ModelOutput
- from transformers.modeling_outputs import CausalLMOutput
- from transformers.generation_utils import (
- BeamHypotheses,
- top_k_top_p_filtering
- )
-except ImportError:
- pass
-
-from .mmfusion import MMFusion
-from .transformermodel import MMBertModel
-from ..modules import VideoTokenMLP
-
-
-class MMFusionNLG(MMFusion):
- def __init__(self, config, **kwargs):
- super().__init__(config)
- if config.model.max_decode_length is not None:
- self.max_length = min(
- config.model.max_decode_length,
- config.dataset.max_len - config.dataset.max_video_len - 3
- )
- else:
- self.max_length = \
- config.dataset.max_len - config.dataset.max_video_len - 3
- self.gen_param = config.gen_param if config.gen_param is not None \
- else {}
-
- def forward(
- self,
- caps,
- cmasks,
- vfeats,
- vmasks,
- attention_mask,
- video_label=None,
- text_label=None,
- **kwargs
- ):
- """use pre-trained LM header for generation."""
- attention_mask, token_type_ids = self._mm_on_the_fly(
- cmasks, vmasks, attention_mask)
-
- outputs = self.mm_encoder(
- input_ids=caps,
- input_video_embeds=vfeats,
- attention_mask=attention_mask,
- token_type_ids=token_type_ids,
- masked_lm_labels=text_label,
- )
- return {"logits": outputs[0]}
-
- @torch.no_grad()
- def generate(
- self,
- caps, cmasks, vfeats, vmasks,
- attention_mask=None,
- bos_token_id=None,
- eos_token_id=None,
- **kwargs
- ):
- # a simplified interface from
- # https://huggingface.co/transformers/v3.4.0/_modules/transformers/generation_utils.html#GenerationMixin.generate
-
- # caps now only have
- # [CLS], [SEP] (for video) and [CLS] (as bos_token)
- assert caps.size(1) == 3
-
- attention_mask, token_type_ids = self._mm_on_the_fly(
- cmasks, vmasks, attention_mask)
-
- output = self.mm_encoder.generate(
- input_ids=caps,
- input_video_embeds=vfeats,
- attention_mask=attention_mask,
- token_type_ids=token_type_ids,
- bos_token_id=bos_token_id,
- eos_token_id=eos_token_id,
- max_length=self.max_length,
- **self.gen_param
- )
- return output
-
-
-class MMBertForNLG(BertPreTrainedModel):
- def __init__(self, config):
- super().__init__(config)
- self.bert = MMBertModel(config)
- self.videomlp = VideoTokenMLP(config)
- # we do not use `BertGenerationOnlyLMHead`
- # because we can reuse pretraining.
- self.cls = BertOnlyMLMHead(config)
- self.hidden_size = config.hidden_size
- self.init_weights()
-
- def get_output_embeddings(self):
- return self.cls.predictions.decoder
-
- def forward(
- self,
- input_ids=None,
- input_video_embeds=None,
- attention_mask=None,
- token_type_ids=None,
- position_ids=None,
- head_mask=None,
- inputs_embeds=None,
- masked_lm_labels=None,
- output_attentions=None,
- output_hidden_states=None,
- return_dict=None,
- ):
- # similar to MMBertForMFMMLM without MFM.
- video_tokens = self.videomlp(input_video_embeds)
- outputs = self.bert(
- input_ids,
- video_tokens,
- attention_mask=attention_mask,
- token_type_ids=token_type_ids,
- position_ids=position_ids,
- head_mask=head_mask,
- inputs_embeds=inputs_embeds,
- output_attentions=output_attentions,
- output_hidden_states=output_hidden_states,
- return_dict=return_dict,
- )
-
- sequence_output = outputs[0]
-
- prediction_scores = None
- if masked_lm_labels is not None:
- text_offset = input_video_embeds.size(1) + 1 # [CLS]
- # recover caps format: [CLS] [SEP] text [SEP]
- text_sequence_output = torch.cat(
- [sequence_output[:, :1], sequence_output[:, text_offset:]],
- dim=1
- )
-
- # only compute select tokens to training to speed up.
- hidden_size = text_sequence_output.size(-1)
- # masked_lm_labels = masked_lm_labels.reshape(-1)
- labels_mask = masked_lm_labels != -100
-
- selected_text_output = text_sequence_output.masked_select(
- labels_mask.unsqueeze(-1)
- ).view(-1, hidden_size)
- prediction_scores = self.cls(selected_text_output)
-
- if not return_dict:
- output = (
- prediction_scores,
- ) + outputs[2:]
- return output
-
- # for generation.
- text_offset = input_video_embeds.size(1) + 2 # [CLS]
- text_sequence_output = sequence_output[:, text_offset:]
- prediction_scores = self.cls(text_sequence_output)
- return CausalLMOutput(
- loss=None,
- logits=prediction_scores,
- )
-
- def prepare_inputs_for_generation(
- self,
- input_ids,
- input_video_embeds,
- attention_mask=None,
- token_type_ids=None,
- **model_kwargs
- ):
- # must return a dictionary.
- seq_len = input_ids.size(1) + input_video_embeds.size(1)
- if attention_mask is not None:
- if len(attention_mask.size()) == 4:
- attention_mask = attention_mask[:, :, :seq_len, :seq_len]
- elif len(attention_mask.size()) == 3:
- attention_mask = attention_mask[:, :seq_len, :seq_len]
- else:
- attention_mask = attention_mask[:, :seq_len]
- if token_type_ids is not None:
- token_type_ids = token_type_ids[:, :seq_len]
-
- return {
- "input_ids": input_ids,
- "input_video_embeds": input_video_embeds,
- "attention_mask": attention_mask,
- "token_type_ids": token_type_ids,
- }
-
- @torch.no_grad()
- def generate(
- self,
- input_ids: Optional[torch.LongTensor] = None,
- decoder_input_ids: Optional[torch.LongTensor] = None,
- max_length: Optional[int] = None,
- min_length: Optional[int] = None,
- do_sample: Optional[bool] = None,
- early_stopping: Optional[bool] = None,
- num_beams: Optional[int] = None,
- temperature: Optional[float] = None,
- top_k: Optional[int] = None,
- top_p: Optional[float] = None,
- repetition_penalty: Optional[float] = None,
- bad_words_ids: Optional[Iterable[int]] = None,
- bos_token_id: Optional[int] = None,
- pad_token_id: Optional[int] = None,
- eos_token_id: Optional[int] = None,
- length_penalty: Optional[float] = None,
- no_repeat_ngram_size: Optional[int] = None,
- num_return_sequences: Optional[int] = None,
- attention_mask: Optional[torch.LongTensor] = None,
- decoder_start_token_id: Optional[int] = None,
- use_cache: Optional[bool] = None,
- **model_kwargs
- ) -> torch.LongTensor:
- r"""
- Generates sequences for models with a language modeling head. The method currently supports greedy decoding,
- beam-search decoding, sampling with temperature, sampling with top-k or nucleus sampling.
- Adapted in part from `Facebook's XLM beam search code
-
-
-
- -FSDP currently has several limitations compared to fairseq's default DDP backend (PyTorch DDP): -* while FSDP is full compatible with pointwise Optimizers (e.g., Adam, AdamW, Adadelta, Adamax, SGD, etc.), it is not currently compatible with non-pointwise Optimizers (e.g., Adagrad, Adafactor, LAMB, etc.) -* FSDP depends on flattening the parameters, so models that currently require `--fp16-no-flatten-grads` may not be supported - -See the [fairscale docs](https://fairscale.readthedocs.io/en/latest/api/nn/fsdp_tips.html) for a more detailed -explanation of these and other limitations. - -
-
-
-
-See the [fairscale docs](https://fairscale.readthedocs.io/en/latest/api/nn/fsdp_tips.html) for a more detailed
-explanation of how FSDP works.
-
-
- -``` -(...) -2021-03-08 12:29:51 | INFO | fairseq_cli.train | num. model params: 13,110,865,920 (num. trained: 13,110,865,920) -(...) -2021-03-08 12:29:51 | INFO | fairseq_cli.train | training on 1 devices (GPUs/TPUs) -2021-03-08 12:29:51 | INFO | fairseq_cli.train | max tokens per GPU = None and batch size per GPU = 8 -(...) -Adam Optimizer #0 is created with AVX2 arithmetic capability. -Config: alpha=0.000100, betas=(0.900000, 0.980000), weight_decay=0.000000, adam_w=1 -(...) -2021-03-08 12:31:36 | INFO | train_inner | {"epoch": 1, "update": 0.0, "loss": "16.475", "ppl": "91120.8", "wps": "0", "ups": "0", "wpb": "16384", "bsz": "8", "num_updates": "1", "lr": "2e-05", "gnorm": "20.751", "loss_scale": "4", "train_wall": "99", "gb_free": "9.3", "wall": "105"} -2021-03-08 12:32:33 | INFO | train_inner | {"epoch": 1, "update": 0.0, "loss": "16.446", "ppl": "89281.6", "wps": "288.7", "ups": "0.02", "wpb": "16384", "bsz": "8", "num_updates": "2", "lr": "4e-05", "gnorm": "19.777", "loss_scale": "4", "train_wall": "57", "gb_free": "9.3", "wall": "161"} -2021-03-08 12:33:12 | INFO | fairseq.trainer | NOTE: gradient overflow detected, ignoring gradient, setting loss scale to: 2.0 -2021-03-08 12:33:51 | INFO | fairseq.trainer | NOTE: gradient overflow detected, ignoring gradient, setting loss scale to: 1.0 -2021-03-08 12:34:45 | INFO | train_inner | {"epoch": 1, "update": 0.001, "loss": "25.22", "ppl": "3.90691e+07", "wps": "123.4", "ups": "0.01", "wpb": "16384", "bsz": "8", "num_updates": "3", "lr": "6e-05", "gnorm": "131.281", "loss_scale": "1", "train_wall": "133", "gb_free": "9.3", "wall": "294"} -2021-03-08 12:35:43 | INFO | train_inner | {"epoch": 1, "update": 0.001, "loss": "18.079", "ppl": "276809", "wps": "285.5", "ups": "0.02", "wpb": "16384", "bsz": "8", "num_updates": "4", "lr": "8e-05", "gnorm": "13.776", "loss_scale": "1", "train_wall": "57", "gb_free": "9.3", "wall": "351"} -2021-03-08 12:36:35 | INFO | train_inner | {"epoch": 1, "update": 0.001, "loss": "23.729", "ppl": "1.39088e+07", "wps": "316.7", "ups": "0.02", "wpb": "16384", "bsz": "8", "num_updates": "5", "lr": "0.0001", "gnorm": "72.774", "loss_scale": "1", "train_wall": "52", "gb_free": "9.3", "wall": "403"} -2021-03-08 12:37:28 | INFO | train_inner | {"epoch": 1, "update": 0.001, "loss": "20.429", "ppl": "1.41203e+06", "wps": "307.6", "ups": "0.02", "wpb": "16384", "bsz": "8", "num_updates": "6", "lr": "8e-05", "gnorm": "60.846", "loss_scale": "1", "train_wall": "53", "gb_free": "9.3", "wall": "456"} -2021-03-08 12:38:27 | INFO | train_inner | {"epoch": 1, "update": 0.001, "loss": "18.965", "ppl": "511684", "wps": "279.4", "ups": "0.02", "wpb": "16384", "bsz": "8", "num_updates": "7", "lr": "6e-05", "gnorm": "22.687", "loss_scale": "1", "train_wall": "59", "gb_free": "9.3", "wall": "515"} -2021-03-08 12:39:18 | INFO | train_inner | {"epoch": 1, "update": 0.001, "loss": "18.345", "ppl": "332887", "wps": "319.1", "ups": "0.02", "wpb": "16384", "bsz": "8", "num_updates": "8", "lr": "4e-05", "gnorm": "8.451", "loss_scale": "1", "train_wall": "51", "gb_free": "9.3", "wall": "566"} -2021-03-08 12:40:11 | INFO | train_inner | {"epoch": 1, "update": 0.002, "loss": "18.262", "ppl": "314336", "wps": "305.9", "ups": "0.02", "wpb": "16384", "bsz": "8", "num_updates": "9", "lr": "2e-05", "gnorm": "6.457", "loss_scale": "1", "train_wall": "54", "gb_free": "9.3", "wall": "620"} -2021-03-08 12:41:04 | INFO | train_inner | {"epoch": 1, "update": 0.002, "loss": "17.556", "ppl": "192686", "wps": "311.8", "ups": "0.02", "wpb": "16384", "bsz": "8", "num_updates": "10", "lr": "0", "gnorm": "5.796", "loss_scale": "1", "train_wall": "53", "gb_free": "9.3", "wall": "673"} -2021-03-08 12:41:04 | INFO | fairseq_cli.train | Stopping training due to num_updates: 10 >= max_update: 10 -2021-03-08 12:41:04 | INFO | fairseq_cli.train | begin validation on "valid" subset -2021-03-08 12:43:15 | INFO | valid | {"epoch": 1, "valid_loss": "17.953", "valid_ppl": "253807", "valid_wps": "1868.4", "valid_wpb": "15400.2", "valid_bsz": "7.6", "valid_num_updates": "10"} -2021-03-08 12:43:15 | INFO | fairseq_cli.train | end of epoch 1 (average epoch stats below) -2021-03-08 12:43:15 | INFO | train | {"epoch": 1, "train_loss": "19.351", "train_ppl": "668509", "train_wps": "210.9", "train_ups": "0.01", "train_wpb": "16384", "train_bsz": "8", "train_num_updates": "10", "train_lr": "0", "train_gnorm": "36.26", "train_loss_scale": "1", "train_train_wall": "667", "train_gb_free": "9.3", "train_wall": "804"} -2021-03-08 12:43:15 | INFO | fairseq_cli.train | done training in 798.6 seconds -``` - -
- -``` -(...) -2021-03-08 18:04:09 | INFO | fairseq_cli.train | num. model params: 13,110,865,920 (num. trained: 13,110,865,920) -(...) -2021-03-08 18:04:09 | INFO | fairseq_cli.train | training on 8 devices (GPUs/TPUs) -2021-03-08 18:04:09 | INFO | fairseq_cli.train | max tokens per GPU = None and batch size per GPU = 8 -(...) -Adam Optimizer #0 is created with AVX2 arithmetic capability. -Config: alpha=0.000100, betas=(0.900000, 0.980000), weight_decay=0.000000, adam_w=1 -(...) -2021-03-08 18:05:06 | INFO | train_inner | {"epoch": 1, "update": 0.001, "loss": "16.408", "ppl": "86945.6", "wps": "0", "ups": "0", "wpb": "131072", "bsz": "64", "num_updates": "1", "lr": "2e-05", "gnorm": "18.27", "loss_scale": "4", "train_wall": "47", "gb_free": "9.3", "wall": "56"} -2021-03-08 18:05:45 | INFO | train_inner | {"epoch": 1, "update": 0.002, "loss": "16.352", "ppl": "83644.3", "wps": "3283.4", "ups": "0.03", "wpb": "131072", "bsz": "64", "num_updates": "2", "lr": "4e-05", "gnorm": "18.411", "loss_scale": "4", "train_wall": "40", "gb_free": "9.3", "wall": "96"} -2021-03-08 18:06:21 | INFO | fairseq.trainer | NOTE: gradient overflow detected, ignoring gradient, setting loss scale to: 2.0 -2021-03-08 18:06:56 | INFO | fairseq.trainer | NOTE: gradient overflow detected, ignoring gradient, setting loss scale to: 1.0 -2021-03-08 18:07:37 | INFO | train_inner | {"epoch": 1, "update": 0.006, "loss": "23.682", "ppl": "1.34537e+07", "wps": "1176.6", "ups": "0.01", "wpb": "131072", "bsz": "64", "num_updates": "3", "lr": "6e-05", "gnorm": "119.682", "loss_scale": "1", "train_wall": "111", "gb_free": "9.3", "wall": "208"} -2021-03-08 18:08:18 | INFO | train_inner | {"epoch": 1, "update": 0.007, "loss": "18.988", "ppl": "519921", "wps": "3189.1", "ups": "0.02", "wpb": "131072", "bsz": "64", "num_updates": "4", "lr": "8e-05", "gnorm": "14.934", "loss_scale": "1", "train_wall": "41", "gb_free": "9.3", "wall": "249"} -2021-03-08 18:08:59 | INFO | train_inner | {"epoch": 1, "update": 0.008, "loss": "20.08", "ppl": "1.10798e+06", "wps": "3223.1", "ups": "0.02", "wpb": "131072", "bsz": "64", "num_updates": "5", "lr": "0.0001", "gnorm": "59.92", "loss_scale": "1", "train_wall": "41", "gb_free": "9.3", "wall": "289"} -2021-03-08 18:09:39 | INFO | train_inner | {"epoch": 1, "update": 0.009, "loss": "18.323", "ppl": "327980", "wps": "3256.6", "ups": "0.02", "wpb": "131072", "bsz": "64", "num_updates": "6", "lr": "8e-05", "gnorm": "37.425", "loss_scale": "1", "train_wall": "40", "gb_free": "9.3", "wall": "330"} -2021-03-08 18:10:20 | INFO | train_inner | {"epoch": 1, "update": 0.01, "loss": "17.264", "ppl": "157354", "wps": "3188.7", "ups": "0.02", "wpb": "131072", "bsz": "64", "num_updates": "7", "lr": "6e-05", "gnorm": "10.824", "loss_scale": "1", "train_wall": "41", "gb_free": "9.3", "wall": "371"} -2021-03-08 18:11:01 | INFO | train_inner | {"epoch": 1, "update": 0.011, "loss": "16.794", "ppl": "113647", "wps": "3230", "ups": "0.02", "wpb": "131072", "bsz": "64", "num_updates": "8", "lr": "4e-05", "gnorm": "5.616", "loss_scale": "1", "train_wall": "41", "gb_free": "9.3", "wall": "411"} -2021-03-08 18:11:39 | INFO | train_inner | {"epoch": 1, "update": 0.012, "loss": "16.706", "ppl": "106938", "wps": "3384", "ups": "0.03", "wpb": "131072", "bsz": "64", "num_updates": "9", "lr": "2e-05", "gnorm": "5.318", "loss_scale": "1", "train_wall": "39", "gb_free": "9.3", "wall": "450"} -2021-03-08 18:12:19 | INFO | train_inner | {"epoch": 1, "update": 0.013, "loss": "16.548", "ppl": "95796.2", "wps": "3274.4", "ups": "0.02", "wpb": "131072", "bsz": "64", "num_updates": "10", "lr": "0", "gnorm": "5.22", "loss_scale": "1", "train_wall": "40", "gb_free": "9.3", "wall": "490"} -2021-03-08 18:12:19 | INFO | fairseq_cli.train | Stopping training due to num_updates: 10 >= max_update: 10 -2021-03-08 18:12:19 | INFO | fairseq_cli.train | begin validation on "valid" subset -2021-03-08 18:12:45 | INFO | valid | {"epoch": 1, "valid_loss": "16.624", "valid_ppl": "101000", "valid_wps": "10855.9", "valid_wpb": "123202", "valid_bsz": "60.5", "valid_num_updates": "10"} -2021-03-08 18:12:45 | INFO | fairseq_cli.train | end of epoch 1 (average epoch stats below) -2021-03-08 18:12:45 | INFO | train | {"epoch": 1, "train_loss": "18.114", "train_ppl": "283776", "train_wps": "2567.8", "train_ups": "0.02", "train_wpb": "131072", "train_bsz": "64", "train_num_updates": "10", "train_lr": "0", "train_gnorm": "29.562", "train_loss_scale": "1", "train_train_wall": "480", "train_gb_free": "9.3", "train_wall": "516"} -2021-03-08 18:12:45 | INFO | fairseq_cli.train | done training in 509.9 seconds -``` - -
- self.score = score # float
-
-
-def coordinate_to_offset(row, col, ncols):
- return int(row * ncols + col)
-
-
-def offset_to_row(offset, ncols):
- return int(offset / ncols)
-
-
-def offset_to_col(offset, ncols):
- return int(offset % ncols)
-
-
-def trimWhitespace(str):
- return re.sub(" +", " ", re.sub(" *$", "", re.sub("^ *", "", str)))
-
-
-def str2toks(str):
- pieces = trimWhitespace(str).split(" ")
- toks = []
- for p in pieces:
- toks.append(Token(p, 0.0, 0.0))
- return toks
-
-
-class EditDistance(object):
- def __init__(self, time_mediated):
- self.time_mediated_ = time_mediated
- self.scores_ = np.nan # Eigen::Matrix
- self.backtraces_ = (
- np.nan
- ) # Eigen::Matrix backtraces_;
- self.confusion_pairs_ = {}
-
- def cost(self, ref, hyp, code):
- if self.time_mediated_:
- if code == Code.match:
- return abs(ref.start - hyp.start) + abs(ref.end - hyp.end)
- elif code == Code.insertion:
- return hyp.end - hyp.start
- elif code == Code.deletion:
- return ref.end - ref.start
- else: # substitution
- return abs(ref.start - hyp.start) + abs(ref.end - hyp.end) + 0.1
- else:
- if code == Code.match:
- return 0
- elif code == Code.insertion or code == Code.deletion:
- return 3
- else: # substitution
- return 4
-
- def get_result(self, refs, hyps):
- res = AlignmentResult(refs=deque(), hyps=deque(), codes=deque(), score=np.nan)
-
- num_rows, num_cols = self.scores_.shape
- res.score = self.scores_[num_rows - 1, num_cols - 1]
-
- curr_offset = coordinate_to_offset(num_rows - 1, num_cols - 1, num_cols)
-
- while curr_offset != 0:
- curr_row = offset_to_row(curr_offset, num_cols)
- curr_col = offset_to_col(curr_offset, num_cols)
-
- prev_offset = self.backtraces_[curr_row, curr_col]
-
- prev_row = offset_to_row(prev_offset, num_cols)
- prev_col = offset_to_col(prev_offset, num_cols)
-
- res.refs.appendleft(curr_row - 1) # Note: this was .push_front() in C++
- res.hyps.appendleft(curr_col - 1)
- if curr_row - 1 == prev_row and curr_col == prev_col:
- res.codes.appendleft(Code.deletion)
- elif curr_row == prev_row and curr_col - 1 == prev_col:
- res.codes.appendleft(Code.insertion)
- else:
- # assert(curr_row - 1 == prev_row and curr_col - 1 == prev_col)
- ref_str = refs[res.refs[0]].label
- hyp_str = hyps[res.hyps[0]].label
-
- if ref_str == hyp_str:
- res.codes.appendleft(Code.match)
- else:
- res.codes.appendleft(Code.substitution)
-
- confusion_pair = "%s -> %s" % (ref_str, hyp_str)
- if confusion_pair not in self.confusion_pairs_:
- self.confusion_pairs_[confusion_pair] = 1
- else:
- self.confusion_pairs_[confusion_pair] += 1
-
- curr_offset = prev_offset
-
- return res
-
- def align(self, refs, hyps):
- if len(refs) == 0 and len(hyps) == 0:
- return np.nan
-
- # NOTE: we're not resetting the values in these matrices because every value
- # will be overridden in the loop below. If this assumption doesn't hold,
- # be sure to set all entries in self.scores_ and self.backtraces_ to 0.
- self.scores_ = np.zeros((len(refs) + 1, len(hyps) + 1))
- self.backtraces_ = np.zeros((len(refs) + 1, len(hyps) + 1))
-
- num_rows, num_cols = self.scores_.shape
-
- for i in range(num_rows):
- for j in range(num_cols):
- if i == 0 and j == 0:
- self.scores_[i, j] = 0.0
- self.backtraces_[i, j] = 0
- continue
-
- if i == 0:
- self.scores_[i, j] = self.scores_[i, j - 1] + self.cost(
- None, hyps[j - 1], Code.insertion
- )
- self.backtraces_[i, j] = coordinate_to_offset(i, j - 1, num_cols)
- continue
-
- if j == 0:
- self.scores_[i, j] = self.scores_[i - 1, j] + self.cost(
- refs[i - 1], None, Code.deletion
- )
- self.backtraces_[i, j] = coordinate_to_offset(i - 1, j, num_cols)
- continue
-
- # Below here both i and j are greater than 0
- ref = refs[i - 1]
- hyp = hyps[j - 1]
- best_score = self.scores_[i - 1, j - 1] + (
- self.cost(ref, hyp, Code.match)
- if (ref.label == hyp.label)
- else self.cost(ref, hyp, Code.substitution)
- )
-
- prev_row = i - 1
- prev_col = j - 1
- ins = self.scores_[i, j - 1] + self.cost(None, hyp, Code.insertion)
- if ins < best_score:
- best_score = ins
- prev_row = i
- prev_col = j - 1
-
- delt = self.scores_[i - 1, j] + self.cost(ref, None, Code.deletion)
- if delt < best_score:
- best_score = delt
- prev_row = i - 1
- prev_col = j
-
- self.scores_[i, j] = best_score
- self.backtraces_[i, j] = coordinate_to_offset(
- prev_row, prev_col, num_cols
- )
-
- return self.get_result(refs, hyps)
-
-
-class WERTransformer(object):
- def __init__(self, hyp_str, ref_str, verbose=True):
- self.ed_ = EditDistance(False)
- self.id2oracle_errs_ = {}
- self.utts_ = 0
- self.words_ = 0
- self.insertions_ = 0
- self.deletions_ = 0
- self.substitutions_ = 0
-
- self.process(["dummy_str", hyp_str, ref_str])
-
- if verbose:
- print("'%s' vs '%s'" % (hyp_str, ref_str))
- self.report_result()
-
- def process(self, input): # std::vector&& input
- if len(input) < 3:
- print(
- "Input must be of the form ... , got ",
- len(input),
- " inputs:",
- )
- return None
-
- # Align
- # std::vector hyps;
- # std::vector refs;
-
- hyps = str2toks(input[-2])
- refs = str2toks(input[-1])
-
- alignment = self.ed_.align(refs, hyps)
- if alignment is None:
- print("Alignment is null")
- return np.nan
-
- # Tally errors
- ins = 0
- dels = 0
- subs = 0
- for code in alignment.codes:
- if code == Code.substitution:
- subs += 1
- elif code == Code.insertion:
- ins += 1
- elif code == Code.deletion:
- dels += 1
-
- # Output
- row = input
- row.append(str(len(refs)))
- row.append(str(ins))
- row.append(str(dels))
- row.append(str(subs))
- # print(row)
-
- # Accumulate
- kIdIndex = 0
- kNBestSep = "/"
-
- pieces = input[kIdIndex].split(kNBestSep)
-
- if len(pieces) == 0:
- print(
- "Error splitting ",
- input[kIdIndex],
- " on '",
- kNBestSep,
- "', got empty list",
- )
- return np.nan
-
- id = pieces[0]
- if id not in self.id2oracle_errs_:
- self.utts_ += 1
- self.words_ += len(refs)
- self.insertions_ += ins
- self.deletions_ += dels
- self.substitutions_ += subs
- self.id2oracle_errs_[id] = [ins, dels, subs]
- else:
- curr_err = ins + dels + subs
- prev_err = np.sum(self.id2oracle_errs_[id])
- if curr_err < prev_err:
- self.id2oracle_errs_[id] = [ins, dels, subs]
-
- return 0
-
- def report_result(self):
- # print("---------- Summary ---------------")
- if self.words_ == 0:
- print("No words counted")
- return
-
- # 1-best
- best_wer = (
- 100.0
- * (self.insertions_ + self.deletions_ + self.substitutions_)
- / self.words_
- )
-
- print(
- "\tWER = %0.2f%% (%i utts, %i words, %0.2f%% ins, "
- "%0.2f%% dels, %0.2f%% subs)"
- % (
- best_wer,
- self.utts_,
- self.words_,
- 100.0 * self.insertions_ / self.words_,
- 100.0 * self.deletions_ / self.words_,
- 100.0 * self.substitutions_ / self.words_,
- )
- )
-
- def wer(self):
- if self.words_ == 0:
- wer = np.nan
- else:
- wer = (
- 100.0
- * (self.insertions_ + self.deletions_ + self.substitutions_)
- / self.words_
- )
- return wer
-
- def stats(self):
- if self.words_ == 0:
- stats = {}
- else:
- wer = (
- 100.0
- * (self.insertions_ + self.deletions_ + self.substitutions_)
- / self.words_
- )
- stats = dict(
- {
- "wer": wer,
- "utts": self.utts_,
- "numwords": self.words_,
- "ins": self.insertions_,
- "dels": self.deletions_,
- "subs": self.substitutions_,
- "confusion_pairs": self.ed_.confusion_pairs_,
- }
- )
- return stats
-
-
-def calc_wer(hyp_str, ref_str):
- t = WERTransformer(hyp_str, ref_str, verbose=0)
- return t.wer()
-
-
-def calc_wer_stats(hyp_str, ref_str):
- t = WERTransformer(hyp_str, ref_str, verbose=0)
- return t.stats()
-
-
-def get_wer_alignment_codes(hyp_str, ref_str):
- """
- INPUT: hypothesis string, reference string
- OUTPUT: List of alignment codes (intermediate results from WER computation)
- """
- t = WERTransformer(hyp_str, ref_str, verbose=0)
- return t.ed_.align(str2toks(ref_str), str2toks(hyp_str)).codes
-
-
-def merge_counts(x, y):
- # Merge two hashes which have 'counts' as their values
- # This can be used for example to merge confusion pair counts
- # conf_pairs = merge_counts(conf_pairs, stats['confusion_pairs'])
- for k, v in y.items():
- if k not in x:
- x[k] = 0
- x[k] += v
- return x
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_recognition/w2l_decoder.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_recognition/w2l_decoder.py
deleted file mode 100644
index fbf2d3524ee40bd0d08b6a9560047d96e49b6045..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_recognition/w2l_decoder.py
+++ /dev/null
@@ -1,486 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-"""
-Flashlight decoders.
-"""
-
-import gc
-import itertools as it
-import os.path as osp
-from typing import List
-import warnings
-from collections import deque, namedtuple
-
-import numpy as np
-import torch
-from examples.speech_recognition.data.replabels import unpack_replabels
-from fairseq import tasks
-from fairseq.utils import apply_to_sample
-from omegaconf import open_dict
-from fairseq.dataclass.utils import convert_namespace_to_omegaconf
-
-
-try:
- from flashlight.lib.text.dictionary import create_word_dict, load_words
- from flashlight.lib.sequence.criterion import CpuViterbiPath, get_data_ptr_as_bytes
- from flashlight.lib.text.decoder import (
- CriterionType,
- LexiconDecoderOptions,
- KenLM,
- LM,
- LMState,
- SmearingMode,
- Trie,
- LexiconDecoder,
- )
-except:
- warnings.warn(
- "flashlight python bindings are required to use this functionality. Please install from https://github.com/facebookresearch/flashlight/tree/master/bindings/python"
- )
- LM = object
- LMState = object
-
-
-class W2lDecoder(object):
- def __init__(self, args, tgt_dict):
- self.tgt_dict = tgt_dict
- self.vocab_size = len(tgt_dict)
- self.nbest = args.nbest
-
- # criterion-specific init
- self.criterion_type = CriterionType.CTC
- self.blank = (
- tgt_dict.index("")
- if "" in tgt_dict.indices
- else tgt_dict.bos()
- )
- if "" in tgt_dict.indices:
- self.silence = tgt_dict.index("")
- elif "|" in tgt_dict.indices:
- self.silence = tgt_dict.index("|")
- else:
- self.silence = tgt_dict.eos()
- self.asg_transitions = None
-
- def generate(self, models, sample, **unused):
- """Generate a batch of inferences."""
- # model.forward normally channels prev_output_tokens into the decoder
- # separately, but SequenceGenerator directly calls model.encoder
- encoder_input = {
- k: v for k, v in sample["net_input"].items() if k != "prev_output_tokens"
- }
- emissions = self.get_emissions(models, encoder_input)
- return self.decode(emissions)
-
- def get_emissions(self, models, encoder_input):
- """Run encoder and normalize emissions"""
- model = models[0]
- encoder_out = model(**encoder_input)
- if hasattr(model, "get_logits"):
- emissions = model.get_logits(encoder_out) # no need to normalize emissions
- else:
- emissions = model.get_normalized_probs(encoder_out, log_probs=True)
- return emissions.transpose(0, 1).float().cpu().contiguous()
-
- def get_tokens(self, idxs):
- """Normalize tokens by handling CTC blank, ASG replabels, etc."""
- idxs = (g[0] for g in it.groupby(idxs))
- idxs = filter(lambda x: x != self.blank, idxs)
- return torch.LongTensor(list(idxs))
-
-
-class W2lViterbiDecoder(W2lDecoder):
- def __init__(self, args, tgt_dict):
- super().__init__(args, tgt_dict)
-
- def decode(self, emissions):
- B, T, N = emissions.size()
- hypos = []
- if self.asg_transitions is None:
- transitions = torch.FloatTensor(N, N).zero_()
- else:
- transitions = torch.FloatTensor(self.asg_transitions).view(N, N)
- viterbi_path = torch.IntTensor(B, T)
- workspace = torch.ByteTensor(CpuViterbiPath.get_workspace_size(B, T, N))
- CpuViterbiPath.compute(
- B,
- T,
- N,
- get_data_ptr_as_bytes(emissions),
- get_data_ptr_as_bytes(transitions),
- get_data_ptr_as_bytes(viterbi_path),
- get_data_ptr_as_bytes(workspace),
- )
- return [
- [{"tokens": self.get_tokens(viterbi_path[b].tolist()), "score": 0}]
- for b in range(B)
- ]
-
-
-class W2lKenLMDecoder(W2lDecoder):
- def __init__(self, args, tgt_dict):
- super().__init__(args, tgt_dict)
-
- self.unit_lm = getattr(args, "unit_lm", False)
-
- if args.lexicon:
- self.lexicon = load_words(args.lexicon)
- self.word_dict = create_word_dict(self.lexicon)
- self.unk_word = self.word_dict.get_index("")
-
- self.lm = KenLM(args.kenlm_model, self.word_dict)
- self.trie = Trie(self.vocab_size, self.silence)
-
- start_state = self.lm.start(False)
- for i, (word, spellings) in enumerate(self.lexicon.items()):
- word_idx = self.word_dict.get_index(word)
- _, score = self.lm.score(start_state, word_idx)
- for spelling in spellings:
- spelling_idxs = [tgt_dict.index(token) for token in spelling]
- assert (
- tgt_dict.unk() not in spelling_idxs
- ), f"{spelling} {spelling_idxs}"
- self.trie.insert(spelling_idxs, word_idx, score)
- self.trie.smear(SmearingMode.MAX)
-
- self.decoder_opts = LexiconDecoderOptions(
- beam_size=args.beam,
- beam_size_token=int(getattr(args, "beam_size_token", len(tgt_dict))),
- beam_threshold=args.beam_threshold,
- lm_weight=args.lm_weight,
- word_score=args.word_score,
- unk_score=args.unk_weight,
- sil_score=args.sil_weight,
- log_add=False,
- criterion_type=self.criterion_type,
- )
-
- if self.asg_transitions is None:
- N = 768
- # self.asg_transitions = torch.FloatTensor(N, N).zero_()
- self.asg_transitions = []
-
- self.decoder = LexiconDecoder(
- self.decoder_opts,
- self.trie,
- self.lm,
- self.silence,
- self.blank,
- self.unk_word,
- self.asg_transitions,
- self.unit_lm,
- )
- else:
- assert args.unit_lm, "lexicon free decoding can only be done with a unit language model"
- from flashlight.lib.text.decoder import LexiconFreeDecoder, LexiconFreeDecoderOptions
-
- d = {w: [[w]] for w in tgt_dict.symbols}
- self.word_dict = create_word_dict(d)
- self.lm = KenLM(args.kenlm_model, self.word_dict)
- self.decoder_opts = LexiconFreeDecoderOptions(
- beam_size=args.beam,
- beam_size_token=int(getattr(args, "beam_size_token", len(tgt_dict))),
- beam_threshold=args.beam_threshold,
- lm_weight=args.lm_weight,
- sil_score=args.sil_weight,
- log_add=False,
- criterion_type=self.criterion_type,
- )
- self.decoder = LexiconFreeDecoder(
- self.decoder_opts, self.lm, self.silence, self.blank, []
- )
-
- def get_timesteps(self, token_idxs: List[int]) -> List[int]:
- """Returns frame numbers corresponding to every non-blank token.
-
- Parameters
- ----------
- token_idxs : List[int]
- IDs of decoded tokens.
-
- Returns
- -------
- List[int]
- Frame numbers corresponding to every non-blank token.
- """
- timesteps = []
- for i, token_idx in enumerate(token_idxs):
- if token_idx == self.blank:
- continue
- if i == 0 or token_idx != token_idxs[i-1]:
- timesteps.append(i)
- return timesteps
-
- def decode(self, emissions):
- B, T, N = emissions.size()
- hypos = []
- for b in range(B):
- emissions_ptr = emissions.data_ptr() + 4 * b * emissions.stride(0)
- results = self.decoder.decode(emissions_ptr, T, N)
-
- nbest_results = results[: self.nbest]
- hypos.append(
- [
- {
- "tokens": self.get_tokens(result.tokens),
- "score": result.score,
- "timesteps": self.get_timesteps(result.tokens),
- "words": [
- self.word_dict.get_entry(x) for x in result.words if x >= 0
- ],
- }
- for result in nbest_results
- ]
- )
- return hypos
-
-
-FairseqLMState = namedtuple("FairseqLMState", ["prefix", "incremental_state", "probs"])
-
-
-class FairseqLM(LM):
- def __init__(self, dictionary, model):
- LM.__init__(self)
- self.dictionary = dictionary
- self.model = model
- self.unk = self.dictionary.unk()
-
- self.save_incremental = False # this currently does not work properly
- self.max_cache = 20_000
-
- model.cuda()
- model.eval()
- model.make_generation_fast_()
-
- self.states = {}
- self.stateq = deque()
-
- def start(self, start_with_nothing):
- state = LMState()
- prefix = torch.LongTensor([[self.dictionary.eos()]])
- incremental_state = {} if self.save_incremental else None
- with torch.no_grad():
- res = self.model(prefix.cuda(), incremental_state=incremental_state)
- probs = self.model.get_normalized_probs(res, log_probs=True, sample=None)
-
- if incremental_state is not None:
- incremental_state = apply_to_sample(lambda x: x.cpu(), incremental_state)
- self.states[state] = FairseqLMState(
- prefix.numpy(), incremental_state, probs[0, -1].cpu().numpy()
- )
- self.stateq.append(state)
-
- return state
-
- def score(self, state: LMState, token_index: int, no_cache: bool = False):
- """
- Evaluate language model based on the current lm state and new word
- Parameters:
- -----------
- state: current lm state
- token_index: index of the word
- (can be lexicon index then you should store inside LM the
- mapping between indices of lexicon and lm, or lm index of a word)
-
- Returns:
- --------
- (LMState, float): pair of (new state, score for the current word)
- """
- curr_state = self.states[state]
-
- def trim_cache(targ_size):
- while len(self.stateq) > targ_size:
- rem_k = self.stateq.popleft()
- rem_st = self.states[rem_k]
- rem_st = FairseqLMState(rem_st.prefix, None, None)
- self.states[rem_k] = rem_st
-
- if curr_state.probs is None:
- new_incremental_state = (
- curr_state.incremental_state.copy()
- if curr_state.incremental_state is not None
- else None
- )
- with torch.no_grad():
- if new_incremental_state is not None:
- new_incremental_state = apply_to_sample(
- lambda x: x.cuda(), new_incremental_state
- )
- elif self.save_incremental:
- new_incremental_state = {}
-
- res = self.model(
- torch.from_numpy(curr_state.prefix).cuda(),
- incremental_state=new_incremental_state,
- )
- probs = self.model.get_normalized_probs(
- res, log_probs=True, sample=None
- )
-
- if new_incremental_state is not None:
- new_incremental_state = apply_to_sample(
- lambda x: x.cpu(), new_incremental_state
- )
-
- curr_state = FairseqLMState(
- curr_state.prefix, new_incremental_state, probs[0, -1].cpu().numpy()
- )
-
- if not no_cache:
- self.states[state] = curr_state
- self.stateq.append(state)
-
- score = curr_state.probs[token_index].item()
-
- trim_cache(self.max_cache)
-
- outstate = state.child(token_index)
- if outstate not in self.states and not no_cache:
- prefix = np.concatenate(
- [curr_state.prefix, torch.LongTensor([[token_index]])], -1
- )
- incr_state = curr_state.incremental_state
-
- self.states[outstate] = FairseqLMState(prefix, incr_state, None)
-
- if token_index == self.unk:
- score = float("-inf")
-
- return outstate, score
-
- def finish(self, state: LMState):
- """
- Evaluate eos for language model based on the current lm state
-
- Returns:
- --------
- (LMState, float): pair of (new state, score for the current word)
- """
- return self.score(state, self.dictionary.eos())
-
- def empty_cache(self):
- self.states = {}
- self.stateq = deque()
- gc.collect()
-
-
-class W2lFairseqLMDecoder(W2lDecoder):
- def __init__(self, args, tgt_dict):
- super().__init__(args, tgt_dict)
-
- self.unit_lm = getattr(args, "unit_lm", False)
-
- self.lexicon = load_words(args.lexicon) if args.lexicon else None
- self.idx_to_wrd = {}
-
- checkpoint = torch.load(args.kenlm_model, map_location="cpu")
-
- if "cfg" in checkpoint and checkpoint["cfg"] is not None:
- lm_args = checkpoint["cfg"]
- else:
- lm_args = convert_namespace_to_omegaconf(checkpoint["args"])
-
- with open_dict(lm_args.task):
- lm_args.task.data = osp.dirname(args.kenlm_model)
-
- task = tasks.setup_task(lm_args.task)
- model = task.build_model(lm_args.model)
- model.load_state_dict(checkpoint["model"], strict=False)
-
- self.trie = Trie(self.vocab_size, self.silence)
-
- self.word_dict = task.dictionary
- self.unk_word = self.word_dict.unk()
- self.lm = FairseqLM(self.word_dict, model)
-
- if self.lexicon:
- start_state = self.lm.start(False)
- for i, (word, spellings) in enumerate(self.lexicon.items()):
- if self.unit_lm:
- word_idx = i
- self.idx_to_wrd[i] = word
- score = 0
- else:
- word_idx = self.word_dict.index(word)
- _, score = self.lm.score(start_state, word_idx, no_cache=True)
-
- for spelling in spellings:
- spelling_idxs = [tgt_dict.index(token) for token in spelling]
- assert (
- tgt_dict.unk() not in spelling_idxs
- ), f"{spelling} {spelling_idxs}"
- self.trie.insert(spelling_idxs, word_idx, score)
- self.trie.smear(SmearingMode.MAX)
-
- self.decoder_opts = LexiconDecoderOptions(
- beam_size=args.beam,
- beam_size_token=int(getattr(args, "beam_size_token", len(tgt_dict))),
- beam_threshold=args.beam_threshold,
- lm_weight=args.lm_weight,
- word_score=args.word_score,
- unk_score=args.unk_weight,
- sil_score=args.sil_weight,
- log_add=False,
- criterion_type=self.criterion_type,
- )
-
- self.decoder = LexiconDecoder(
- self.decoder_opts,
- self.trie,
- self.lm,
- self.silence,
- self.blank,
- self.unk_word,
- [],
- self.unit_lm,
- )
- else:
- assert args.unit_lm, "lexicon free decoding can only be done with a unit language model"
- from flashlight.lib.text.decoder import LexiconFreeDecoder, LexiconFreeDecoderOptions
-
- d = {w: [[w]] for w in tgt_dict.symbols}
- self.word_dict = create_word_dict(d)
- self.lm = KenLM(args.kenlm_model, self.word_dict)
- self.decoder_opts = LexiconFreeDecoderOptions(
- beam_size=args.beam,
- beam_size_token=int(getattr(args, "beam_size_token", len(tgt_dict))),
- beam_threshold=args.beam_threshold,
- lm_weight=args.lm_weight,
- sil_score=args.sil_weight,
- log_add=False,
- criterion_type=self.criterion_type,
- )
- self.decoder = LexiconFreeDecoder(
- self.decoder_opts, self.lm, self.silence, self.blank, []
- )
-
- def decode(self, emissions):
- B, T, N = emissions.size()
- hypos = []
-
- def idx_to_word(idx):
- if self.unit_lm:
- return self.idx_to_wrd[idx]
- else:
- return self.word_dict[idx]
-
- def make_hypo(result):
- hypo = {"tokens": self.get_tokens(result.tokens), "score": result.score}
- if self.lexicon:
- hypo["words"] = [idx_to_word(x) for x in result.words if x >= 0]
- return hypo
-
- for b in range(B):
- emissions_ptr = emissions.data_ptr() + 4 * b * emissions.stride(0)
- results = self.decoder.decode(emissions_ptr, T, N)
-
- nbest_results = results[: self.nbest]
- hypos.append([make_hypo(result) for result in nbest_results])
- self.lm.empty_cache()
-
- return hypos
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/README.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/README.md
deleted file mode 100644
index a31e7f68bd3128494d70c0a4dfa75b9d54aa4288..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/README.md
+++ /dev/null
@@ -1,38 +0,0 @@
-Speech Synthesis (S^2)
-===
-[https://arxiv.org/abs/2109.06912](https://arxiv.org/abs/2109.06912)
-
-Speech synthesis with fairseq.
-
-## Features
-
-- Autoregressive and non-autoregressive models
-- Multi-speaker synthesis
-- Audio preprocessing (denoising, VAD, etc.) for less curated data
-- Automatic metrics for model development
-- Similar data configuration as [S2T](../speech_to_text/README.md)
-
-
-## Examples
-- [Single-speaker synthesis on LJSpeech](docs/ljspeech_example.md)
-- [Multi-speaker synthesis on VCTK](docs/vctk_example.md)
-- [Multi-speaker synthesis on Common Voice](docs/common_voice_example.md)
-
-
-## Citation
-Please cite as:
-```
-@article{wang2021fairseqs2,
- title={fairseq S\^{} 2: A Scalable and Integrable Speech Synthesis Toolkit},
- author={Wang, Changhan and Hsu, Wei-Ning and Adi, Yossi and Polyak, Adam and Lee, Ann and Chen, Peng-Jen and Gu, Jiatao and Pino, Juan},
- journal={arXiv preprint arXiv:2109.06912},
- year={2021}
-}
-
-@inproceedings{ott2019fairseq,
- title = {fairseq: A Fast, Extensible Toolkit for Sequence Modeling},
- author = {Myle Ott and Sergey Edunov and Alexei Baevski and Angela Fan and Sam Gross and Nathan Ng and David Grangier and Michael Auli},
- booktitle = {Proceedings of NAACL-HLT 2019: Demonstrations},
- year = {2019},
-}
-```
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/__init__.py
deleted file mode 100644
index 6264236915a7269a4d920ee8213004374dd86a9a..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/data_utils.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/data_utils.py
deleted file mode 100644
index 3b2d079a9a8273a7331f2a07c46eaefe568947cf..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/data_utils.py
+++ /dev/null
@@ -1,344 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import io
-import os
-from pathlib import Path
-from typing import Optional, List, Dict
-import zipfile
-import tempfile
-from dataclasses import dataclass
-from itertools import groupby
-
-import torch
-import torch.nn.functional as F
-import numpy as np
-from tqdm import tqdm
-
-from examples.speech_to_text.data_utils import load_tsv_to_dicts
-from fairseq.data.audio.audio_utils import (
- TTSSpectrogram, TTSMelScale, parse_path, read_from_stored_zip, is_npy_data
-)
-
-
-def trim_or_pad_to_target_length(
- data_1d_or_2d: np.ndarray, target_length: int
-) -> np.ndarray:
- assert len(data_1d_or_2d.shape) in {1, 2}
- delta = data_1d_or_2d.shape[0] - target_length
- if delta >= 0: # trim if being longer
- data_1d_or_2d = data_1d_or_2d[: target_length]
- else: # pad if being shorter
- if len(data_1d_or_2d.shape) == 1:
- data_1d_or_2d = np.concatenate(
- [data_1d_or_2d, np.zeros(-delta)], axis=0
- )
- else:
- data_1d_or_2d = np.concatenate(
- [data_1d_or_2d, np.zeros((-delta, data_1d_or_2d.shape[1]))],
- axis=0
- )
- return data_1d_or_2d
-
-
-def extract_logmel_spectrogram(
- waveform: torch.Tensor, sample_rate: int,
- output_path: Optional[Path] = None, win_length: int = 1024,
- hop_length: int = 256, n_fft: int = 1024,
- win_fn: callable = torch.hann_window, n_mels: int = 80,
- f_min: float = 0., f_max: float = 8000, eps: float = 1e-5,
- overwrite: bool = False, target_length: Optional[int] = None
-):
- if output_path is not None and output_path.is_file() and not overwrite:
- return
-
- spectrogram_transform = TTSSpectrogram(
- n_fft=n_fft, win_length=win_length, hop_length=hop_length,
- window_fn=win_fn
- )
- mel_scale_transform = TTSMelScale(
- n_mels=n_mels, sample_rate=sample_rate, f_min=f_min, f_max=f_max,
- n_stft=n_fft // 2 + 1
- )
- spectrogram = spectrogram_transform(waveform)
- mel_spec = mel_scale_transform(spectrogram)
- logmel_spec = torch.clamp(mel_spec, min=eps).log()
- assert len(logmel_spec.shape) == 3 and logmel_spec.shape[0] == 1
- logmel_spec = logmel_spec.squeeze().t() # D x T -> T x D
- if target_length is not None:
- logmel_spec = trim_or_pad_to_target_length(logmel_spec, target_length)
-
- if output_path is not None:
- np.save(output_path.as_posix(), logmel_spec)
- else:
- return logmel_spec
-
-
-def extract_pitch(
- waveform: torch.Tensor, sample_rate: int,
- output_path: Optional[Path] = None, hop_length: int = 256,
- log_scale: bool = True, phoneme_durations: Optional[List[int]] = None
-):
- if output_path is not None and output_path.is_file():
- return
-
- try:
- import pyworld
- except ImportError:
- raise ImportError("Please install PyWORLD: pip install pyworld")
-
- _waveform = waveform.squeeze(0).double().numpy()
- pitch, t = pyworld.dio(
- _waveform, sample_rate, frame_period=hop_length / sample_rate * 1000
- )
- pitch = pyworld.stonemask(_waveform, pitch, t, sample_rate)
-
- if phoneme_durations is not None:
- pitch = trim_or_pad_to_target_length(pitch, sum(phoneme_durations))
- try:
- from scipy.interpolate import interp1d
- except ImportError:
- raise ImportError("Please install SciPy: pip install scipy")
- nonzero_ids = np.where(pitch != 0)[0]
- if len(nonzero_ids) == 0:
- print((f"{output_path} has all empty values in the pitch contour"))
- return
- elif len(nonzero_ids) == 1:
- print((f"{output_path} has only one non-zero values in the pitch contour"))
- return
- else:
- interp_fn = interp1d(
- nonzero_ids,
- pitch[nonzero_ids],
- fill_value=(pitch[nonzero_ids[0]], pitch[nonzero_ids[-1]]),
- bounds_error=False,
- )
- pitch = interp_fn(np.arange(0, len(pitch)))
- d_cumsum = np.cumsum(np.concatenate([np.array([0]), phoneme_durations]))
- pitch = np.array(
- [
- np.mean(pitch[d_cumsum[i-1]: d_cumsum[i]])
- for i in range(1, len(d_cumsum))
- ]
- )
- assert len(pitch) == len(phoneme_durations)
-
- if log_scale:
- pitch = np.log(pitch + 1)
-
- if output_path is not None:
- np.save(output_path.as_posix(), pitch)
- else:
- return pitch
-
-
-def extract_energy(
- waveform: torch.Tensor, output_path: Optional[Path] = None,
- hop_length: int = 256, n_fft: int = 1024, log_scale: bool = True,
- phoneme_durations: Optional[List[int]] = None
-):
- if output_path is not None and output_path.is_file():
- return
-
- assert len(waveform.shape) == 2 and waveform.shape[0] == 1
- waveform = waveform.view(1, 1, waveform.shape[1])
- waveform = F.pad(
- waveform.unsqueeze(1), [n_fft // 2, n_fft // 2, 0, 0],
- mode="reflect"
- )
- waveform = waveform.squeeze(1)
-
- fourier_basis = np.fft.fft(np.eye(n_fft))
- cutoff = int((n_fft / 2 + 1))
- fourier_basis = np.vstack(
- [np.real(fourier_basis[:cutoff, :]),
- np.imag(fourier_basis[:cutoff, :])]
- )
-
- forward_basis = torch.FloatTensor(fourier_basis[:, None, :])
- forward_transform = F.conv1d(
- waveform, forward_basis, stride=hop_length, padding=0
- )
-
- real_part = forward_transform[:, :cutoff, :]
- imag_part = forward_transform[:, cutoff:, :]
- magnitude = torch.sqrt(real_part ** 2 + imag_part ** 2)
- energy = torch.norm(magnitude, dim=1).squeeze(0).numpy()
-
- if phoneme_durations is not None:
- energy = trim_or_pad_to_target_length(energy, sum(phoneme_durations))
- d_cumsum = np.cumsum(np.concatenate([np.array([0]), phoneme_durations]))
- energy = np.array(
- [
- np.mean(energy[d_cumsum[i - 1]: d_cumsum[i]])
- for i in range(1, len(d_cumsum))
- ]
- )
- assert len(energy) == len(phoneme_durations)
-
- if log_scale:
- energy = np.log(energy + 1)
-
- if output_path is not None:
- np.save(output_path.as_posix(), energy)
- else:
- return energy
-
-
-def get_global_cmvn(feature_root: Path, output_path: Optional[Path] = None):
- mean_x, mean_x2, n_frames = None, None, 0
- feature_paths = feature_root.glob("*.npy")
- for p in tqdm(feature_paths):
- with open(p, 'rb') as f:
- frames = np.load(f).squeeze()
-
- n_frames += frames.shape[0]
-
- cur_mean_x = frames.sum(axis=0)
- if mean_x is None:
- mean_x = cur_mean_x
- else:
- mean_x += cur_mean_x
-
- cur_mean_x2 = (frames ** 2).sum(axis=0)
- if mean_x2 is None:
- mean_x2 = cur_mean_x2
- else:
- mean_x2 += cur_mean_x2
-
- mean_x /= n_frames
- mean_x2 /= n_frames
- var_x = mean_x2 - mean_x ** 2
- std_x = np.sqrt(np.maximum(var_x, 1e-10))
-
- if output_path is not None:
- with open(output_path, 'wb') as f:
- np.savez(f, mean=mean_x, std=std_x)
- else:
- return {"mean": mean_x, "std": std_x}
-
-
-def ipa_phonemize(text, lang="en-us", use_g2p=False):
- if use_g2p:
- assert lang == "en-us", "g2pE phonemizer only works for en-us"
- try:
- from g2p_en import G2p
- g2p = G2p()
- return " ".join("|" if p == " " else p for p in g2p(text))
- except ImportError:
- raise ImportError(
- "Please install phonemizer: pip install g2p_en"
- )
- else:
- try:
- from phonemizer import phonemize
- from phonemizer.separator import Separator
- return phonemize(
- text, backend='espeak', language=lang,
- separator=Separator(word="| ", phone=" ")
- )
- except ImportError:
- raise ImportError(
- "Please install phonemizer: pip install phonemizer"
- )
-
-
-@dataclass
-class ForceAlignmentInfo(object):
- tokens: List[str]
- frame_durations: List[int]
- start_sec: Optional[float]
- end_sec: Optional[float]
-
-
-def get_mfa_alignment_by_sample_id(
- textgrid_zip_path: str, sample_id: str, sample_rate: int,
- hop_length: int, silence_phones: List[str] = ("sil", "sp", "spn")
-) -> ForceAlignmentInfo:
- try:
- import tgt
- except ImportError:
- raise ImportError("Please install TextGridTools: pip install tgt")
-
- filename = f"{sample_id}.TextGrid"
- out_root = Path(tempfile.gettempdir())
- tgt_path = out_root / filename
- with zipfile.ZipFile(textgrid_zip_path) as f_zip:
- f_zip.extract(filename, path=out_root)
- textgrid = tgt.io.read_textgrid(tgt_path.as_posix())
- os.remove(tgt_path)
-
- phones, frame_durations = [], []
- start_sec, end_sec, end_idx = 0, 0, 0
- for t in textgrid.get_tier_by_name("phones")._objects:
- s, e, p = t.start_time, t.end_time, t.text
- # Trim leading silences
- if len(phones) == 0:
- if p in silence_phones:
- continue
- else:
- start_sec = s
- phones.append(p)
- if p not in silence_phones:
- end_sec = e
- end_idx = len(phones)
- r = sample_rate / hop_length
- frame_durations.append(int(np.round(e * r) - np.round(s * r)))
- # Trim tailing silences
- phones = phones[:end_idx]
- frame_durations = frame_durations[:end_idx]
-
- return ForceAlignmentInfo(
- tokens=phones, frame_durations=frame_durations, start_sec=start_sec,
- end_sec=end_sec
- )
-
-
-def get_mfa_alignment(
- textgrid_zip_path: str, sample_ids: List[str], sample_rate: int,
- hop_length: int
-) -> Dict[str, ForceAlignmentInfo]:
- return {
- i: get_mfa_alignment_by_sample_id(
- textgrid_zip_path, i, sample_rate, hop_length
- ) for i in tqdm(sample_ids)
- }
-
-
-def get_unit_alignment(
- id_to_unit_tsv_path: str, sample_ids: List[str]
-) -> Dict[str, ForceAlignmentInfo]:
- id_to_units = {
- e["id"]: e["units"] for e in load_tsv_to_dicts(id_to_unit_tsv_path)
- }
- id_to_units = {i: id_to_units[i].split() for i in sample_ids}
- id_to_units_collapsed = {
- i: [uu for uu, _ in groupby(u)] for i, u in id_to_units.items()
- }
- id_to_durations = {
- i: [len(list(g)) for _, g in groupby(u)] for i, u in id_to_units.items()
- }
-
- return {
- i: ForceAlignmentInfo(
- tokens=id_to_units_collapsed[i], frame_durations=id_to_durations[i],
- start_sec=None, end_sec=None
- )
- for i in sample_ids
- }
-
-
-def get_feature_value_min_max(feature_paths: List[str]):
- v_min, v_max = 1e-8, -1e-8
- for p in tqdm(feature_paths):
- _path, slice_ptr = parse_path(p)
- assert len(slice_ptr) == 2
- byte_data = read_from_stored_zip(_path, slice_ptr[0], slice_ptr[1])
- assert is_npy_data(byte_data)
- path_or_fp = io.BytesIO(byte_data)
- features = np.load(path_or_fp).squeeze()
- v_min = min(v_min, features.min().item())
- v_max = max(v_max, features.max().item())
- return v_min, v_max
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/docs/common_voice_example.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/docs/common_voice_example.md
deleted file mode 100644
index 1c0eef69a0adcfb60e6d89c6df63311fbb1eb4aa..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/docs/common_voice_example.md
+++ /dev/null
@@ -1,67 +0,0 @@
-[[Back]](..)
-
-# Common Voice
-
-[Common Voice](https://commonvoice.mozilla.org/en/datasets) is a public domain speech corpus with 11.2K hours of read
-speech in 76 languages (the latest version 7.0). We provide examples for building
-[Transformer](https://arxiv.org/abs/1809.08895) models on this dataset.
-
-
-## Data preparation
-[Download](https://commonvoice.mozilla.org/en/datasets) and unpack Common Voice v4 to a path `${DATA_ROOT}/${LANG_ID}`.
-Create splits and generate audio manifests with
-```bash
-python -m examples.speech_synthesis.preprocessing.get_common_voice_audio_manifest \
- --data-root ${DATA_ROOT} \
- --lang ${LANG_ID} \
- --output-manifest-root ${AUDIO_MANIFEST_ROOT} --convert-to-wav
-```
-
-To denoise audio and trim leading/trailing silence using signal processing based VAD, run
-```bash
-for SPLIT in dev test train; do
- python -m examples.speech_synthesis.preprocessing.denoise_and_vad_audio \
- --audio-manifest ${AUDIO_MANIFEST_ROOT}/${SPLIT}.audio.tsv \
- --output-dir ${PROCESSED_DATA_ROOT} \
- --denoise --vad --vad-agg-level 2
-done
-```
-
-which generates a new audio TSV manifest under `${PROCESSED_DATA_ROOT}` with updated path to the processed audio and
-a new column for SNR.
-
-To do filtering by CER, follow the [Automatic Evaluation](../docs/ljspeech_example.md#automatic-evaluation) section to
-run ASR model (add `--eval-target` to `get_eval_manifest` for evaluation on the reference audio; add `--err-unit char`
-to `eval_asr` to compute CER instead of WER). The example-level CER is saved to
-`${EVAL_OUTPUT_ROOT}/uer_cer.${SPLIT}.tsv`.
-
-Then, extract log-Mel spectrograms, generate feature manifest and create data configuration YAML with
-```bash
-python -m examples.speech_synthesis.preprocessing.get_feature_manifest \
- --audio-manifest-root ${AUDIO_MANIFEST_ROOT} \
- --output-root ${FEATURE_MANIFEST_ROOT} \
- --ipa-vocab --lang ${LANG_ID} \
- --snr-threshold 15 \
- --cer-threshold 0.1 --cer-tsv-path ${EVAL_OUTPUT_ROOT}/uer_cer.${SPLIT}.tsv
-```
-where we use phoneme inputs (`--ipa-vocab`) as example. For sample filtering, we set the SNR and CER threshold
-to 15 and 10%, respectively.
-
-
-## Training
-(Please refer to [the LJSpeech example](../docs/ljspeech_example.md#transformer).)
-
-
-## Inference
-(Please refer to [the LJSpeech example](../docs/ljspeech_example.md#inference).)
-
-## Automatic Evaluation
-(Please refer to [the LJSpeech example](../docs/ljspeech_example.md#automatic-evaluation).)
-
-## Results
-
-| Language | Speakers | --arch | Params | Test MCD | Model |
-|---|---|---|---|---|---|
-| English | 200 | tts_transformer | 54M | 3.8 | [Download](https://dl.fbaipublicfiles.com/fairseq/s2/cv4_en200_transformer_phn.tar) |
-
-[[Back]](..)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/docs/ljspeech_example.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/docs/ljspeech_example.md
deleted file mode 100644
index 836c30d6d5fbd0af3f57f58e903a579612587f25..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/docs/ljspeech_example.md
+++ /dev/null
@@ -1,137 +0,0 @@
-[[Back]](..)
-
-# LJSpeech
-
-[LJSpeech](https://keithito.com/LJ-Speech-Dataset) is a public domain TTS
-corpus with around 24 hours of English speech sampled at 22.05kHz. We provide examples for building
-[Transformer](https://arxiv.org/abs/1809.08895) and [FastSpeech 2](https://arxiv.org/abs/2006.04558)
-models on this dataset.
-
-
-## Data preparation
-
-Download data, create splits and generate audio manifests with
-```bash
-python -m examples.speech_synthesis.preprocessing.get_ljspeech_audio_manifest \
- --output-data-root ${AUDIO_DATA_ROOT} \
- --output-manifest-root ${AUDIO_MANIFEST_ROOT}
-```
-
-Then, extract log-Mel spectrograms, generate feature manifest and create data configuration YAML with
-```bash
-python -m examples.speech_synthesis.preprocessing.get_feature_manifest \
- --audio-manifest-root ${AUDIO_MANIFEST_ROOT} \
- --output-root ${FEATURE_MANIFEST_ROOT} \
- --ipa-vocab --use-g2p
-```
-where we use phoneme inputs (`--ipa-vocab --use-g2p`) as example.
-
-FastSpeech 2 additionally requires frame durations, pitch and energy as auxiliary training targets.
-Add `--add-fastspeech-targets` to include these fields in the feature manifests. We get frame durations either from
-phoneme-level force-alignment or frame-level pseudo-text unit sequence. They should be pre-computed and specified via:
-- `--textgrid-zip ${TEXT_GRID_ZIP_PATH}` for a ZIP file, inside which there is one
- [TextGrid](https://www.fon.hum.uva.nl/praat/manual/TextGrid.html) file per sample to provide force-alignment info.
-- `--id-to-units-tsv ${ID_TO_UNIT_TSV}` for a TSV file, where there are 2 columns for sample ID and
- space-delimited pseudo-text unit sequence, respectively.
-
-For your convenience, we provide pre-computed
-[force-alignment](https://dl.fbaipublicfiles.com/fairseq/s2/ljspeech_mfa.zip) from
-[Montreal Forced Aligner](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) and
-[pseudo-text units](s3://dl.fbaipublicfiles.com/fairseq/s2/ljspeech_hubert.tsv) from
-[HuBERT](https://github.com/pytorch/fairseq/tree/main/examples/hubert). You can also generate them by yourself using
-a different software or model.
-
-
-## Training
-#### Transformer
-```bash
-fairseq-train ${FEATURE_MANIFEST_ROOT} --save-dir ${SAVE_DIR} \
- --config-yaml config.yaml --train-subset train --valid-subset dev \
- --num-workers 4 --max-tokens 30000 --max-update 200000 \
- --task text_to_speech --criterion tacotron2 --arch tts_transformer \
- --clip-norm 5.0 --n-frames-per-step 4 --bce-pos-weight 5.0 \
- --dropout 0.1 --attention-dropout 0.1 --activation-dropout 0.1 \
- --encoder-normalize-before --decoder-normalize-before \
- --optimizer adam --lr 2e-3 --lr-scheduler inverse_sqrt --warmup-updates 4000 \
- --seed 1 --update-freq 8 --eval-inference --best-checkpoint-metric mcd_loss
-```
-where `SAVE_DIR` is the checkpoint root path. We set `--update-freq 8` to simulate 8 GPUs with 1 GPU. You may want to
-update it accordingly when using more than 1 GPU.
-
-#### FastSpeech2
-```bash
-fairseq-train ${FEATURE_MANIFEST_ROOT} --save-dir ${SAVE_DIR} \
- --config-yaml config.yaml --train-subset train --valid-subset dev \
- --num-workers 4 --max-sentences 6 --max-update 200000 \
- --task text_to_speech --criterion fastspeech2 --arch fastspeech2 \
- --clip-norm 5.0 --n-frames-per-step 1 \
- --dropout 0.1 --attention-dropout 0.1 \
- --optimizer adam --lr 5e-4 --lr-scheduler inverse_sqrt --warmup-updates 4000 \
- --seed 1 --update-freq 8 --eval-inference --best-checkpoint-metric mcd_loss
-```
-
-
-## Inference
-Average the last 5 checkpoints, generate the test split spectrogram and waveform using the default Griffin-Lim vocoder:
-```bash
-SPLIT=test
-CHECKPOINT_NAME=avg_last_5
-CHECKPOINT_PATH=${SAVE_DIR}/checkpoint_${CHECKPOINT_NAME}.pt
-python scripts/average_checkpoints.py --inputs ${SAVE_DIR} \
- --num-epoch-checkpoints 5 \
- --output ${CHECKPOINT_PATH}
-
-python -m examples.speech_synthesis.generate_waveform ${FEATURE_MANIFEST_ROOT} \
- --config-yaml config.yaml --gen-subset ${SPLIT} --task text_to_speech \
- --path ${CHECKPOINT_PATH} --max-tokens 50000 --spec-bwd-max-iter 32 \
- --dump-waveforms
-```
-which dumps files (waveform, feature, attention plot, etc.) to `${SAVE_DIR}/generate-${CHECKPOINT_NAME}-${SPLIT}`. To
-re-synthesize target waveforms for automatic evaluation, add `--dump-target`.
-
-## Automatic Evaluation
-To start with, generate the manifest for synthetic speech, which will be taken as inputs by evaluation scripts.
-```bash
-python -m examples.speech_synthesis.evaluation.get_eval_manifest \
- --generation-root ${SAVE_DIR}/generate-${CHECKPOINT_NAME}-${SPLIT} \
- --audio-manifest ${AUDIO_MANIFEST_ROOT}/${SPLIT}.audio.tsv \
- --output-path ${EVAL_OUTPUT_ROOT}/eval.tsv \
- --vocoder griffin_lim --sample-rate 22050 --audio-format flac \
- --use-resynthesized-target
-```
-Speech recognition (ASR) models usually operate at lower sample rates (e.g. 16kHz). For the WER/CER metric,
-you may need to resample the audios accordingly --- add `--output-sample-rate 16000` for `generate_waveform.py` and
-use `--sample-rate 16000` for `get_eval_manifest.py`.
-
-
-#### WER/CER metric
-We use wav2vec 2.0 ASR model as example. [Download](https://github.com/pytorch/fairseq/tree/main/examples/wav2vec)
-the model checkpoint and dictionary, then compute WER/CER with
-```bash
-python -m examples.speech_synthesis.evaluation.eval_asr \
- --audio-header syn --text-header text --err-unit char --split ${SPLIT} \
- --w2v-ckpt ${WAV2VEC2_CHECKPOINT_PATH} --w2v-dict-dir ${WAV2VEC2_DICT_DIR} \
- --raw-manifest ${EVAL_OUTPUT_ROOT}/eval_16khz.tsv --asr-dir ${EVAL_OUTPUT_ROOT}/asr
-```
-
-#### MCD/MSD metric
-```bash
-python -m examples.speech_synthesis.evaluation.eval_sp \
- ${EVAL_OUTPUT_ROOT}/eval.tsv --mcd --msd
-```
-
-#### F0 metrics
-```bash
-python -m examples.speech_synthesis.evaluation.eval_f0 \
- ${EVAL_OUTPUT_ROOT}/eval.tsv --gpe --vde --ffe
-```
-
-
-## Results
-
-| --arch | Params | Test MCD | Model |
-|---|---|---|---|
-| tts_transformer | 54M | 3.8 | [Download](https://dl.fbaipublicfiles.com/fairseq/s2/ljspeech_transformer_phn.tar) |
-| fastspeech2 | 41M | 3.8 | [Download](https://dl.fbaipublicfiles.com/fairseq/s2/ljspeech_fastspeech2_phn.tar) |
-
-[[Back]](..)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/docs/vctk_example.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/docs/vctk_example.md
deleted file mode 100644
index 6808256d44ef08b0350aa4d74fa062673990137a..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/docs/vctk_example.md
+++ /dev/null
@@ -1,61 +0,0 @@
-[[Back]](..)
-
-# VCTK
-
-[VCTK](https://datashare.ed.ac.uk/handle/10283/3443) is an open English speech corpus. We provide examples
-for building [Transformer](https://arxiv.org/abs/1809.08895) models on this dataset.
-
-
-## Data preparation
-Download data, create splits and generate audio manifests with
-```bash
-python -m examples.speech_synthesis.preprocessing.get_vctk_audio_manifest \
- --output-data-root ${AUDIO_DATA_ROOT} \
- --output-manifest-root ${AUDIO_MANIFEST_ROOT}
-```
-
-To denoise audio and trim leading/trailing silence using signal processing based VAD, run
-```bash
-for SPLIT in dev test train; do
- python -m examples.speech_synthesis.preprocessing.denoise_and_vad_audio \
- --audio-manifest ${AUDIO_MANIFEST_ROOT}/${SPLIT}.audio.tsv \
- --output-dir ${PROCESSED_DATA_ROOT} \
- --denoise --vad --vad-agg-level 3
-done
-```
-which generates a new audio TSV manifest under `${PROCESSED_DATA_ROOT}` with updated path to the processed audio and
-a new column for SNR.
-
-To do filtering by CER, follow the [Automatic Evaluation](../docs/ljspeech_example.md#automatic-evaluation) section to
-run ASR model (add `--eval-target` to `get_eval_manifest` for evaluation on the reference audio; add `--err-unit char`
-to `eval_asr` to compute CER instead of WER). The example-level CER is saved to
-`${EVAL_OUTPUT_ROOT}/uer_cer.${SPLIT}.tsv`.
-
-Then, extract log-Mel spectrograms, generate feature manifest and create data configuration YAML with
-```bash
-python -m examples.speech_synthesis.preprocessing.get_feature_manifest \
- --audio-manifest-root ${PROCESSED_DATA_ROOT} \
- --output-root ${FEATURE_MANIFEST_ROOT} \
- --ipa-vocab --use-g2p \
- --snr-threshold 15 \
- --cer-threshold 0.1 --cer-tsv-path ${EVAL_OUTPUT_ROOT}/uer_cer.${SPLIT}.tsv
-```
-where we use phoneme inputs (`--ipa-vocab --use-g2p`) as example. For sample filtering, we set the SNR and CER threshold
-to 15 and 10%, respectively.
-
-## Training
-(Please refer to [the LJSpeech example](../docs/ljspeech_example.md#transformer).)
-
-## Inference
-(Please refer to [the LJSpeech example](../docs/ljspeech_example.md#inference).)
-
-## Automatic Evaluation
-(Please refer to [the LJSpeech example](../docs/ljspeech_example.md#automatic-evaluation).)
-
-## Results
-
-| --arch | Params | Test MCD | Model |
-|---|---|---|---|
-| tts_transformer | 54M | 3.4 | [Download](https://dl.fbaipublicfiles.com/fairseq/s2/vctk_transformer_phn.tar) |
-
-[[Back]](..)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/evaluation/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/evaluation/__init__.py
deleted file mode 100644
index 6264236915a7269a4d920ee8213004374dd86a9a..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/evaluation/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/evaluation/eval_asr.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/evaluation/eval_asr.py
deleted file mode 100644
index 005a11bfb34ca477ad9e133acd60f249e66cda47..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/evaluation/eval_asr.py
+++ /dev/null
@@ -1,128 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import editdistance
-import re
-import shutil
-import soundfile as sf
-import subprocess
-from pathlib import Path
-
-from examples.speech_to_text.data_utils import load_tsv_to_dicts
-
-
-def preprocess_text(text):
- text = "|".join(re.sub(r"[^A-Z' ]", " ", text.upper()).split())
- text = " ".join(text)
- return text
-
-
-def prepare_w2v_data(
- dict_dir, sample_rate, label, audio_paths, texts, split, data_dir
-):
- data_dir.mkdir(parents=True, exist_ok=True)
- shutil.copyfile(
- dict_dir / f"dict.{label}.txt",
- data_dir / f"dict.{label}.txt"
- )
- with open(data_dir / f"{split}.tsv", "w") as f:
- f.write("/\n")
- for audio_path in audio_paths:
- wav, sr = sf.read(audio_path)
- assert sr == sample_rate, f"{sr} != sample_rate"
- nsample = len(wav)
- f.write(f"{audio_path}\t{nsample}\n")
- with open(data_dir / f"{split}.{label}", "w") as f:
- for text in texts:
- text = preprocess_text(text)
- f.write(f"{text}\n")
-
-
-def run_asr(asr_dir, split, w2v_ckpt, w2v_label, res_dir):
- """
- results will be saved at
- {res_dir}/{ref,hypo}.word-{w2v_ckpt.filename}-{split}.txt
- """
- cmd = ["python", "-m", "examples.speech_recognition.infer"]
- cmd += [str(asr_dir.resolve())]
- cmd += ["--task", "audio_finetuning", "--nbest", "1", "--quiet"]
- cmd += ["--w2l-decoder", "viterbi", "--criterion", "ctc"]
- cmd += ["--post-process", "letter", "--max-tokens", "4000000"]
- cmd += ["--path", str(w2v_ckpt.resolve()), "--labels", w2v_label]
- cmd += ["--gen-subset", split, "--results-path", str(res_dir.resolve())]
-
- print(f"running cmd:\n{' '.join(cmd)}")
- subprocess.run(cmd, check=True)
-
-
-def compute_error_rate(hyp_wrd_path, ref_wrd_path, unit="word"):
- """each line is " (None-)" """
- tokenize_line = {
- "word": lambda x: re.sub(r" \(.*\)$", "", x.rstrip()).split(),
- "char": lambda x: list(re.sub(r" \(.*\)$", "", x.rstrip()))
- }.get(unit)
- if tokenize_line is None:
- raise ValueError(f"{unit} not supported")
-
- inds = [int(re.sub(r"\D*(\d*)\D*", r"\1", line))
- for line in open(hyp_wrd_path)]
- hyps = [tokenize_line(line) for line in open(hyp_wrd_path)]
- refs = [tokenize_line(line) for line in open(ref_wrd_path)]
- assert(len(hyps) == len(refs))
- err_rates = [
- editdistance.eval(hyp, ref) / len(ref) for hyp, ref in zip(hyps, refs)
- ]
- ind_to_err_rates = {i: e for i, e in zip(inds, err_rates)}
- return ind_to_err_rates
-
-
-def main(args):
- samples = load_tsv_to_dicts(args.raw_manifest)
- ids = [
- sample[args.id_header] if args.id_header else "" for sample in samples
- ]
- audio_paths = [sample[args.audio_header] for sample in samples]
- texts = [sample[args.text_header] for sample in samples]
-
- prepare_w2v_data(
- args.w2v_dict_dir,
- args.w2v_sample_rate,
- args.w2v_label,
- audio_paths,
- texts,
- args.split,
- args.asr_dir
- )
- run_asr(args.asr_dir, args.split, args.w2v_ckpt, args.w2v_label, args.asr_dir)
- ind_to_err_rates = compute_error_rate(
- args.asr_dir / f"hypo.word-{args.w2v_ckpt.name}-{args.split}.txt",
- args.asr_dir / f"ref.word-{args.w2v_ckpt.name}-{args.split}.txt",
- args.err_unit,
- )
-
- uer_path = args.asr_dir / f"uer_{args.err_unit}.{args.split}.tsv"
- with open(uer_path, "w") as f:
- f.write("id\taudio\tuer\n")
- for ind, (id_, audio_path) in enumerate(zip(ids, audio_paths)):
- f.write(f"{id_}\t{audio_path}\t{ind_to_err_rates[ind]:.4f}\n")
-
-
-if __name__ == "__main__":
- parser = argparse.ArgumentParser()
- parser.add_argument("--raw-manifest", required=True, type=Path)
- parser.add_argument("--asr-dir", required=True, type=Path)
- parser.add_argument("--id-header", default="id", type=str)
- parser.add_argument("--audio-header", default="audio", type=str)
- parser.add_argument("--text-header", default="src_text", type=str)
- parser.add_argument("--split", default="raw", type=str)
- parser.add_argument("--w2v-ckpt", required=True, type=Path)
- parser.add_argument("--w2v-dict-dir", required=True, type=Path)
- parser.add_argument("--w2v-sample-rate", default=16000, type=int)
- parser.add_argument("--w2v-label", default="ltr", type=str)
- parser.add_argument("--err-unit", default="word", type=str)
- args = parser.parse_args()
-
- main(args)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/evaluation/eval_f0.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/evaluation/eval_f0.py
deleted file mode 100644
index df721d683113b44957149cfc3cddaba36520a22c..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/evaluation/eval_f0.py
+++ /dev/null
@@ -1,266 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-"""
-Signal processing-based evaluation using waveforms
-"""
-import numpy as np
-import os.path as op
-
-import torchaudio
-import tqdm
-from tabulate import tabulate
-
-from examples.speech_synthesis.utils import (
- gross_pitch_error, voicing_decision_error, f0_frame_error
-)
-from examples.speech_synthesis.evaluation.eval_sp import load_eval_spec
-
-
-def difference_function(x, n, tau_max):
- """
- Compute difference function of data x. This solution is implemented directly
- with Numpy fft.
-
-
- :param x: audio data
- :param n: length of data
- :param tau_max: integration window size
- :return: difference function
- :rtype: list
- """
-
- x = np.array(x, np.float64)
- w = x.size
- tau_max = min(tau_max, w)
- x_cumsum = np.concatenate((np.array([0.]), (x * x).cumsum()))
- size = w + tau_max
- p2 = (size // 32).bit_length()
- nice_numbers = (16, 18, 20, 24, 25, 27, 30, 32)
- size_pad = min(x * 2 ** p2 for x in nice_numbers if x * 2 ** p2 >= size)
- fc = np.fft.rfft(x, size_pad)
- conv = np.fft.irfft(fc * fc.conjugate())[:tau_max]
- return x_cumsum[w:w - tau_max:-1] + x_cumsum[w] - x_cumsum[:tau_max] - \
- 2 * conv
-
-
-def cumulative_mean_normalized_difference_function(df, n):
- """
- Compute cumulative mean normalized difference function (CMND).
-
- :param df: Difference function
- :param n: length of data
- :return: cumulative mean normalized difference function
- :rtype: list
- """
-
- # scipy method
- cmn_df = df[1:] * range(1, n) / np.cumsum(df[1:]).astype(float)
- return np.insert(cmn_df, 0, 1)
-
-
-def get_pitch(cmdf, tau_min, tau_max, harmo_th=0.1):
- """
- Return fundamental period of a frame based on CMND function.
-
- :param cmdf: Cumulative Mean Normalized Difference function
- :param tau_min: minimum period for speech
- :param tau_max: maximum period for speech
- :param harmo_th: harmonicity threshold to determine if it is necessary to
- compute pitch frequency
- :return: fundamental period if there is values under threshold, 0 otherwise
- :rtype: float
- """
- tau = tau_min
- while tau < tau_max:
- if cmdf[tau] < harmo_th:
- while tau + 1 < tau_max and cmdf[tau + 1] < cmdf[tau]:
- tau += 1
- return tau
- tau += 1
-
- return 0 # if unvoiced
-
-
-def compute_yin(sig, sr, w_len=512, w_step=256, f0_min=100, f0_max=500,
- harmo_thresh=0.1):
- """
-
- Compute the Yin Algorithm. Return fundamental frequency and harmonic rate.
-
- https://github.com/NVIDIA/mellotron adaption of
- https://github.com/patriceguyot/Yin
-
- :param sig: Audio signal (list of float)
- :param sr: sampling rate (int)
- :param w_len: size of the analysis window (samples)
- :param w_step: size of the lag between two consecutives windows (samples)
- :param f0_min: Minimum fundamental frequency that can be detected (hertz)
- :param f0_max: Maximum fundamental frequency that can be detected (hertz)
- :param harmo_thresh: Threshold of detection. The yalgorithmù return the
- first minimum of the CMND function below this threshold.
-
- :returns:
-
- * pitches: list of fundamental frequencies,
- * harmonic_rates: list of harmonic rate values for each fundamental
- frequency value (= confidence value)
- * argmins: minimums of the Cumulative Mean Normalized DifferenceFunction
- * times: list of time of each estimation
- :rtype: tuple
- """
-
- tau_min = int(sr / f0_max)
- tau_max = int(sr / f0_min)
-
- # time values for each analysis window
- time_scale = range(0, len(sig) - w_len, w_step)
- times = [t/float(sr) for t in time_scale]
- frames = [sig[t:t + w_len] for t in time_scale]
-
- pitches = [0.0] * len(time_scale)
- harmonic_rates = [0.0] * len(time_scale)
- argmins = [0.0] * len(time_scale)
-
- for i, frame in enumerate(frames):
- # Compute YIN
- df = difference_function(frame, w_len, tau_max)
- cm_df = cumulative_mean_normalized_difference_function(df, tau_max)
- p = get_pitch(cm_df, tau_min, tau_max, harmo_thresh)
-
- # Get results
- if np.argmin(cm_df) > tau_min:
- argmins[i] = float(sr / np.argmin(cm_df))
- if p != 0: # A pitch was found
- pitches[i] = float(sr / p)
- harmonic_rates[i] = cm_df[p]
- else: # No pitch, but we compute a value of the harmonic rate
- harmonic_rates[i] = min(cm_df)
-
- return pitches, harmonic_rates, argmins, times
-
-
-def extract_f0(samples):
- f0_samples = []
- for sample in tqdm.tqdm(samples):
- if not op.isfile(sample["ref"]) or not op.isfile(sample["syn"]):
- f0_samples.append(None)
- continue
-
- # assume single channel
- yref, sr = torchaudio.load(sample["ref"])
- ysyn, _sr = torchaudio.load(sample["syn"])
- yref, ysyn = yref[0], ysyn[0]
- assert sr == _sr, f"{sr} != {_sr}"
-
- yref_f0 = compute_yin(yref, sr)
- ysyn_f0 = compute_yin(ysyn, sr)
-
- f0_samples += [
- {
- "ref": yref_f0,
- "syn": ysyn_f0
- }
- ]
-
- return f0_samples
-
-
-def eval_f0_error(samples, distortion_fn):
- results = []
- for sample in tqdm.tqdm(samples):
- if sample is None:
- results.append(None)
- continue
- # assume single channel
- yref_f, _, _, yref_t = sample["ref"]
- ysyn_f, _, _, ysyn_t = sample["syn"]
-
- yref_f = np.array(yref_f)
- yref_t = np.array(yref_t)
- ysyn_f = np.array(ysyn_f)
- ysyn_t = np.array(ysyn_t)
-
- distortion = distortion_fn(yref_t, yref_f, ysyn_t, ysyn_f)
- results.append((distortion.item(),
- len(yref_f),
- len(ysyn_f)
- ))
- return results
-
-
-def eval_gross_pitch_error(samples):
- return eval_f0_error(samples, gross_pitch_error)
-
-
-def eval_voicing_decision_error(samples):
- return eval_f0_error(samples, voicing_decision_error)
-
-
-def eval_f0_frame_error(samples):
- return eval_f0_error(samples, f0_frame_error)
-
-
-def print_results(results, show_bin):
- results = np.array(list(filter(lambda x: x is not None, results)))
-
- np.set_printoptions(precision=3)
-
- def _print_result(results):
- res = {
- "nutt": len(results),
- "error": results[:, 0].mean(),
- "std": results[:, 0].std(),
- "dur_ref": int(results[:, 1].sum()),
- "dur_syn": int(results[:, 2].sum()),
- }
- print(tabulate([res.values()], res.keys(), floatfmt=".4f"))
-
- print(">>>> ALL")
- _print_result(results)
-
- if show_bin:
- edges = [0, 200, 400, 600, 800, 1000, 2000, 4000]
- for i in range(1, len(edges)):
- mask = np.logical_and(results[:, 1] >= edges[i-1],
- results[:, 1] < edges[i])
- if not mask.any():
- continue
- bin_results = results[mask]
- print(f">>>> ({edges[i-1]}, {edges[i]})")
- _print_result(bin_results)
-
-
-def main(eval_f0, gpe, vde, ffe, show_bin):
- samples = load_eval_spec(eval_f0)
- if gpe or vde or ffe:
- f0_samples = extract_f0(samples)
-
- if gpe:
- print("===== Evaluate Gross Pitch Error =====")
- results = eval_gross_pitch_error(f0_samples)
- print_results(results, show_bin)
- if vde:
- print("===== Evaluate Voicing Decision Error =====")
- results = eval_voicing_decision_error(f0_samples)
- print_results(results, show_bin)
- if ffe:
- print("===== Evaluate F0 Frame Error =====")
- results = eval_f0_frame_error(f0_samples)
- print_results(results, show_bin)
-
-
-if __name__ == "__main__":
- import argparse
-
- parser = argparse.ArgumentParser()
- parser.add_argument("eval_f0")
- parser.add_argument("--gpe", action="store_true")
- parser.add_argument("--vde", action="store_true")
- parser.add_argument("--ffe", action="store_true")
- parser.add_argument("--show-bin", action="store_true")
- args = parser.parse_args()
-
- main(args.eval_f0, args.gpe, args.vde, args.ffe, args.show_bin)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/evaluation/eval_sp.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/evaluation/eval_sp.py
deleted file mode 100644
index 702c4980389624f788abc0b42cdf54757a52512f..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/evaluation/eval_sp.py
+++ /dev/null
@@ -1,131 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-
-"""
-Signal processing-based evaluation using waveforms
-"""
-
-import csv
-import numpy as np
-import os.path as op
-
-import torch
-import tqdm
-from tabulate import tabulate
-import torchaudio
-
-from examples.speech_synthesis.utils import batch_mel_spectral_distortion
-from fairseq.tasks.text_to_speech import batch_mel_cepstral_distortion
-
-
-def load_eval_spec(path):
- with open(path) as f:
- reader = csv.DictReader(f, delimiter='\t')
- samples = list(reader)
- return samples
-
-
-def eval_distortion(samples, distortion_fn, device="cuda"):
- nmiss = 0
- results = []
- for sample in tqdm.tqdm(samples):
- if not op.isfile(sample["ref"]) or not op.isfile(sample["syn"]):
- nmiss += 1
- results.append(None)
- continue
- # assume single channel
- yref, sr = torchaudio.load(sample["ref"])
- ysyn, _sr = torchaudio.load(sample["syn"])
- yref, ysyn = yref[0].to(device), ysyn[0].to(device)
- assert sr == _sr, f"{sr} != {_sr}"
-
- distortion, extra = distortion_fn([yref], [ysyn], sr, None)[0]
- _, _, _, _, _, pathmap = extra
- nins = torch.sum(pathmap.sum(dim=1) - 1) # extra frames in syn
- ndel = torch.sum(pathmap.sum(dim=0) - 1) # missing frames from syn
- results.append(
- (distortion.item(), # path distortion
- pathmap.size(0), # yref num frames
- pathmap.size(1), # ysyn num frames
- pathmap.sum().item(), # path length
- nins.item(), # insertion
- ndel.item(), # deletion
- )
- )
- return results
-
-
-def eval_mel_cepstral_distortion(samples, device="cuda"):
- return eval_distortion(samples, batch_mel_cepstral_distortion, device)
-
-
-def eval_mel_spectral_distortion(samples, device="cuda"):
- return eval_distortion(samples, batch_mel_spectral_distortion, device)
-
-
-def print_results(results, show_bin):
- results = np.array(list(filter(lambda x: x is not None, results)))
-
- np.set_printoptions(precision=3)
-
- def _print_result(results):
- dist, dur_ref, dur_syn, dur_ali, nins, ndel = results.sum(axis=0)
- res = {
- "nutt": len(results),
- "dist": dist,
- "dur_ref": int(dur_ref),
- "dur_syn": int(dur_syn),
- "dur_ali": int(dur_ali),
- "dist_per_ref_frm": dist/dur_ref,
- "dist_per_syn_frm": dist/dur_syn,
- "dist_per_ali_frm": dist/dur_ali,
- "ins": nins/dur_ref,
- "del": ndel/dur_ref,
- }
- print(tabulate(
- [res.values()],
- res.keys(),
- floatfmt=".4f"
- ))
-
- print(">>>> ALL")
- _print_result(results)
-
- if show_bin:
- edges = [0, 200, 400, 600, 800, 1000, 2000, 4000]
- for i in range(1, len(edges)):
- mask = np.logical_and(results[:, 1] >= edges[i-1],
- results[:, 1] < edges[i])
- if not mask.any():
- continue
- bin_results = results[mask]
- print(f">>>> ({edges[i-1]}, {edges[i]})")
- _print_result(bin_results)
-
-
-def main(eval_spec, mcd, msd, show_bin):
- samples = load_eval_spec(eval_spec)
- device = "cpu"
- if mcd:
- print("===== Evaluate Mean Cepstral Distortion =====")
- results = eval_mel_cepstral_distortion(samples, device)
- print_results(results, show_bin)
- if msd:
- print("===== Evaluate Mean Spectral Distortion =====")
- results = eval_mel_spectral_distortion(samples, device)
- print_results(results, show_bin)
-
-
-if __name__ == "__main__":
- import argparse
- parser = argparse.ArgumentParser()
- parser.add_argument("eval_spec")
- parser.add_argument("--mcd", action="store_true")
- parser.add_argument("--msd", action="store_true")
- parser.add_argument("--show-bin", action="store_true")
- args = parser.parse_args()
-
- main(args.eval_spec, args.mcd, args.msd, args.show_bin)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/evaluation/get_eval_manifest.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/evaluation/get_eval_manifest.py
deleted file mode 100644
index 44b3685bb221a5bd4522668465902fb1d2eb40ec..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/evaluation/get_eval_manifest.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-
-import csv
-from pathlib import Path
-
-
-def main(args):
- """
- `uid syn ref text`
- """
- in_root = Path(args.generation_root).resolve()
- ext = args.audio_format
- with open(args.audio_manifest) as f, open(args.output_path, "w") as f_out:
- reader = csv.DictReader(
- f, delimiter="\t", quotechar=None, doublequote=False,
- lineterminator="\n", quoting=csv.QUOTE_NONE
- )
- header = ["id", "syn", "ref", "text", "speaker"]
- f_out.write("\t".join(header) + "\n")
- for row in reader:
- dir_name = f"{ext}_{args.sample_rate}hz_{args.vocoder}"
- id_ = row["id"]
- syn = (in_root / dir_name / f"{id_}.{ext}").as_posix()
- ref = row["audio"]
- if args.use_resynthesized_target:
- ref = (in_root / f"{dir_name}_tgt" / f"{id_}.{ext}").as_posix()
- if args.eval_target:
- syn = row["audio"]
- sample = [id_, syn, ref, row["tgt_text"], row["speaker"]]
- f_out.write("\t".join(sample) + "\n")
- print(f"wrote evaluation file to {args.output_path}")
-
-
-if __name__ == "__main__":
- import argparse
- parser = argparse.ArgumentParser()
- parser.add_argument(
- "--generation-root", help="output directory for generate_waveform.py"
- )
- parser.add_argument(
- "--audio-manifest",
- help="used to determine the original utterance ID and text"
- )
- parser.add_argument(
- "--output-path", help="path to output evaluation spec file"
- )
- parser.add_argument(
- "--use-resynthesized-target", action="store_true",
- help="use resynthesized reference instead of the original audio"
- )
- parser.add_argument(
- "--eval-target", action="store_true",
- help="evaluate reference instead of model prediction"
- )
- parser.add_argument("--vocoder", type=str, default="griffin_lim")
- parser.add_argument("--sample-rate", type=int, default=22_050)
- parser.add_argument("--audio-format", type=str, default="wav")
- args = parser.parse_args()
-
- main(args)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/generate_waveform.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/generate_waveform.py
deleted file mode 100644
index 3b56190dbe7bbce72992e3a547415899df2f18db..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/generate_waveform.py
+++ /dev/null
@@ -1,192 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import ast
-import logging
-import matplotlib.pyplot as plt
-import numpy as np
-from pathlib import Path
-import soundfile as sf
-import sys
-import torch
-import torchaudio
-
-from fairseq import checkpoint_utils, options, tasks, utils
-from fairseq.logging import progress_bar
-from fairseq.tasks.text_to_speech import plot_tts_output
-from fairseq.data.audio.text_to_speech_dataset import TextToSpeechDataset
-
-
-logging.basicConfig()
-logging.root.setLevel(logging.INFO)
-logging.basicConfig(level=logging.INFO)
-logger = logging.getLogger(__name__)
-
-
-def make_parser():
- parser = options.get_speech_generation_parser()
- parser.add_argument("--dump-features", action="store_true")
- parser.add_argument("--dump-waveforms", action="store_true")
- parser.add_argument("--dump-attentions", action="store_true")
- parser.add_argument("--dump-eos-probs", action="store_true")
- parser.add_argument("--dump-plots", action="store_true")
- parser.add_argument("--dump-target", action="store_true")
- parser.add_argument("--output-sample-rate", default=22050, type=int)
- parser.add_argument("--teacher-forcing", action="store_true")
- parser.add_argument(
- "--audio-format", type=str, default="wav", choices=["wav", "flac"]
- )
- return parser
-
-
-def postprocess_results(
- dataset: TextToSpeechDataset, sample, hypos, resample_fn, dump_target
-):
- def to_np(x):
- return None if x is None else x.detach().cpu().numpy()
-
- sample_ids = [dataset.ids[i] for i in sample["id"].tolist()]
- texts = sample["src_texts"] if "src_texts" in sample else [""] * len(hypos)
- attns = [to_np(hypo["attn"]) for hypo in hypos]
- eos_probs = [to_np(hypo.get("eos_prob", None)) for hypo in hypos]
- feat_preds = [to_np(hypo["feature"]) for hypo in hypos]
- wave_preds = [to_np(resample_fn(h["waveform"])) for h in hypos]
- if dump_target:
- feat_targs = [to_np(hypo["targ_feature"]) for hypo in hypos]
- wave_targs = [to_np(resample_fn(h["targ_waveform"])) for h in hypos]
- else:
- feat_targs = [None for _ in hypos]
- wave_targs = [None for _ in hypos]
-
- return zip(sample_ids, texts, attns, eos_probs, feat_preds, wave_preds,
- feat_targs, wave_targs)
-
-
-def dump_result(
- is_na_model,
- args,
- vocoder,
- sample_id,
- text,
- attn,
- eos_prob,
- feat_pred,
- wave_pred,
- feat_targ,
- wave_targ,
-):
- sample_rate = args.output_sample_rate
- out_root = Path(args.results_path)
- if args.dump_features:
- feat_dir = out_root / "feat"
- feat_dir.mkdir(exist_ok=True, parents=True)
- np.save(feat_dir / f"{sample_id}.npy", feat_pred)
- if args.dump_target:
- feat_tgt_dir = out_root / "feat_tgt"
- feat_tgt_dir.mkdir(exist_ok=True, parents=True)
- np.save(feat_tgt_dir / f"{sample_id}.npy", feat_targ)
- if args.dump_attentions:
- attn_dir = out_root / "attn"
- attn_dir.mkdir(exist_ok=True, parents=True)
- np.save(attn_dir / f"{sample_id}.npy", attn.numpy())
- if args.dump_eos_probs and not is_na_model:
- eos_dir = out_root / "eos"
- eos_dir.mkdir(exist_ok=True, parents=True)
- np.save(eos_dir / f"{sample_id}.npy", eos_prob)
-
- if args.dump_plots:
- images = [feat_pred.T] if is_na_model else [feat_pred.T, attn]
- names = ["output"] if is_na_model else ["output", "alignment"]
- if feat_targ is not None:
- images = [feat_targ.T] + images
- names = [f"target (idx={sample_id})"] + names
- if is_na_model:
- plot_tts_output(images, names, attn, "alignment", suptitle=text)
- else:
- plot_tts_output(images, names, eos_prob, "eos prob", suptitle=text)
- plot_dir = out_root / "plot"
- plot_dir.mkdir(exist_ok=True, parents=True)
- plt.savefig(plot_dir / f"{sample_id}.png")
- plt.close()
-
- if args.dump_waveforms:
- ext = args.audio_format
- if wave_pred is not None:
- wav_dir = out_root / f"{ext}_{sample_rate}hz_{vocoder}"
- wav_dir.mkdir(exist_ok=True, parents=True)
- sf.write(wav_dir / f"{sample_id}.{ext}", wave_pred, sample_rate)
- if args.dump_target and wave_targ is not None:
- wav_tgt_dir = out_root / f"{ext}_{sample_rate}hz_{vocoder}_tgt"
- wav_tgt_dir.mkdir(exist_ok=True, parents=True)
- sf.write(wav_tgt_dir / f"{sample_id}.{ext}", wave_targ, sample_rate)
-
-
-def main(args):
- assert(args.dump_features or args.dump_waveforms or args.dump_attentions
- or args.dump_eos_probs or args.dump_plots)
- if args.max_tokens is None and args.batch_size is None:
- args.max_tokens = 8000
- logger.info(args)
-
- use_cuda = torch.cuda.is_available() and not args.cpu
- task = tasks.setup_task(args)
- models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task(
- [args.path],
- task=task,
- arg_overrides=ast.literal_eval(args.model_overrides),
- )
- model = models[0].cuda() if use_cuda else models[0]
- # use the original n_frames_per_step
- task.args.n_frames_per_step = saved_cfg.task.n_frames_per_step
- task.load_dataset(args.gen_subset, task_cfg=saved_cfg.task)
-
- data_cfg = task.data_cfg
- sample_rate = data_cfg.config.get("features", {}).get("sample_rate", 22050)
- resample_fn = {
- False: lambda x: x,
- True: lambda x: torchaudio.sox_effects.apply_effects_tensor(
- x.detach().cpu().unsqueeze(0), sample_rate,
- [['rate', str(args.output_sample_rate)]]
- )[0].squeeze(0)
- }.get(args.output_sample_rate != sample_rate)
- if args.output_sample_rate != sample_rate:
- logger.info(f"resampling to {args.output_sample_rate}Hz")
-
- generator = task.build_generator([model], args)
- itr = task.get_batch_iterator(
- dataset=task.dataset(args.gen_subset),
- max_tokens=args.max_tokens,
- max_sentences=args.batch_size,
- max_positions=(sys.maxsize, sys.maxsize),
- ignore_invalid_inputs=args.skip_invalid_size_inputs_valid_test,
- required_batch_size_multiple=args.required_batch_size_multiple,
- num_shards=args.num_shards,
- shard_id=args.shard_id,
- num_workers=args.num_workers,
- data_buffer_size=args.data_buffer_size,
- ).next_epoch_itr(shuffle=False)
-
- Path(args.results_path).mkdir(exist_ok=True, parents=True)
- is_na_model = getattr(model, "NON_AUTOREGRESSIVE", False)
- dataset = task.dataset(args.gen_subset)
- vocoder = task.args.vocoder
- with progress_bar.build_progress_bar(args, itr) as t:
- for sample in t:
- sample = utils.move_to_cuda(sample) if use_cuda else sample
- hypos = generator.generate(model, sample, has_targ=args.dump_target)
- for result in postprocess_results(
- dataset, sample, hypos, resample_fn, args.dump_target
- ):
- dump_result(is_na_model, args, vocoder, *result)
-
-
-def cli_main():
- parser = make_parser()
- args = options.parse_args_and_arch(parser)
- main(args)
-
-
-if __name__ == "__main__":
- cli_main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/__init__.py
deleted file mode 100644
index 6264236915a7269a4d920ee8213004374dd86a9a..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoise_and_vad_audio.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoise_and_vad_audio.py
deleted file mode 100644
index 4e13b38a5d3fb44dd3969e6afcb8f202274ee3b7..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoise_and_vad_audio.py
+++ /dev/null
@@ -1,204 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import logging
-import os
-import csv
-import tempfile
-from collections import defaultdict
-from pathlib import Path
-
-import torchaudio
-try:
- import webrtcvad
-except ImportError:
- raise ImportError("Please install py-webrtcvad: pip install webrtcvad")
-import pandas as pd
-from tqdm import tqdm
-
-from examples.speech_synthesis.preprocessing.denoiser.pretrained import master64
-import examples.speech_synthesis.preprocessing.denoiser.utils as utils
-from examples.speech_synthesis.preprocessing.vad import (
- frame_generator, vad_collector, read_wave, write_wave, FS_MS, THRESHOLD,
- SCALE
-)
-from examples.speech_to_text.data_utils import save_df_to_tsv
-
-
-log = logging.getLogger(__name__)
-
-PATHS = ["after_denoise", "after_vad"]
-MIN_T = 0.05
-
-
-def generate_tmp_filename(extension="txt"):
- return tempfile._get_default_tempdir() + "/" + \
- next(tempfile._get_candidate_names()) + "." + extension
-
-
-def convert_sr(inpath, sr, output_path=None):
- if not output_path:
- output_path = generate_tmp_filename("wav")
- cmd = f"sox {inpath} -r {sr} {output_path}"
- os.system(cmd)
- return output_path
-
-
-def apply_vad(vad, inpath):
- audio, sample_rate = read_wave(inpath)
- frames = frame_generator(FS_MS, audio, sample_rate)
- frames = list(frames)
- segments = vad_collector(sample_rate, FS_MS, 300, vad, frames)
- merge_segments = list()
- timestamp_start = 0.0
- timestamp_end = 0.0
- # removing start, end, and long sequences of sils
- for i, segment in enumerate(segments):
- merge_segments.append(segment[0])
- if i and timestamp_start:
- sil_duration = segment[1] - timestamp_end
- if sil_duration > THRESHOLD:
- merge_segments.append(int(THRESHOLD / SCALE) * (b'\x00'))
- else:
- merge_segments.append(int((sil_duration / SCALE)) * (b'\x00'))
- timestamp_start = segment[1]
- timestamp_end = segment[2]
- segment = b''.join(merge_segments)
- return segment, sample_rate
-
-
-def write(wav, filename, sr=16_000):
- # Normalize audio if it prevents clipping
- wav = wav / max(wav.abs().max().item(), 1)
- torchaudio.save(filename, wav.cpu(), sr, encoding="PCM_S",
- bits_per_sample=16)
-
-
-def process(args):
- # making sure we are requested either denoise or vad
- if not args.denoise and not args.vad:
- log.error("No denoise or vad is requested.")
- return
-
- log.info("Creating out directories...")
- if args.denoise:
- out_denoise = Path(args.output_dir).absolute().joinpath(PATHS[0])
- out_denoise.mkdir(parents=True, exist_ok=True)
- if args.vad:
- out_vad = Path(args.output_dir).absolute().joinpath(PATHS[1])
- out_vad.mkdir(parents=True, exist_ok=True)
-
- log.info("Loading pre-trained speech enhancement model...")
- model = master64().to(args.device)
-
- log.info("Building the VAD model...")
- vad = webrtcvad.Vad(int(args.vad_agg_level))
-
- # preparing the output dict
- output_dict = defaultdict(list)
-
- log.info(f"Parsing input manifest: {args.audio_manifest}")
- with open(args.audio_manifest, "r") as f:
- manifest_dict = csv.DictReader(f, delimiter="\t")
- for row in tqdm(manifest_dict):
- filename = str(row["audio"])
-
- final_output = filename
- keep_sample = True
- n_frames = row["n_frames"]
- snr = -1
- if args.denoise:
- output_path_denoise = out_denoise.joinpath(Path(filename).name)
- # convert to 16khz in case we use a differet sr
- tmp_path = convert_sr(final_output, 16000)
-
- # loading audio file and generating the enhanced version
- out, sr = torchaudio.load(tmp_path)
- out = out.to(args.device)
- estimate = model(out)
- estimate = (1 - args.dry_wet) * estimate + args.dry_wet * out
- write(estimate[0], str(output_path_denoise), sr)
-
- snr = utils.cal_snr(out, estimate)
- snr = snr.cpu().detach().numpy()[0][0]
- final_output = str(output_path_denoise)
-
- if args.vad:
- output_path_vad = out_vad.joinpath(Path(filename).name)
- sr = torchaudio.info(final_output).sample_rate
- if sr in [16000, 32000, 48000]:
- tmp_path = final_output
- elif sr < 16000:
- tmp_path = convert_sr(final_output, 16000)
- elif sr < 32000:
- tmp_path = convert_sr(final_output, 32000)
- else:
- tmp_path = convert_sr(final_output, 48000)
- # apply VAD
- segment, sample_rate = apply_vad(vad, tmp_path)
- if len(segment) < sample_rate * MIN_T:
- keep_sample = False
- print((
- f"WARNING: skip {filename} because it is too short "
- f"after VAD ({len(segment) / sample_rate} < {MIN_T})"
- ))
- else:
- if sample_rate != sr:
- tmp_path = generate_tmp_filename("wav")
- write_wave(tmp_path, segment, sample_rate)
- convert_sr(tmp_path, sr,
- output_path=str(output_path_vad))
- else:
- write_wave(str(output_path_vad), segment, sample_rate)
- final_output = str(output_path_vad)
- segment, _ = torchaudio.load(final_output)
- n_frames = segment.size(1)
-
- if keep_sample:
- output_dict["id"].append(row["id"])
- output_dict["audio"].append(final_output)
- output_dict["n_frames"].append(n_frames)
- output_dict["tgt_text"].append(row["tgt_text"])
- output_dict["speaker"].append(row["speaker"])
- output_dict["src_text"].append(row["src_text"])
- output_dict["snr"].append(snr)
-
- out_tsv_path = Path(args.output_dir) / Path(args.audio_manifest).name
- log.info(f"Saving manifest to {out_tsv_path.as_posix()}")
- save_df_to_tsv(pd.DataFrame.from_dict(output_dict), out_tsv_path)
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument("--audio-manifest", "-i", required=True,
- type=str, help="path to the input manifest.")
- parser.add_argument(
- "--output-dir", "-o", required=True, type=str,
- help="path to the output dir. it will contain files after denoising and"
- " vad"
- )
- parser.add_argument("--vad-agg-level", "-a", type=int, default=2,
- help="the aggresive level of the vad [0-3].")
- parser.add_argument(
- "--dry-wet", "-dw", type=float, default=0.01,
- help="the level of linear interpolation between noisy and enhanced "
- "files."
- )
- parser.add_argument(
- "--device", "-d", type=str, default="cpu",
- help="the device to be used for the speech enhancement model: "
- "cpu | cuda."
- )
- parser.add_argument("--denoise", action="store_true",
- help="apply a denoising")
- parser.add_argument("--vad", action="store_true", help="apply a VAD")
- args = parser.parse_args()
-
- process(args)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoiser/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoiser/__init__.py
deleted file mode 100644
index 6264236915a7269a4d920ee8213004374dd86a9a..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoiser/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoiser/demucs.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoiser/demucs.py
deleted file mode 100644
index 3f70e73d6a37d32e05b6cf0e87f42e13c467cd52..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoiser/demucs.py
+++ /dev/null
@@ -1,473 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-# All rights reserved.
-#
-# This source code is licensed under the license found in the
-# LICENSE file in the root directory of this source tree.
-# author: adefossez
-
-import math
-import time
-
-import torch as th
-from torch import nn
-from torch.nn import functional as F
-
-from .resample import downsample2, upsample2
-from .utils import capture_init
-
-
-class BLSTM(nn.Module):
- def __init__(self, dim, layers=2, bi=True):
- super().__init__()
- klass = nn.LSTM
- self.lstm = klass(
- bidirectional=bi, num_layers=layers, hidden_size=dim, input_size=dim
- )
- self.linear = None
- if bi:
- self.linear = nn.Linear(2 * dim, dim)
-
- def forward(self, x, hidden=None):
- x, hidden = self.lstm(x, hidden)
- if self.linear:
- x = self.linear(x)
- return x, hidden
-
-
-def rescale_conv(conv, reference):
- std = conv.weight.std().detach()
- scale = (std / reference)**0.5
- conv.weight.data /= scale
- if conv.bias is not None:
- conv.bias.data /= scale
-
-
-def rescale_module(module, reference):
- for sub in module.modules():
- if isinstance(sub, (nn.Conv1d, nn.ConvTranspose1d)):
- rescale_conv(sub, reference)
-
-
-class Demucs(nn.Module):
- """
- Demucs speech enhancement model.
- Args:
- - chin (int): number of input channels.
- - chout (int): number of output channels.
- - hidden (int): number of initial hidden channels.
- - depth (int): number of layers.
- - kernel_size (int): kernel size for each layer.
- - stride (int): stride for each layer.
- - causal (bool): if false, uses BiLSTM instead of LSTM.
- - resample (int): amount of resampling to apply to the input/output.
- Can be one of 1, 2 or 4.
- - growth (float): number of channels is multiplied by this for every layer.
- - max_hidden (int): maximum number of channels. Can be useful to
- control the size/speed of the model.
- - normalize (bool): if true, normalize the input.
- - glu (bool): if true uses GLU instead of ReLU in 1x1 convolutions.
- - rescale (float): controls custom weight initialization.
- See https://arxiv.org/abs/1911.13254.
- - floor (float): stability flooring when normalizing.
-
- """
- @capture_init
- def __init__(self,
- chin=1,
- chout=1,
- hidden=48,
- depth=5,
- kernel_size=8,
- stride=4,
- causal=True,
- resample=4,
- growth=2,
- max_hidden=10_000,
- normalize=True,
- glu=True,
- rescale=0.1,
- floor=1e-3):
-
- super().__init__()
- if resample not in [1, 2, 4]:
- raise ValueError("Resample should be 1, 2 or 4.")
-
- self.chin = chin
- self.chout = chout
- self.hidden = hidden
- self.depth = depth
- self.kernel_size = kernel_size
- self.stride = stride
- self.causal = causal
- self.floor = floor
- self.resample = resample
- self.normalize = normalize
-
- self.encoder = nn.ModuleList()
- self.decoder = nn.ModuleList()
- activation = nn.GLU(1) if glu else nn.ReLU()
- ch_scale = 2 if glu else 1
-
- for index in range(depth):
- encode = []
- encode += [
- nn.Conv1d(chin, hidden, kernel_size, stride),
- nn.ReLU(),
- nn.Conv1d(hidden, hidden * ch_scale, 1), activation,
- ]
- self.encoder.append(nn.Sequential(*encode))
-
- decode = []
- decode += [
- nn.Conv1d(hidden, ch_scale * hidden, 1), activation,
- nn.ConvTranspose1d(hidden, chout, kernel_size, stride),
- ]
- if index > 0:
- decode.append(nn.ReLU())
- self.decoder.insert(0, nn.Sequential(*decode))
- chout = hidden
- chin = hidden
- hidden = min(int(growth * hidden), max_hidden)
-
- self.lstm = BLSTM(chin, bi=not causal)
- if rescale:
- rescale_module(self, reference=rescale)
-
- def valid_length(self, length):
- """
- Return the nearest valid length to use with the model so that
- there is no time steps left over in a convolutions, e.g. for all
- layers, size of the input - kernel_size % stride = 0.
-
- If the mixture has a valid length, the estimated sources
- will have exactly the same length.
- """
- length = math.ceil(length * self.resample)
- for _ in range(self.depth):
- length = math.ceil((length - self.kernel_size) / self.stride) + 1
- length = max(length, 1)
- for _ in range(self.depth):
- length = (length - 1) * self.stride + self.kernel_size
- length = int(math.ceil(length / self.resample))
- return int(length)
-
- @property
- def total_stride(self):
- return self.stride ** self.depth // self.resample
-
- def forward(self, mix):
- if mix.dim() == 2:
- mix = mix.unsqueeze(1)
-
- if self.normalize:
- mono = mix.mean(dim=1, keepdim=True)
- std = mono.std(dim=-1, keepdim=True)
- mix = mix / (self.floor + std)
- else:
- std = 1
- length = mix.shape[-1]
- x = mix
- x = F.pad(x, (0, self.valid_length(length) - length))
- if self.resample == 2:
- x = upsample2(x)
- elif self.resample == 4:
- x = upsample2(x)
- x = upsample2(x)
- skips = []
- for encode in self.encoder:
- x = encode(x)
- skips.append(x)
- x = x.permute(2, 0, 1)
- x, _ = self.lstm(x)
- x = x.permute(1, 2, 0)
- for decode in self.decoder:
- skip = skips.pop(-1)
- x = x + skip[..., :x.shape[-1]]
- x = decode(x)
- if self.resample == 2:
- x = downsample2(x)
- elif self.resample == 4:
- x = downsample2(x)
- x = downsample2(x)
-
- x = x[..., :length]
- return std * x
-
-
-def fast_conv(conv, x):
- """
- Faster convolution evaluation if either kernel size is 1
- or length of sequence is 1.
- """
- batch, chin, length = x.shape
- chout, chin, kernel = conv.weight.shape
- assert batch == 1
- if kernel == 1:
- x = x.view(chin, length)
- out = th.addmm(conv.bias.view(-1, 1),
- conv.weight.view(chout, chin), x)
- elif length == kernel:
- x = x.view(chin * kernel, 1)
- out = th.addmm(conv.bias.view(-1, 1),
- conv.weight.view(chout, chin * kernel), x)
- else:
- out = conv(x)
- return out.view(batch, chout, -1)
-
-
-class DemucsStreamer:
- """
- Streaming implementation for Demucs. It supports being fed with any amount
- of audio at a time. You will get back as much audio as possible at that
- point.
-
- Args:
- - demucs (Demucs): Demucs model.
- - dry (float): amount of dry (e.g. input) signal to keep. 0 is maximum
- noise removal, 1 just returns the input signal. Small values > 0
- allows to limit distortions.
- - num_frames (int): number of frames to process at once. Higher values
- will increase overall latency but improve the real time factor.
- - resample_lookahead (int): extra lookahead used for the resampling.
- - resample_buffer (int): size of the buffer of previous inputs/outputs
- kept for resampling.
- """
- def __init__(self, demucs,
- dry=0,
- num_frames=1,
- resample_lookahead=64,
- resample_buffer=256):
- device = next(iter(demucs.parameters())).device
- self.demucs = demucs
- self.lstm_state = None
- self.conv_state = None
- self.dry = dry
- self.resample_lookahead = resample_lookahead
- resample_buffer = min(demucs.total_stride, resample_buffer)
- self.resample_buffer = resample_buffer
- self.frame_length = demucs.valid_length(1) + \
- demucs.total_stride * (num_frames - 1)
- self.total_length = self.frame_length + self.resample_lookahead
- self.stride = demucs.total_stride * num_frames
- self.resample_in = th.zeros(demucs.chin, resample_buffer, device=device)
- self.resample_out = th.zeros(
- demucs.chin, resample_buffer, device=device
- )
-
- self.frames = 0
- self.total_time = 0
- self.variance = 0
- self.pending = th.zeros(demucs.chin, 0, device=device)
-
- bias = demucs.decoder[0][2].bias
- weight = demucs.decoder[0][2].weight
- chin, chout, kernel = weight.shape
- self._bias = bias.view(-1, 1).repeat(1, kernel).view(-1, 1)
- self._weight = weight.permute(1, 2, 0).contiguous()
-
- def reset_time_per_frame(self):
- self.total_time = 0
- self.frames = 0
-
- @property
- def time_per_frame(self):
- return self.total_time / self.frames
-
- def flush(self):
- """
- Flush remaining audio by padding it with zero. Call this
- when you have no more input and want to get back the last chunk of audio.
- """
- pending_length = self.pending.shape[1]
- padding = th.zeros(
- self.demucs.chin, self.total_length, device=self.pending.device
- )
- out = self.feed(padding)
- return out[:, :pending_length]
-
- def feed(self, wav):
- """
- Apply the model to mix using true real time evaluation.
- Normalization is done online as is the resampling.
- """
- begin = time.time()
- demucs = self.demucs
- resample_buffer = self.resample_buffer
- stride = self.stride
- resample = demucs.resample
-
- if wav.dim() != 2:
- raise ValueError("input wav should be two dimensional.")
- chin, _ = wav.shape
- if chin != demucs.chin:
- raise ValueError(f"Expected {demucs.chin} channels, got {chin}")
-
- self.pending = th.cat([self.pending, wav], dim=1)
- outs = []
- while self.pending.shape[1] >= self.total_length:
- self.frames += 1
- frame = self.pending[:, :self.total_length]
- dry_signal = frame[:, :stride]
- if demucs.normalize:
- mono = frame.mean(0)
- variance = (mono**2).mean()
- self.variance = variance / self.frames + \
- (1 - 1 / self.frames) * self.variance
- frame = frame / (demucs.floor + math.sqrt(self.variance))
- frame = th.cat([self.resample_in, frame], dim=-1)
- self.resample_in[:] = frame[:, stride - resample_buffer:stride]
-
- if resample == 4:
- frame = upsample2(upsample2(frame))
- elif resample == 2:
- frame = upsample2(frame)
- # remove pre sampling buffer
- frame = frame[:, resample * resample_buffer:]
- # remove extra samples after window
- frame = frame[:, :resample * self.frame_length]
-
- out, extra = self._separate_frame(frame)
- padded_out = th.cat([self.resample_out, out, extra], 1)
- self.resample_out[:] = out[:, -resample_buffer:]
- if resample == 4:
- out = downsample2(downsample2(padded_out))
- elif resample == 2:
- out = downsample2(padded_out)
- else:
- out = padded_out
-
- out = out[:, resample_buffer // resample:]
- out = out[:, :stride]
-
- if demucs.normalize:
- out *= math.sqrt(self.variance)
- out = self.dry * dry_signal + (1 - self.dry) * out
- outs.append(out)
- self.pending = self.pending[:, stride:]
-
- self.total_time += time.time() - begin
- if outs:
- out = th.cat(outs, 1)
- else:
- out = th.zeros(chin, 0, device=wav.device)
- return out
-
- def _separate_frame(self, frame):
- demucs = self.demucs
- skips = []
- next_state = []
- first = self.conv_state is None
- stride = self.stride * demucs.resample
- x = frame[None]
- for idx, encode in enumerate(demucs.encoder):
- stride //= demucs.stride
- length = x.shape[2]
- if idx == demucs.depth - 1:
- # This is sligthly faster for the last conv
- x = fast_conv(encode[0], x)
- x = encode[1](x)
- x = fast_conv(encode[2], x)
- x = encode[3](x)
- else:
- if not first:
- prev = self.conv_state.pop(0)
- prev = prev[..., stride:]
- tgt = (length - demucs.kernel_size) // demucs.stride + 1
- missing = tgt - prev.shape[-1]
- offset = length - demucs.kernel_size - \
- demucs.stride * (missing - 1)
- x = x[..., offset:]
- x = encode[1](encode[0](x))
- x = fast_conv(encode[2], x)
- x = encode[3](x)
- if not first:
- x = th.cat([prev, x], -1)
- next_state.append(x)
- skips.append(x)
-
- x = x.permute(2, 0, 1)
- x, self.lstm_state = demucs.lstm(x, self.lstm_state)
- x = x.permute(1, 2, 0)
- # In the following, x contains only correct samples, i.e. the one
- # for which each time position is covered by two window of the upper
- # layer. extra contains extra samples to the right, and is used only as
- # a better padding for the online resampling.
- extra = None
- for idx, decode in enumerate(demucs.decoder):
- skip = skips.pop(-1)
- x += skip[..., :x.shape[-1]]
- x = fast_conv(decode[0], x)
- x = decode[1](x)
-
- if extra is not None:
- skip = skip[..., x.shape[-1]:]
- extra += skip[..., :extra.shape[-1]]
- extra = decode[2](decode[1](decode[0](extra)))
- x = decode[2](x)
- next_state.append(
- x[..., -demucs.stride:] - decode[2].bias.view(-1, 1)
- )
- if extra is None:
- extra = x[..., -demucs.stride:]
- else:
- extra[..., :demucs.stride] += next_state[-1]
- x = x[..., :-demucs.stride]
-
- if not first:
- prev = self.conv_state.pop(0)
- x[..., :demucs.stride] += prev
- if idx != demucs.depth - 1:
- x = decode[3](x)
- extra = decode[3](extra)
- self.conv_state = next_state
- return x[0], extra[0]
-
-
-def test():
- import argparse
- parser = argparse.ArgumentParser(
- "denoiser.demucs",
- description="Benchmark the streaming Demucs implementation, as well as "
- "checking the delta with the offline implementation.")
- parser.add_argument("--depth", default=5, type=int)
- parser.add_argument("--resample", default=4, type=int)
- parser.add_argument("--hidden", default=48, type=int)
- parser.add_argument("--sample_rate", default=16000, type=float)
- parser.add_argument("--device", default="cpu")
- parser.add_argument("-t", "--num_threads", type=int)
- parser.add_argument("-f", "--num_frames", type=int, default=1)
- args = parser.parse_args()
- if args.num_threads:
- th.set_num_threads(args.num_threads)
- sr = args.sample_rate
- sr_ms = sr / 1000
- demucs = Demucs(
- depth=args.depth, hidden=args.hidden, resample=args.resample
- ).to(args.device)
- x = th.randn(1, int(sr * 4)).to(args.device)
- out = demucs(x[None])[0]
- streamer = DemucsStreamer(demucs, num_frames=args.num_frames)
- out_rt = []
- frame_size = streamer.total_length
- with th.no_grad():
- while x.shape[1] > 0:
- out_rt.append(streamer.feed(x[:, :frame_size]))
- x = x[:, frame_size:]
- frame_size = streamer.demucs.total_stride
- out_rt.append(streamer.flush())
- out_rt = th.cat(out_rt, 1)
- model_size = sum(p.numel() for p in demucs.parameters()) * 4 / 2**20
- initial_lag = streamer.total_length / sr_ms
- tpf = 1000 * streamer.time_per_frame
- print(f"model size: {model_size:.1f}MB, ", end='')
- print(f"delta batch/streaming: {th.norm(out - out_rt) / th.norm(out):.2%}")
- print(f"initial lag: {initial_lag:.1f}ms, ", end='')
- print(f"stride: {streamer.stride * args.num_frames / sr_ms:.1f}ms")
- print(f"time per frame: {tpf:.1f}ms, ", end='')
- rtf = (1000 * streamer.time_per_frame) / (streamer.stride / sr_ms)
- print(f"RTF: {rtf:.2f}")
- print(f"Total lag with computation: {initial_lag + tpf:.1f}ms")
-
-
-if __name__ == "__main__":
- test()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoiser/pretrained.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoiser/pretrained.py
deleted file mode 100644
index 2fa846075b6872cdcc0baebca0b9acbb9ffcd287..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoiser/pretrained.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-# All rights reserved.
-#
-# This source code is licensed under the license found in the
-# LICENSE file in the root directory of this source tree.
-# author: adefossez
-
-import logging
-
-import torch.hub
-
-from .demucs import Demucs
-from .utils import deserialize_model
-
-logger = logging.getLogger(__name__)
-ROOT = "https://dl.fbaipublicfiles.com/adiyoss/denoiser/"
-DNS_48_URL = ROOT + "dns48-11decc9d8e3f0998.th"
-DNS_64_URL = ROOT + "dns64-a7761ff99a7d5bb6.th"
-MASTER_64_URL = ROOT + "master64-8a5dfb4bb92753dd.th"
-
-
-def _demucs(pretrained, url, **kwargs):
- model = Demucs(**kwargs)
- if pretrained:
- state_dict = torch.hub.load_state_dict_from_url(url, map_location='cpu')
- model.load_state_dict(state_dict)
- return model
-
-
-def dns48(pretrained=True):
- return _demucs(pretrained, DNS_48_URL, hidden=48)
-
-
-def dns64(pretrained=True):
- return _demucs(pretrained, DNS_64_URL, hidden=64)
-
-
-def master64(pretrained=True):
- return _demucs(pretrained, MASTER_64_URL, hidden=64)
-
-
-def add_model_flags(parser):
- group = parser.add_mutually_exclusive_group(required=False)
- group.add_argument(
- "-m", "--model_path", help="Path to local trained model."
- )
- group.add_argument(
- "--dns48", action="store_true",
- help="Use pre-trained real time H=48 model trained on DNS."
- )
- group.add_argument(
- "--dns64", action="store_true",
- help="Use pre-trained real time H=64 model trained on DNS."
- )
- group.add_argument(
- "--master64", action="store_true",
- help="Use pre-trained real time H=64 model trained on DNS and Valentini."
- )
-
-
-def get_model(args):
- """
- Load local model package or torchhub pre-trained model.
- """
- if args.model_path:
- logger.info("Loading model from %s", args.model_path)
- pkg = torch.load(args.model_path)
- model = deserialize_model(pkg)
- elif args.dns64:
- logger.info("Loading pre-trained real time H=64 model trained on DNS.")
- model = dns64()
- elif args.master64:
- logger.info(
- "Loading pre-trained real time H=64 model trained on DNS and Valentini."
- )
- model = master64()
- else:
- logger.info("Loading pre-trained real time H=48 model trained on DNS.")
- model = dns48()
- logger.debug(model)
- return model
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoiser/resample.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoiser/resample.py
deleted file mode 100644
index 1222addc424d4f898d602009e4032907241aadfe..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoiser/resample.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-# All rights reserved.
-#
-# This source code is licensed under the license found in the
-# LICENSE file in the root directory of this source tree.
-# author: adefossez
-
-import math
-
-import torch as th
-from torch.nn import functional as F
-
-
-def sinc(t):
- """sinc.
-
- :param t: the input tensor
- """
- return th.where(t == 0, th.tensor(1., device=t.device, dtype=t.dtype),
- th.sin(t) / t)
-
-
-def kernel_upsample2(zeros=56):
- """kernel_upsample2.
-
- """
- win = th.hann_window(4 * zeros + 1, periodic=False)
- winodd = win[1::2]
- t = th.linspace(-zeros + 0.5, zeros - 0.5, 2 * zeros)
- t *= math.pi
- kernel = (sinc(t) * winodd).view(1, 1, -1)
- return kernel
-
-
-def upsample2(x, zeros=56):
- """
- Upsampling the input by 2 using sinc interpolation.
- Smith, Julius, and Phil Gossett. "A flexible sampling-rate conversion method."
- ICASSP'84. IEEE International Conference on Acoustics, Speech, and Signal Processing.
- Vol. 9. IEEE, 1984.
- """
- *other, time = x.shape
- kernel = kernel_upsample2(zeros).to(x)
- out = F.conv1d(x.view(-1, 1, time), kernel, padding=zeros)[..., 1:].view(
- *other, time
- )
- y = th.stack([x, out], dim=-1)
- return y.view(*other, -1)
-
-
-def kernel_downsample2(zeros=56):
- """kernel_downsample2.
-
- """
- win = th.hann_window(4 * zeros + 1, periodic=False)
- winodd = win[1::2]
- t = th.linspace(-zeros + 0.5, zeros - 0.5, 2 * zeros)
- t.mul_(math.pi)
- kernel = (sinc(t) * winodd).view(1, 1, -1)
- return kernel
-
-
-def downsample2(x, zeros=56):
- """
- Downsampling the input by 2 using sinc interpolation.
- Smith, Julius, and Phil Gossett. "A flexible sampling-rate conversion method."
- ICASSP'84. IEEE International Conference on Acoustics, Speech, and Signal Processing.
- Vol. 9. IEEE, 1984.
- """
- if x.shape[-1] % 2 != 0:
- x = F.pad(x, (0, 1))
- xeven = x[..., ::2]
- xodd = x[..., 1::2]
- *other, time = xodd.shape
- kernel = kernel_downsample2(zeros).to(x)
- out = xeven + F.conv1d(
- xodd.view(-1, 1, time), kernel, padding=zeros
- )[..., :-1].view(*other, time)
- return out.view(*other, -1).mul(0.5)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoiser/utils.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoiser/utils.py
deleted file mode 100644
index 734d047f1bb8e3aa98c88e152eee7f91fea3d814..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/denoiser/utils.py
+++ /dev/null
@@ -1,176 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-# All rights reserved.
-#
-# This source code is licensed under the license found in the
-# LICENSE file in the root directory of this source tree.
-# author: adefossez
-
-import functools
-import logging
-from contextlib import contextmanager
-import inspect
-import time
-
-logger = logging.getLogger(__name__)
-
-EPS = 1e-8
-
-
-def capture_init(init):
- """capture_init.
-
- Decorate `__init__` with this, and you can then
- recover the *args and **kwargs passed to it in `self._init_args_kwargs`
- """
- @functools.wraps(init)
- def __init__(self, *args, **kwargs):
- self._init_args_kwargs = (args, kwargs)
- init(self, *args, **kwargs)
-
- return __init__
-
-
-def deserialize_model(package, strict=False):
- """deserialize_model.
-
- """
- klass = package['class']
- if strict:
- model = klass(*package['args'], **package['kwargs'])
- else:
- sig = inspect.signature(klass)
- kw = package['kwargs']
- for key in list(kw):
- if key not in sig.parameters:
- logger.warning("Dropping inexistant parameter %s", key)
- del kw[key]
- model = klass(*package['args'], **kw)
- model.load_state_dict(package['state'])
- return model
-
-
-def copy_state(state):
- return {k: v.cpu().clone() for k, v in state.items()}
-
-
-def serialize_model(model):
- args, kwargs = model._init_args_kwargs
- state = copy_state(model.state_dict())
- return {"class": model.__class__, "args": args, "kwargs": kwargs, "state": state}
-
-
-@contextmanager
-def swap_state(model, state):
- """
- Context manager that swaps the state of a model, e.g:
-
- # model is in old state
- with swap_state(model, new_state):
- # model in new state
- # model back to old state
- """
- old_state = copy_state(model.state_dict())
- model.load_state_dict(state)
- try:
- yield
- finally:
- model.load_state_dict(old_state)
-
-
-def pull_metric(history, name):
- out = []
- for metrics in history:
- if name in metrics:
- out.append(metrics[name])
- return out
-
-
-class LogProgress:
- """
- Sort of like tqdm but using log lines and not as real time.
- Args:
- - logger: logger obtained from `logging.getLogger`,
- - iterable: iterable object to wrap
- - updates (int): number of lines that will be printed, e.g.
- if `updates=5`, log every 1/5th of the total length.
- - total (int): length of the iterable, in case it does not support
- `len`.
- - name (str): prefix to use in the log.
- - level: logging level (like `logging.INFO`).
- """
- def __init__(self,
- logger,
- iterable,
- updates=5,
- total=None,
- name="LogProgress",
- level=logging.INFO):
- self.iterable = iterable
- self.total = total or len(iterable)
- self.updates = updates
- self.name = name
- self.logger = logger
- self.level = level
-
- def update(self, **infos):
- self._infos = infos
-
- def __iter__(self):
- self._iterator = iter(self.iterable)
- self._index = -1
- self._infos = {}
- self._begin = time.time()
- return self
-
- def __next__(self):
- self._index += 1
- try:
- value = next(self._iterator)
- except StopIteration:
- raise
- else:
- return value
- finally:
- log_every = max(1, self.total // self.updates)
- # logging is delayed by 1 it, in order to have the metrics from update
- if self._index >= 1 and self._index % log_every == 0:
- self._log()
-
- def _log(self):
- self._speed = (1 + self._index) / (time.time() - self._begin)
- infos = " | ".join(f"{k.capitalize()} {v}" for k, v in self._infos.items())
- if self._speed < 1e-4:
- speed = "oo sec/it"
- elif self._speed < 0.1:
- speed = f"{1/self._speed:.1f} sec/it"
- else:
- speed = f"{self._speed:.1f} it/sec"
- out = f"{self.name} | {self._index}/{self.total} | {speed}"
- if infos:
- out += " | " + infos
- self.logger.log(self.level, out)
-
-
-def colorize(text, color):
- """
- Display text with some ANSI color in the terminal.
- """
- code = f"\033[{color}m"
- restore = "\033[0m"
- return "".join([code, text, restore])
-
-
-def bold(text):
- """
- Display text in bold in the terminal.
- """
- return colorize(text, "1")
-
-
-def cal_snr(lbl, est):
- import torch
- y = 10.0 * torch.log10(
- torch.sum(lbl**2, dim=-1) / (torch.sum((est-lbl)**2, dim=-1) + EPS) +
- EPS
- )
- return y
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/get_common_voice_audio_manifest.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/get_common_voice_audio_manifest.py
deleted file mode 100644
index a30254604311a488a1d4959f941051890ed32b2e..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/get_common_voice_audio_manifest.py
+++ /dev/null
@@ -1,140 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import logging
-from pathlib import Path
-from collections import defaultdict
-from typing import List, Dict, Tuple
-
-import pandas as pd
-import numpy as np
-import torchaudio
-from tqdm import tqdm
-
-from examples.speech_to_text.data_utils import load_df_from_tsv, save_df_to_tsv
-
-
-log = logging.getLogger(__name__)
-
-SPLITS = ["train", "dev", "test"]
-
-
-def get_top_n(
- root: Path, n_speakers: int = 10, min_n_tokens: int = 5
-) -> pd.DataFrame:
- df = load_df_from_tsv(root / "validated.tsv")
- df["n_tokens"] = [len(s.split()) for s in df["sentence"]]
- df = df[df["n_tokens"] >= min_n_tokens]
- df["n_frames"] = [
- torchaudio.info((root / "clips" / p).as_posix()).num_frames
- for p in tqdm(df["path"])
- ]
- df["id"] = [Path(p).stem for p in df["path"]]
- total_duration_ms = df.groupby("client_id")["n_frames"].agg(["sum"])
- total_duration_ms = total_duration_ms.sort_values("sum", ascending=False)
-
- top_n_total_duration_ms = total_duration_ms.head(n_speakers)
- top_n_client_ids = set(top_n_total_duration_ms.index.tolist())
- df_top_n = df[df["client_id"].isin(top_n_client_ids)]
- return df_top_n
-
-
-def get_splits(
- df, train_split_ratio=0.99, speaker_in_all_splits=False, rand_seed=0
-) -> Tuple[Dict[str, str], List[str]]:
- np.random.seed(rand_seed)
- dev_split_ratio = (1. - train_split_ratio) / 3
- grouped = list(df.groupby("client_id"))
- id_to_split = {}
- for _, cur_df in tqdm(grouped):
- cur_n_examples = len(cur_df)
- if speaker_in_all_splits and cur_n_examples < 3:
- continue
- cur_n_train = int(cur_n_examples * train_split_ratio)
- cur_n_dev = int(cur_n_examples * dev_split_ratio)
- cur_n_test = cur_n_examples - cur_n_dev - cur_n_train
- if speaker_in_all_splits and cur_n_dev * cur_n_test == 0:
- cur_n_dev, cur_n_test = 1, 1
- cur_n_train = cur_n_examples - cur_n_dev - cur_n_test
- cur_indices = cur_df.index.tolist()
- cur_shuffled_indices = np.random.permutation(cur_n_examples)
- cur_shuffled_indices = [cur_indices[i] for i in cur_shuffled_indices]
- cur_indices_by_split = {
- "train": cur_shuffled_indices[:cur_n_train],
- "dev": cur_shuffled_indices[cur_n_train: cur_n_train + cur_n_dev],
- "test": cur_shuffled_indices[cur_n_train + cur_n_dev:]
- }
- for split in SPLITS:
- for i in cur_indices_by_split[split]:
- id_ = df["id"].loc[i]
- id_to_split[id_] = split
- return id_to_split, sorted(df["client_id"].unique())
-
-
-def convert_to_wav(root: Path, filenames: List[str], target_sr=16_000):
- out_root = root / "wav"
- out_root.mkdir(exist_ok=True, parents=True)
- print("Converting to WAV...")
- for n in tqdm(filenames):
- in_path = (root / "clips" / n).as_posix()
- waveform, sr = torchaudio.load(in_path)
- converted, converted_sr = torchaudio.sox_effects.apply_effects_tensor(
- waveform, sr, [["rate", str(target_sr)], ["channels", "1"]]
- )
- out_path = (out_root / Path(n).with_suffix(".wav").name).as_posix()
- torchaudio.save(out_path, converted, converted_sr, encoding="PCM_S",
- bits_per_sample=16)
-
-
-def process(args):
- data_root = Path(args.data_root).absolute() / args.lang
-
- # Generate TSV manifest
- print("Generating manifest...")
-
- df_top_n = get_top_n(data_root)
- id_to_split, speakers = get_splits(df_top_n)
-
- if args.convert_to_wav:
- convert_to_wav(data_root, df_top_n["path"].tolist())
-
- manifest_by_split = {split: defaultdict(list) for split in SPLITS}
- for sample in tqdm(df_top_n.to_dict(orient="index").values()):
- sample_id = sample["id"]
- split = id_to_split[sample_id]
- manifest_by_split[split]["id"].append(sample_id)
- if args.convert_to_wav:
- audio_path = data_root / "wav" / f"{sample_id}.wav"
- else:
- audio_path = data_root / "clips" / f"{sample_id}.mp3"
- manifest_by_split[split]["audio"].append(audio_path.as_posix())
- manifest_by_split[split]["n_frames"].append(sample["n_frames"])
- manifest_by_split[split]["tgt_text"].append(sample["sentence"])
- manifest_by_split[split]["speaker"].append(sample["client_id"])
- manifest_by_split[split]["src_text"].append(sample["sentence"])
-
- output_root = Path(args.output_manifest_root).absolute()
- output_root.mkdir(parents=True, exist_ok=True)
- for split in SPLITS:
- save_df_to_tsv(
- pd.DataFrame.from_dict(manifest_by_split[split]),
- output_root / f"{split}.audio.tsv"
- )
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument("--data-root", "-d", required=True, type=str)
- parser.add_argument("--output-manifest-root", "-m", required=True, type=str)
- parser.add_argument("--lang", "-l", required=True, type=str)
- parser.add_argument("--convert-to-wav", action="store_true")
- args = parser.parse_args()
-
- process(args)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/get_feature_manifest.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/get_feature_manifest.py
deleted file mode 100644
index 4a1e119b327c0ff4fac105bd7a83fcb547eb3c2d..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/get_feature_manifest.py
+++ /dev/null
@@ -1,262 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import logging
-from pathlib import Path
-import shutil
-from tempfile import NamedTemporaryFile
-from collections import Counter, defaultdict
-
-import pandas as pd
-import torchaudio
-from tqdm import tqdm
-
-from fairseq.data.audio.audio_utils import convert_waveform
-from examples.speech_to_text.data_utils import (
- create_zip,
- gen_config_yaml,
- gen_vocab,
- get_zip_manifest,
- load_tsv_to_dicts,
- save_df_to_tsv
-)
-from examples.speech_synthesis.data_utils import (
- extract_logmel_spectrogram, extract_pitch, extract_energy, get_global_cmvn,
- ipa_phonemize, get_mfa_alignment, get_unit_alignment,
- get_feature_value_min_max
-)
-
-
-log = logging.getLogger(__name__)
-
-
-def process(args):
- assert "train" in args.splits
- out_root = Path(args.output_root).absolute()
- out_root.mkdir(exist_ok=True)
-
- print("Fetching data...")
- audio_manifest_root = Path(args.audio_manifest_root).absolute()
- samples = []
- for s in args.splits:
- for e in load_tsv_to_dicts(audio_manifest_root / f"{s}.audio.tsv"):
- e["split"] = s
- samples.append(e)
- sample_ids = [s["id"] for s in samples]
-
- # Get alignment info
- id_to_alignment = None
- if args.textgrid_zip is not None:
- assert args.id_to_units_tsv is None
- id_to_alignment = get_mfa_alignment(
- args.textgrid_zip, sample_ids, args.sample_rate, args.hop_length
- )
- elif args.id_to_units_tsv is not None:
- # assume identical hop length on the unit sequence
- id_to_alignment = get_unit_alignment(args.id_to_units_tsv, sample_ids)
-
- # Extract features and pack features into ZIP
- feature_name = "logmelspec80"
- zip_path = out_root / f"{feature_name}.zip"
- pitch_zip_path = out_root / "pitch.zip"
- energy_zip_path = out_root / "energy.zip"
- gcmvn_npz_path = out_root / "gcmvn_stats.npz"
- if zip_path.exists() and gcmvn_npz_path.exists():
- print(f"{zip_path} and {gcmvn_npz_path} exist.")
- else:
- feature_root = out_root / feature_name
- feature_root.mkdir(exist_ok=True)
- pitch_root = out_root / "pitch"
- energy_root = out_root / "energy"
- if args.add_fastspeech_targets:
- pitch_root.mkdir(exist_ok=True)
- energy_root.mkdir(exist_ok=True)
- print("Extracting Mel spectrogram features...")
- for sample in tqdm(samples):
- waveform, sample_rate = torchaudio.load(sample["audio"])
- waveform, sample_rate = convert_waveform(
- waveform, sample_rate, normalize_volume=args.normalize_volume,
- to_sample_rate=args.sample_rate
- )
- sample_id = sample["id"]
- target_length = None
- if id_to_alignment is not None:
- a = id_to_alignment[sample_id]
- target_length = sum(a.frame_durations)
- if a.start_sec is not None and a.end_sec is not None:
- start_frame = int(a.start_sec * sample_rate)
- end_frame = int(a.end_sec * sample_rate)
- waveform = waveform[:, start_frame: end_frame]
- extract_logmel_spectrogram(
- waveform, sample_rate, feature_root / f"{sample_id}.npy",
- win_length=args.win_length, hop_length=args.hop_length,
- n_fft=args.n_fft, n_mels=args.n_mels, f_min=args.f_min,
- f_max=args.f_max, target_length=target_length
- )
- if args.add_fastspeech_targets:
- assert id_to_alignment is not None
- extract_pitch(
- waveform, sample_rate, pitch_root / f"{sample_id}.npy",
- hop_length=args.hop_length, log_scale=True,
- phoneme_durations=id_to_alignment[sample_id].frame_durations
- )
- extract_energy(
- waveform, energy_root / f"{sample_id}.npy",
- hop_length=args.hop_length, n_fft=args.n_fft,
- log_scale=True,
- phoneme_durations=id_to_alignment[sample_id].frame_durations
- )
- print("ZIPing features...")
- create_zip(feature_root, zip_path)
- get_global_cmvn(feature_root, gcmvn_npz_path)
- shutil.rmtree(feature_root)
- if args.add_fastspeech_targets:
- create_zip(pitch_root, pitch_zip_path)
- shutil.rmtree(pitch_root)
- create_zip(energy_root, energy_zip_path)
- shutil.rmtree(energy_root)
-
- print("Fetching ZIP manifest...")
- audio_paths, audio_lengths = get_zip_manifest(zip_path)
- pitch_paths, pitch_lengths, energy_paths, energy_lengths = [None] * 4
- if args.add_fastspeech_targets:
- pitch_paths, pitch_lengths = get_zip_manifest(pitch_zip_path)
- energy_paths, energy_lengths = get_zip_manifest(energy_zip_path)
- # Generate TSV manifest
- print("Generating manifest...")
- id_to_cer = None
- if args.cer_threshold is not None:
- assert Path(args.cer_tsv_path).is_file()
- id_to_cer = {
- x["id"]: x["uer"] for x in load_tsv_to_dicts(args.cer_tsv_path)
- }
- manifest_by_split = {split: defaultdict(list) for split in args.splits}
- for sample in tqdm(samples):
- sample_id, split = sample["id"], sample["split"]
-
- if args.snr_threshold is not None and "snr" in sample \
- and sample["snr"] < args.snr_threshold:
- continue
- if args.cer_threshold is not None \
- and id_to_cer[sample_id] > args.cer_threhold:
- continue
-
- normalized_utt = sample["tgt_text"]
- if id_to_alignment is not None:
- normalized_utt = " ".join(id_to_alignment[sample_id].tokens)
- elif args.ipa_vocab:
- normalized_utt = ipa_phonemize(
- normalized_utt, lang=args.lang, use_g2p=args.use_g2p
- )
- manifest_by_split[split]["id"].append(sample_id)
- manifest_by_split[split]["audio"].append(audio_paths[sample_id])
- manifest_by_split[split]["n_frames"].append(audio_lengths[sample_id])
- manifest_by_split[split]["tgt_text"].append(normalized_utt)
- manifest_by_split[split]["speaker"].append(sample["speaker"])
- manifest_by_split[split]["src_text"].append(sample["src_text"])
- if args.add_fastspeech_targets:
- assert id_to_alignment is not None
- duration = " ".join(
- str(d) for d in id_to_alignment[sample_id].frame_durations
- )
- manifest_by_split[split]["duration"].append(duration)
- manifest_by_split[split]["pitch"].append(pitch_paths[sample_id])
- manifest_by_split[split]["energy"].append(energy_paths[sample_id])
- for split in args.splits:
- save_df_to_tsv(
- pd.DataFrame.from_dict(manifest_by_split[split]),
- out_root / f"{split}.tsv"
- )
- # Generate vocab
- vocab_name, spm_filename = None, None
- if id_to_alignment is not None or args.ipa_vocab:
- vocab = Counter()
- for t in manifest_by_split["train"]["tgt_text"]:
- vocab.update(t.split(" "))
- vocab_name = "vocab.txt"
- with open(out_root / vocab_name, "w") as f:
- for s, c in vocab.most_common():
- f.write(f"{s} {c}\n")
- else:
- spm_filename_prefix = "spm_char"
- spm_filename = f"{spm_filename_prefix}.model"
- with NamedTemporaryFile(mode="w") as f:
- for t in manifest_by_split["train"]["tgt_text"]:
- f.write(t + "\n")
- f.flush() # needed to ensure gen_vocab sees dumped text
- gen_vocab(Path(f.name), out_root / spm_filename_prefix, "char")
- # Generate speaker list
- speakers = sorted({sample["speaker"] for sample in samples})
- speakers_path = out_root / "speakers.txt"
- with open(speakers_path, "w") as f:
- for speaker in speakers:
- f.write(f"{speaker}\n")
- # Generate config YAML
- win_len_t = args.win_length / args.sample_rate
- hop_len_t = args.hop_length / args.sample_rate
- extra = {
- "sample_rate": args.sample_rate,
- "features": {
- "type": "spectrogram+melscale+log",
- "eps": 1e-5, "n_mels": args.n_mels, "n_fft": args.n_fft,
- "window_fn": "hann", "win_length": args.win_length,
- "hop_length": args.hop_length, "sample_rate": args.sample_rate,
- "win_len_t": win_len_t, "hop_len_t": hop_len_t,
- "f_min": args.f_min, "f_max": args.f_max,
- "n_stft": args.n_fft // 2 + 1
- }
- }
- if len(speakers) > 1:
- extra["speaker_set_filename"] = "speakers.txt"
- if args.add_fastspeech_targets:
- pitch_min, pitch_max = get_feature_value_min_max(
- [(out_root / n).as_posix() for n in pitch_paths.values()]
- )
- energy_min, energy_max = get_feature_value_min_max(
- [(out_root / n).as_posix() for n in energy_paths.values()]
- )
- extra["features"]["pitch_min"] = pitch_min
- extra["features"]["pitch_max"] = pitch_max
- extra["features"]["energy_min"] = energy_min
- extra["features"]["energy_max"] = energy_max
- gen_config_yaml(
- out_root, spm_filename=spm_filename, vocab_name=vocab_name,
- audio_root=out_root.as_posix(), input_channels=None,
- input_feat_per_channel=None, specaugment_policy=None,
- cmvn_type="global", gcmvn_path=gcmvn_npz_path, extra=extra
- )
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument("--audio-manifest-root", "-m", required=True, type=str)
- parser.add_argument("--output-root", "-o", required=True, type=str)
- parser.add_argument("--splits", "-s", type=str, nargs="+",
- default=["train", "dev", "test"])
- parser.add_argument("--ipa-vocab", action="store_true")
- parser.add_argument("--use-g2p", action="store_true")
- parser.add_argument("--lang", type=str, default="en-us")
- parser.add_argument("--win-length", type=int, default=1024)
- parser.add_argument("--hop-length", type=int, default=256)
- parser.add_argument("--n-fft", type=int, default=1024)
- parser.add_argument("--n-mels", type=int, default=80)
- parser.add_argument("--f-min", type=int, default=20)
- parser.add_argument("--f-max", type=int, default=8000)
- parser.add_argument("--sample-rate", type=int, default=22050)
- parser.add_argument("--normalize-volume", "-n", action="store_true")
- parser.add_argument("--textgrid-zip", type=str, default=None)
- parser.add_argument("--id-to-units-tsv", type=str, default=None)
- parser.add_argument("--add-fastspeech-targets", action="store_true")
- parser.add_argument("--snr-threshold", type=float, default=None)
- parser.add_argument("--cer-threshold", type=float, default=None)
- parser.add_argument("--cer-tsv-path", type=str, default="")
- args = parser.parse_args()
-
- process(args)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/get_ljspeech_audio_manifest.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/get_ljspeech_audio_manifest.py
deleted file mode 100644
index 7ec1fb7521b8a9b821d28bcaaaedb034f6e95e0b..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/get_ljspeech_audio_manifest.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import logging
-from pathlib import Path
-from collections import defaultdict
-
-import pandas as pd
-from torchaudio.datasets import LJSPEECH
-from tqdm import tqdm
-
-from examples.speech_to_text.data_utils import save_df_to_tsv
-
-
-log = logging.getLogger(__name__)
-
-SPLITS = ["train", "dev", "test"]
-
-
-def process(args):
- out_root = Path(args.output_data_root).absolute()
- out_root.mkdir(parents=True, exist_ok=True)
-
- # Generate TSV manifest
- print("Generating manifest...")
- # following FastSpeech's splits
- dataset = LJSPEECH(out_root.as_posix(), download=True)
- id_to_split = {}
- for x in dataset._flist:
- id_ = x[0]
- speaker = id_.split("-")[0]
- id_to_split[id_] = {
- "LJ001": "test", "LJ002": "test", "LJ003": "dev"
- }.get(speaker, "train")
- manifest_by_split = {split: defaultdict(list) for split in SPLITS}
- progress = tqdm(enumerate(dataset), total=len(dataset))
- for i, (waveform, _, utt, normalized_utt) in progress:
- sample_id = dataset._flist[i][0]
- split = id_to_split[sample_id]
- manifest_by_split[split]["id"].append(sample_id)
- audio_path = f"{dataset._path}/{sample_id}.wav"
- manifest_by_split[split]["audio"].append(audio_path)
- manifest_by_split[split]["n_frames"].append(len(waveform[0]))
- manifest_by_split[split]["tgt_text"].append(normalized_utt)
- manifest_by_split[split]["speaker"].append("ljspeech")
- manifest_by_split[split]["src_text"].append(utt)
-
- manifest_root = Path(args.output_manifest_root).absolute()
- manifest_root.mkdir(parents=True, exist_ok=True)
- for split in SPLITS:
- save_df_to_tsv(
- pd.DataFrame.from_dict(manifest_by_split[split]),
- manifest_root / f"{split}.audio.tsv"
- )
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument("--output-data-root", "-d", required=True, type=str)
- parser.add_argument("--output-manifest-root", "-m", required=True, type=str)
- args = parser.parse_args()
-
- process(args)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/get_speaker_embedding.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/get_speaker_embedding.py
deleted file mode 100644
index 0e3e4c5cd7aef15dae0b41b0ec7b33e17f66597f..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/get_speaker_embedding.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-
-import argparse
-from collections import defaultdict
-from itertools import chain
-from pathlib import Path
-
-import numpy as np
-import torchaudio
-import torchaudio.sox_effects as ta_sox
-import yaml
-from tqdm import tqdm
-
-from examples.speech_to_text.data_utils import load_tsv_to_dicts
-from examples.speech_synthesis.preprocessing.speaker_embedder import SpkrEmbedder
-
-
-def extract_embedding(audio_path, embedder):
- wav, sr = torchaudio.load(audio_path) # 2D
- if sr != embedder.RATE:
- wav, sr = ta_sox.apply_effects_tensor(
- wav, sr, [["rate", str(embedder.RATE)]]
- )
- try:
- emb = embedder([wav[0].cuda().float()]).cpu().numpy()
- except RuntimeError:
- emb = None
- return emb
-
-
-def process(args):
- print("Fetching data...")
- raw_manifest_root = Path(args.raw_manifest_root).absolute()
- samples = [load_tsv_to_dicts(raw_manifest_root / (s + ".tsv"))
- for s in args.splits]
- samples = list(chain(*samples))
- with open(args.config, "r") as f:
- config = yaml.load(f, Loader=yaml.FullLoader)
- with open(f"{config['audio_root']}/{config['speaker_set_filename']}") as f:
- speaker_to_id = {r.strip(): i for i, r in enumerate(f)}
-
- embedder = SpkrEmbedder(args.ckpt).cuda()
- speaker_to_cnt = defaultdict(float)
- speaker_to_emb = defaultdict(float)
- for sample in tqdm(samples, desc="extract emb"):
- emb = extract_embedding(sample["audio"], embedder)
- if emb is not None:
- speaker_to_cnt[sample["speaker"]] += 1
- speaker_to_emb[sample["speaker"]] += emb
- if len(speaker_to_emb) != len(speaker_to_id):
- missed = set(speaker_to_id) - set(speaker_to_emb.keys())
- print(
- f"WARNING: missing embeddings for {len(missed)} speaker:\n{missed}"
- )
- speaker_emb_mat = np.zeros((len(speaker_to_id), len(emb)), float)
- for speaker in speaker_to_emb:
- idx = speaker_to_id[speaker]
- emb = speaker_to_emb[speaker]
- cnt = speaker_to_cnt[speaker]
- speaker_emb_mat[idx, :] = emb / cnt
- speaker_emb_name = "speaker_emb.npy"
- speaker_emb_path = f"{config['audio_root']}/{speaker_emb_name}"
- np.save(speaker_emb_path, speaker_emb_mat)
- config["speaker_emb_filename"] = speaker_emb_name
-
- with open(args.new_config, "w") as f:
- yaml.dump(config, f)
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument("--raw-manifest-root", "-m", required=True, type=str)
- parser.add_argument("--splits", "-s", type=str, nargs="+",
- default=["train"])
- parser.add_argument("--config", "-c", required=True, type=str)
- parser.add_argument("--new-config", "-n", required=True, type=str)
- parser.add_argument("--ckpt", required=True, type=str,
- help="speaker embedder checkpoint")
- args = parser.parse_args()
-
- process(args)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/get_vctk_audio_manifest.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/get_vctk_audio_manifest.py
deleted file mode 100644
index 7afa40fcd195465a225c9f251734e84fe6b3c7ef..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/get_vctk_audio_manifest.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import logging
-import numpy as np
-import re
-from pathlib import Path
-from collections import defaultdict
-
-import pandas as pd
-from torchaudio.datasets import VCTK
-from tqdm import tqdm
-
-from examples.speech_to_text.data_utils import save_df_to_tsv
-
-
-log = logging.getLogger(__name__)
-
-SPLITS = ["train", "dev", "test"]
-
-
-def normalize_text(text):
- return re.sub(r"[^a-zA-Z.?!,'\- ]", '', text)
-
-
-def process(args):
- out_root = Path(args.output_data_root).absolute()
- out_root.mkdir(parents=True, exist_ok=True)
-
- # Generate TSV manifest
- print("Generating manifest...")
- dataset = VCTK(out_root.as_posix(), download=False)
- ids = list(dataset._walker)
- np.random.seed(args.seed)
- np.random.shuffle(ids)
- n_train = len(ids) - args.n_dev - args.n_test
- _split = ["train"] * n_train + ["dev"] * args.n_dev + ["test"] * args.n_test
- id_to_split = dict(zip(ids, _split))
- manifest_by_split = {split: defaultdict(list) for split in SPLITS}
- progress = tqdm(enumerate(dataset), total=len(dataset))
- for i, (waveform, _, text, speaker_id, _) in progress:
- sample_id = dataset._walker[i]
- _split = id_to_split[sample_id]
- audio_dir = Path(dataset._path) / dataset._folder_audio / speaker_id
- audio_path = audio_dir / f"{sample_id}.wav"
- text = normalize_text(text)
- manifest_by_split[_split]["id"].append(sample_id)
- manifest_by_split[_split]["audio"].append(audio_path.as_posix())
- manifest_by_split[_split]["n_frames"].append(len(waveform[0]))
- manifest_by_split[_split]["tgt_text"].append(text)
- manifest_by_split[_split]["speaker"].append(speaker_id)
- manifest_by_split[_split]["src_text"].append(text)
-
- manifest_root = Path(args.output_manifest_root).absolute()
- manifest_root.mkdir(parents=True, exist_ok=True)
- for _split in SPLITS:
- save_df_to_tsv(
- pd.DataFrame.from_dict(manifest_by_split[_split]),
- manifest_root / f"{_split}.audio.tsv"
- )
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument("--output-data-root", "-d", required=True, type=str)
- parser.add_argument("--output-manifest-root", "-m", required=True, type=str)
- parser.add_argument("--n-dev", default=50, type=int)
- parser.add_argument("--n-test", default=100, type=int)
- parser.add_argument("--seed", "-s", default=1234, type=int)
- args = parser.parse_args()
-
- process(args)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/speaker_embedder/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/speaker_embedder/__init__.py
deleted file mode 100644
index 3b178676ba322ef613df42977cb498101f841b09..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/speaker_embedder/__init__.py
+++ /dev/null
@@ -1,135 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-
-import librosa
-import torch
-import torch.nn as nn
-import torch.nn.functional as F
-import torch.utils.data
-import torchaudio
-
-
-EMBEDDER_PARAMS = {
- 'num_mels': 40,
- 'n_fft': 512,
- 'emb_dim': 256,
- 'lstm_hidden': 768,
- 'lstm_layers': 3,
- 'window': 80,
- 'stride': 40,
-}
-
-
-def set_requires_grad(nets, requires_grad=False):
- """Set requies_grad=Fasle for all the networks to avoid unnecessary
- computations
- Parameters:
- nets (network list) -- a list of networks
- requires_grad (bool) -- whether the networks require gradients or not
- """
- if not isinstance(nets, list):
- nets = [nets]
- for net in nets:
- if net is not None:
- for param in net.parameters():
- param.requires_grad = requires_grad
-
-
-class LinearNorm(nn.Module):
- def __init__(self, hp):
- super(LinearNorm, self).__init__()
- self.linear_layer = nn.Linear(hp["lstm_hidden"], hp["emb_dim"])
-
- def forward(self, x):
- return self.linear_layer(x)
-
-
-class SpeechEmbedder(nn.Module):
- def __init__(self, hp):
- super(SpeechEmbedder, self).__init__()
- self.lstm = nn.LSTM(hp["num_mels"],
- hp["lstm_hidden"],
- num_layers=hp["lstm_layers"],
- batch_first=True)
- self.proj = LinearNorm(hp)
- self.hp = hp
-
- def forward(self, mel):
- # (num_mels, T) -> (num_mels, T', window)
- mels = mel.unfold(1, self.hp["window"], self.hp["stride"])
- mels = mels.permute(1, 2, 0) # (T', window, num_mels)
- x, _ = self.lstm(mels) # (T', window, lstm_hidden)
- x = x[:, -1, :] # (T', lstm_hidden), use last frame only
- x = self.proj(x) # (T', emb_dim)
- x = x / torch.norm(x, p=2, dim=1, keepdim=True) # (T', emb_dim)
-
- x = x.mean(dim=0)
- if x.norm(p=2) != 0:
- x = x / x.norm(p=2)
- return x
-
-
-class SpkrEmbedder(nn.Module):
- RATE = 16000
-
- def __init__(
- self,
- embedder_path,
- embedder_params=EMBEDDER_PARAMS,
- rate=16000,
- hop_length=160,
- win_length=400,
- pad=False,
- ):
- super(SpkrEmbedder, self).__init__()
- embedder_pt = torch.load(embedder_path, map_location="cpu")
- self.embedder = SpeechEmbedder(embedder_params)
- self.embedder.load_state_dict(embedder_pt)
- self.embedder.eval()
- set_requires_grad(self.embedder, requires_grad=False)
- self.embedder_params = embedder_params
-
- self.register_buffer('mel_basis', torch.from_numpy(
- librosa.filters.mel(
- sr=self.RATE,
- n_fft=self.embedder_params["n_fft"],
- n_mels=self.embedder_params["num_mels"])
- )
- )
-
- self.resample = None
- if rate != self.RATE:
- self.resample = torchaudio.transforms.Resample(rate, self.RATE)
- self.hop_length = hop_length
- self.win_length = win_length
- self.pad = pad
-
- def get_mel(self, y):
- if self.pad and y.shape[-1] < 14000:
- y = F.pad(y, (0, 14000 - y.shape[-1]))
-
- window = torch.hann_window(self.win_length).to(y)
- y = torch.stft(y, n_fft=self.embedder_params["n_fft"],
- hop_length=self.hop_length,
- win_length=self.win_length,
- window=window)
- magnitudes = torch.norm(y, dim=-1, p=2) ** 2
- mel = torch.log10(self.mel_basis @ magnitudes + 1e-6)
- return mel
-
- def forward(self, inputs):
- dvecs = []
- for wav in inputs:
- mel = self.get_mel(wav)
- if mel.dim() == 3:
- mel = mel.squeeze(0)
- dvecs += [self.embedder(mel)]
- dvecs = torch.stack(dvecs)
-
- dvec = torch.mean(dvecs, dim=0)
- dvec = dvec / torch.norm(dvec)
-
- return dvec
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/vad/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/vad/__init__.py
deleted file mode 100644
index 9cf121081fbde2f5085ed380f0841649d143a4be..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/preprocessing/vad/__init__.py
+++ /dev/null
@@ -1,192 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-
-import collections
-import contextlib
-import wave
-
-try:
- import webrtcvad
-except ImportError:
- raise ImportError("Please install py-webrtcvad: pip install webrtcvad")
-import argparse
-import os
-import logging
-from tqdm import tqdm
-
-AUDIO_SUFFIX = '.wav'
-FS_MS = 30
-SCALE = 6e-5
-THRESHOLD = 0.3
-
-
-def read_wave(path):
- """Reads a .wav file.
- Takes the path, and returns (PCM audio data, sample rate).
- """
- with contextlib.closing(wave.open(path, 'rb')) as wf:
- num_channels = wf.getnchannels()
- assert num_channels == 1
- sample_width = wf.getsampwidth()
- assert sample_width == 2
- sample_rate = wf.getframerate()
- assert sample_rate in (8000, 16000, 32000, 48000)
- pcm_data = wf.readframes(wf.getnframes())
- return pcm_data, sample_rate
-
-
-def write_wave(path, audio, sample_rate):
- """Writes a .wav file.
- Takes path, PCM audio data, and sample rate.
- """
- with contextlib.closing(wave.open(path, 'wb')) as wf:
- wf.setnchannels(1)
- wf.setsampwidth(2)
- wf.setframerate(sample_rate)
- wf.writeframes(audio)
-
-
-class Frame(object):
- """Represents a "frame" of audio data."""
- def __init__(self, bytes, timestamp, duration):
- self.bytes = bytes
- self.timestamp = timestamp
- self.duration = duration
-
-
-def frame_generator(frame_duration_ms, audio, sample_rate):
- """Generates audio frames from PCM audio data.
- Takes the desired frame duration in milliseconds, the PCM data, and
- the sample rate.
- Yields Frames of the requested duration.
- """
- n = int(sample_rate * (frame_duration_ms / 1000.0) * 2)
- offset = 0
- timestamp = 0.0
- duration = (float(n) / sample_rate) / 2.0
- while offset + n < len(audio):
- yield Frame(audio[offset:offset + n], timestamp, duration)
- timestamp += duration
- offset += n
-
-
-def vad_collector(sample_rate, frame_duration_ms,
- padding_duration_ms, vad, frames):
- """Filters out non-voiced audio frames.
- Given a webrtcvad.Vad and a source of audio frames, yields only
- the voiced audio.
- Uses a padded, sliding window algorithm over the audio frames.
- When more than 90% of the frames in the window are voiced (as
- reported by the VAD), the collector triggers and begins yielding
- audio frames. Then the collector waits until 90% of the frames in
- the window are unvoiced to detrigger.
- The window is padded at the front and back to provide a small
- amount of silence or the beginnings/endings of speech around the
- voiced frames.
- Arguments:
- sample_rate - The audio sample rate, in Hz.
- frame_duration_ms - The frame duration in milliseconds.
- padding_duration_ms - The amount to pad the window, in milliseconds.
- vad - An instance of webrtcvad.Vad.
- frames - a source of audio frames (sequence or generator).
- Returns: A generator that yields PCM audio data.
- """
- num_padding_frames = int(padding_duration_ms / frame_duration_ms)
- # We use a deque for our sliding window/ring buffer.
- ring_buffer = collections.deque(maxlen=num_padding_frames)
- # We have two states: TRIGGERED and NOTTRIGGERED. We start in the
- # NOTTRIGGERED state.
- triggered = False
-
- voiced_frames = []
- for frame in frames:
- is_speech = vad.is_speech(frame.bytes, sample_rate)
-
- # sys.stdout.write('1' if is_speech else '0')
- if not triggered:
- ring_buffer.append((frame, is_speech))
- num_voiced = len([f for f, speech in ring_buffer if speech])
- # If we're NOTTRIGGERED and more than 90% of the frames in
- # the ring buffer are voiced frames, then enter the
- # TRIGGERED state.
- if num_voiced > 0.9 * ring_buffer.maxlen:
- triggered = True
- # We want to yield all the audio we see from now until
- # we are NOTTRIGGERED, but we have to start with the
- # audio that's already in the ring buffer.
- for f, _ in ring_buffer:
- voiced_frames.append(f)
- ring_buffer.clear()
- else:
- # We're in the TRIGGERED state, so collect the audio data
- # and add it to the ring buffer.
- voiced_frames.append(frame)
- ring_buffer.append((frame, is_speech))
- num_unvoiced = len([f for f, speech in ring_buffer if not speech])
- # If more than 90% of the frames in the ring buffer are
- # unvoiced, then enter NOTTRIGGERED and yield whatever
- # audio we've collected.
- if num_unvoiced > 0.9 * ring_buffer.maxlen:
- triggered = False
- yield [b''.join([f.bytes for f in voiced_frames]),
- voiced_frames[0].timestamp, voiced_frames[-1].timestamp]
- ring_buffer.clear()
- voiced_frames = []
- # If we have any leftover voiced audio when we run out of input,
- # yield it.
- if voiced_frames:
- yield [b''.join([f.bytes for f in voiced_frames]),
- voiced_frames[0].timestamp, voiced_frames[-1].timestamp]
-
-
-def main(args):
- # create output folder
- try:
- cmd = f"mkdir -p {args.out_path}"
- os.system(cmd)
- except Exception:
- logging.error("Can not create output folder")
- exit(-1)
-
- # build vad object
- vad = webrtcvad.Vad(int(args.agg))
- # iterating over wavs in dir
- for file in tqdm(os.listdir(args.in_path)):
- if file.endswith(AUDIO_SUFFIX):
- audio_inpath = os.path.join(args.in_path, file)
- audio_outpath = os.path.join(args.out_path, file)
- audio, sample_rate = read_wave(audio_inpath)
- frames = frame_generator(FS_MS, audio, sample_rate)
- frames = list(frames)
- segments = vad_collector(sample_rate, FS_MS, 300, vad, frames)
- merge_segments = list()
- timestamp_start = 0.0
- timestamp_end = 0.0
- # removing start, end, and long sequences of sils
- for i, segment in enumerate(segments):
- merge_segments.append(segment[0])
- if i and timestamp_start:
- sil_duration = segment[1] - timestamp_end
- if sil_duration > THRESHOLD:
- merge_segments.append(int(THRESHOLD / SCALE)*(b'\x00'))
- else:
- merge_segments.append(int((sil_duration / SCALE))*(b'\x00'))
- timestamp_start = segment[1]
- timestamp_end = segment[2]
- segment = b''.join(merge_segments)
- write_wave(audio_outpath, segment, sample_rate)
-
-
-if __name__ == '__main__':
- parser = argparse.ArgumentParser(description='Apply vad to a file of fils.')
- parser.add_argument('in_path', type=str, help='Path to the input files')
- parser.add_argument('out_path', type=str,
- help='Path to save the processed files')
- parser.add_argument('--agg', type=int, default=3,
- help='The level of aggressiveness of the VAD: [0-3]')
- args = parser.parse_args()
-
- main(args)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/utils.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/utils.py
deleted file mode 100644
index 2c7b03733d2290d3834d2c68a16034198daa1e69..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_synthesis/utils.py
+++ /dev/null
@@ -1,101 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import numpy as np
-import torch
-from scipy.interpolate import interp1d
-import torchaudio
-
-from fairseq.tasks.text_to_speech import (
- batch_compute_distortion, compute_rms_dist
-)
-
-
-def batch_mel_spectral_distortion(
- y1, y2, sr, normalize_type="path", mel_fn=None
-):
- """
- https://arxiv.org/pdf/2011.03568.pdf
-
- Same as Mel Cepstral Distortion, but computed on log-mel spectrograms.
- """
- if mel_fn is None or mel_fn.sample_rate != sr:
- mel_fn = torchaudio.transforms.MelSpectrogram(
- sr, n_fft=int(0.05 * sr), win_length=int(0.05 * sr),
- hop_length=int(0.0125 * sr), f_min=20, n_mels=80,
- window_fn=torch.hann_window
- ).to(y1[0].device)
- offset = 1e-6
- return batch_compute_distortion(
- y1, y2, sr, lambda y: torch.log(mel_fn(y) + offset).transpose(-1, -2),
- compute_rms_dist, normalize_type
- )
-
-
-# This code is based on
-# "https://github.com/bastibe/MAPS-Scripts/blob/master/helper.py"
-def _same_t_in_true_and_est(func):
- def new_func(true_t, true_f, est_t, est_f):
- assert type(true_t) is np.ndarray
- assert type(true_f) is np.ndarray
- assert type(est_t) is np.ndarray
- assert type(est_f) is np.ndarray
-
- interpolated_f = interp1d(
- est_t, est_f, bounds_error=False, kind='nearest', fill_value=0
- )(true_t)
- return func(true_t, true_f, true_t, interpolated_f)
-
- return new_func
-
-
-@_same_t_in_true_and_est
-def gross_pitch_error(true_t, true_f, est_t, est_f):
- """The relative frequency in percent of pitch estimates that are
- outside a threshold around the true pitch. Only frames that are
- considered pitched by both the ground truth and the estimator (if
- applicable) are considered.
- """
-
- correct_frames = _true_voiced_frames(true_t, true_f, est_t, est_f)
- gross_pitch_error_frames = _gross_pitch_error_frames(
- true_t, true_f, est_t, est_f
- )
- return np.sum(gross_pitch_error_frames) / np.sum(correct_frames)
-
-
-def _gross_pitch_error_frames(true_t, true_f, est_t, est_f, eps=1e-8):
- voiced_frames = _true_voiced_frames(true_t, true_f, est_t, est_f)
- true_f_p_eps = [x + eps for x in true_f]
- pitch_error_frames = np.abs(est_f / true_f_p_eps - 1) > 0.2
- return voiced_frames & pitch_error_frames
-
-
-def _true_voiced_frames(true_t, true_f, est_t, est_f):
- return (est_f != 0) & (true_f != 0)
-
-
-def _voicing_decision_error_frames(true_t, true_f, est_t, est_f):
- return (est_f != 0) != (true_f != 0)
-
-
-@_same_t_in_true_and_est
-def f0_frame_error(true_t, true_f, est_t, est_f):
- gross_pitch_error_frames = _gross_pitch_error_frames(
- true_t, true_f, est_t, est_f
- )
- voicing_decision_error_frames = _voicing_decision_error_frames(
- true_t, true_f, est_t, est_f
- )
- return (np.sum(gross_pitch_error_frames) +
- np.sum(voicing_decision_error_frames)) / (len(true_t))
-
-
-@_same_t_in_true_and_est
-def voicing_decision_error(true_t, true_f, est_t, est_f):
- voicing_decision_error_frames = _voicing_decision_error_frames(
- true_t, true_f, est_t, est_f
- )
- return np.sum(voicing_decision_error_frames) / (len(true_t))
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/README.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/README.md
deleted file mode 100644
index c1aa11929a434a0d146dcfa05fc067d0fac1b310..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/README.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# Joint Speech Text training in Fairseq
-An extension of Fairseq s2t project with the speech to text task enhanced by the co-trained text to text mapping task. More details about Fairseq s2t can be found [here](../speech_to_text/README.md)
-
-## Examples
-Examples of speech text joint training in fairseq
-- [English-to-German MuST-C model](docs/ende-mustc.md)
-- [IWSLT 2021 Multilingual Speech Translation](docs/iwslt2021.md)
-- [Speech Text Joint Pre-training ](docs/pre-training.md)
-## Citation
-Please cite as:
-```
-@inproceedings{Tang2022UnifiedSP,
- title={Unified Speech-Text Pre-training for Speech Translation and Recognition},
- author={Yun Tang and Hongyu Gong and Ning Dong and Changhan Wang and Wei-Ning Hsu and Jiatao Gu and Alexei Baevski and Xian Li and Abdelrahman Mohamed and Michael Auli and Juan Miguel Pino},
- booktitle={ACL},
- year={2022}
-}
-@inproceedings{Tang2021IST,
- title = {Improving Speech Translation by Understanding and Learning from the Auxiliary Text Translation Task},
- author = {Yun Tang and Juan Pino and Xian Li and Changhan Wang and Dmitriy Genzel},
- booktitle = {ACL},
- year = {2021},
-}
-
-@inproceedings{Tang2021FST,
- title = {FST: the FAIR Speech Translation System for the IWSLT21 Multilingual Shared Task},
- author = {Yun Tang and Hongyu Gong and Xian Li and Changhan Wang and Juan Pino and Holger Schwenk and Naman Goyal},
- booktitle = {IWSLT},
- year = {2021},
-}
-@inproceedings{Tang2021AGM,
- title={A General Multi-Task Learning Framework to Leverage Text Data for Speech to Text Tasks},
- author={Yun Tang and J. Pino and Changhan Wang and Xutai Ma and Dmitriy Genzel},
- booktitle={ICASSP},
- year={2021}
-}
-
-@inproceedings{wang2020fairseqs2t,
- title = {fairseq S2T: Fast Speech-to-Text Modeling with fairseq},
- author = {Changhan Wang and Yun Tang and Xutai Ma and Anne Wu and Dmytro Okhonko and Juan Pino},
- booktitle = {Proceedings of the 2020 Conference of the Asian Chapter of the Association for Computational Linguistics (AACL): System Demonstrations},
- year = {2020},
-}
-
-@inproceedings{ott2019fairseq,
- title = {fairseq: A Fast, Extensible Toolkit for Sequence Modeling},
- author = {Myle Ott and Sergey Edunov and Alexei Baevski and Angela Fan and Sam Gross and Nathan Ng and David Grangier and Michael Auli},
- booktitle = {Proceedings of NAACL-HLT 2019: Demonstrations},
- year = {2019},
-}
-```
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/__init__.py
deleted file mode 100644
index 239d2e69f9a235095dee1ea7b3a94164a77273f5..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-from . import tasks, criterions, models # noqa
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/configs/mustc_noise.list b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/configs/mustc_noise.list
deleted file mode 100644
index 02eeac4e009f77b765004272f59a1618214da18d..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/configs/mustc_noise.list
+++ /dev/null
@@ -1,49 +0,0 @@
-"(Applause) NOISE
-"(Laughter) VOICE
-"(Laughter)" VOICE
-(Applause) NOISE
-(Applause). NOISE
-(Audience) VOICE
-(Audio) NOISE
-(Beat) NOISE
-(Beatboxing) VOICE
-(Beep) NOISE
-(Beeps) NOISE
-(Cheering) VOICE
-(Cheers) VOICE
-(Claps) NOISE
-(Clicking) NOISE
-(Clunk) NOISE
-(Coughs) NOISE
-(Drums) NOISE
-(Explosion) NOISE
-(Gasps) VOICE
-(Guitar) NOISE
-(Honk) NOISE
-(Laugher) VOICE
-(Laughing) VOICE
-(Laughs) VOICE
-(Laughter) VOICE
-(Laughter). VOICE
-(Laughter)... VOICE
-(Mumbling) VOICE
-(Music) NOISE
-(Noise) NOISE
-(Recording) VOICE
-(Ringing) NOISE
-(Shouts) VOICE
-(Sigh) VOICE
-(Sighs) VOICE
-(Silence) NOISE
-(Singing) VOICE
-(Sings) VOICE
-(Spanish) VOICE
-(Static) NOISE
-(Tones) NOISE
-(Trumpet) NOISE
-(Video) NOISE
-(Video): NOISE
-(Voice-over) NOISE
-(Whistle) NOISE
-(Whistling) NOISE
-(video): NOISE
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/criterions/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/criterions/__init__.py
deleted file mode 100644
index 7faae73119321af0b34fe8e26499a2ef5577291a..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/criterions/__init__.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import importlib
-import os
-
-
-for file in os.listdir(os.path.dirname(__file__)):
- if file.endswith(".py") and not file.startswith("_"):
- criterion_name = file[: file.find(".py")]
- importlib.import_module(
- "examples.speech_text_joint_to_text.criterions." + criterion_name
- )
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/criterions/multi_modality_compound.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/criterions/multi_modality_compound.py
deleted file mode 100644
index b3a5506a2d29436e33776ff956e066205d907f99..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/criterions/multi_modality_compound.py
+++ /dev/null
@@ -1,181 +0,0 @@
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-import logging
-import math
-from dataclasses import dataclass, field
-
-from fairseq import utils
-from fairseq.logging import metrics
-from fairseq.criterions import FairseqCriterion, register_criterion
-from fairseq.criterions.ctc import CtcCriterion, CtcCriterionConfig
-from fairseq.criterions.label_smoothed_cross_entropy import (
- LabelSmoothedCrossEntropyCriterionConfig,
-)
-from fairseq.logging.meters import safe_round
-
-from .multi_modality_cross_entropy import SpeechTextPreTrainCrossEntCriterion
-
-logger = logging.getLogger(__name__)
-
-
-@dataclass
-class SpeechTextPreTrainCompoundCriterionConfig(
- LabelSmoothedCrossEntropyCriterionConfig
-):
- zero_infinity: bool = field(
- default=False,
- metadata={"help": "zero inf loss when source length <= target length"},
- )
- post_process: str = field(
- default="none",
- metadata={
- "help": "how to post process predictions into words. can be letter, "
- "wordpiece, BPE symbols, etc. "
- "See fairseq.data.data_utils.post_process() for full list of options"
- },
- )
-
-
-@register_criterion(
- "speech_text_pretrain_compound", dataclass=SpeechTextPreTrainCompoundCriterionConfig
-)
-class SpeechTextPreTrainCompoundCriterion(FairseqCriterion):
- def __init__(
- self,
- task,
- sentence_avg,
- label_smoothing,
- report_accuracy=False,
- zero_infinity=False,
- post_process=None,
- ):
- super().__init__(task)
- self.xent = SpeechTextPreTrainCrossEntCriterion(
- task, sentence_avg, label_smoothing, report_accuracy
- )
- cfg_dict = {
- "zero_infinity": zero_infinity,
- "sentence_avg": sentence_avg,
- "post_process": post_process,
- }
- cfg_ctc = CtcCriterionConfig(**cfg_dict)
- self.ctc = CtcCriterion(cfg_ctc, task)
-
- def forward(self, model, sample, reduce=True):
- mode = sample["net_input"]["mode"]
- if mode == "sup_speech_ctc": # CTC
- sample["net_input"][
- "src_lengths"
- ] = None # get downsampled src_lengths from padding_mask
- loss, sample_size, logging_output = self.ctc(model, sample, reduce)
- logging_output["mode"] = SpeechTextPreTrainCompoundCriterion.mode2value(
- "CTC"
- )
- else:
- loss, sample_size, logging_output = self.xent(model, sample, reduce)
- logging_output["mode"] = SpeechTextPreTrainCompoundCriterion.mode2value(
- "xent"
- )
-
- return loss, sample_size, logging_output
-
- @staticmethod
- def logging_outputs_can_be_summed() -> bool:
- """
- Whether the logging outputs returned by `forward` can be summed
- across workers prior to calling `reduce_metrics`. Setting this
- to True will improves distributed training speed.
- """
- return True
-
- @staticmethod
- def mode2value(mode): # make the logging_outputs_can_be_summed = True
- if mode == "CTC":
- return 907 # prime number
- if mode == "xent":
- return 887 # prime number
- return 0
-
- @staticmethod
- def value2mode(value):
- if value % 907 == 0:
- return "CTC"
- if value % 887 == 0:
- return "xent"
- raise ValueError("Unknow mode")
-
- @staticmethod
- def reduce_metrics(logging_outputs) -> None:
- """Aggregate logging outputs from data parallel training."""
-
- def _get_mode(logging_outputs):
- mds = [
- SpeechTextPreTrainCompoundCriterion.value2mode(log["mode"])
- for log in logging_outputs
- ]
- if sum([1 if l != mds[0] else 0 for l in mds]) > 0:
- raise ValueError("mode in one mini-batch is expected to be the same!")
- return mds[0]
-
- log_mode = _get_mode(logging_outputs)
- if log_mode == "xent":
- return SpeechTextPreTrainCrossEntCriterion.reduce_metrics(logging_outputs)
-
- # ctc loss
- loss_sum = utils.item(sum(log.get("loss", 0) for log in logging_outputs))
- ntokens = utils.item(sum(log.get("ntokens", 0) for log in logging_outputs))
- nsentences = utils.item(
- sum(log.get("nsentences", 0) for log in logging_outputs)
- )
- sample_size = utils.item(
- sum(log.get("sample_size", 0) for log in logging_outputs)
- )
-
- metrics.log_scalar(
- "ctc_loss", loss_sum / sample_size / math.log(2), sample_size, round=3
- )
- metrics.log_scalar("ctc_ntokens", ntokens)
- metrics.log_scalar("ctc_nsentences", nsentences)
- if sample_size != ntokens:
- metrics.log_scalar(
- "ctc_nll_loss", loss_sum / ntokens / math.log(2), ntokens, round=3
- )
-
- c_errors = sum(log.get("c_errors", 0) for log in logging_outputs)
- metrics.log_scalar("_c_errors", c_errors)
- c_total = sum(log.get("c_total", 0) for log in logging_outputs)
- metrics.log_scalar("_c_total", c_total)
- w_errors = sum(log.get("w_errors", 0) for log in logging_outputs)
- metrics.log_scalar("_w_errors", w_errors)
- wv_errors = sum(log.get("wv_errors", 0) for log in logging_outputs)
- metrics.log_scalar("_wv_errors", wv_errors)
- w_total = sum(log.get("w_total", 0) for log in logging_outputs)
- metrics.log_scalar("_w_total", w_total)
-
- if c_total > 0:
- metrics.log_derived(
- "uer",
- lambda meters: safe_round(
- meters["_c_errors"].sum * 100.0 / meters["_c_total"].sum, 3
- )
- if meters["_c_total"].sum > 0
- else float("nan"),
- )
- if w_total > 0:
- metrics.log_derived(
- "wer",
- lambda meters: safe_round(
- meters["_w_errors"].sum * 100.0 / meters["_w_total"].sum, 3
- )
- if meters["_w_total"].sum > 0
- else float("nan"),
- )
- metrics.log_derived(
- "raw_wer",
- lambda meters: safe_round(
- meters["_wv_errors"].sum * 100.0 / meters["_w_total"].sum, 3
- )
- if meters["_w_total"].sum > 0
- else float("nan"),
- )
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/criterions/multi_modality_cross_entropy.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/criterions/multi_modality_cross_entropy.py
deleted file mode 100644
index 6c9cb0f20dd3fc9376e78b85e383cf3a43f254c4..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/criterions/multi_modality_cross_entropy.py
+++ /dev/null
@@ -1,101 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-import torch
-
-from fairseq import utils
-from fairseq.criterions import register_criterion
-from fairseq.criterions.label_smoothed_cross_entropy import (
- LabelSmoothedCrossEntropyCriterion,
- LabelSmoothedCrossEntropyCriterionConfig,
- label_smoothed_nll_loss,
-)
-
-
-@register_criterion(
- "speech_text_pretrain_cross_entropy",
- dataclass=LabelSmoothedCrossEntropyCriterionConfig,
-)
-class SpeechTextPreTrainCrossEntCriterion(LabelSmoothedCrossEntropyCriterion):
- def __init__(self, task, sentence_avg, label_smoothing, report_accuracy=False):
- super().__init__(
- task, sentence_avg, label_smoothing, report_accuracy=report_accuracy
- )
-
- def forward(self, model, sample, reduce=True):
- net_output = model(**sample["net_input"])
- loss, nll_loss, nsentences, ntokens, n_correct = self.compute_loss(
- model, net_output, sample, reduce=reduce
- )
- sample_size = nsentences if self.sentence_avg else ntokens
- logging_output = {
- "loss": loss.data,
- "nll_loss": nll_loss.data,
- "ntokens": ntokens,
- "nsentences": nsentences,
- "sample_size": sample_size,
- }
- if self.report_accuracy:
- logging_output["n_correct"] = utils.item(n_correct)
- logging_output["total"] = utils.item(ntokens)
- return loss, sample_size, logging_output
-
- def get_lprobs_and_target(self, model, net_output, sample):
- lprobs = model.get_normalized_probs(net_output, log_probs=True)
- target = model.get_targets(sample, net_output)
- assert self.ignore_prefix_size == 0
- if self.ignore_prefix_size > 0:
- if getattr(lprobs, "batch_first", False):
- lprobs = lprobs[:, self.ignore_prefix_size :, :].contiguous()
- target = target[:, self.ignore_prefix_size :].contiguous()
- else:
- lprobs = lprobs[self.ignore_prefix_size :, :, :].contiguous()
- target = target[self.ignore_prefix_size :, :].contiguous()
- return lprobs, target
-
- def compute_loss(self, model, net_output, sample, reduce=True):
- lprobs, target = self.get_lprobs_and_target(model, net_output, sample)
- n_correct = 0
- if isinstance(target, dict):
- t_lprobs = target["target_logprobs"]
-
- if not lprobs.batch_first:
- lprobs = lprobs.transpose(0, 1)
- t_lprobs = t_lprobs.transpose(0, 1)
- nsentences, seq_len = lprobs.size()[:2]
- ntokens = nsentences * seq_len
- t_probs = t_lprobs.exp()
- mask_indices = (
- net_output[1]["mask_indices"][0]
- if len(net_output[1]["mask_indices"]) > 0
- else None
- )
-
- # mask_indices is True for those masking frames
- if mask_indices is not None: # B X T
- t_probs = t_probs.masked_fill(mask_indices.eq(False).unsqueeze(-1), 0)
- ntokens = mask_indices.int().sum()
- t_probs = t_probs.detach()
- t_lprobs = t_lprobs.detach()
- loss = (
- -(t_probs * (lprobs - t_lprobs)).sum()
- if reduce
- else -(t_probs * (lprobs - t_lprobs)).sum(-1, keepdim=True)
- )
- nll_loss = loss
- else:
- nsentences = target.size(0)
- mask = target.ne(self.padding_idx)
- loss, nll_loss = label_smoothed_nll_loss(
- lprobs.view(-1, lprobs.size(-1)),
- target.view(-1),
- self.eps,
- ignore_index=self.padding_idx,
- reduce=reduce,
- )
- n_correct = torch.sum(
- lprobs.argmax(-1).masked_select(mask).eq(target.masked_select(mask))
- )
- ntokens = torch.sum(mask)
- return loss, nll_loss, nsentences, ntokens, n_correct
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/criterions/text_guide_cross_entropy_acc.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/criterions/text_guide_cross_entropy_acc.py
deleted file mode 100644
index fd6ff155c97726615c18f30e3913ad87ba5f80b9..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/criterions/text_guide_cross_entropy_acc.py
+++ /dev/null
@@ -1,224 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-import math
-
-import torch
-import torch.nn.functional as F
-from fairseq import utils
-from fairseq.criterions import FairseqCriterion, register_criterion
-from fairseq.criterions.label_smoothed_cross_entropy import label_smoothed_nll_loss
-from fairseq.logging import metrics
-
-
-@register_criterion("guided_label_smoothed_cross_entropy_with_accuracy")
-class GuidedCrossEntAccCriterion(FairseqCriterion):
- def __init__(
- self,
- task,
- sentence_avg,
- guide_alpha,
- text_input_cost_ratio,
- label_smoothing,
- disable_text_guide_update_num=0,
- attentive_cost_regularization=0,
- ):
- """
- guide_alpha: alpha to inteplate nll and kd loss
- text_input_cost_ratio: loss ratio for text only input data
- label_smoothing: label smoothing ratio
- disable_text_guide_update_num: only use nll loss for the first N updates
- attentive_cost_regularization: ratio fo attentive cost
- """
- super().__init__(task)
- self.alpha = guide_alpha
- self.attn_beta = attentive_cost_regularization
- self.sentence_avg = sentence_avg
- self.eps = label_smoothing
- self.text_input_cost_ratio = text_input_cost_ratio
- self.disable_update_num = disable_text_guide_update_num
- assert self.alpha >= 0 and self.alpha <= 1.0
-
- @staticmethod
- def add_args(parser):
- """Add criterion-specific arguments to the parser."""
- # fmt: off
- parser.add_argument('--label-smoothing', default=0., type=float, metavar='D',
- help='epsilon for label smoothing, 0 means no label smoothing')
- # fmt: off
- parser.add_argument('--guide-alpha', default=0., type=float, metavar='D',
- help='alpha to merge kd cost from text to speech input with ce loss')
- # fmt: off
- parser.add_argument('--disable-text-guide-update-num', default=0, type=int, metavar='D',
- help='disable guided target from text for the first N updates.')
- parser.add_argument("--attentive-cost-regularization", default=0.0, type=float, metavar='D',
- help="use encoder attentive loss regularization with cost ratio D")
- parser.add_argument("--attentive-cost-without-normalize", action='store_true',
- help="Don't do normalization during attentive cost computation")
-
- def forward(self, model, sample, reduce=True):
- reduction = 'sum' if reduce else 'none'
- net_input = sample["net_input"]
- net_output = model(**net_input)
- attn_cost = None
- lprobs = model.get_normalized_probs(net_output, log_probs=True)
- is_dual_input = True if net_input['src_tokens'] is not None and net_input.get('src_txt_tokens') is not None else False
- target = model.get_targets(sample, net_output)
- src_token_num = 0
- if is_dual_input:
- # lprobs_spch from speech encoder and lprobs_text from text encoder
- lprobs_spch, lprobs_text = torch.chunk(lprobs, 2)
- lprobs_spch.batch_first = lprobs.batch_first
- lprobs_text.batch_first = lprobs.batch_first
-
- speech_loss, speech_nll_loss, speech_correct, speech_total = \
- self.guide_loss_and_acc(model, lprobs_spch, lprobs_text, target, reduce=(reduction == 'sum'))
- text_loss, text_nll_loss, text_correct, text_total = self.compute_loss_and_acc(model, lprobs_text, target, reduction=reduction)
- loss = (speech_loss + text_loss)
- nll_loss = (speech_nll_loss + text_nll_loss)
- correct = speech_correct + text_correct
- total = speech_total + text_total
-
- attn_cost = net_output[1].get('attn_cost')
- if attn_cost is not None:
- # attn_cost is batch_first and padding tokens have been masked already
- src_token_num = attn_cost.ne(0).sum()
- attn_cost = attn_cost.sum()
- loss = loss + attn_cost * self.attn_beta
- else:
- attn_cost = 0
- else:
- loss, nll_loss, correct, total = self.compute_loss_and_acc(model, lprobs, target, reduction=reduction)
- if sample["net_input"]['src_tokens'] is None: # text input only
- loss = loss * self.text_input_cost_ratio
- speech_loss = None
- speech_nll_loss = None
-
- sample_size, logging_output = self.get_logging_output(
- sample, loss, nll_loss, correct, total, src_token_num, speech_loss, speech_nll_loss, attn_cost, is_dual_input
- )
- return loss, sample_size, logging_output
-
- def compute_loss_and_acc(self, model, lprobs, target, reduction='sum'):
- if not lprobs.batch_first:
- lprobs = lprobs.transpose(0, 1)
- lprobs = lprobs.view(-1, lprobs.size(-1)) # -> (B x T) x C
- target = target.view(-1)
- loss, nll_loss = label_smoothed_nll_loss(
- lprobs, target, self.eps, ignore_index=self.padding_idx, reduce=(reduction == 'sum'),
- )
-
- mask = target.ne(self.padding_idx)
- correct = torch.sum(lprobs.argmax(1).masked_select(mask).eq(target.masked_select(mask)))
- total = torch.sum(mask)
- return loss, nll_loss, correct, total
-
- def guide_loss_and_acc(self, model, lprobs, lprobs_teacher, target, reduce=True):
- """ lprobs_teacher is used as guide for lprobs """
- if self.alpha == 0.0 or model.num_updates < self.disable_update_num:
- return self.compute_loss_and_acc(model, lprobs, target, reduction=('sum' if reduce else 'none'))
- if not lprobs.batch_first:
- lprobs = lprobs.transpose(0, 1)
- lprobs_teacher = lprobs_teacher.transpose(0, 1)
-
- lprobs = lprobs.view(-1, lprobs.size(-1)).float() # -> (B x T) x C
- lprobs_teacher = lprobs_teacher.view(-1, lprobs_teacher.size(-1)).float() # -> (B x T) x C
- target = target.view(-1)
- loss = F.nll_loss(lprobs, target, ignore_index=self.padding_idx, reduction='sum' if reduce else 'none')
- nll_loss = loss
- probs_teacher = lprobs_teacher.exp().masked_fill_(target.unsqueeze(-1).eq(self.padding_idx), 0)
- probs_teacher = probs_teacher.detach()
- guide_loss = -(probs_teacher*lprobs).sum() if reduce else -(probs_teacher*lprobs).sum(-1, keepdim=True)
- loss = self.alpha*guide_loss + (1.0 - self.alpha)*loss
-
- mask = target.ne(self.padding_idx)
- correct = torch.sum(lprobs.argmax(1).masked_select(mask).eq(target.masked_select(mask)))
- total = torch.sum(mask)
- return loss, nll_loss, correct, total
-
- def get_logging_output(
- self,
- sample,
- loss,
- nll_loss,
- correct,
- total,
- src_token_num=0,
- speech_loss=None,
- speech_nll_loss=None,
- attn_cost=None,
- is_dual_input=False,
- ):
-
- sample_size = (
- sample["target"].size(0) if self.sentence_avg else sample["ntokens"]
- )
- mul_size = 2 if is_dual_input else 1
-
- logging_output = {
- "loss": utils.item(loss.data), # * sample['ntokens'],
- "nll_loss": utils.item(nll_loss.data), # * sample['ntokens'],
- "ntokens": sample["ntokens"]*mul_size,
- "nsentences": sample["target"].size(0)*mul_size,
- "sample_size": sample_size*mul_size,
- "correct": utils.item(correct.data),
- "total": utils.item(total.data),
- "src_token_num": utils.item(src_token_num.data) if src_token_num > 0 else 0,
- "nframes": torch.sum(sample["net_input"]["src_lengths"]).item(),
- }
-
- if speech_loss is not None:
- logging_output["speech_loss"] = utils.item(speech_loss.data)
- logging_output["speech_nll_loss"] = utils.item(speech_nll_loss.data)
- logging_output["sample_size_speech_cost"] = sample_size
- logging_output["speech_attn_loss"] = attn_cost
-
- return sample_size*mul_size, logging_output
-
- @staticmethod
- def aggregate_logging_outputs(logging_outputs):
- """Aggregate logging outputs from data parallel training."""
- correct_sum = sum(log.get("correct", 0) for log in logging_outputs)
- total_sum = sum(log.get("total", 0) for log in logging_outputs)
- src_token_sum = sum(log.get("src_token_num", 0) for log in logging_outputs)
- loss_sum = sum(log.get("loss", 0) for log in logging_outputs)
- nll_loss_sum = sum(log.get("nll_loss", 0) for log in logging_outputs)
- ntokens = sum(log.get("ntokens", 0) for log in logging_outputs)
- nsentences = sum(log.get("nsentences", 0) for log in logging_outputs)
- sample_size = sum(log.get("sample_size", 0) for log in logging_outputs)
- nframes = sum(log.get("nframes", 0) for log in logging_outputs)
- speech_loss_sum = sum(log.get("speech_loss", 0) for log in logging_outputs)
- speech_nll_loss_sum = sum(log.get("speech_nll_loss", 0) for log in logging_outputs)
- speech_attn_loss_sum = sum(log.get("speech_attn_loss", 0) for log in logging_outputs)
- sample_size_speech = sum(log.get("sample_size_speech_cost", 0) for log in logging_outputs)
-
- agg_output = {
- "loss": loss_sum / sample_size / math.log(2) if sample_size > 0 else 0.0,
- "nll_loss": nll_loss_sum / sample_size / math.log(2) if sample_size > 0 else 0.0,
- # if args.sentence_avg, then sample_size is nsentences, and loss
- # is per-sentence loss; else sample_size is ntokens, and the loss
- # becomes per-output token loss
- "speech_loss": speech_loss_sum / sample_size_speech / math.log(2) if sample_size_speech > 0 else 0.0,
- "speech_nll_loss": speech_nll_loss_sum / sample_size_speech / math.log(2) if sample_size_speech > 0 else 0.0,
- "speech_attn_loss": speech_attn_loss_sum / src_token_sum / math.log(2) if src_token_sum > 0 else 0.0,
- "ntokens": ntokens,
- "nsentences": nsentences,
- "nframes": nframes,
- "sample_size": sample_size,
- "acc": correct_sum * 100.0 / total_sum if total_sum > 0 else 0.0,
- "correct": correct_sum,
- "total": total_sum,
- "src_token_num": src_token_sum,
- # total is the number of validate tokens
- }
- return agg_output
-
- @classmethod
- def reduce_metrics(cls, logging_outputs):
- """Aggregate logging outputs from data parallel training."""
- agg_logging_outputs = cls.aggregate_logging_outputs(logging_outputs)
- for k, v in agg_logging_outputs.items():
- if k in {'nsentences', 'ntokens', 'sample_size'}:
- continue
- metrics.log_scalar(k, v, round=3)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/data/pair_denoising_dataset.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/data/pair_denoising_dataset.py
deleted file mode 100644
index fc94fbaf11f09884f7ecf1d4ead1e61d15e265a5..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/data/pair_denoising_dataset.py
+++ /dev/null
@@ -1,318 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import copy
-import math
-import re
-
-import torch
-
-from fairseq.data import data_utils
-from fairseq.data.language_pair_dataset import LanguagePairDataset
-
-
-# Part of the code is modified from DenoisingDataset
-# compared with DenoisingDataset, no permute_sentences or documents (rotate_ratio, permute_sentence_ratio)
-class LanguagePairDenoisingDataset(LanguagePairDataset):
- def __init__(
- self,
- src,
- src_sizes,
- src_dict,
- tgt,
- tgt_sizes,
- tgt_dict,
- mask_idx,
- mask_whole_words,
- seed,
- args,
- left_pad_source=True,
- left_pad_target=False,
- shuffle=True,
- input_feeding=True,
- remove_eos_from_source=False,
- append_eos_to_target=False,
- align_dataset=None,
- constraints=None,
- append_bos=False,
- eos=None,
- num_buckets=0,
- src_lang_id=None,
- tgt_lang_id=None,
- pad_to_multiple=1,
- ):
- super().__init__(
- src,
- src_sizes,
- src_dict,
- tgt,
- tgt_sizes,
- tgt_dict,
- left_pad_source,
- left_pad_target,
- shuffle,
- input_feeding,
- remove_eos_from_source,
- append_eos_to_target,
- align_dataset,
- constraints,
- append_bos,
- eos,
- num_buckets,
- src_lang_id,
- tgt_lang_id,
- pad_to_multiple,
- )
-
- self.mask_idx = mask_idx
- self.mask_whole_word = mask_whole_words
- self.mask_ratio = args.mask
- self.random_ratio = args.mask_random
- self.insert_ratio = args.insert
-
- self.replace_length = args.replace_length
-
- if self.replace_length not in [-1, 0, 1]:
- raise ValueError(f"invalid arg: replace_length={self.replace_length}")
- if args.mask_length not in ["subword", "word", "span-poisson"]:
- raise ValueError(f"invalid arg: mask-length={args.mask_length}")
- if args.mask_length == "subword" and args.replace_length not in [0, 1]:
- raise ValueError("if using subwords, use replace-length=1 or 0")
-
- self.mask_span_distribution = None
- if args.mask_length == "span-poisson":
- # Text infilling: "A number of text spans are sampled, with span lengths drawn from a Poisson distribution (λ = 3). Each span is replaced with a single [MASK] token. 0-length spans correspond to the insertion of [MASK] tokens."
- _lambda = args.poisson_lambda
-
- lambda_to_the_k = 1
- e_to_the_minus_lambda = math.exp(-_lambda)
- k_factorial = 1
- ps = []
- for k in range(0, 128):
- ps.append(e_to_the_minus_lambda * lambda_to_the_k / k_factorial)
- lambda_to_the_k *= _lambda
- k_factorial *= k + 1
- if ps[-1] < 0.0000001:
- break
- ps = torch.FloatTensor(ps)
- self.mask_span_distribution = torch.distributions.Categorical(ps)
-
- self.epoch = 0
- self.seed = seed
-
- def _is_phoneme(x):
- if re.search("",
- "",
- "",
- "",
- "",
- "",
- ):
- return False
- return True
-
- self.voc_valid_ids = torch.LongTensor(
- [i for i, x in enumerate(self.src_dict.symbols) if _is_phoneme(x)]
- )
- self.voc_valid_size = self.voc_valid_ids.size(0)
-
- @property
- def can_reuse_epoch_itr_across_epochs(self):
- return False
-
- def set_epoch(self, epoch, **unused):
- self.epoch = epoch
-
- def __getitem__(self, index):
- tgt_item = self.tgt[index] if self.tgt is not None else None
- src_item = copy.deepcopy(self.src[index])
- with data_utils.numpy_seed(self.seed, self.epoch, index):
- source = src_item
- assert source[-1] == self.eos
- if self.mask_ratio > 0:
- source = self.add_whole_word_mask(source, self.mask_ratio)
-
- if self.insert_ratio > 0:
- source = self.add_insertion_noise(source, self.insert_ratio)
- src_item = source
-
- if self.append_eos_to_target:
- eos = self.tgt_dict.eos() if self.tgt_dict else self.src_dict.eos()
- if self.tgt and self.tgt[index][-1] != eos:
- tgt_item = torch.cat([self.tgt[index], torch.LongTensor([eos])])
-
- if self.append_bos:
- bos = self.tgt_dict.bos() if self.tgt_dict else self.src_dict.bos()
- if self.tgt and self.tgt[index][0] != bos:
- tgt_item = torch.cat([torch.LongTensor([bos]), self.tgt[index]])
-
- bos = self.src_dict.bos()
- if src_item[0] != bos:
- src_item = torch.cat([torch.LongTensor([bos]), src_item])
-
- if self.remove_eos_from_source:
- eos = self.src_dict.eos()
- if src_item[-1] == eos:
- src_item = src_item[:-1]
-
- example = {
- "id": index,
- "source": src_item,
- "target": tgt_item,
- }
- if self.align_dataset is not None:
- example["alignment"] = self.align_dataset[index]
- if self.constraints is not None:
- example["constraints"] = self.constraints[index]
- if self.src_lang_id is not None:
- example["src_lang_id"] = self.src_lang_id
- if self.tgt_lang_id is not None:
- example["tgt_lang_id"] = self.tgt_lang_id
- return example
-
- # following functions are borrowed from denoising_dataset
- def word_starts(self, source):
- if self.mask_whole_word is not None:
- is_word_start = self.mask_whole_word.gather(0, source)
- else:
- is_word_start = torch.ones(source.size())
- is_word_start[0] = 0
- is_word_start[-1] = 0
- return is_word_start
-
- def add_whole_word_mask(self, source, p):
- is_word_start = self.word_starts(source)
- num_to_mask = int(math.ceil(is_word_start.float().sum() * p))
- num_inserts = 0
- if num_to_mask == 0:
- return source
-
- if self.mask_span_distribution is not None:
- lengths = self.mask_span_distribution.sample(sample_shape=(num_to_mask,))
-
- # Make sure we have enough to mask
- cum_length = torch.cumsum(lengths, 0)
- while cum_length[-1] < num_to_mask:
- lengths = torch.cat(
- [
- lengths,
- self.mask_span_distribution.sample(sample_shape=(num_to_mask,)),
- ],
- dim=0,
- )
- cum_length = torch.cumsum(lengths, 0)
-
- # Trim to masking budget
- i = 0
- while cum_length[i] < num_to_mask:
- i += 1
- lengths[i] = num_to_mask - (0 if i == 0 else cum_length[i - 1])
- num_to_mask = i + 1
- lengths = lengths[:num_to_mask]
-
- # Handle 0-length mask (inserts) separately
- lengths = lengths[lengths > 0]
- num_inserts = num_to_mask - lengths.size(0)
- num_to_mask -= num_inserts
- if num_to_mask == 0:
- return self.add_insertion_noise(source, num_inserts / source.size(0))
-
- assert (lengths > 0).all()
- else:
- lengths = torch.ones((num_to_mask,)).long()
- assert is_word_start[-1] == 0
- word_starts = is_word_start.nonzero(as_tuple=False)
- indices = word_starts[
- torch.randperm(word_starts.size(0))[:num_to_mask]
- ].squeeze(1)
- mask_random = torch.FloatTensor(num_to_mask).uniform_() < self.random_ratio
-
- source_length = source.size(0)
- assert source_length - 1 not in indices
- to_keep = torch.ones(source_length, dtype=torch.bool)
- is_word_start[
- -1
- ] = 255 # acts as a long length, so spans don't go over the end of doc
- if self.replace_length == 0:
- to_keep[indices] = 0
- else:
- # keep index, but replace it with [MASK]
- source[indices] = self.mask_idx
- source[indices[mask_random]] = self.voc_valid_ids[
- torch.randint(0, self.voc_valid_size - 1, size=(mask_random.sum(),))
- ]
-
- if self.mask_span_distribution is not None:
- assert len(lengths.size()) == 1
- assert lengths.size() == indices.size()
- lengths -= 1
- while indices.size(0) > 0:
- assert lengths.size() == indices.size()
- lengths -= is_word_start[indices + 1].long()
- uncompleted = lengths >= 0
- indices = indices[uncompleted] + 1
- mask_random = mask_random[uncompleted]
- lengths = lengths[uncompleted]
- if self.replace_length != -1:
- # delete token
- to_keep[indices] = 0
- else:
- # keep index, but replace it with [MASK]
- source[indices] = self.mask_idx
- source[indices[mask_random]] = self.voc_valid_ids[
- torch.randint(
- 0, self.voc_valid_size - 1, size=(mask_random.sum(),)
- )
- ]
- else:
- # A bit faster when all lengths are 1
- while indices.size(0) > 0:
- uncompleted = is_word_start[indices + 1] == 0
- indices = indices[uncompleted] + 1
- mask_random = mask_random[uncompleted]
- if self.replace_length != -1:
- # delete token
- to_keep[indices] = 0
- else:
- # keep index, but replace it with [MASK]
- source[indices] = self.mask_idx
- source[indices[mask_random]] = self.voc_valid_ids[
- torch.randint(
- 0, self.voc_valid_size - 1, size=(mask_random.sum(),)
- )
- ]
-
- assert source_length - 1 not in indices
-
- source = source[to_keep]
-
- if num_inserts > 0:
- source = self.add_insertion_noise(source, num_inserts / source.size(0))
-
- return source
-
- def add_insertion_noise(self, tokens, p):
- if p == 0.0:
- return tokens
-
- num_tokens = len(tokens)
- n = int(math.ceil(num_tokens * p))
-
- noise_indices = torch.randperm(num_tokens + n - 2)[:n] + 1
- noise_mask = torch.zeros(size=(num_tokens + n,), dtype=torch.bool)
- noise_mask[noise_indices] = 1
- result = torch.LongTensor(n + len(tokens)).fill_(-1)
-
- num_random = int(math.ceil(n * self.random_ratio))
- result[noise_indices[num_random:]] = self.mask_idx
- result[noise_indices[:num_random]] = self.voc_valid_ids[
- torch.randint(0, self.voc_valid_size - 1, size=(num_random,))
- ]
-
- result[~noise_mask] = tokens
-
- assert (result >= 0).all()
- return result
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/docs/ende-mustc.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/docs/ende-mustc.md
deleted file mode 100644
index 1acf6e001be3b4ddfe40b3d4dc25bb4754a97ef3..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/docs/ende-mustc.md
+++ /dev/null
@@ -1,118 +0,0 @@
-[[Back]](..)
-
-# Joint Speech Text Training for the MuST-C English to German Speech Translation task
-
-Joint Training Baseline: it is based on paper ["A general multi-task learning framework to leverage text data for speech to text tasks"](https://arxiv.org/pdf/2010.11338.pdf)
-
-Enhanced Joint Training: the joint training is enhanced with pre-trained models, cross attentive regularization and online knowledge distillation based on paper ["Improving Speech Translation by Understanding and Learning from the Auxiliary Text Translation Task"](https://research.fb.com/publications/improving-speech-translation-by-understanding-and-learning-from-the-auxiliary-text-translation-task)
-
-## Prepare Data
-#### Download files
-- Sentence piece model [spm.model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/must_c/en_de/spm.model)
-- Dictionary [dict.txt](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/must_c/en_de/dict.txt)
-- config [config.yaml](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/must_c/en_de/config.yaml)
-#### Prepare MuST-C data set
-- Please follow the data preparation in the [S2T example](https://github.com/pytorch/fairseq/blob/main/examples/speech_to_text/docs/mustc_example.md)
-- Convert source text under the "src_text" column in the tsv file into phoneme representation.
-```bash
- python examples/speech_text_joint_to_text/scripts/g2p_encode.py \
- --lower-case --do-filter --use-word-start --no-punc \
- --reserve-word examples/speech_text_joint_to_text/configs/mustc_noise.list \
- --data-path ${must_c_en_de_src_text} \
- --out-path ${must_c_en_de_src_text_pho}
-```
-- Replace the source text under the "src_text" column in the tsv file with the corresponding phoneme reprentation generated in the step above.
-Below is the snapshot for the MuST-C en-de dev tsv
-```
-id audio n_frames tgt_text src_text speaker
-ted_767_0 en-de/flac.zip:10071514743:48445 56160 Heute spreche ich zu Ihnen über Energie und Klima. ▁AY1 M ▁G OW1 IH0 NG ▁T UW1 ▁T AO1 K ▁T AH0 D EY1 ▁AH0 B AW1 T ▁EH1 N ER0 JH IY0 ▁AH0 N D ▁K L AY1 M AH0 T spk.767_
-ted_767_1 en-de/flac.zip:1214217978:205678 226080 Und das überrascht vielleicht etwas, weil sich meine Vollzeitbeschäftigung bei der Stiftung hauptsächlich um Impfstoffe und Saatgut dreht, um die Dinge, die wir erfinden und liefern müssen um den ärmsten 2 Milliarden ein besseres Leben zu ermöglichen. ▁AH0 N D ▁DH AE1 T ▁M AY1 T ▁S IY1 M ▁AH0 ▁B IH1 T ▁S ER0 P R AY1 Z IH0 NG ▁B IH0 K AO1 Z ▁M AY1 ▁F UH1 L ▁T AY1 M ▁W ER1 K ▁AE1 T ▁DH AH0 ▁F AW0 N D EY1 SH AH0 N ▁IH1 Z ▁M OW1 S T L IY0 ▁AH0 B AW1 T ▁V AE2 K S IY1 N Z ▁AH0 N D ▁S IY1 D Z ▁AH0 B AW1 T ▁DH AH0 ▁TH IH1 NG Z ▁DH AE1 T ▁W IY1 ▁N IY1 D ▁T UW1 ▁IH0 N V EH1 N T ▁AH0 N D ▁D IH0 L IH1 V ER0 ▁T UW1 ▁HH EH1 L P ▁DH AH0 ▁P UH1 R IH0 S T ▁T UW1 ▁B IH1 L Y AH0 N ▁L AY1 V ▁B EH1 T ER0 ▁L IH1 V Z spk.767_
-```
-- Prepare phoneme dictionary and save to $MANIFEST_ROOT as [src_dict.txt](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/must_c/en_de/src_dict.txt)
-#### Prepare WMT text data
-- [Download wmt data](https://github.com/pytorch/fairseq/blob/main/examples/translation/prepare-wmt14en2de.sh)
-- Convert source text (English) into phoneme representation as above
-- Generate binary parallel files with "fairseq-preprocess" from fairseq for training and validation. The source input is English phoneme representation and the target input is German sentencepiece token . The output is saved under $parallel_text_data
-
-## Training
-The model is trained with 8 v100 GPUs.
-
-#### Download pretrained models
-- [pretrain_encoder](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_joint_asr_transformer_m.pt)
-- [pretrain_nmt](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/must_c/en_de/checkpoint_mt.pt)
-
-#### Training scripts
-- Jointly trained model from scratch
-```bash
-python train.py ${MANIFEST_ROOT} \
- --save-dir ${save_dir} \
- --num-workers 8 \
- --task speech_text_joint_to_text \
- --arch dualinputs2ttransformer_s \
- --user-dir examples/speech_text_joint_to_text \
- --max-epoch 100 --update-mix-data \
- --optimizer adam --lr-scheduler inverse_sqrt \
- --lr 0.001 --update-freq 4 --clip-norm 10.0 \
- --criterion guided_label_smoothed_cross_entropy_with_accuracy \
- --label-smoothing 0.1 --max-tokens 10000 --max-tokens-text 10000 \
- --max-positions-text 400 --seed 2 --speech-encoder-layers 12 \
- --text-encoder-layers 6 --encoder-shared-layers 6 --decoder-layers 6 \
- --dropout 0.1 --warmup-updates 20000 \
- --text-sample-ratio 0.25 --parallel-text-data ${parallel_text_data} \
- --text-input-cost-ratio 0.5 --enc-grad-mult 2.0 --add-speech-eos \
- --log-format json --langpairs en-de --noise-token '"'"'▁NOISE'"'"' \
- --mask-text-ratio 0.0 --max-tokens-valid 20000 --ddp-backend no_c10d \
- --log-interval 100 --data-buffer-size 50 --config-yaml config.yaml \
- --keep-last-epochs 10
-```
-- Jointly trained model with good initialization, cross attentive loss and online knowledge distillation
-```bash
-python train.py ${MANIFEST_ROOT} \
- --save-dir ${save_dir} \
- --num-workers 8 \
- --task speech_text_joint_to_text \
- --arch dualinputs2ttransformer_m \
- --user-dir examples/speech_text_joint_to_text \
- --max-epoch 100 --update-mix-data \
- --optimizer adam --lr-scheduler inverse_sqrt \
- --lr 0.002 --update-freq 4 --clip-norm 10.0 \
- --criterion guided_label_smoothed_cross_entropy_with_accuracy \
- --guide-alpha 0.8 --disable-text-guide-update-num 5000 \
- --label-smoothing 0.1 --max-tokens 10000 --max-tokens-text 10000 \
- --max-positions-text 400 --seed 2 --speech-encoder-layers 12 \
- --text-encoder-layers 6 --encoder-shared-layers 6 --decoder-layers 6 \
- --dropout 0.1 --warmup-updates 20000 --attentive-cost-regularization 0.02 \
- --text-sample-ratio 0.25 --parallel-text-data ${parallel_text_data} \
- --text-input-cost-ratio 0.5 --enc-grad-mult 2.0 --add-speech-eos \
- --log-format json --langpairs en-de --noise-token '"'"'▁NOISE'"'"' \
- --mask-text-ratio 0.0 --max-tokens-valid 20000 --ddp-backend no_c10d \
- --log-interval 100 --data-buffer-size 50 --config-yaml config.yaml \
- --load-pretrain-speech-encoder ${pretrain_encoder} \
- --load-pretrain-decoder ${pretrain_nmt} \
- --load-pretrain-text-encoder-last ${pretrain_nmt} \
- --keep-last-epochs 10
-```
-
-## Evaluation
-```bash
-python ./fairseq_cli/generate.py \
- ${MANIFEST_ROOT} \
- --task speech_text_joint_to_text \
- --max-tokens 25000 \
- --nbest 1 \
- --results-path ${infer_results} \
- --batch-size 512 \
- --path ${model} \
- --gen-subset tst-COMMON_st \
- --config-yaml config.yaml \
- --scoring sacrebleu \
- --beam 5 --lenpen 1.0 \
- --user-dir examples/speech_text_joint_to_text \
- --load-speech-only
-```
-
-## Results (Joint training with initialization + CAR + online KD)
-|Direction|En-De | En-Es | En-Fr |
-|---|---|---|---|
-|BLEU|27.4| 31.2 | 37.6 |
-|checkpoint | [link](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/must_c/en_de/checkpoint_ave_10.pt) |[link](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/must_c/en_es/checkpoint_ave_10.pt)|[link](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/must_c/en_fr/checkpoint_ave_10.pt)|
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/docs/iwslt2021.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/docs/iwslt2021.md
deleted file mode 100644
index 0af0fbff1bd4d113f910912ce2dad516ff6eea79..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/docs/iwslt2021.md
+++ /dev/null
@@ -1,76 +0,0 @@
-[[Back]](..)
-
-# Joint Speech Text Training for the 2021 IWSLT multilingual speech translation
-
-This directory contains the code from paper ["FST: the FAIR Speech Translation System for the IWSLT21 Multilingual Shared Task"](https://arxiv.org/pdf/2107.06959.pdf).
-
-## Prepare Data
-#### Download files
-- Sentence piece model [spm.model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/iwslt/iwslt_data/spm.model)
-- Dictionary [tgt_dict.txt](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/iwslt/iwslt_data/dict.txt)
-- Config [config.yaml](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/iwslt/iwslt_data/config.yaml)
-
-#### Prepare
-- Please follow the data preparation in [speech-to-text](https://github.com/pytorch/fairseq/blob/main/examples/speech_to_text/docs/mtedx_example.md) with option "--use-audio-input" for raw audio tsv files.
-- Prepare tsv files with phoneme based source text (under column 'src_text') as [MuST-C](ende-mustc.md) example.
-
-
-## Training
-
-#### Download pretrained models
-- [Pretrained mbart model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/iwslt/iwslt_data/mbart.pt)
-- [Pretrained w2v model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/iwslt/iwslt_data/xlsr_53_56k.pt)
-
-
-#### Training scripts
-
-```bash
-python train.py ${MANIFEST_ROOT} \
- --save-dir ${save_dir} \
- --user-dir examples/speech_text_joint_to_text \
- --train-subset train_es_en_tedx,train_es_es_tedx,train_fr_en_tedx,train_fr_es_tedx,train_fr_fr_tedx,train_it_it_tedx,train_pt_en_tedx,train_pt_pt_tedx \
- --valid-subset valid_es_en_tedx,valid_es_es_tedx,valid_es_fr_tedx,valid_es_it_tedx,valid_es_pt_tedx,valid_fr_en_tedx,valid_fr_es_tedx,valid_fr_fr_tedx,valid_fr_pt_tedx,valid_it_en_tedx,valid_it_es_tedx,valid_it_it_tedx,valid_pt_en_tedx,valid_pt_es_tedx,valid_pt_pt_tedx \
- --config-yaml config.yaml --ddp-backend no_c10d \
- --num-workers 2 --task speech_text_joint_to_text \
- --criterion guided_label_smoothed_cross_entropy_with_accuracy \
- --label-smoothing 0.3 --guide-alpha 0.8 \
- --disable-text-guide-update-num 5000 --arch dualinputxmtransformer_base \
- --max-tokens 500000 --max-sentences 3 --max-tokens-valid 800000 \
- --max-source-positions 800000 --enc-grad-mult 2.0 \
- --attentive-cost-regularization 0.02 --optimizer adam \
- --clip-norm 1.0 --log-format simple --log-interval 200 \
- --keep-last-epochs 5 --seed 1 \
- --w2v-path ${w2v_path} \
- --load-pretrained-mbart-from ${mbart_path} \
- --max-update 1000000 --update-freq 4 \
- --skip-invalid-size-inputs-valid-test \
- --skip-encoder-projection --save-interval 1 \
- --attention-dropout 0.3 --mbart-dropout 0.3 \
- --finetune-w2v-params all --finetune-mbart-decoder-params all \
- --finetune-mbart-encoder-params all --stack-w2v-mbart-encoder \
- --drop-w2v-layers 12 --normalize \
- --lr 5e-05 --lr-scheduler inverse_sqrt --warmup-updates 5000
-```
-
-## Evaluation
-```bash
-python ./fairseq_cli/generate.py
- ${MANIFEST_ROOT} \
- --task speech_text_joint_to_text \
- --user-dir ./examples/speech_text_joint_to_text \
- --load-speech-only --gen-subset test_es_en_tedx \
- --path ${model} \
- --max-source-positions 800000 \
- --skip-invalid-size-inputs-valid-test \
- --config-yaml config.yaml \
- --infer-target-lang en \
- --max-tokens 800000 \
- --beam 5 \
- --results-path ${RESULTS_DIR} \
- --scoring sacrebleu
-```
-The trained model can be downloaded [here](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/iwslt/iwslt_data/checkpoint17.pt)
-
-|direction|es_en|fr_en|pt_en|it_en|fr_es|pt_es|it_es|es_es|fr_fr|pt_pt|it_it|
-|---|---|---|---|---|---|---|---|---|---|---|---|
-|BLEU|31.62|36.93|35.07|27.12|38.87|35.57|34.13|74.59|74.64|70.84|69.76|
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/docs/pre-training.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/docs/pre-training.md
deleted file mode 100644
index 6d9e2cb0bbc5afdd3f31e9e6867ec435f4ccf6cc..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/docs/pre-training.md
+++ /dev/null
@@ -1,192 +0,0 @@
-[[Back]](..)
-
-# Unified Speech-Text Pre-training for Speech Translation and Recognition
-
-This directory contains the pre-training recipes from paper ["Unified Speech-Text Pre-training for Speech Translation and Recognition"](https://arxiv.org/abs/2204.05409).
-
-## Librispeech ASR Pre-training
-### Prepare Data
-#### Download files
-#### Prepare pre-training data
-- Text to text task (T2T): prepare the binary data following the similar steps in [EN_DE Joint training](./ende-mustc.md). The source data is presented as phomeme token sequence and the target data is coded as subword tokens via SentencePiece. The text data is downloaded from [openslr](https://www.openslr.org/12)
-- Self-supervised speech learning task (SSL): The data is prepared as [wav2vec 2.0](https://github.com/pytorch/fairseq/tree/main/examples/wav2vec/README.md)
-- Speech to phoneme classification task (S2P): The tsv file contains 5 fields: "id", "audio", "n_frames", "tgt_text", and "align". The tgt_text field is corresponding to the phoneme based representation of the speech data. "align" field contains the alignment information. The phoneme level forced alignment for the labelled speech data (i.e. Librispeech) can be obtained via [kaldi](http://kaldi-asr.org) or [MFA](https://montrealcorpustools.github.io/Montreal-Forced-Aligner/). The segmentation information is normalized to 0$\sim$1 for the whole utterance. The snapshot of the tsv file is below:
-```
-id audio n_frames tgt_text align
-116-288045-0000 /librispeech/dev-other/116/288045/116-288045-0000.flac 170400 ▁AE1 Z AY1 ▁AH0 P R OW1 CH T ▁DH AH1 ▁S IH1 T IY0 AY1 ▁HH ER1 D ▁B EH1 L Z ▁R IH1 NG IH0 NG ▁AE1 N D AH0 ▁L IH1 T AH0 L ▁L EY1 T ER0 AY1 ▁F AW1 N D ▁DH AH0 ▁S T R IY1 T S ▁AH0 S T IH1 R ▁W IH0 TH ▁TH R AO1 NG Z ▁AH0 V ▁W EH1 L ▁D R EH1 S T ▁P IY1 P AH0 L ▁IH1 N ▁F AE1 M L IY0 ▁G R UW1 P S ▁W EH1 N D IH0 NG ▁DH EH1 R ▁W EY1 ▁HH IH1 DH ER0 ▁AH0 N D ▁TH IH1 DH ER0 0.047977 0.056444 0.064911 0.075259 0.081844 0.089370 0.095014 0.104421 0.109125 0.111947 0.115710 0.120414 0.134525 0.141110 0.143932 0.174036 0.176858 0.190028 0.199436 0.207902 0.218250 0.224835 0.231421 0.242709 0.251176 0.257761 0.263405 0.268109 0.270931 0.290687 0.342427 0.349953 0.353716 0.356538 0.360301 0.363123 0.365945 0.368768 0.371590 0.376294 0.384760 0.394167 0.401693 0.409219 0.419567 0.430856 0.441204 0.444026 0.446849 0.449671 0.456256 0.463782 0.471308 0.477893 0.486359 0.491063 0.494826 0.501411 0.512700 0.517404 0.520226 0.534337 0.540922 0.545626 0.550329 0.559737 0.568203 0.583255 0.592662 0.600188 0.603951 0.611477 0.619003 0.624647 0.634055 0.639699 0.646284 0.653810 0.659454 0.664158 0.670743 0.682032 0.687676 0.692380 0.708373 0.713076 0.719661 0.729069 0.740357 0.744120 0.748824 0.752587 0.761994 0.770461 0.781750 0.790216 0.805268 0.808090 0.823142 0.832549 0.836312 0.840075 0.843838 0.851364 0.854186 0.857008 0.862653 0.878645 0.898401 0.901223 0.906867 0.913452 0.920038 0.926623 0.934149 0.939793 0.942615 0.945437 0.952023 0.957667 0.977422 1.000000
-
-```
-- Speech to text task (S2T): The data preparation follow the steps in [EN_DE Joint training](./ende-mustc.md).
-
-#### Prepare fine-tuning data:
-We re-use the data from T2T and S2T tasks in the fine-tuning stage.
-
-### Model Build
-#### Pre-training
-```
-python train.py $T2T_DATA \
- --save-dir $SAVE_PRE_PATH --user-dir examples/speech_text_joint_to_text --task speech_text_joint_denoising \
- --criterion speech_text_pretrain_cross_entropy --optimizer adam --weight-decay 0.01 --config-yaml config_s2p.yaml --config-s2s-yaml config.yaml --ddp-backend no_c10d \
- --lang-pairs pho-wrd --num-workers 4 --log-interval 500 --save-interval-updates 5000 --keep-interval-updates 1 --no-emb-update-unsup --report-accuracy --lr 0.001 --end-learning-rate 1e-06 \
- --lr-scheduler polynomial_decay --warmup-updates 10000 --total-num-update 800000 --update-freq 6 --validate-interval-updates 10000 --train-subset train \
- --valid-subset valid,valid_sup_speech,valid_sup_speech_s2s,valid_unsup_speech --dataset-impl mmap \
- --sup-speech-data $S2P_DATA_PATH --sup-speech-train-subset train_960.ali --sup-speech-valid-subset dev-clean.ali --sup-speech-s2s-data $S2T_DATA_PATH \
- --sup-speech-s2s-train-subset train --sup-speech-s2s-valid-subset dev-clean --unsup-speech-train-data $SSL_DATA_PATH/train.tsv --unsup-speech-valid-data $SSL_DATA_PATH/valid.tsv \
- --batch-size 200 --batch-size-valid 150 --max-source-positions 1024 --max-target-positions 1024 --max-text-tokens 3072 --max-speech-positions 600000 \
- --max-sample-size 750000 --min-sample-size 64000 --max-speech-tokens 750000 --max-tokens-valid 750000 --skip-invalid-size-inputs-valid-test \
- --unsupervised-speech-sample-ratio 3.0 --supervised-speech-sample-ratio 5 --supervised-speech-s2s-sample-ratio 5 --text-sample-ratio 1.0 --mask 0.3 --mask-random 0.1 \
- --mask-length span-poisson --speech-sup-mask-prob 0.3 --speech-unsup-mask-prob 0.7 --use-mask-whole-words --arch speech_text_pretrain_bart_base_stack \
- --no-scale-feature --activation-fn gelu --speech-extractor-mode default --stacked-encoder all --encoder-normalize-before --decoder-normalize-before \
- --encoder-learned-pos --decoder-learned-pos --dropout 0.1 --load-pretrained-mbart-encoder-from $BART --load-pretrained-mbart-decoder-from $BART
-```
-The current implementation also supports model pre-training without the forced alignment supervised data. In this case, CTC is used to optimize the S2P task. We need to do following changes for the setting:
-1. options to be added
-```
---use-sup-speech-ctc --criterion speech_text_pretrain_compound
-```
-2. options to be deleted
-```
---same-data-update --criterion speech_text_pretrain_cross_entropy
-```
-However, we find the CTC based pre-training is still worse than the forced alignment based setting. It could be partially due to the inferior pre-training setting that we re-use the forced alignment based pre-training setting for the CTC based pre-training.
-
-#### Fine-tuning
-```
-python train.py $S2T_DATA_PATH \
- --save-dir $SAVE_FT_PATH --num-workers 8 --task speech_text_joint_to_text --arch dualinputs2twavtransformer_base_stack \
- --user-dir examples/speech_text_joint_to_text --max-update 100000 --optimizer adam --lr-scheduler inverse_sqrt --lr 0.0003 --update-freq 3 --clip-norm 10.0 \
- --criterion guided_label_smoothed_cross_entropy_with_accuracy --guide-alpha 0.8 --label-smoothing 0.1 --warmup-updates 20000 --attentive-cost-regularization 0.02 \
- --enc-grad-mult 2.0 --max-tokens 800000 --max-source-positions 800000 --max-tokens-text 10000 --max-positions-text 1024 --max-target-positions 1024 --no-scale-feature \
- --activation-fn gelu --load-pretrained-speech-text-encoder $SAVE_PRE_PATH/checkpoint_last.pt --load-pretrained-speech-text-decoder $SAVE_PRE_PATH/checkpoint_last.pt \
- --encoder-normalize-before --decoder-normalize-before --speech-extractor-mode default --speech-mask-channel-length 64 --speech-mask-channel-prob 0.5 \
- --speech-mask-length 10 --speech-mask-prob 0.65 --text-sample-ratio 0.25 --mask-text-ratio 0.3 --mask-text-type random --parallel-text-data text_bin \
- --text-input-cost-ratio 0.5 --langpairs pho-wrd --update-mix-data --log-format json --max-tokens-valid 800000 --ddp-backend no_c10d --log-interval 500 \
- --config-yaml config.yaml --skip-invalid-size-inputs-valid-test --keep-last-epochs 50 --layernorm-embedding --encoder-learned-pos --decoder-learned-pos
-```
-
-### Evaluation
-The last 10 epoch models from fine-tuning is conducted model average to get $FINAL_MODEL
-```
-python ./fairseq_cli/generate.py \
- $S2T_DATA_PATH \
- --task speech_text_joint_to_text \
- --max-tokens 800000 \
- --max-source-positions 800000 \
- --nbest 1 \
- --results-path $RESULTS_LOG \
- --batch-size 512 \
- --path $FINAL_MODEL \
- --gen-subset $SUBSET \
- --config-yaml config.yaml \
- --scoring wer \
- --beam 10 --lenpen 1.0 examples/speech_text_joint_to_text \
- --user-dir examples/speech_text_joint_to_text --load-speech-only \
- --model-overrides {'load_pretrained_speech_text_decoder':'','load_pretrained_speech_text_encoder':''}
-```
-
-### Results and models
-| | dev-clean | dev-other | test-clean | test-other |
-|---|---|---|---|---|
-| WER| 2.0 | 4.4 | 2.1 |4.6 |
-
-**Model Links**:
-- [config_s2p.yaml](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/librispeech/pretrain/config_s2p.yaml): Config for S2P
-- [spm.model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/librispeech/finetuned/spm.model): Sentence Piece model
-- [src_dict.txt](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/librispeech/finetuned/src_dict.txt): Source Phoneme Dictionary
-- [tgt_dict.txt](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/librispeech/finetuned/tgt_dict.txt): Target Sentence Piece Dictionary
-- [config.yaml](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/librispeech/finetuned/config.yaml): Config for S2T
-- [BART](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/librispeech/pretrain/bart.pt): trained from Librispeech text data
-- [Joint Pre-trained model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/librispeech/pretrain/checkpoint6.pt): model pre-trained with 960 hours Librispeech data (S2P, S2T) Librispeech text training data (T2T) and Librilight data (SSL)
-- [Fine-tuned model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/librispeech/finetuned/checkpoint_ave_10.pt): the pre-trained model is fined one 960 hours Librispeech speech and text data. (S2T + T2T)
-
-## MuST-C
-### Prepare Data
-Compared with the ASR Librispeech ASR recipe, the differences are below:
-- Replace the speech data with corresponding MuST-C data
-- Parallel text data from WMT is replaced the Librispeech text data
-
-### Model Build
-#### Pre-training
-EN-DE is used as an example
-```
-python train.py $TXT_DATA \
- --save-dir $SAVE_PRE_PATH --user-dir examples/speech_text_joint_to_text --task speech_text_joint_denoising --criterion speech_text_pretrain_cross_entropy --optimizer adam --weight-decay 0.01 \
- --config-yaml config_s2p.yaml --config-s2s-yaml config.yaml --ddp-backend no_c10d --lang-pairs-bitext en-fr --num-workers 4 --log-interval 500 --save-interval-updates 5000 --keep-interval-updates 1 \
- --no-emb-update-unsup --use-decoder-output-proj --report-accuracy --lr 0.001 --end-learning-rate 1e-06 --lr-scheduler polynomial_decay --warmup-updates 10000 --total-num-update 800000 \
- --update-freq 8 --validate-interval-updates 10000 --train-subset train --valid-subset valid_sup_speech,valid_sup_speech_s2s,valid_unsup_speech --dataset-impl mmap \
- --sup-speech-data $S2P_DATA_PATH --sup-speech-train-subset train --sup-speech-valid-subset dev --sup-speech-s2s-data $S2T_DATA_PATH --sup-speech-s2s-train-subset train \
- --sup-speech-s2s-valid-subset dev --unsup-speech-train-data $SSL_DATA_PATH/train.tsv --unsup-speech-valid-data $SSL_DATA_PATH/valid.tsv --batch-size 200 --batch-size-valid 100 \
- --max-source-positions 1024 --max-target-positions 1024 --max-text-tokens 2048 --max-speech-positions 600000 --max-sample-size 600000 --min-sample-size 64000 \
- --max-speech-tokens 600000 --max-tokens-valid 600000 --skip-invalid-size-inputs-valid-test --unsupervised-speech-sample-ratio 1.2 --supervised-speech-sample-ratio 10 \
- --supervised-speech-s2s-sample-ratio 10 --bitext-sample-ratio 0.5 --mask 0.3 --mask-random 0.1 --mask-length span-poisson --speech-sup-mask-prob 0.3 \
- --speech-unsup-mask-prob 0.7 --use-mask-whole-words --arch speech_text_pretrain_bart_base_stack --no-scale-feature --activation-fn gelu --speech-extractor-mode default \
- --stacked-encoder s2s --encoder-normalize-before --decoder-normalize-before --encoder-learned-pos --decoder-learned-pos --dropout 0.1 \
- --load-pretrained-mbart-encoder-from $EN_FR_NMT --load-pretrained-mbart-decoder-from $EN_FR_NMT
-```
-#### Fine-tuning
-```
-python train.py $S2T_DATA_PATH \
- --save-dir $SAVE_FT_PATH --num-workers 8 --task speech_text_joint_to_text --arch dualinputs2twavtransformer_base_stack --user-dir examples/speech_text_joint_to_text \
- --max-epoch 25 --update-mix-data --optimizer adam --lr-scheduler inverse_sqrt --lr 0.0003 --update-freq 4 --clip-norm 10.0 --warmup-updates 20000 \
- --criterion guided_label_smoothed_cross_entropy_with_accuracy --guide-alpha 0.8 --attentive-cost-regularization 0.02 --enc-grad-mult 2.0 --label-smoothing 0.1 \
- --max-tokens 800000 --max-source-positions 800000 --max-tokens-text 10000 --max-positions-text 1024 --load-pretrained-speech-text-encoder $SAVE_PRE_PATH/checkpoint_last.pt \
- --load-pretrained-speech-text-decoder $SAVE_PRE_PATH/checkpoint_last.pt --speech-mask-channel-length 64 --speech-mask-channel-prob 0.5 --speech-mask-length 10 \
- --speech-mask-prob 0.65 --text-sample-ratio 0.05 --mask-text-ratio 0.3 --mask-text-type random --parallel-text-data data-bin-wt --text-input-cost-ratio 0.5 \
- --langpairs en-fr --log-format json --max-tokens-valid 800000 --ddp-backend no_c10d --log-interval 100 --config-yaml config.yaml --skip-invalid-size-inputs-valid-test \
- --noise-token '▁NOISE' --keep-last-epochs 40 --layernorm-embedding --encoder-learned-pos --decoder-learned-pos --activation-fn gelu \
- --speech-extractor-mode default --max-target-positions 1024 --encoder-normalize-before --decoder-normalize-before
-```
-
-### Evaluation
-The last 10 epoch models from fine-tuning is conducted model average to get $FINAL_MODEL
-```
-python fairseq_cli/generate.py \
- $S2T_DATA_PATH \
- --task speech_text_joint_to_text \
- --nbest 1 \
- --max-tokens 800000 \
- --max-source-positions 800000 \
- --results-path $RESULTS_LOG \
- --batch-size 512 \
- --path $FINAL_MODEL \
- --gen-subset $SUBSET \
- --config-yaml config.yaml \
- --scoring sacrebleu \
- --beam 10 --lenpen 1.0 examples/speech_text_joint_to_text \
- --user-dir examples/speech_text_joint_to_text --load-speech-only \
- --model-overrides {'load_pretrained_speech_text_decoder':'','load_pretrained_speech_text_encoder':''}
-```
-
-
-### Results and models
-| | en-fr | en-es | en-de |
-|---|---|---|---|
-| BLEU| 39.7 | 33.2 |29.2 |
-
-
-**Model Links**:
-1. DE
- - [de config.yaml](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/de/config.yaml)
- - [de src_dict.txt](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/de/src_dict.txt)
- - [de tgt_dict.txt](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/de/tgt_dict.txt)
- - [de spm.model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/de/spm.model)
- - [de pre-trained nmt model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/de/nmt.pt)
- - [de pre-trained model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/de/checkpoint_pretraing.pt)
- - [de fine-tuned model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/de/checkpoint_finetune_ave10.pt)
-2. ES
- - [es config.yaml](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/es/config.yaml)
- - [es src_dict.txt](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/es/src_dict.txt)
- - [es tgt_dict.txt](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/es/tgt_dict.txt)
- - [es spm.model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/es/spm.model)
- - [es pre-trained nmt model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/es/nmt.pt)
- - [es pre-trained model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/es/checkpoint_pretraing.pt)
- - [es fine-tuned model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/es/checkpoint_finetune_ave10.pt)
-3. FR
- - [fr config.yaml](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/fr/config.yaml)
- - [fr src_dict.txt](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/fr/src_dict.txt)
- - [fr tgt_dict.txt](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/fr/tgt_dict.txt)
- - [fr spm.model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/fr/spm.model)
- - [fr pre-trained nmt model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/fr/nmt.pt)
- - [fr pre-trained model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/fr/checkpoint_pretraing.pt)
- - [fr fine-tuned model](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/fr/checkpoint_finetune_ave10.pt)
-4. [config_s2p.yaml](https://dl.fbaipublicfiles.com/joint_speech_text_4_s2t/acl2022/must_c/config_s2p.yaml)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/models/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/models/__init__.py
deleted file mode 100644
index 5fc5d9e21b2b5d272bd67610958efbdb1eecb158..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/models/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import importlib
-import os
-
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/models/joint_speech_text_pretrain_transformer.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/models/joint_speech_text_pretrain_transformer.py
deleted file mode 100644
index 6f917398a5e42402a4ad2b56c02ba98fee7f29e5..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/models/joint_speech_text_pretrain_transformer.py
+++ /dev/null
@@ -1,698 +0,0 @@
-#!/usr/bin/env python3
-
-import logging
-from collections import OrderedDict, namedtuple
-from typing import Dict, Optional
-
-import torch
-import torch.nn as nn
-import torch.nn.functional as F
-from torch import Tensor
-
-from fairseq import checkpoint_utils, utils
-from fairseq.file_io import PathManager
-from fairseq.models import (
- FairseqDecoder,
- FairseqEncoderDecoderModel,
- register_model,
- register_model_architecture,
-)
-from fairseq.models.speech_to_text import (
- MultiInputDecoder,
- MultiModalityEncoder,
- SpeechWavTransformerEncoder,
- StackedSpeechWavTransformerEncoder,
-)
-from fairseq.models.transformer import (
- TransformerDecoder,
- TransformerEncoder,
- TransformerModel,
-)
-
-logger = logging.getLogger(__name__)
-
-
-class SpeechTextPreTrainEncoder(MultiModalityEncoder):
- def __init__(
- self,
- dictionary,
- sup_speech_encoder,
- sup_s2s_speech_encoder,
- unsup_speech_encoder,
- text_encoder,
- ):
- super().__init__(dictionary)
- self.sup_speech_encoder = sup_speech_encoder
- self.sup_s2s_speech_encoder = sup_s2s_speech_encoder
- self.unsup_speech_encoder = unsup_speech_encoder
- self.text_encoder = text_encoder
-
- @classmethod
- def update_transformer_encoder_cfg(cls, args, update_dict):
- cfg = dict(args._get_kwargs())
- for fkey in update_dict.keys():
- cfg[fkey] = update_dict[fkey]
- cfg.pop("_name", None) # remove keys start with _
- model_args = namedtuple("args", cfg.keys())(*cfg.values())
- return model_args
-
- @classmethod
- def build_text_encoder(cls, args, src_dictionary):
- enc_emb = nn.Embedding(
- len(src_dictionary), args.encoder_embed_dim, src_dictionary.pad()
- )
- model_args = cls.update_transformer_encoder_cfg(
- args, {"encoder_layers": args.text_encoder_layers}
- )
- text_encoder = TransformerEncoder(model_args, src_dictionary, enc_emb)
- return text_encoder
-
- @classmethod
- def build_speech_encoder(cls, args):
- model_args = cls.update_transformer_encoder_cfg(
- args,
- {
- "encoder_layers": args.speech_encoder_layers,
- "speech_mask_prob": args.speech_sup_mask_prob,
- },
- )
- speech_encoder = SpeechWavTransformerEncoder(model_args)
- return speech_encoder
-
- @classmethod
- def share_layers(cls, src_layers, tgt_layers): # share layer but not dropout
- # share parameters in src_layers with tgt_layers
- assert len(src_layers) == len(tgt_layers)
- for i, ly in enumerate(src_layers):
- tly = tgt_layers[i]
- tly.self_attn = ly.self_attn
- tly.self_attn_layer_norm = ly.self_attn_layer_norm
- tly.activation_fn = ly.activation_fn
- tly.normalize_before = ly.normalize_before
- tly.fc1 = ly.fc1
- tly.fc2 = ly.fc2
- tly.final_layer_norm = ly.final_layer_norm
- if hasattr(tly, "encoder_attn"):
- tly.encoder_attn = ly.encoder_attn
- tly.encoder_attn_layer_norm = ly.encoder_attn_layer_norm
- return tgt_layers
-
- @classmethod
- def build_unsup_speech_encoder(cls, args, sup_speech_encoder):
- model_args = cls.update_transformer_encoder_cfg(
- args,
- {
- "encoder_layers": args.speech_encoder_layers,
- "speech_mask_prob": args.speech_unsup_mask_prob,
- "encoder_layerdrop": 0.0,
- "decoder_layerdrop": 0.0,
- "dropout": args.speech_unsup_dropout,
- "activation_dropout": args.speech_unsup_dropout,
- "attention_dropout": 0.0,
- "dropout_features": args.speech_unsup_feature_dropout,
- "dropout_input": args.speech_unsup_feature_dropout,
- },
- )
-
- unsup_speech_encoder = SpeechWavTransformerEncoder(model_args, alway_mask=True)
- unsup_speech_encoder.layer_norm = sup_speech_encoder.layer_norm
- unsup_speech_encoder.layers = cls.share_layers(
- sup_speech_encoder.layers, unsup_speech_encoder.layers
- )
- unsup_speech_encoder.mask_emb = sup_speech_encoder.mask_emb
- unsup_speech_encoder.embed_positions = sup_speech_encoder.embed_positions
- unsup_speech_encoder.feat_layer_norm = sup_speech_encoder.feat_layer_norm
- unsup_speech_encoder.feat_proj = sup_speech_encoder.feat_proj
- unsup_speech_encoder.subsample = sup_speech_encoder.subsample
- return unsup_speech_encoder
-
- @classmethod
- def build_encoder(cls, args, dictionary):
- text_encoder = cls.build_text_encoder(args, dictionary)
- if getattr(args, "load_pretrained_mbart_encoder_from", None):
- text_encoder = checkpoint_utils.load_pretrained_component_from_model(
- component=text_encoder,
- checkpoint=args.load_pretrained_mbart_encoder_from,
- )
- speech_encoder = cls.build_speech_encoder(args)
- if getattr(args, "load_pretrained_feature_extractor_from", None):
-
- def load_feature_extractor(component, checkpoint):
- if not PathManager.exists(checkpoint):
- raise IOError("Model file not found: {}".format(checkpoint))
- state = checkpoint_utils.load_checkpoint_to_cpu(checkpoint)
- component_state_dict = OrderedDict()
-
- component_prefix = "feature_extractor"
- for key in state["model"].keys():
- if key.startswith(component_prefix):
- component_subkey = key[len(component_prefix) + 1 :]
- component_state_dict[component_subkey] = state["model"][key]
- component.load_state_dict(component_state_dict, strict=True)
- return component
-
- speech_encoder.subsample = load_feature_extractor(
- speech_encoder.subsample, args.load_pretrained_feature_extractor_from
- )
- speech_s2s_encoder = speech_encoder
- unsup_speech_encoder = cls.build_unsup_speech_encoder(args, speech_encoder)
- if getattr(args, "stacked_encoder", "none") != "none":
- if args.encoder_shared_text_layers_from_begin > 0:
- raise ValueError(
- "We can not stack encoders and share encoders at the same time!"
- )
- speech_s2s_encoder = StackedSpeechWavTransformerEncoder(
- speech_encoder, text_encoder.layers, text_encoder.layer_norm
- )
- if args.stacked_encoder == "all":
- speech_encoder = speech_s2s_encoder
- unsup_speech_encoder = StackedSpeechWavTransformerEncoder(
- unsup_speech_encoder, text_encoder.layers, text_encoder.layer_norm
- )
- else:
- cls.share_speech_text_encoder(
- speech_encoder, text_encoder, args.encoder_shared_text_layers_from_begin
- )
- return SpeechTextPreTrainEncoder(
- dictionary,
- speech_encoder,
- speech_s2s_encoder,
- unsup_speech_encoder,
- text_encoder,
- )
-
- @classmethod
- def share_speech_text_encoder(
- cls, speech_encoder, text_encoder, shared_layers_from_begin
- ):
- if shared_layers_from_begin > 0:
- num_text_encoder_layers = len(text_encoder.layers)
- assert len(speech_encoder.layers) >= shared_layers_from_begin
- assert num_text_encoder_layers >= shared_layers_from_begin
- assert len(speech_encoder.layers) >= num_text_encoder_layers
- for i, ly in enumerate(
- speech_encoder.layers[
- -num_text_encoder_layers : -num_text_encoder_layers
- + shared_layers_from_begin
- ]
- ):
- assert isinstance(text_encoder.layers[i], type(ly))
- text_encoder.layers[i] = ly
-
- def select_encoder(self, mode, **kwargs):
- if mode in ("speech", "sup_speech_ctc", "sup_speech_ali", "sup_speech_s2s"):
- kwargs["features_only"] = True
- if mode == "sup_speech_s2s":
- return self.sup_s2s_speech_encoder, kwargs
- return self.sup_speech_encoder, kwargs
- elif mode == "unsup_speech":
- kwargs["features_only"] = False
- return self.unsup_speech_encoder, kwargs
- elif mode in ("text", "bitext"):
- return self.text_encoder, kwargs
- else:
- raise NotImplementedError(f"{mode} is not supported")
- return None, kwargs
-
- def forward(self, src_tokens, src_lengths=None, mode="", alignment=None, **kwargs):
- return super().forward(src_tokens, src_lengths, mode, **kwargs)
-
-
-# SpeechDummyDecoder works as an extension of encoder, so we could fit encoder only training into seq2seq training
-class SpeechDummyDecoder(FairseqDecoder):
- def __init__(
- self,
- dictionary,
- output_embedding,
- no_emb_update_unsup=False,
- use_output_proj=False,
- ):
- super().__init__(dictionary)
- self.output_embedding = output_embedding
- num_embedding, num_dim = self.output_embedding.weight.size()
- self.out_proj = (
- None if use_output_proj is False else nn.Linear(num_dim, num_dim)
- )
- self.no_emb_update_unsup = no_emb_update_unsup
-
- def extend_alignment(self, alignment, src_lengths, prev_output_tokens):
- # alignment: B X N
- # src_lengths: B X T
- # prev_output_tokens: B X (N + 1)
- tgt_tokens = prev_output_tokens[
- :, 1:
- ] # remove the leading start of sentence token
- ext_alignment = (
- torch.ones(len(src_lengths), src_lengths.max(), device=src_lengths.device)
- .long()
- .fill_(self.dictionary.pad())
- )
- for bs in range(src_lengths.size(0)):
- tgt_length = tgt_tokens[bs].ne(self.dictionary.pad()).sum().item()
- assert tgt_length == sum(alignment[bs].ne(1)) + 1
- src_st = 0
- for i in range(tgt_length):
- tok = tgt_tokens[bs][i]
- src_ed = (alignment[bs][i] * src_lengths[bs]).int().item()
- ext_alignment[bs][src_st:src_ed].fill_(tok)
- src_st = src_ed
- return ext_alignment
-
- def forward(
- self,
- prev_output_tokens,
- encoder_out,
- incremental_state=None,
- mode="speech",
- alignment=None,
- **kwargs,
- ):
- """
- Args:
- prev_output_tokens (LongTensor): previous decoder outputs of shape
- `(batch, tgt_len)`, for teacher forcing
- encoder_out (optional): output from the encoder, used for
- encoder-side attention
- incremental_state (dict): dictionary used for storing state during
- :ref:`Incremental decoding`
- features_only (bool, optional): only return features without
- applying output layer (default: False).
- full_context_alignment (bool, optional): don't apply
- auto-regressive mask to self-attention (default: False).
-
- Returns:
- sup_speech_ctc:
- dictionary{"logits": logits, "padding_mask": padding_mask}
- sup_speech_ali and unsup_speech:
- tuple:
- - the decoder's output of shape `(batch, tgt_len, vocab)`
- - a dictionary with any model-specific outputs
- """
- emb_weight = self.output_embedding.weight
- if (
- mode == "unsup_speech" and self.no_emb_update_unsup
- ): # no gradient for embedding here
- emb_weight = emb_weight.detach()
- enc_out = (
- encoder_out["encoder_out"][0]
- if self.out_proj is None
- else self.out_proj(encoder_out["encoder_out"][0])
- )
- logits = F.linear(enc_out, emb_weight, None).transpose(0, 1) # B X T X C
- others = None
- if mode in (
- "speech",
- "sup_speech_ctc",
- ): # speech data with label, do forcealignment
- if len(encoder_out["encoder_padding_mask"]) > 0:
- padding_mask = encoder_out["encoder_padding_mask"][0]
- logits = logits.masked_fill(padding_mask, float("-inf"))
- else:
- seq_len, bsz = encoder_out["encoder_out"][0].size()[:2]
- padding_mask = torch.zeros(
- bsz, seq_len, device=encoder_out["encoder_out"][0].device
- ).bool()
- return {"x": logits, "padding_mask": padding_mask}
- elif mode == "sup_speech_ali":
- src_lengths = None
- if len(encoder_out["encoder_padding_mask"]) > 0:
- src_lengths = (1 - encoder_out["encoder_padding_mask"][0].long()).sum(
- -1
- )
- else:
- seq_len, bsz = encoder_out["encoder_out"][0].size()[:2]
- src_lengths = (
- torch.ones(bsz, device=encoder_out["encoder_out"][0].device).long()
- * seq_len
- )
- assert alignment is not None
- alignment = self.extend_alignment(
- alignment, src_lengths, prev_output_tokens
- )
- others = {"pseudo_target_tokens": alignment}
- elif mode == "unsup_speech":
- enc_out_ori = (
- encoder_out["encoder_unmasked_out"][0]
- if self.out_proj is None
- else self.out_proj(encoder_out["encoder_unmasked_out"][0])
- )
- logits_ori = F.linear(enc_out_ori, emb_weight, None).transpose(0, 1)
- if len(encoder_out["encoder_padding_mask"]) > 0:
- encoder_padding_mask = encoder_out["encoder_padding_mask"][0]
- logits_ori = logits_ori.masked_fill(encoder_padding_mask, float("-inf"))
- pseudo_labels = utils.log_softmax(logits_ori, dim=-1)
- others = {
- "pseudo_target_logprobs": pseudo_labels,
- "padding_mask": encoder_out["encoder_padding_mask"], # B X T
- "mask_indices": encoder_out[
- "mask_indices"
- ], # True for masked frames B X T
- }
- return logits, others
-
- def get_normalized_probs(
- self,
- net_output: Dict[str, Tensor],
- log_probs: bool,
- sample: Optional[Dict[str, Tensor]] = None,
- ):
- return self.get_normalized_probs_scriptable(
- (net_output["x"], None), log_probs, sample
- )
-
-
-class SpeechTextPreTrainDecoder(MultiInputDecoder):
- def __init__(self, dictionary, speech_decoder, text_decoder):
- super().__init__(dictionary)
- self.speech_decoder = speech_decoder
- self.text_decoder = text_decoder
-
- def select_decoder(self, mode, **kwargs):
- if mode == "unsup_speech":
- kwargs["mode"] = mode
- return self.speech_decoder, kwargs
- if mode in ("text", "bitext"):
- return self.text_decoder, kwargs
- if mode in ("speech", "sup_speech_ctc", "sup_speech_ali"):
- kwargs["mode"] = mode
- return self.speech_decoder, kwargs
- if mode in ("speech", "sup_speech_s2s"):
- if "alignment" in kwargs:
- del kwargs["alignment"]
- return self.text_decoder, kwargs
-
- raise NotImplementedError(f"{mode} is not supported")
- return None, kwargs
-
- def get_normalized_probs(
- self,
- net_output,
- log_probs,
- sample=None,
- ):
- """Get normalized probabilities (or log probs) from a net's output."""
- if isinstance(net_output, dict):
- return self.speech_decoder.get_normalized_probs(
- net_output, log_probs, sample
- )
- return self.text_decoder.get_normalized_probs(net_output, log_probs, sample)
-
- @classmethod
- def build_text_decoder(cls, args, tgt_dictionary, dec_emb_share=None):
- dec_emb = (
- nn.Embedding(
- len(tgt_dictionary), args.decoder_embed_dim, tgt_dictionary.pad()
- )
- if dec_emb_share is None
- else dec_emb_share
- )
- text_decoder = TransformerDecoder(args, tgt_dictionary, dec_emb)
- return text_decoder
-
- @classmethod
- def build_dummy_speech_decoder(cls, args, dictionary, dec_emb_share=None):
- dec_emb = (
- nn.Embedding(len(dictionary), args.decoder_embed_dim, dictionary.pad())
- if dec_emb_share is None
- else dec_emb_share
- )
- speech_decoder = SpeechDummyDecoder(
- dictionary,
- dec_emb,
- no_emb_update_unsup=getattr(args, "no_emb_update_unsup", False),
- use_output_proj=getattr(args, "use_decoder_output_proj", False),
- )
- return speech_decoder
-
- @classmethod
- def build_decoder(
- cls, args, text_dictionary, speech_dictionary, speech_output_embedding
- ):
- text_decoder = cls.build_text_decoder(args, text_dictionary)
- speech_decoder = cls.build_dummy_speech_decoder(
- args, speech_dictionary, speech_output_embedding
- )
- if getattr(args, "load_pretrained_mbart_decoder_from", None):
- text_decoder = checkpoint_utils.load_pretrained_component_from_model(
- component=text_decoder,
- checkpoint=args.load_pretrained_mbart_decoder_from,
- )
- return SpeechTextPreTrainDecoder(text_dictionary, speech_decoder, text_decoder)
-
-
-@register_model("speech_text_pretrain_bart")
-class SpeechTextPreTrainModel(FairseqEncoderDecoderModel):
- def __init__(self, encoder, decoder):
- super().__init__(encoder, decoder)
- self.num_updates = 0
-
- def forward(
- self, src_tokens, src_lengths, prev_output_tokens, src_lang_ids=None, **kwargs
- ):
- if src_lang_ids is not None:
- encoder_out = self.encoder(
- src_tokens, src_lengths=src_lengths, src_lang_ids=src_lang_ids, **kwargs
- )
- else:
- encoder_out = self.encoder(src_tokens, src_lengths=src_lengths, **kwargs)
- decoder_out = self.decoder(
- prev_output_tokens, encoder_out=encoder_out, **kwargs
- )
- return decoder_out
-
- def max_positions(self):
- return None # it is provided in task
-
- def get_targets(self, sample, net_output):
- mode = sample["net_input"]["mode"]
- if mode == "unsup_speech":
- return {"target_logprobs": net_output[1]["pseudo_target_logprobs"]}
- if mode == "sup_speech_ali":
- return net_output[1]["pseudo_target_tokens"]
- return sample["target"]
-
- def get_normalized_probs(
- self,
- net_output,
- log_probs,
- sample=None,
- ):
- # net_output['encoder_out'] is a (B, T, D) tensor
- lprobs = self.get_normalized_probs_scriptable(net_output, log_probs, sample)
- lprobs.batch_first = True
- return lprobs
-
- @staticmethod
- def add_args(parser):
- TransformerModel.add_args(parser)
- SpeechWavTransformerEncoder.add_args(parser)
- parser.add_argument(
- "--speech-sup-mask-prob",
- type=float,
- help="probability of replacing a token with mask (sup-speech)",
- )
- parser.add_argument(
- "--speech-unsup-mask-prob",
- type=float,
- help="probability of replacing a token with mask (unsup-speech)",
- )
- parser.add_argument(
- "--load-pretrained-mbart-encoder-from",
- type=str,
- metavar="STR",
- help="model to take text encoder weights from (for initialization)",
- )
-
- parser.add_argument(
- "--load-pretrained-mbart-decoder-from",
- type=str,
- metavar="STR",
- help="model to take text decoder weights from (for initialization)",
- )
-
- parser.add_argument(
- "--load-pretrained-feature-extractor-from",
- type=str,
- metavar="STR",
- help="model to take feature extractor weights from (for initialization)",
- )
-
- parser.add_argument(
- "--speech-unsup-dropout",
- type=float,
- default=0,
- help="dropout for unsupervised speech encoder",
- )
-
- parser.add_argument(
- "--speech-unsup-feature-dropout",
- type=float,
- default=0,
- help="dropout for unsupervised speech feature encoder",
- )
-
- parser.add_argument(
- "--encoder-shared-text-layers-from-begin",
- type=int,
- help="number of text encoder layers shared with speech encoder (from first layer)",
- )
-
- parser.add_argument(
- "--stacked-encoder",
- default="none",
- choices=["none", "s2s", "all"],
- help="stack speech and text encoders",
- )
-
- parser.add_argument("--use-decoder-output-proj", action="store_true")
-
- @classmethod
- def build_model(cls, args, task):
- encoder = SpeechTextPreTrainEncoder.build_encoder(args, task.src_dict)
- decoder = SpeechTextPreTrainDecoder.build_decoder(
- args, task.tgt_dict, task.src_dict, encoder.text_encoder.embed_tokens
- )
- model = SpeechTextPreTrainModel(encoder, decoder)
- return model
-
- def upgrade_state_dict(self, state_dict):
- """Upgrade old state dicts to work with newer code."""
- if "decoder.speech_decoder.output_projection.weight" in state_dict:
- del state_dict["decoder.speech_decoder.output_projection.weight"]
- self.upgrade_state_dict_named(state_dict, "")
-
-
-@register_model_architecture(
- "speech_text_pretrain_bart", "speech_text_pretrain_bart_base"
-)
-def speech_text_pretrain_bart_base(args):
- # speech masking
- args.dropout_input = getattr(args, "dropout_input", 0)
- args.dropout_features = getattr(args, "dropout_features", 0)
- args.speech_mask_length = getattr(args, "speech_mask_length", 10)
- args.speech_mask_prob = getattr(args, "speech_mask_prob", 0.65)
- args.speech_sup_mask_prob = getattr(args, "speech_sup_mask_prob", 0.3)
- args.speech_unsup_mask_prob = getattr(
- args, "speech_unsup_mask_prob", args.speech_mask_prob
- )
- args.speech_mask_selection = getattr(args, "speech_mask_selection", "static")
- args.speech_mask_other = getattr(args, "speech_mask_other", 0)
- args.speech_mask_min_space = getattr(args, "speech_mask_min_space", 1)
- args.speech_no_mask_overlap = getattr(args, "speech_no_mask_overlap", False)
-
- args.speech_mask_channel_length = getattr(args, "speech_mask_channel_length", 10)
- args.speech_mask_channel_prob = getattr(args, "speech_mask_channel_prob", 0.0)
- args.speech_mask_channel_selection = getattr(
- args, "speech_mask_channel_selection", "static"
- )
- args.speech_mask_channel_other = getattr(args, "speech_mask_channel_other", 0)
- args.speech_mask_channel_min_space = getattr(
- args, "speech_mask_channel_min_space", 1
- )
- args.speech_no_mask_channel_overlap = getattr(
- args, "speech_no_mask_channel_overlap", False
- )
- args.no_scale_feature = getattr(args, "", False)
- args.feature_grad_mult = getattr(args, "feature_grad_mult", 1.0) # 0.1
-
- # Transformer
- args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 768)
- args.encoder_ffn_embed_dim = getattr(
- args, "encoder_ffn_embed_dim", args.encoder_embed_dim * 4
- )
- args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 12)
- args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False)
- args.encoder_layerdrop = getattr(args, "encoder_layerdrop", 0)
- args.encoder_learned_pos = getattr(args, "encoder_learned_pos", False)
- args.speech_conv_bias = getattr(args, "speech_conv_bias", False)
-
- args.decoder_embed_dim = getattr(args, "decoder_embed_dim", args.encoder_embed_dim)
- args.decoder_ffn_embed_dim = getattr(
- args, "decoder_ffn_embed_dim", args.encoder_ffn_embed_dim
- )
- args.decoder_attention_heads = getattr(
- args, "decoder_attention_heads", args.encoder_attention_heads
- )
- args.decoder_normalize_before = getattr(args, "decoder_normalize_before", False)
- args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False)
- args.dropout = getattr(args, "dropout", 0.1)
- args.attention_dropout = getattr(args, "attention_dropout", args.dropout)
- args.activation_dropout = getattr(args, "activation_dropout", 0.0)
- args.activation_fn = getattr(args, "activation_fn", "relu") # gelu?
- args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None)
- args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0)
-
- args.speech_unsup_dropout = getattr(args, "speech_unsup_dropout", 0)
- args.speech_unsup_feature_dropout = getattr(args, "speech_unsup_feature_dropout", 0)
-
- args.tie_adaptive_weights = getattr(args, "tie_adaptive_weights", False)
- args.share_decoder_input_output_embed = getattr(
- args, "share_decoder_input_output_embed", False
- )
- args.no_token_positional_embeddings = getattr(
- args, "no_token_positional_embeddings", False
- )
- args.adaptive_input = getattr(args, "adaptive_input", False)
- args.decoder_layerdrop = getattr(args, "decoder_layerdrop", 0.0)
- args.decoder_output_dim = getattr(
- args, "decoder_output_dim", args.decoder_embed_dim
- )
- args.layernorm_embedding = getattr(args, "layernorm_embedding", False)
- args.no_scale_embedding = getattr(args, "no_scale_embedding", False)
- args.quant_noise_pq = getattr(args, "quant_noise_pq", 0)
-
- args.speech_encoder_layers = getattr(args, "speech_encoder_layers", 12)
- args.text_encoder_layers = getattr(args, "text_encoder_layers", 6)
- args.encoder_shared_text_layers_from_begin = getattr(
- args, "encoder_shared_text_layers_from_begin", 6
- )
- args.decoder_layers = getattr(args, "decoder_layers", 6)
-
- args.no_emb_update_unsup = getattr(args, "no_emb_update_unsup", False)
-
-
-@register_model_architecture(
- "speech_text_pretrain_bart", "speech_text_pretrain_bart_base_stack"
-)
-def speech_text_pretrain_bart_base_stack(args):
- args.speech_encoder_layers = getattr(args, "speech_encoder_layers", 6)
- args.text_encoder_layers = getattr(args, "text_encoder_layers", 6)
- args.encoder_shared_text_layers_from_begin = getattr(
- args, "encoder_shared_text_layers_from_begin", 0
- )
- args.stacked_encoder = getattr(args, "stacked_encoder", "all")
- args.layernorm_embedding = getattr(args, "layernorm_embedding", True)
- speech_text_pretrain_bart_base(args)
-
-
-@register_model_architecture(
- "speech_text_pretrain_bart", "speech_text_pretrain_bart_large"
-)
-def speech_text_pretrain_bart_large(args):
- args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024)
- args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16)
- args.speech_encoder_layers = getattr(args, "speech_encoder_layers", 24)
- args.text_encoder_layers = getattr(args, "text_encoder_layers", 12)
- args.encoder_shared_text_layers_from_begin = getattr(
- args, "encoder_shared_text_layers_from_begin", 12
- )
- args.decoder_layers = getattr(args, "decoder_layers", 12)
- args.dropout = getattr(args, "dropout", 0.3)
- speech_text_pretrain_bart_base(args)
-
-
-@register_model_architecture(
- "speech_text_pretrain_bart", "speech_text_pretrain_bart_large_stack"
-)
-def speech_text_pretrain_bart_large_stack(args):
- args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024)
- args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16)
- args.speech_encoder_layers = getattr(args, "speech_encoder_layers", 6)
- args.text_encoder_layers = getattr(args, "text_encoder_layers", 12)
- args.encoder_shared_text_layers_from_begin = getattr(
- args, "encoder_shared_text_layers_from_begin", 0
- )
- args.decoder_layers = getattr(args, "decoder_layers", 12)
- args.stacked_encoder = getattr(args, "stacked_encoder", "s2s")
- args.layernorm_embedding = getattr(args, "layernorm_embedding", True)
- speech_text_pretrain_bart_base(args)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/models/s2t_dualinputtransformer.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/models/s2t_dualinputtransformer.py
deleted file mode 100644
index c4ec41bda1a6f555a4a33a515eeba5c3178808bc..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/models/s2t_dualinputtransformer.py
+++ /dev/null
@@ -1,1093 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import logging
-from collections import namedtuple
-
-import torch
-import torch.nn as nn
-from fairseq import checkpoint_utils
-from fairseq import utils
-from fairseq.models import (
- FairseqEncoder,
- FairseqDecoder,
- FairseqEncoderDecoderModel,
- register_model,
- register_model_architecture,
-)
-from fairseq.models.fairseq_encoder import EncoderOut
-from fairseq.models.speech_to_text import (
- TransformerDecoder,
- S2TTransformerEncoder,
-)
-from fairseq.models.transformer import TransformerEncoder
-from fairseq.modules import (
- TransformerEncoderLayer,
- GradMultiply,
- LayerNorm,
-)
-
-logger = logging.getLogger(__name__)
-
-
-class SpeechEoSEncoder(FairseqEncoder):
- def __init__(self, encoder, eos_num, feat_dim, adapter_type="None", adapter_dim=0):
- super().__init__(None)
- self.encoder = encoder
- self.eos_num = eos_num # downsampling rate for speech input feature
- self.eos_emb = (
- nn.Parameter(torch.zeros(1, feat_dim), requires_grad=True)
- if eos_num > 0
- else None
- )
- self.adapter = self.add_adapter(adapter_type, adapter_dim)
-
- def add_adapter(self, adapter_type, adapter_dim):
- def _make_identity(linear, eps=1e-5):
- assert isinstance(linear, nn.Linear)
- linear.weight.data.mul_(eps)
- linear.weight.data.fill_diagonal_(1.0)
- if linear.bias is not None:
- linear.bias.data.mul_(eps)
-
- adapter = None
- if adapter_type == "Linear":
- assert adapter_dim > 0
- adapter = nn.Sequential(
- nn.Linear(adapter_dim, adapter_dim), LayerNorm(adapter_dim)
- )
- # initialize the adapter as identity matrix first
- _make_identity(adapter[0])
-
- elif adapter_type == "MLP":
- assert adapter_dim > 0
- # assume the model is pre-norm model
- adapter = nn.Sequential(
- nn.Linear(adapter_dim, 2 * adapter_dim),
- nn.ReLU(),
- nn.Linear(2 * adapter_dim, adapter_dim),
- LayerNorm(adapter_dim),
- )
- _make_identity(adapter[0])
- _make_identity(adapter[2])
- return adapter
-
- def add_eos(self, src_tokens, src_lengths):
- bsz, max_seq_len, fdim = src_tokens.size()
- if self.eos_num > 0:
- src_token_eos = torch.zeros(
- [bsz, max_seq_len + self.eos_num, fdim],
- dtype=src_tokens.dtype,
- device=src_tokens.device,
- )
- src_token_eos[:, :max_seq_len] = src_tokens
- for bi in range(bsz):
- src_token_eos[bi][
- src_lengths[bi] : src_lengths[bi] + self.eos_num
- ] = self.eos_emb.expand(self.eos_num, fdim)
- src_lengths = src_lengths + self.eos_num
- src_tokens = src_token_eos
- return src_tokens, src_lengths
-
- def apply_adapter(self, enc_out):
- if self.adapter is None:
- return enc_out
- rst = self.adapter(enc_out.encoder_out)
- if enc_out.encoder_padding_mask is not None:
- rst.masked_fill_(
- enc_out.encoder_padding_mask.transpose(0, 1).unsqueeze(-1), 0
- )
- return EncoderOut(
- encoder_out=rst,
- encoder_padding_mask=enc_out.encoder_padding_mask,
- encoder_embedding=enc_out.encoder_embedding,
- encoder_states=enc_out.encoder_states,
- src_tokens=enc_out.src_tokens,
- src_lengths=enc_out.src_lengths,
- )
-
- def forward(self, src_tokens, src_lengths=None, return_all_hiddens=False, **kwargs):
- """
- src_tokens: padded tensor (B, T, C * feat)
- src_lengths: tensor of original lengths of input utterances (B,)
- """
- src_tokens, src_lengths = self.add_eos(src_tokens, src_lengths)
- enc_out = self.encoder(src_tokens, src_lengths, return_all_hiddens)
- enc_out = self.apply_adapter(enc_out)
- return enc_out
-
- def reorder_encoder_out(self, encoder_out, new_order):
- return self.encoder.reorder_encoder_out(encoder_out, new_order)
-
-
-class DualInputEncoder(FairseqEncoder):
- def __init__(
- self,
- args,
- spch_encoder,
- text_encoder,
- dictionary,
- cross_attentive_loss_before_last_layer=-1,
- ):
- super().__init__(dictionary)
-
- self.spch_encoder = spch_encoder
- self.text_encoder = text_encoder
- self.enc_grad_mult = args.enc_grad_mult
- self.cross_attentive_loss_before_last_layer = (
- cross_attentive_loss_before_last_layer
- )
- self.use_cross_attentive_loss = (
- False if cross_attentive_loss_before_last_layer <= -1 else True
- )
- self.enc2_along_grad_mult = args.enc2_along_grad_mult
-
- @classmethod
- def set_shared_layer(cls, share_level, src_layer, tgt_layer):
- """
- share parameters from tgt_layer to src_layer
- share_level:
- 0: share everything
- 1: share everything but different model
- 2: share weight but not bias, layernorm
- """
- if share_level == 0:
- return tgt_layer
- if isinstance(src_layer, nn.Linear):
- return tgt_layer
- if isinstance(src_layer, TransformerEncoderLayer):
- assert src_layer.embed_dim == tgt_layer.embed_dim
- assert src_layer.normalize_before == tgt_layer.normalize_before
- if share_level == 1:
- src_layer.fc1 = tgt_layer.fc1
- src_layer.fc2 = tgt_layer.fc2
- src_layer.self_attn = tgt_layer.self_attn
- src_layer.final_layer_norm = tgt_layer.final_layer_norm
- src_layer.self_attn_layer_norm = tgt_layer.self_attn_layer_norm
- src_layer.layernorm_embedding = tgt_layer.layernorm_embedding
- else:
- src_layer.fc1.weight = tgt_layer.fc1.weight
- src_layer.fc2.weight = tgt_layer.fc2.weight
- src_layer.self_attn.k_proj.weight = tgt_layer.self_attn.k_proj.weight
- src_layer.self_attn.v_proj.weight = tgt_layer.self_attn.v_proj.weight
- src_layer.self_attn.q_proj.weight = tgt_layer.self_attn.q_proj.weight
- src_layer.self_attn.out_proj.weight = (
- tgt_layer.self_attn.out_proj.weight
- )
- else:
- if share_level == 1:
- return tgt_layer
- return src_layer
-
- @classmethod
- def build_spch_encoder(cls, args):
- cfg = {
- "input_feat_per_channel": args.input_feat_per_channel,
- "input_channels": args.input_channels,
- "conv_kernel_sizes": args.conv_kernel_sizes,
- "conv_channels": args.conv_channels,
- "encoder_embed_dim": args.encoder_embed_dim,
- "encoder_ffn_embed_dim": args.encoder_ffn_embed_dim,
- "encoder_layers": args.speech_encoder_layers,
- "encoder_layerdrop": args.encoder_layerdrop,
- "encoder_attention_heads": args.encoder_attention_heads,
- "max_source_positions": args.max_source_positions,
- "dropout": args.dropout,
- "encoder_normalize_before": args.encoder_normalize_before,
- "activation_dropout": args.activation_dropout,
- "attention_dropout": args.attention_dropout,
- "activation_fn": args.activation_fn,
- "layernorm_embedding": args.layernorm_embedding,
- "no_token_positional_embeddings": args.no_token_positional_embeddings,
- "no_scale_embedding": args.no_scale_embedding,
- "quant_noise_pq": args.quant_noise_pq,
- "encoder_freezing_updates": 0,
- }
- model_args = namedtuple("args", cfg.keys())(*cfg.values())
- spch_encoder = S2TTransformerEncoder(model_args)
- if args.add_speech_eos:
- spch_encoder = SpeechEoSEncoder(
- spch_encoder,
- 2 * len(args.conv_kernel_sizes.split(",")),
- args.input_feat_per_channel,
- adapter_type=getattr(args, "speech_encoder_adapter_type", "None"),
- adapter_dim=args.encoder_embed_dim,
- )
- return spch_encoder
-
- @classmethod
- def build_text_encoder(cls, args, src_dictionary, spch_encoder):
- if args.encoder_shared_layers > 0:
- mx_shared_layers = (
- args.speech_encoder_layers
- if args.speech_encoder_layers < args.text_encoder_layers
- else args.text_encoder_layers
- )
- args.encoder_shared_layers = (
- args.encoder_shared_layers
- if args.encoder_shared_layers <= mx_shared_layers
- else mx_shared_layers
- )
- cfg = {
- "encoder_embed_dim": args.encoder_text_embed_dim,
- "encoder_ffn_embed_dim": args.encoder_ffn_embed_dim,
- "encoder_layers": args.text_encoder_layers,
- "encoder_layerdrop": args.encoder_layerdrop,
- "encoder_attention_heads": args.encoder_attention_heads,
- "encoder_learned_pos": args.encoder_learned_pos,
- "max_source_positions": args.max_source_positions,
- "dropout": args.dropout,
- "encoder_normalize_before": args.encoder_normalize_before,
- "activation_dropout": args.activation_dropout,
- "attention_dropout": args.attention_dropout,
- "activation_fn": args.activation_fn,
- "adaptive_input": args.adaptive_input,
- "no_token_positional_embeddings": args.no_token_positional_embeddings,
- "no_scale_embedding": args.no_scale_embedding,
- "quant_noise_pq": args.quant_noise_pq,
- }
- model_args = namedtuple("args", cfg.keys())(*cfg.values())
- enc_emb = nn.Embedding(
- len(src_dictionary), model_args.encoder_embed_dim, src_dictionary.pad()
- )
- text_encoder = TransformerEncoder(model_args, src_dictionary, enc_emb)
- if args.add_speech_eos:
- spch_encoder = spch_encoder.encoder
- if args.encoder_shared_layers > 0:
- text_encoder.layer_norm = cls.set_shared_layer(
- args.encoder_shared_layer_level,
- text_encoder.layer_norm,
- spch_encoder.layer_norm,
- )
- for i, ly in enumerate(
- spch_encoder.transformer_layers[-args.encoder_shared_layers :]
- ):
- ly_id = i + args.text_encoder_layers - args.encoder_shared_layers
- if not isinstance(text_encoder.layers[ly_id], type(ly)):
- if text_encoder.layers[ly_id]._get_name() not in ('TransformerEncoderLayerBase', 'TransformerEncoderLayer'):
- raise ValueError("The shared layers are expected from the same class")
- text_encoder.layers[ly_id] = cls.set_shared_layer(
- args.encoder_shared_layer_level,
- text_encoder.layers[ly_id],
- ly,
- )
- return text_encoder
-
- def mult_rst_grad(self, rst, ratio):
- assert isinstance(rst, dict) # instead of EncoderOut
- assert len(rst["encoder_out"]) == 1
- rst["encoder_out"][0] = GradMultiply.apply(rst["encoder_out"][0], ratio)
- return rst
-
- def process_attentive_loss_states(self, rst, interstates):
- assert isinstance(rst, dict) # instead of EncoderOut
- rst["encoder_states"] = interstates
- return rst
-
- def forward(
- self,
- src_tokens,
- src_lengths=None,
- src_txt_tokens=None,
- src_txt_lengths=None,
- **kwargs
- ):
- """
- Args:
- src_tokens: padded tensor (B, T, C * feat)
- src_lengths: tensor of original lengths of input utterances (speech) (B,)
- src_txt_tokens: padded tensor (B, T)
- src_txt_lengths: tensor of original lengths of input utterances (text) (B,)
- """
- # src_tokens only: inference
- # src_tokens, src_lengths: speech only training
- # src_txt_tokens, src_txt_lengths: text only training
- # all valid: speech + text training
-
- if src_tokens is None and src_txt_tokens is None:
- raise ValueError(
- "src_tokens and src_txt_tokens cannot be None at the same time"
- )
- ret1 = None
- ret2 = None
- return_all_hiddens = False
- if src_tokens is not None:
- if (
- self.use_cross_attentive_loss and src_txt_tokens is not None
- ): # remove self.training so we can get attn score during validation step
- return_all_hiddens = True
- ret1 = self.spch_encoder(
- src_tokens, src_lengths, return_all_hiddens=return_all_hiddens
- )
-
- if self.use_cross_attentive_loss and src_txt_tokens is not None:
- assert self.cross_attentive_loss_before_last_layer < len(
- ret1["encoder_states"]
- )
- ret1 = self.process_attentive_loss_states(
- ret1,
- ret1["encoder_states"][
- -self.cross_attentive_loss_before_last_layer - 1
- ],
- )
-
- if src_txt_tokens is not None:
- ret2 = self.text_encoder(
- src_txt_tokens, src_txt_lengths, return_all_hiddens=return_all_hiddens
- )
- if return_all_hiddens:
- if self.cross_attentive_loss_before_last_layer == len(
- self.text_encoder.layers
- ):
- text_embedding, _ = self.text_encoder.forward_embedding(
- src_txt_tokens
- )
- text_embedding = text_embedding.transpose(0, 1)
- ret2 = self.process_attentive_loss_states(ret2, text_embedding)
- else:
- assert self.cross_attentive_loss_before_last_layer < len(
- self.text_encoder.layers
- )
- ret2 = self.process_attentive_loss_states(
- ret2,
- ret2["encoder_states"][
- -self.cross_attentive_loss_before_last_layer - 1
- ],
- )
-
- def merge_output(rst1, rst2):
- if rst1 is None:
- if not (self.enc2_along_grad_mult == 1.0 or self.training):
- rst2 = self.mult_rst_grad(rst2, self.enc2_along_grad_mult)
- return rst2
- if rst2 is None:
- return rst1
- if self.enc_grad_mult != 1.0 and self.training:
- rst1 = self.mult_rst_grad(rst1, self.enc_grad_mult)
- rst2 = self.mult_rst_grad(rst2, self.enc_grad_mult)
- rst = (rst1, rst2)
- return rst
-
- return merge_output(ret1, ret2)
-
- def reorder_encoder_out(self, encoder_out, new_order):
- assert self.training is False # used for inference only
- return self.spch_encoder.reorder_encoder_out(encoder_out, new_order)
-
-
-# TransformerMultiInputDecoder: take one or two encoder inputs
-class TransformerMultiInputDecoder(FairseqDecoder):
- def __init__(
- self,
- dictionary,
- spch_decoder,
- text_decoder,
- compute_cross_attentive_loss=False,
- cross_attentive_loss_with_norm=True,
- cross_attentive_loss_reverse=False,
- ):
-
- super().__init__(dictionary)
- self.spch_decoder = spch_decoder
- self.text_decoder = text_decoder
- self.compute_cross_attentive_loss = compute_cross_attentive_loss
- self.cross_attentive_loss_with_norm = cross_attentive_loss_with_norm
- self.cross_attentive_loss_reverse = cross_attentive_loss_reverse
-
- @classmethod
- def share_spchdecoder(cls, task_args, text_decoder, spch_decoder):
- if task_args.decoder_shared_layer_level == 0:
- return text_decoder
- assert text_decoder.embed_tokens == spch_decoder.embed_tokens
- spch_decoder.project_in_dim = text_decoder.project_in_dim
- spch_decoder.embed_positions = text_decoder.embed_positions
- spch_decoder.layernorm_embedding = text_decoder.layernorm_embedding
- spch_decoder.project_out_dim = text_decoder.project_out_dim
- spch_decoder.adaptive_softmax = text_decoder.adaptive_softmax
- if task_args.decoder_shared_layer_level == 1:
- spch_decoder.output_projection = text_decoder.output_projection
- spch_decoder.layer_norm = text_decoder.layer_norm
- else: # 2
- spch_decoder.output_projection.weight = (
- text_decoder.output_projection.weight
- )
- for i, ly in enumerate(text_decoder.layers):
- sly = spch_decoder.layers[i]
- sly.self_attn = ly.self_attn
- sly.self_attn_layer_norm = ly.self_attn_layer_norm
- # sly.encoder_attn = ly.encoder_attn
- if (
- task_args.decoder_shared_layer_level == 1
- ): # share everything, but under different models
- sly.encoder_attn = ly.encoder_attn
- sly.encoder_attn_layer_norm = ly.encoder_attn_layer_norm
- sly.fc1 = ly.fc1
- sly.fc2 = ly.fc2
- sly.final_layer_norm = ly.final_layer_norm
- else: # task_args.decoder_shared_layer_level == 2: #separated encoder_attn_layer_norm and bias
- sly.encoder_attn.k_proj.weight = ly.encoder_attn.k_proj.weight
- sly.encoder_attn.v_proj.weight = ly.encoder_attn.v_proj.weight
- sly.encoder_attn.q_proj.weight = ly.encoder_attn.q_proj.weight
- sly.encoder_attn.out_proj.weight = ly.encoder_attn.out_proj.weight
- sly.fc1.weight = ly.fc1.weight
- sly.fc2.weight = ly.fc2.weight
-
- return spch_decoder
-
- def cross_attentive_loss(
- self, teacher_states, student_states, teacher_masking, student_masking, eps=1e-6
- ):
- x = teacher_states.transpose(0, 1) # from T X B X D to B X T X D
- y = student_states.transpose(0, 1)
- if self.cross_attentive_loss_with_norm:
- x = x / (x.norm(dim=2, keepdim=True) + eps)
- y = y / (y.norm(dim=2, keepdim=True) + eps)
- dim = x.size(-1)
- # lengths: batch X seqLen
- sim_scores_xy = torch.bmm(x, y.transpose(1, 2)) # batch X lenx X leny ]
- if y.dtype == torch.float16:
- sim_scores_xy = sim_scores_xy.float()
- y = y.float()
- x = x.float()
- if teacher_masking != []:
- assert len(teacher_masking) == 1
- sim_scores_xy = sim_scores_xy.masked_fill(
- teacher_masking[0].unsqueeze(-1), float("-inf")
- )
- if student_masking != []:
- sim_scores_xy = sim_scores_xy.masked_fill(
- student_masking[0].unsqueeze(1), float("-inf")
- )
- # do masking
- y_weights = utils.softmax(sim_scores_xy, dim=-1)
- if teacher_masking != []:
- y_weights = y_weights.masked_fill(teacher_masking[0].unsqueeze(-1), 0)
- x_reconstruct_from_y = torch.bmm(y_weights, y)
-
- sim_scores_xx = torch.bmm(x, x.transpose(1, 2)) # batch X lenx X lenx ]
- x_weights = utils.softmax(sim_scores_xx, dim=-1)
- if teacher_masking != []:
- x_weights = x_weights.masked_fill(teacher_masking[0].unsqueeze(-1), 0)
-
- # no gradient for teacher state
- x_reconstruct_from_x = torch.bmm(x_weights, x).detach()
- cost = (x_reconstruct_from_x - x_reconstruct_from_y).norm(dim=2)
- if teacher_masking != []:
- cost = cost.masked_fill(teacher_masking[0], 0)
-
- if not self.cross_attentive_loss_with_norm:
- cost = cost / dim
- return cost
-
- def forward(
- self,
- prev_output_tokens,
- encoder_out,
- incremental_state=None,
- has_txt_input=False,
- **kwargs
- ):
- """
- Args:
- prev_output_tokens (LongTensor): previous decoder outputs of shape
- `(batch, tgt_len)`, for input feeding/teacher forcing. If there are
- two or more input during training, they will share the same prev_output_tokens
- encoder_out (tuple[Tensor]): output from the encoder, used for
- encoder-side attention. It will be tuple if there are more inputs, but a tensor
- if only one input
- incremental_state ([dict]): dictionary used for storing state during
- :ref:`Incremental decoding`. It is only valid for inference, only from single
- input
- Returns:
- tuple:
- - the last decoder layer's output of shape `(batch, tgt_len,
- vocab)`. If there are N inputs, batch will be N bigger than a single input
- - the last decoder layer's attention weights of shape `(batch,
- tgt_len, src_len)`
- """
- assert not isinstance(encoder_out, EncoderOut)
- if isinstance(encoder_out, tuple): # training with mulitple input
- rst = []
- assert len(encoder_out) == 2
- for i, eo in enumerate(encoder_out):
- assert incremental_state is None
- if i == 0:
- rst.append(
- self.spch_decoder(prev_output_tokens, eo, incremental_state)
- )
- else:
- rst.append(
- self.text_decoder(prev_output_tokens, eo, incremental_state)
- )
- dec_out = torch.cat([r[0] for r in rst], dim=0)
- attn_cost = None
- if self.compute_cross_attentive_loss:
- assert isinstance(encoder_out[0], dict)
- if self.cross_attentive_loss_reverse:
- attn_cost = self.cross_attentive_loss(
- teacher_states=encoder_out[1]["encoder_states"], # text_states
- student_states=encoder_out[0]["encoder_states"], # spch_states
- teacher_masking=encoder_out[1]["encoder_padding_mask"],
- student_masking=encoder_out[0]["encoder_padding_mask"],
- )
- else:
- attn_cost = self.cross_attentive_loss(
- teacher_states=encoder_out[0]["encoder_states"], # spch_states
- student_states=encoder_out[1]["encoder_states"], # text_states
- teacher_masking=encoder_out[0]["encoder_padding_mask"],
- student_masking=encoder_out[1]["encoder_padding_mask"],
- )
-
- return (dec_out, {"attn_cost": attn_cost})
- else: # inference or training with one input
- if has_txt_input:
- return self.text_decoder(
- prev_output_tokens, encoder_out, incremental_state
- )
- return self.spch_decoder(prev_output_tokens, encoder_out, incremental_state)
-
-
-# Note:
-# dual input transformer:
-# encoder: S2TTransformerEncoder for speech + TransformerEncoder for text
-# decoder: TransformerDecoder for text
-@register_model("dual_input_s2t_transformer")
-class DualInputS2TTransformerModel(FairseqEncoderDecoderModel):
- def __init__(self, encoder, decoder):
- super().__init__(encoder, decoder)
- self.num_updates = 0
-
- def max_positions(self):
- return None # it is provided in task
-
- @staticmethod
- def add_args(parser):
- """Add model-specific arguments to the parser."""
- # encoder 1: S2TTransformerEncoder for speech
- parser.add_argument(
- "--conv-kernel-sizes",
- type=str,
- metavar="N",
- help="kernel sizes of Conv1d subsampling layers",
- )
- parser.add_argument(
- "--conv-channels",
- type=int,
- metavar="N",
- help="# of channels in Conv1d subsampling layers",
- )
- parser.add_argument(
- "--enc-output-dim",
- type=int,
- metavar="N",
- help="""
- encoder output dimension, can be None. If specified, projecting the
- transformer output to the specified dimension""",
- )
- # standard Transformer
- parser.add_argument(
- "--activation-fn",
- type=str,
- default="relu",
- choices=utils.get_available_activation_fns(),
- help="activation function to use",
- )
- parser.add_argument(
- "--dropout", type=float, metavar="D", help="dropout probability"
- )
- parser.add_argument(
- "--attention-dropout",
- type=float,
- metavar="D",
- help="dropout probability for attention weights",
- )
- parser.add_argument(
- "--activation-dropout",
- "--relu-dropout",
- type=float,
- metavar="D",
- help="dropout probability after activation in FFN.",
- )
- parser.add_argument(
- "--encoder-embed-dim",
- type=int,
- metavar="N",
- help="encoder embedding dimension",
- )
- parser.add_argument(
- "--encoder-text-embed-dim",
- type=int,
- metavar="N",
- help="encoder text embedding dimension",
- )
- parser.add_argument(
- "--encoder-ffn-embed-dim",
- type=int,
- metavar="N",
- help="encoder embedding dimension for FFN",
- )
- parser.add_argument(
- "--encoder-attention-heads",
- type=int,
- metavar="N",
- help="num encoder attention heads",
- )
- parser.add_argument(
- "--decoder-embed-dim",
- type=int,
- metavar="N",
- help="decoder embedding dimension",
- )
- parser.add_argument(
- "--decoder-ffn-embed-dim",
- type=int,
- metavar="N",
- help="decoder embedding dimension for FFN",
- )
- parser.add_argument(
- "--decoder-layers", type=int, metavar="N", help="num decoder layers"
- )
- parser.add_argument(
- "--decoder-attention-heads",
- type=int,
- metavar="N",
- help="num decoder attention heads",
- )
- parser.add_argument(
- "--layernorm-embedding",
- action="store_true",
- help="add layernorm to embedding",
- )
- parser.add_argument(
- "--no-scale-embedding",
- action="store_true",
- help="if True, dont scale embeddings",
- )
- # non-standard transformer parameters
- parser.add_argument(
- "--speech-encoder-layers",
- type=int,
- metavar="N",
- help="num speech encoder layers",
- )
- parser.add_argument(
- "--text-encoder-layers",
- type=int,
- metavar="N",
- help="num text encoder layers",
- )
- parser.add_argument(
- "--encoder-shared-layers",
- type=int,
- metavar="N",
- help="num shared encoder layers",
- )
- parser.add_argument(
- "--encoder-shared-layer-level",
- type=int,
- metavar="N",
- default=0,
- choices=[0, 1, 2],
- help="share layer level 0: all share 1: all share with separate model 2: share weight but not bias and layernorm",
- )
-
- parser.add_argument(
- "--decoder-shared-layer-level",
- default=0,
- choices=[0, 1, 2],
- type=int,
- metavar="N",
- help="0: share everything; 1: share everything with different model 2: no share layer_norm and bias",
- )
- ###
- parser.add_argument(
- "--text-input-cost-ratio",
- type=float,
- default=1.0,
- metavar="V",
- help="text input cost ratio relative to speech input cost",
- )
- parser.add_argument(
- "--init-scale",
- type=float,
- default=1.0,
- metavar="V",
- help="scale the initial weight by given factor",
- )
- parser.add_argument(
- "--enc-grad-mult",
- type=float,
- metavar="V",
- default=1.0,
- help="multiply enc1 and enc2 gradient by V",
- )
- parser.add_argument(
- "--enc2-along-grad-mult",
- type=float,
- metavar="V",
- default=1.0,
- help="multiply enc2 gradient by V if only enc2 is used",
- )
- parser.add_argument(
- "--load-pretrain-encoder",
- type=str,
- default="",
- metavar="EXPR",
- help=""" path to the pretrained encoder """,
- )
- parser.add_argument(
- "--load-pretrain-speech-encoder",
- type=str,
- default="",
- metavar="EXPR",
- help=""" path to the pretrained speech encoder """,
- )
- parser.add_argument(
- "--load-pretrain-text-encoder",
- type=str,
- default="",
- metavar="EXPR",
- help=""" path to the pretrained text encoder """,
- )
- parser.add_argument(
- "--load-pretrain-text-encoder-last",
- type=str,
- default="",
- metavar="EXPR",
- help=""" path to the pretrained text encoder """,
- )
- parser.add_argument(
- "--load-pretrain-decoder",
- type=str,
- metavar="EXPR",
- default="",
- help=""" path to the pretrained encoder """,
- )
- parser.add_argument(
- "--add-speech-eos",
- action="store_true",
- help="add eos token at the end of input feature",
- )
- parser.add_argument(
- "--speech-encoder-adapter-type",
- type=str,
- metavar="EXPR",
- default="None",
- choices=["None", "Linear", "MLP"],
- help="add speech encoder adapter",
- )
-
- @classmethod
- def build_encoder(cls, args, task):
- spch_encoder = DualInputEncoder.build_spch_encoder(args)
- text_encoder = DualInputEncoder.build_text_encoder(
- args, task.src_dict, spch_encoder
- )
- cross_attentive_loss_before_last_layer = (
- 0 if getattr(args, "attentive_cost_regularization", 0.0) > 0.0 else -1
- )
- encoder = DualInputEncoder(
- args,
- spch_encoder,
- text_encoder,
- task.src_dict,
- cross_attentive_loss_before_last_layer,
- )
- if args.init_scale != 1.0:
- with torch.no_grad():
- for param in encoder.parameters():
- param.data.mul_(args.init_scale)
- if args.load_pretrain_text_encoder != "":
- checkpoint_utils.load_pretrained_component_from_model(
- text_encoder, args.load_pretrain_text_encoder
- )
- if args.load_pretrain_speech_encoder != "":
- if hasattr(spch_encoder, "encoder"):
- checkpoint_utils.load_pretrained_component_from_model(
- spch_encoder.encoder, args.load_pretrain_speech_encoder
- )
- else:
- checkpoint_utils.load_pretrained_component_from_model(
- spch_encoder, args.load_pretrain_speech_encoder
- )
- if (
- args.load_pretrain_text_encoder_last != ""
- ): # if share encoder, speech encoder parameters will be used.
- # It provides a chance to use pre-trained mt encoder instead
- checkpoint_utils.load_pretrained_component_from_model(
- text_encoder, args.load_pretrain_text_encoder_last
- )
-
- if args.load_pretrain_encoder != "":
- checkpoint_utils.load_pretrained_component_from_model(
- encoder, args.load_pretrain_encoder
- )
- return encoder
-
- @classmethod
- def build_decoder(cls, args, task):
- dec_cfg = {
- "decoder_layerdrop": args.decoder_layerdrop,
- "share_decoder_input_output_embed": args.share_decoder_input_output_embed,
- "decoder_embed_dim": args.decoder_embed_dim,
- "max_target_positions": args.max_target_positions,
- "dropout": args.dropout,
- "encoder_learned_pos": args.encoder_learned_pos,
- "decoder_learned_pos": args.decoder_learned_pos,
- "layernorm_embedding": args.layernorm_embedding,
- "decoder_normalize_before": args.decoder_normalize_before,
- "activation_dropout": args.activation_dropout,
- "attention_dropout": args.attention_dropout,
- "decoder_ffn_embed_dim": args.decoder_ffn_embed_dim,
- "decoder_layers": args.decoder_layers,
- "decoder_attention_heads": args.decoder_attention_heads,
- "decoder_output_dim": args.decoder_embed_dim,
- "no_scale_embedding": args.no_scale_embedding,
- "adaptive_input": args.adaptive_input,
- "quant_noise_pq": args.quant_noise_pq,
- "adaptive_softmax_cutoff": args.adaptive_softmax_cutoff,
- "tie_adaptive_weights": args.tie_adaptive_weights,
- "no_token_positional_embeddings": args.no_token_positional_embeddings,
- "encoder": {"embed_dim":args.encoder_embed_dim}
- }
- dec_cfg = namedtuple("args", dec_cfg.keys())(*dec_cfg.values())
- dec_emb = nn.Embedding(
- len(task.target_dictionary),
- args.decoder_embed_dim,
- task.target_dictionary.pad(),
- )
- compute_cross_attentive_loss = (
- True if getattr(args, "attentive_cost_regularization", 0.0) > 0.0 else False
- )
- cross_attentive_loss_without_norm = getattr(
- args, "attentive_cost_without_normalize", False
- )
- cross_attentive_loss_reverse = (
- False # getattr(args, "attentive_cost_reverse", False)
- )
-
- text_decoder = TransformerDecoder(dec_cfg, task.target_dictionary, dec_emb)
- spch_decoder = TransformerDecoder(dec_cfg, task.target_dictionary, dec_emb)
- spch_decoder = TransformerMultiInputDecoder.share_spchdecoder(
- args, text_decoder, spch_decoder
- )
- decoder = TransformerMultiInputDecoder(
- dictionary=task.target_dictionary,
- spch_decoder=spch_decoder,
- text_decoder=text_decoder,
- compute_cross_attentive_loss=compute_cross_attentive_loss,
- cross_attentive_loss_with_norm=True
- if not cross_attentive_loss_without_norm
- else False,
- cross_attentive_loss_reverse=cross_attentive_loss_reverse,
- )
- if args.init_scale != 1.0:
- with torch.no_grad():
- for param in decoder.parameters():
- param.data.mul_(args.init_scale)
- if args.load_pretrain_decoder != "":
- try:
- checkpoint_utils.load_pretrained_component_from_model(
- decoder, args.load_pretrain_decoder
- )
- except RuntimeError:
- checkpoint_utils.load_pretrained_component_from_model(
- decoder.text_decoder, args.load_pretrain_decoder
- )
- if args.decoder_shared_layer_level > 0:
- checkpoint_utils.load_pretrained_component_from_model(
- decoder.spch_decoder, args.load_pretrain_decoder
- )
-
- return decoder
-
- @classmethod
- def build_model(cls, args, task):
- """Build a new model instance."""
- # make sure that all args are properly defaulted
- # (in case there are any new ones)
- dualinputs2ttransformer_base(args)
-
- encoder = cls.build_encoder(args, task)
- decoder = cls.build_decoder(args, task)
- return cls(encoder, decoder)
-
- def get_normalized_probs(self, net_output, log_probs, sample=None):
- # net_output['encoder_out'] is a (B, T, D) tensor
- lprobs = super().get_normalized_probs(net_output, log_probs, sample)
- lprobs.batch_first = True
- return lprobs
-
- def set_num_updates(self, num_updates):
- """Set the number of parameters updates."""
- super().set_num_updates(num_updates)
- self.num_updates = num_updates
-
- def forward(
- self,
- src_tokens,
- src_lengths,
- prev_output_tokens,
- use_encoder_outputs=False,
- src_txt_tokens=None,
- src_txt_lengths=None,
- mode="sup_speech",
- **kwargs
- ):
- """
- Run the forward pass for an encoder-decoder model.
-
- First feed a batch of source tokens through the encoder. Then, feed the
- encoder output and previous decoder outputs (i.e., teacher forcing) to
- the decoder to produce the next outputs::
-
- encoder_out = self.encoder(src_tokens, src_lengths)
- return self.decoder(prev_output_tokens, encoder_out)
-
- Args:
- src_tokens (LongTensor): tokens in the source language of shape
- `(batch, src_len)`
- src_lengths (LongTensor): source sentence lengths of shape `(batch)`
- prev_output_tokens (LongTensor): previous decoder outputs of shape
- `(batch, tgt_len)`, for teacher forcing
- mode = 'sup_speech' or 'text'
-
- Returns:
- tuple:
- - the decoder's output of shape `(batch, tgt_len, vocab)`
- - a dictionary with any model-specific outputs
- """
- if mode == "text":
- assert src_txt_tokens is None
- src_txt_tokens = src_tokens
- src_txt_lengths = src_lengths
- src_tokens = None
- src_lengths = None
- encoder_out = self.encoder(
- src_tokens,
- src_lengths=src_lengths,
- src_txt_tokens=src_txt_tokens,
- src_txt_lengths=src_txt_lengths,
- **kwargs
- )
- has_txt_input = True if src_txt_tokens is not None else False
- decoder_out = self.decoder(
- prev_output_tokens,
- encoder_out=encoder_out,
- has_txt_input=has_txt_input,
- **kwargs
- )
- if use_encoder_outputs:
- return decoder_out, encoder_out
- return decoder_out
-
-
-@register_model_architecture(
- "dual_input_s2t_transformer", "dualinputs2ttransformer_base"
-)
-def dualinputs2ttransformer_base(args):
- args.encoder_freezing_updates = getattr(args, "encoder_freezing_updates", 0)
- # Convolutional subsampler
- args.input_feat_per_channel = getattr(args, "input_feat_per_channel", 80)
- args.conv_kernel_sizes = getattr(args, "conv_kernel_sizes", "5,5")
- args.conv_channels = getattr(args, "conv_channels", 1024)
- # Transformer
- args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512)
- args.encoder_text_embed_dim = getattr(
- args, "encoder_text_embed_dim", args.encoder_embed_dim
- )
- args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 2048)
- args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 8)
- args.encoder_normalize_before = getattr(args, "encoder_normalize_before", True)
- args.encoder_layerdrop = getattr(args, "encoder_layerdrop", 0)
- args.encoder_learned_pos = getattr(args, "encoder_learned_pos", False)
-
- args.decoder_embed_dim = getattr(args, "decoder_embed_dim", args.encoder_embed_dim)
- args.decoder_ffn_embed_dim = getattr(
- args, "decoder_ffn_embed_dim", args.encoder_ffn_embed_dim
- )
- args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8)
- args.decoder_normalize_before = getattr(args, "decoder_normalize_before", True)
- args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False)
- args.dropout = getattr(args, "dropout", 0.1)
- args.attention_dropout = getattr(args, "attention_dropout", args.dropout)
- args.activation_dropout = getattr(args, "activation_dropout", args.dropout)
- args.activation_fn = getattr(args, "activation_fn", "relu")
- args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None)
- args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0)
- args.tie_adaptive_weights = getattr(args, "tie_adaptive_weights", False)
- args.share_decoder_input_output_embed = getattr(
- args, "share_decoder_input_output_embed", False
- )
- args.no_token_positional_embeddings = getattr(
- args, "no_token_positional_embeddings", False
- )
- args.adaptive_input = getattr(args, "adaptive_input", False)
- args.decoder_layerdrop = getattr(args, "decoder_layerdrop", 0.0)
- args.decoder_output_dim = getattr(
- args, "decoder_output_dim", args.decoder_embed_dim
- )
- args.layernorm_embedding = getattr(args, "layernorm_embedding", False)
- args.no_scale_embedding = getattr(args, "no_scale_embedding", False)
- args.quant_noise_pq = getattr(args, "quant_noise_pq", 0)
-
- args.speech_encoder_layers = getattr(args, "speech_encoder_layers", 10)
- args.text_encoder_layers = getattr(args, "text_encoder_layers", 6)
- args.encoder_shared_layers = getattr(args, "encoder_shared_layers", 0)
- args.decoder_layers = getattr(args, "decoder_layers", 6)
-
- args.add_speech_eos = getattr(args, "add_speech_eos", False)
-
-
-@register_model_architecture("dual_input_s2t_transformer", "dualinputs2ttransformer_s")
-def dualinputs2ttransformer_s(args):
- args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 256)
- args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 256 * 4)
- args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 4)
- args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 4)
- args.dropout = getattr(args, "dropout", 0.1)
- args.speech_encoder_layers = getattr(args, "speech_encoder_layers", 7)
- args.text_encoder_layers = getattr(args, "text_encoder_layers", 7)
- args.decoder_layers = getattr(args, "decoder_layers", 7)
- dualinputs2ttransformer_base(args)
-
-
-@register_model_architecture("dual_input_s2t_transformer", "dualinputs2ttransformer_m")
-def dualinputs2ttransformer_m(args):
- args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512)
- args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 512 * 4)
- args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 8)
- args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8)
- args.dropout = getattr(args, "dropout", 0.15)
- args.speech_encoder_layers = getattr(args, "speech_encoder_layers", 10)
- args.text_encoder_layers = getattr(args, "text_encoder_layers", 6)
- args.decoder_layers = getattr(args, "decoder_layers", 6)
- dualinputs2ttransformer_base(args)
-
-
-@register_model_architecture("dual_input_s2t_transformer", "dualinputs2ttransformer_b")
-def dualinputs2ttransformer_b(args):
- args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 768)
- args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 768 * 4)
- args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 12)
- args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 12)
- args.dropout = getattr(args, "dropout", 0.15)
- args.speech_encoder_layers = getattr(args, "speech_encoder_layers", 12)
- args.text_encoder_layers = getattr(args, "text_encoder_layers", 6)
- args.decoder_layers = getattr(args, "decoder_layers", 6)
- dualinputs2ttransformer_base(args)
-
-
-@register_model_architecture("dual_input_s2t_transformer", "dualinputs2ttransformer_l")
-def dualinputs2ttransformer_l(args):
- args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024)
- args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 1024 * 4)
- args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16)
- args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 16)
- args.dropout = getattr(args, "dropout", 0.2)
- args.speech_encoder_layers = getattr(args, "speech_encoder_layers", 12)
- args.text_encoder_layers = getattr(args, "text_encoder_layers", 6)
- args.decoder_layers = getattr(args, "decoder_layers", 6)
- dualinputs2ttransformer_base(args)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/models/s2t_dualinputwavtransformer.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/models/s2t_dualinputwavtransformer.py
deleted file mode 100644
index 66e4b3f1ec89fca8a2b9355fcff83a069a641cd6..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/models/s2t_dualinputwavtransformer.py
+++ /dev/null
@@ -1,526 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import logging
-from collections import OrderedDict, namedtuple
-
-import torch.nn as nn
-
-from fairseq import checkpoint_utils, utils
-from fairseq.checkpoint_utils import load_checkpoint_to_cpu
-from fairseq.file_io import PathManager
-from fairseq.models import register_model, register_model_architecture
-from fairseq.models.speech_to_text import (
- SpeechWavTransformerEncoder,
- StackedSpeechWavTransformerEncoder,
- TransformerDecoder,
-)
-from fairseq.models.transformer import TransformerEncoder
-
-from .s2t_dualinputtransformer import (
- DualInputEncoder,
- DualInputS2TTransformerModel,
- TransformerMultiInputDecoder,
-)
-
-logger = logging.getLogger(__name__)
-
-
-@register_model("dual_input_wav_transformer")
-class DualInputWavTransformerModel(DualInputS2TTransformerModel):
- def __init__(self, encoder, decoder):
- super().__init__(encoder, decoder)
-
- @staticmethod
- def add_args(parser):
- def add_transformer_args(parser):
- # We can't use TransformerModel.add_args(parser), since it defines max-source-positions which is duplicated with tasks/speech_to_text.py
- # Transformer
- parser.add_argument(
- "--activation-fn",
- type=str,
- default="relu",
- choices=utils.get_available_activation_fns(),
- help="activation function to use",
- )
- parser.add_argument(
- "--dropout", type=float, metavar="D", help="dropout probability"
- )
- parser.add_argument(
- "--attention-dropout",
- type=float,
- metavar="D",
- help="dropout probability for attention weights",
- )
- parser.add_argument(
- "--activation-dropout",
- "--relu-dropout",
- type=float,
- metavar="D",
- help="dropout probability after activation in FFN.",
- )
- parser.add_argument(
- "--encoder-embed-dim",
- type=int,
- metavar="N",
- help="encoder embedding dimension",
- )
- parser.add_argument(
- "--encoder-ffn-embed-dim",
- type=int,
- metavar="N",
- help="encoder embedding dimension for FFN",
- )
- parser.add_argument(
- "--encoder-layers", type=int, metavar="N", help="num encoder layers"
- )
- parser.add_argument(
- "--encoder-attention-heads",
- type=int,
- metavar="N",
- help="num encoder attention heads",
- )
- parser.add_argument(
- "--encoder-normalize-before",
- action="store_true",
- help="apply layernorm before each encoder block",
- )
- parser.add_argument(
- "--decoder-embed-dim",
- type=int,
- metavar="N",
- help="decoder embedding dimension",
- )
- parser.add_argument(
- "--decoder-ffn-embed-dim",
- type=int,
- metavar="N",
- help="decoder embedding dimension for FFN",
- )
- parser.add_argument(
- "--decoder-layers", type=int, metavar="N", help="num decoder layers"
- )
- parser.add_argument(
- "--decoder-attention-heads",
- type=int,
- metavar="N",
- help="num decoder attention heads",
- )
- parser.add_argument(
- "--decoder-normalize-before",
- action="store_true",
- help="apply layernorm before each decoder block",
- )
- parser.add_argument(
- "--share-decoder-input-output-embed",
- action="store_true",
- help="share decoder input and output embeddings",
- )
- parser.add_argument(
- "--layernorm-embedding",
- action="store_true",
- help="add layernorm to embedding",
- )
- parser.add_argument(
- "--no-scale-embedding",
- action="store_true",
- help="if True, dont scale embeddings",
- )
-
- parser.add_argument(
- "--encoder-learned-pos",
- action="store_true",
- help="use learned positional embeddings",
- )
- parser.add_argument(
- "--decoder-learned-pos",
- action="store_true",
- help="use learned positional embeddings",
- )
-
- add_transformer_args(parser)
- SpeechWavTransformerEncoder.add_args(parser)
- parser.add_argument(
- "--load-pretrained-speech-text-encoder",
- type=str,
- default="",
- metavar="EXPR",
- help=""" path to the pretrained speech text encoder from SpeechTextPreTrainModel """,
- )
- parser.add_argument(
- "--load-pretrained-wav2vec-encoder",
- type=str,
- default="",
- metavar="EXPR",
- help=""" path to the pretrained speech text encoder from wav2vec """,
- )
-
- parser.add_argument(
- "--load-pretrained-speech-text-decoder",
- type=str,
- default="",
- metavar="EXPR",
- help=""" path to the pretrained speech text decoder from SpeechTextPreTrainModel """,
- )
- parser.add_argument(
- "--load-pretrained-text-decoder",
- type=str,
- default="",
- metavar="EXPR",
- help=""" path to the pretrained text decoder """,
- )
- parser.add_argument(
- "--load-init-encoder",
- type=str,
- default="",
- metavar="EXPR",
- help=""" path to load seed encoder model """,
- )
- parser.add_argument(
- "--load-init-decoder",
- type=str,
- default="",
- metavar="EXPR",
- help=""" path to load seed decoder model """,
- )
-
- parser.add_argument(
- "--text-input-cost-ratio",
- type=float,
- default=1.0,
- metavar="V",
- help="text input cost ratio relative to speech input cost",
- )
- parser.add_argument(
- "--enc-grad-mult",
- type=float,
- metavar="V",
- default=1.0,
- help="multiply enc1 and enc2 gradient by V",
- )
- parser.add_argument(
- "--enc2-along-grad-mult",
- type=float,
- metavar="V",
- default=1.0,
- help="multiply enc2 gradient by V if only enc2 is used",
- )
- parser.add_argument(
- "--no-strict-check-pretrain-model",
- action="store_true",
- help="Don't apply strict model check for the pretrained model",
- )
-
- parser.add_argument(
- "--stacked-encoder",
- action="store_true",
- help="stack speech and text encoders",
- )
-
- @classmethod
- def update_transformer_encoder_cfg(cls, args, update_dict):
- cfg = dict(args._get_kwargs())
- for fkey in update_dict.keys():
- cfg[fkey] = update_dict[fkey]
- cfg.pop("_name", None) # remove keys start with _
- model_args = namedtuple("args", cfg.keys())(*cfg.values())
- return model_args
-
- @classmethod
- def build_text_encoder(cls, args, src_dictionary):
- enc_emb = nn.Embedding(
- len(src_dictionary), args.encoder_embed_dim, src_dictionary.pad()
- )
- model_args = cls.update_transformer_encoder_cfg(
- args,
- {
- "encoder_layers": args.text_encoder_layers,
- "max_source_positions": args.max_positions_text,
- },
- )
- text_encoder = TransformerEncoder(model_args, src_dictionary, enc_emb)
- return text_encoder
-
- @classmethod
- def build_speech_encoder(cls, args):
- model_args = cls.update_transformer_encoder_cfg(
- args, {"encoder_layers": args.speech_encoder_layers}
- )
- speech_encoder = SpeechWavTransformerEncoder(model_args)
- return speech_encoder
-
- @classmethod
- def check_args(cls, condition, is_strict, msg):
- if condition:
- return
- if is_strict:
- raise ValueError(msg)
- logger.warn(msg)
-
- @classmethod
- def build_encoder(cls, args, task):
- # text_encoder = cls.build_text_encoder(args, task.source_dictionary )
- text_encoder = cls.build_text_encoder(args, task.src_dict)
- speech_encoder = cls.build_speech_encoder(args)
- if args.load_pretrained_wav2vec_encoder:
- component_pairs = (
- ("feature_extractor", speech_encoder.subsample),
- ("post_extract_proj", speech_encoder.feat_proj),
- ("layer_norm", speech_encoder.feat_layer_norm),
- ("encoder.pos_conv", speech_encoder.embed_positions),
- ("encoder.layers", speech_encoder.layers),
- ("encoder.layer_norm", speech_encoder.layer_norm),
- ("mask_emb", speech_encoder.mask_emb),
- )
- state = cls.load_pretrained_speech_text_components(
- args.load_pretrained_wav2vec_encoder, component_pairs
- )
- cls.check_args(
- args.encoder_normalize_before
- == state["cfg"]["model"]["layer_norm_first"],
- not args.no_strict_check_pretrain_model,
- f"encoder_normalize_before {args.encoder_normalize_before} doesn't match with the pretrained model",
- )
- cls.check_args(
- args.activation_fn == state["cfg"]["model"]["activation_fn"],
- not args.no_strict_check_pretrain_model,
- f"activation_fn {args.activation_fn} doesn't match with the pretrained model",
- )
-
- if getattr(args, "stacked_encoder", False):
- if args.encoder_shared_text_layers_from_begin > 0:
- raise ValueError(
- "We can not stack encoders and share encoders at the same time!"
- )
- speech_encoder = StackedSpeechWavTransformerEncoder(
- speech_encoder, text_encoder.layers, text_encoder.layer_norm
- )
- else:
- cls.share_speech_text_encoder(
- speech_encoder, text_encoder, args.encoder_shared_text_layers_from_begin
- )
-
- cross_attentive_loss_before_last_layer = (
- 0 if getattr(args, "attentive_cost_regularization", 0.0) > 0.0 else -1
- )
- encoder = DualInputEncoder(
- args,
- speech_encoder,
- text_encoder,
- task.src_dict,
- cross_attentive_loss_before_last_layer,
- )
- if args.load_pretrained_speech_text_encoder:
- component_pairs = (
- ("encoder.sup_s2s_speech_encoder", encoder.spch_encoder),
- ("encoder.text_encoder", encoder.text_encoder),
- )
- cls.load_pretrained_speech_text_components(
- args.load_pretrained_speech_text_encoder, component_pairs
- )
- if getattr(args, "load_init_encoder", "") != "":
- checkpoint_utils.load_pretrained_component_from_model(
- encoder, args.load_init_encoder
- )
- return encoder
-
- @classmethod
- def build_text_decoder(cls, args, tgt_dictionary, dec_emb_share=None):
- dec_emb = (
- nn.Embedding(
- len(tgt_dictionary), args.decoder_embed_dim, tgt_dictionary.pad()
- )
- if dec_emb_share is None
- else dec_emb_share
- )
- text_decoder = TransformerDecoder(args, tgt_dictionary, dec_emb)
- return text_decoder
-
- @classmethod
- def build_decoder(cls, args, task):
- text_decoder = cls.build_text_decoder(args, task.target_dictionary)
- compute_cross_attentive_loss = (
- True if getattr(args, "attentive_cost_regularization", 0.0) > 0.0 else False
- )
- cross_attentive_loss_without_norm = getattr(
- args, "attentive_cost_without_normalize", False
- )
- cross_attentive_loss_reverse = (
- False # getattr(args, "attentive_cost_reverse", False)
- )
- if getattr(args, "load_pretrained_text_decoder", "") != "":
- checkpoint_utils.load_pretrained_component_from_model(
- text_decoder, args.load_pretrained_text_decoder
- )
-
- if args.load_pretrained_speech_text_decoder:
- component_pairs = (("decoder.text_decoder", text_decoder),)
- cls.load_pretrained_speech_text_components(
- args.load_pretrained_speech_text_decoder, component_pairs
- )
-
- decoder = TransformerMultiInputDecoder(
- dictionary=task.target_dictionary,
- spch_decoder=text_decoder,
- text_decoder=text_decoder,
- compute_cross_attentive_loss=compute_cross_attentive_loss,
- cross_attentive_loss_with_norm=True
- if not cross_attentive_loss_without_norm
- else False,
- cross_attentive_loss_reverse=cross_attentive_loss_reverse,
- )
- if getattr(args, "load_init_decoder", "") != "":
- checkpoint_utils.load_pretrained_component_from_model(
- decoder, args.load_init_decoder
- )
- return decoder
-
- @classmethod
- def load_pretrained_speech_text_components(cls, checkpoint, component_pairs):
- if not PathManager.exists(checkpoint):
- raise IOError("Model file not found: {}".format(checkpoint))
- state = load_checkpoint_to_cpu(checkpoint)
- for component_type, component in component_pairs:
- if isinstance(component, nn.parameter.Parameter):
- component.data.copy_(state["model"][component_type])
- else:
- component_state_dict = OrderedDict()
- for key in state["model"].keys():
- if key.startswith(component_type):
- component_subkey = key[len(component_type) + 1 :]
- component_state_dict[component_subkey] = state["model"][key]
- component.load_state_dict(component_state_dict, strict=True)
- return state
-
- @classmethod
- def share_speech_text_encoder(
- cls, speech_encoder, text_encoder, shared_layers_from_begin
- ):
- if shared_layers_from_begin > 0:
- num_text_encoder_layers = len(text_encoder.layers)
- assert len(speech_encoder.layers) >= shared_layers_from_begin
- assert num_text_encoder_layers >= shared_layers_from_begin
- assert len(speech_encoder.layers) >= num_text_encoder_layers
- for i, ly in enumerate(
- speech_encoder.layers[
- -num_text_encoder_layers : -num_text_encoder_layers
- + shared_layers_from_begin
- ]
- ):
- assert isinstance(text_encoder.layers[i], type(ly))
- text_encoder.layers[i] = ly
-
-
-@register_model_architecture(
- "dual_input_wav_transformer", "dualinputs2twavtransformer_base"
-)
-def dualinputs2twavtransformer_base(args):
- # speech masking
- args.dropout_input = getattr(args, "dropout_input", 0)
- args.dropout_features = getattr(args, "dropout_features", 0)
- args.speech_mask_length = getattr(args, "speech_mask_length", 10)
- args.speech_mask_prob = getattr(args, "speech_mask_prob", 0.65)
- args.speech_mask_selection = getattr(args, "speech_mask_selection", "static")
- args.speech_mask_other = getattr(args, "speech_mask_other", 0)
- args.speech_mask_min_space = getattr(args, "speech_mask_min_space", 1)
- args.speech_no_mask_overlap = getattr(args, "speech_no_mask_overlap", False)
- args.speech_conv_bias = getattr(args, "speech_conv_bias", False)
- args.speech_extractor_mode = getattr(args, "speech_extractor_mode", "default")
- args.no_strict_check_pretrain_model = getattr(
- args, "no_strict_check_pretrain_model", False
- )
-
- args.speech_mask_channel_length = getattr(args, "speech_mask_channel_length", 10)
- args.speech_mask_channel_prob = getattr(args, "speech_mask_channel_prob", 0.0)
- args.speech_mask_channel_selection = getattr(
- args, "speech_mask_channel_selection", "static"
- )
- args.speech_mask_channel_other = getattr(args, "speech_mask_channel_other", 0)
- args.speech_mask_channel_min_space = getattr(
- args, "speech_mask_channel_min_space", 1
- )
- args.speech_no_mask_channel_overlap = getattr(
- args, "speech_no_mask_channel_overlap", False
- )
- args.no_scale_feature = getattr(args, "", False)
- args.feature_grad_mult = getattr(args, "feature_grad_mult", 0.0) # 0.1
-
- # Transformer
- args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 768)
- args.encoder_ffn_embed_dim = getattr(
- args, "encoder_ffn_embed_dim", args.encoder_embed_dim * 4
- )
- args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 12)
- args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False)
- args.encoder_layerdrop = getattr(args, "encoder_layerdrop", 0.1)
- args.encoder_learned_pos = getattr(args, "encoder_learned_pos", False)
-
- args.decoder_embed_dim = getattr(args, "decoder_embed_dim", args.encoder_embed_dim)
- args.decoder_ffn_embed_dim = getattr(
- args, "decoder_ffn_embed_dim", args.encoder_ffn_embed_dim
- )
- args.decoder_attention_heads = getattr(
- args, "decoder_attention_heads", args.encoder_attention_heads
- )
- args.decoder_normalize_before = getattr(args, "decoder_normalize_before", False)
- args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False)
- args.dropout = getattr(args, "dropout", 0.1)
- args.attention_dropout = getattr(args, "attention_dropout", 0)
- args.activation_dropout = getattr(args, "activation_dropout", args.dropout)
- args.activation_fn = getattr(args, "activation_fn", "relu") # gelu?
- args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None)
- args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0)
- args.tie_adaptive_weights = getattr(args, "tie_adaptive_weights", False)
- args.share_decoder_input_output_embed = getattr(
- args, "share_decoder_input_output_embed", False
- )
- args.no_token_positional_embeddings = getattr(
- args, "no_token_positional_embeddings", False
- )
- args.adaptive_input = getattr(args, "adaptive_input", False)
- args.decoder_layerdrop = getattr(args, "decoder_layerdrop", 0.0)
- args.decoder_output_dim = getattr(
- args, "decoder_output_dim", args.decoder_embed_dim
- )
- args.layernorm_embedding = getattr(args, "layernorm_embedding", False)
- args.no_scale_embedding = getattr(args, "no_scale_embedding", False)
- args.quant_noise_pq = getattr(args, "quant_noise_pq", 0)
-
- args.speech_encoder_layers = getattr(args, "speech_encoder_layers", 12)
- args.text_encoder_layers = getattr(args, "text_encoder_layers", 6)
- args.encoder_shared_text_layers_from_begin = getattr(
- args, "encoder_shared_text_layers_from_begin", 6
- )
- args.decoder_layers = getattr(args, "decoder_layers", 6)
-
-
-@register_model_architecture(
- "dual_input_wav_transformer", "dualinputs2twavtransformer_base_stack"
-)
-def dualinputs2twavtransformer_base_stack(args):
- args.speech_encoder_layers = getattr(args, "speech_encoder_layers", 6)
- args.text_encoder_layers = getattr(args, "text_encoder_layers", 6)
- args.encoder_shared_text_layers_from_begin = getattr(
- args, "encoder_shared_text_layers_from_begin", 0
- )
- args.decoder_layers = getattr(args, "decoder_layers", 6)
- args.stacked_encoder = getattr(args, "stacked_encoder", True)
- args.layernorm_embedding = getattr(args, "layernorm_embedding", True)
- dualinputs2twavtransformer_base(args)
-
-
-@register_model_architecture(
- "dual_input_wav_transformer", "dualinputs2twavtransformer_large"
-)
-def dualinputs2twavtransformer_large(args):
- args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024)
- args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16)
- args.speech_encoder_layers = getattr(args, "speech_encoder_layers", 24)
- args.text_encoder_layers = getattr(args, "text_encoder_layers", 12)
- args.encoder_shared_text_layers_from_begin = getattr(
- args, "encoder_shared_text_layers_from_begin", 12
- )
- args.decoder_layers = getattr(args, "decoder_layers", 12)
- dualinputs2twavtransformer_base(args)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/models/s2t_dualinputxmtransformer.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/models/s2t_dualinputxmtransformer.py
deleted file mode 100644
index 7b4cbb0aa61ac2d5efa9eae7a861f219d842f516..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/models/s2t_dualinputxmtransformer.py
+++ /dev/null
@@ -1,584 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import copy
-
-import torch.nn as nn
-from fairseq import checkpoint_utils
-from fairseq import utils
-from fairseq.data.data_utils import lengths_to_padding_mask
-from fairseq.models import (
- register_model,
- register_model_architecture,
- FairseqEncoder,
-)
-from fairseq.models.speech_to_text import Wav2VecEncoderWithAdaptor
-from fairseq.models.speech_to_text.xm_transformer import (
- set_default_adaptor_args,
- set_default_w2v_encoder_args,
- need_finetuning
-)
-from fairseq.models.transformer import TransformerEncoder, TransformerDecoder
-from fairseq.models.wav2vec import TransformerSentenceEncoderLayer
-from fairseq.utils import safe_hasattr
-
-from .s2t_dualinputtransformer import (
- DualInputS2TTransformerModel,
- TransformerMultiInputDecoder,
- DualInputEncoder,
-)
-
-
-class TransformerSentenceEncoderLayerStd(TransformerSentenceEncoderLayer):
- def __init__(self, sent_enc_layer):
- super(TransformerSentenceEncoderLayer, self).__init__()
- self.embedding_dim = sent_enc_layer.embedding_dim
- self.dropout = sent_enc_layer.dropout
- self.activation_dropout = sent_enc_layer.activation_dropout
-
- # Initialize blocks
- self.activation_fn = sent_enc_layer.activation_fn
- self.self_attn = sent_enc_layer.self_attn
-
- self.dropout1 = sent_enc_layer.dropout1
- self.dropout2 = sent_enc_layer.dropout2
- self.dropout3 = sent_enc_layer.dropout3
-
- self.layer_norm_first = sent_enc_layer.layer_norm_first
-
- # layer norm associated with the self attention layer
- self.self_attn_layer_norm = sent_enc_layer.self_attn_layer_norm
- self.fc1 = sent_enc_layer.fc1
- self.fc2 = sent_enc_layer.fc2
-
- # layer norm associated with the position wise feed-forward NN
- self.final_layer_norm = sent_enc_layer.final_layer_norm
-
- def forward(
- self,
- x,
- self_attn_mask=None,
- self_attn_padding_mask=None,
- need_weights=None,
- att_args=None,
- ):
- x, attn = super().forward(
- x, self_attn_mask, self_attn_padding_mask, need_weights, att_args
- )
- return x
-
-
-# TODO retire SharedEncoder
-class SharedEncoder(FairseqEncoder):
- def __init__(self, wav2vec_enc, mbart_enc, adaptor, shared_layers):
- super().__init__(None)
- self.w2v_encoder = wav2vec_enc
- self.shared_layers = self.w2v_encoder.w2v_model.encoder.layers[-shared_layers:]
- self.w2v_encoder.w2v_model.encoder.layers = (
- self.w2v_encoder.w2v_model.encoder.layers[:-shared_layers]
- )
- self.adaptor = adaptor
- if self.shared_layers[-1].layer_norm_first:
- self.final_layer_norm = mbart_enc.layer_norm
- else:
- mbart_enc.layer_norm = None
- self.final_layer_norm = None
- shared_layer_from = len(mbart_enc.layers) - shared_layers
- if shared_layer_from < 0:
- shared_layer_from = 0
- for layer_id, layer in enumerate(self.shared_layers):
- mbart_enc.layers[
- shared_layer_from + layer_id
- ] = TransformerSentenceEncoderLayerStd(layer)
-
- def forward(self, src_tokens, src_lengths=None, **kwargs):
- padding_mask = lengths_to_padding_mask(src_lengths)
- if not padding_mask.any():
- padding_mask = None
-
- out = self.w2v_encoder.forward(src_tokens, padding_mask, tbc=True)
- x = out["encoder_out"]
- enc_padding_mask = None
- if out["encoder_padding_mask"] is not None:
- enc_padding_mask = out["encoder_padding_mask"].transpose(
- 0, 1
- ) # T X B --> B X T
-
- x, enc_padding_mask = self.adaptor(x, enc_padding_mask)
- for layer in self.shared_layers:
- x, _ = layer(x, enc_padding_mask)
- if self.final_layer_norm is not None:
- x = self.final_layer_norm(x)
-
- return {
- "encoder_out": [x], # T x B x C
- "encoder_padding_mask": [enc_padding_mask]
- if enc_padding_mask is not None
- else [], # B x T
- "encoder_embedding": [], # B x T x C
- "encoder_states": [], # List[T x B x C]
- "src_tokens": [],
- "src_lengths": [],
- }
-
-
-class StackedWav2VecEncoderWithAdaptor(FairseqEncoder):
- def __init__(
- self,
- wav2vec_enc,
- mbart_enc_layers,
- mbart_layer_norm,
- adaptor,
- drop_w2v_layers=0,
- ):
- super().__init__(None)
- self.w2v_encoder = wav2vec_enc
- self.adaptor = adaptor
- self.mbart_encoder_layers = mbart_enc_layers
- self.final_layer_norm = mbart_layer_norm
- if drop_w2v_layers > 0:
- self.w2v_encoder.w2v_model.encoder.layers = (
- self.w2v_encoder.w2v_model.encoder.layers[:-drop_w2v_layers]
- )
-
- def forward(self, src_tokens, src_lengths=None, return_all_hiddens=False, **kwargs):
- padding_mask = lengths_to_padding_mask(src_lengths)
- if not padding_mask.any():
- padding_mask = None
-
- out = self.w2v_encoder.forward(src_tokens, padding_mask, tbc=True)
- x = out["encoder_out"]
- enc_padding_mask = None
- if out["padding_mask"] is not None:
- enc_padding_mask = out["padding_mask"] # B X T
-
- x, enc_padding_mask = self.adaptor(x, enc_padding_mask)
- encoder_states = []
- for layer in self.mbart_encoder_layers:
- x = layer(x, enc_padding_mask)
- if return_all_hiddens:
- encoder_states.append(x)
- if self.final_layer_norm is not None:
- x = self.final_layer_norm(x)
-
- return {
- "encoder_out": [x], # T x B x C
- "encoder_padding_mask": [enc_padding_mask]
- if enc_padding_mask is not None
- else [], # B x T
- "encoder_embedding": [], # B x T x C
- "encoder_states": encoder_states, # List[T x B x C]
- "src_tokens": [],
- "src_lengths": [],
- }
-
- def reorder_encoder_out(self, encoder_out, new_order):
- new_encoder_out = (
- []
- if len(encoder_out["encoder_out"]) == 0
- else [x.index_select(1, new_order) for x in encoder_out["encoder_out"]]
- )
-
- new_encoder_padding_mask = (
- []
- if len(encoder_out["encoder_padding_mask"]) == 0
- else [
- x.index_select(0, new_order)
- for x in encoder_out["encoder_padding_mask"]
- ]
- )
-
- new_encoder_embedding = (
- []
- if len(encoder_out["encoder_embedding"]) == 0
- else [
- x.index_select(0, new_order) for x in encoder_out["encoder_embedding"]
- ]
- )
-
- encoder_states = encoder_out["encoder_states"]
- if len(encoder_states) > 0:
- for idx, state in enumerate(encoder_states):
- encoder_states[idx] = state.index_select(1, new_order)
-
- return {
- "encoder_out": new_encoder_out, # T x B x C
- "encoder_padding_mask": new_encoder_padding_mask, # B x T
- "encoder_embedding": new_encoder_embedding, # B x T x C
- "encoder_states": encoder_states, # List[T x B x C]
- "src_tokens": [], # B x T
- "src_lengths": [], # B x 1
- }
-
-
-# Note:
-# dual input transformer:
-# encoder: wav2vec for speech + mbart encoder for text
-# decoder: mbart decoder for text
-@register_model("dual_input_xm_transformer")
-class DualInputXMTransformerModel(DualInputS2TTransformerModel):
- def __init__(self, encoder, decoder):
- super().__init__(encoder, decoder)
-
- @staticmethod
- def add_args(parser):
- """Add model-specific arguments to the parser."""
- # wav2vec encoder
- Wav2VecEncoderWithAdaptor.add_args(parser)
- # add_decoder_args(parser)
- # mbart Transformer
- parser.add_argument(
- "--activation-fn",
- type=str,
- default="relu",
- choices=utils.get_available_activation_fns(),
- help="activation function to use",
- )
-
- parser.add_argument(
- "--mbart-dropout", type=float, metavar="D", help="dropout probability"
- )
- parser.add_argument(
- "--mbart-attention-dropout",
- type=float,
- metavar="D",
- help="dropout probability for attention weights",
- )
- parser.add_argument(
- "--mbart-activation-dropout",
- type=float,
- metavar="D",
- help="dropout probability after activation in FFN.",
- )
-
- parser.add_argument(
- "--encoder-embed-dim",
- type=int,
- metavar="N",
- help="encoder embedding dimension",
- )
- parser.add_argument(
- "--encoder-ffn-embed-dim",
- type=int,
- metavar="N",
- help="encoder embedding dimension for FFN",
- )
- parser.add_argument(
- "--encoder-layers", type=int, metavar="N", help="num encoder layers"
- )
- parser.add_argument(
- "--encoder-attention-heads",
- type=int,
- metavar="N",
- help="num encoder attention heads",
- )
- parser.add_argument(
- "--encoder-normalize-before",
- action="store_true",
- help="apply layernorm before each encoder block",
- )
-
- parser.add_argument(
- "--decoder-embed-dim",
- type=int,
- metavar="N",
- help="decoder embedding dimension",
- )
- parser.add_argument(
- "--decoder-ffn-embed-dim",
- type=int,
- metavar="N",
- help="decoder embedding dimension for FFN",
- )
- parser.add_argument(
- "--decoder-layers", type=int, metavar="N", help="num decoder layers"
- )
- parser.add_argument(
- "--decoder-attention-heads",
- type=int,
- metavar="N",
- help="num decoder attention heads",
- )
- parser.add_argument(
- "--decoder-normalize-before",
- action="store_true",
- help="apply layernorm before each decoder block",
- )
- parser.add_argument(
- "--layernorm-embedding",
- action="store_true",
- help="add layernorm to embedding",
- )
- parser.add_argument(
- "--no-scale-embedding",
- action="store_true",
- help="if True, dont scale embeddings",
- )
- parser.add_argument(
- "--load-pretrained-mbart-from",
- type=str,
- metavar="STR",
- help="model to take text encoder decoder weights from (for initialization)",
- )
- # parser.add_argument("--finetune-w2v-params", type=str, metavar="STR",
- # help="comma-separated param strings to finetune.")
- parser.add_argument(
- "--finetune-mbart-decoder-params",
- type=str,
- metavar="STR",
- help="comma-separated param strings to finetune.",
- )
- parser.add_argument(
- "--finetune-mbart-encoder-params",
- type=str,
- metavar="STR",
- help="comma-separated param strings to finetune.",
- )
- parser.add_argument(
- "--skip-encoder-projection",
- action="store_true",
- help="skip the projection layer in encoder",
- )
-
- parser.add_argument(
- "--enc-grad-mult",
- type=float,
- metavar="V",
- default=1.0,
- help="multiply enc1 and enc2 gradient by V",
- )
- parser.add_argument(
- "--enc2-along-grad-mult",
- type=float,
- metavar="V",
- default=1.0,
- help="multiply enc2 gradient by V if only enc2 is used",
- )
- parser.add_argument(
- "--text-input-cost-ratio",
- type=float,
- default=1.0,
- metavar="V",
- help="text input cost ratio relative to speech input cost",
- )
- parser.add_argument(
- "--stack-w2v-mbart-encoder",
- action="store_true",
- help="stack w2v and mbart encoder",
- )
- parser.add_argument(
- "--stack-w2v-mbart-nonorm-encoder",
- action="store_true",
- help="stack w2v and mbart encoder",
- )
- parser.add_argument(
- "--no-final-norm-decoder", action="store_true", help="no layer norm"
- )
- parser.add_argument(
- "--drop-w2v-layers",
- type=int,
- default=0,
- metavar="N",
- help="drop w2v encoder layers",
- )
-
- parser.add_argument(
- "--share-w2v-text-encoder",
- action="store_true",
- help="share w2v encoder layers with text encoder",
- )
- parser.add_argument(
- "--shared-w2v-layers",
- type=int,
- default=0,
- metavar="N",
- help="shared encoder layers from w2v encoder",
- )
-
- @classmethod
- def build_encoder(cls, args, task):
- _args = copy.deepcopy(args)
- _args.dropout = args.mbart_dropout
- _args.attention_dropout = args.mbart_attention_dropout
- _args.activation_dropout = args.mbart_activation_dropout
- _args.max_source_positions = 1024
- enc_emb = nn.Embedding(
- len(task.src_dict), _args.encoder_embed_dim, task.src_dict.pad()
- )
- text_encoder = TransformerEncoder(_args, task.src_dict, enc_emb)
- spch_encoder = Wav2VecEncoderWithAdaptor(args)
- if getattr(args, "load_pretrained_mbart_from", None):
- text_encoder = checkpoint_utils.load_pretrained_component_from_model(
- component=text_encoder, checkpoint=args.load_pretrained_mbart_from
- )
- if getattr(args, "stack_w2v_mbart_encoder", False):
- assert getattr(args, "share_w2v_text_encoder", False) is False
- spch_encoder = StackedWav2VecEncoderWithAdaptor(
- spch_encoder.w2v_encoder,
- text_encoder.layers,
- text_encoder.layer_norm,
- spch_encoder.adaptor,
- args.drop_w2v_layers,
- )
- elif getattr(args, "stack_w2v_mbart_nonorm_encoder", False):
- text_encoder.layer_norm = None
- spch_encoder = StackedWav2VecEncoderWithAdaptor(
- spch_encoder.w2v_encoder,
- text_encoder.layers,
- text_encoder.layer_norm,
- spch_encoder.adaptor,
- args.drop_w2v_layers,
- )
- elif getattr(args, "share_w2v_text_encoder", False):
- spch_encoder = SharedEncoder(
- spch_encoder.w2v_encoder,
- text_encoder,
- spch_encoder.adaptor,
- args.shared_w2v_layers,
- )
-
- for k, p in spch_encoder.named_parameters():
- # Freeze pretrained models by default
- if safe_hasattr(
- args, "finetune_w2v_params"
- ) and need_finetuning(args.finetune_w2v_params, k):
- p.requires_grad = True
- else:
- p.requires_grad = False
- for k, p in text_encoder.named_parameters():
- # Freeze pretrained models by default
- if safe_hasattr(
- args, "finetune_mbart_encoder_params"
- ) and need_finetuning(
- args.finetune_mbart_encoder_params, k
- ):
- p.requires_grad = True
- else:
- p.requires_grad = False
- cross_attentive_loss_before_last_layer = (
- 0 if getattr(args, "attentive_cost_regularization", 0.0) > 0.0 else -1
- )
- encoder = DualInputEncoder(
- args,
- spch_encoder,
- text_encoder,
- task.src_dict,
- cross_attentive_loss_before_last_layer,
- )
- return encoder
-
- @classmethod
- def build_decoder(cls, args, task):
- _args = copy.deepcopy(args)
- _args.dropout = args.mbart_dropout
- _args.attention_dropout = args.mbart_attention_dropout
- _args.activation_dropout = args.mbart_activation_dropout
- _args.max_target_positions = 1024
- dec_emb = nn.Embedding(
- len(task.tgt_dict), _args.encoder_embed_dim, task.tgt_dict.pad()
- )
- decoder = TransformerDecoder(_args, task.tgt_dict, dec_emb)
- if getattr(args, "load_pretrained_mbart_from", None):
- decoder = checkpoint_utils.load_pretrained_component_from_model(
- component=decoder, checkpoint=args.load_pretrained_mbart_from
- )
- if getattr(args, "no_final_norm_decoder", False):
- decoder.layer_norm = None
- for k, p in decoder.named_parameters():
- # Freeze pretrained models by default
- if safe_hasattr(
- args, "finetune_mbart_decoder_params"
- ) and need_finetuning(
- args.finetune_mbart_decoder_params, k
- ):
- p.requires_grad = True
- else:
- p.requires_grad = False
-
- compute_cross_attentive_loss = (
- True if getattr(args, "attentive_cost_regularization", 0.0) > 0.0 else False
- )
- cross_attentive_loss_without_norm = getattr(
- args, "attentive_cost_without_normalize", False
- )
- cross_attentive_loss_reverse = (
- False # getattr(args, "attentive_cost_reverse", False)
- )
- decoder = TransformerMultiInputDecoder(
- dictionary=task.target_dictionary,
- spch_decoder=decoder,
- text_decoder=decoder,
- compute_cross_attentive_loss=compute_cross_attentive_loss,
- cross_attentive_loss_with_norm=True
- if not cross_attentive_loss_without_norm
- else False,
- cross_attentive_loss_reverse=cross_attentive_loss_reverse,
- )
- return decoder
-
- @classmethod
- def build_model(cls, args, task):
- """Build a new model instance."""
- # make sure that all args are properly defaulted
- # (in case there are any new ones)
- dualinputxmtransformer_base(args)
-
- encoder = cls.build_encoder(args, task)
- decoder = cls.build_decoder(args, task)
- return cls(encoder, decoder)
-
-
-@register_model_architecture("dual_input_xm_transformer", "dualinputxmtransformer_base")
-def dualinputxmtransformer_base(args):
- # wav2vec encoder
- set_default_w2v_encoder_args(args)
- set_default_adaptor_args(args)
-
- # mbart model
- args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024)
- args.encoder_ffn_embed_dim = getattr(
- args, "encoder_ffn_embed_dim", 4 * args.encoder_embed_dim
- )
- args.encoder_layers = getattr(args, "encoder_layers", 12)
- args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16)
- args.encoder_normalize_before = getattr(args, "encoder_normalize_before", True)
- args.encoder_layerdrop = getattr(args, "encoder_layerdrop", 0)
- args.encoder_learned_pos = getattr(args, "encoder_learned_pos", True)
-
- args.decoder_embed_path = getattr(args, "decoder_embed_path", None)
- args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 1024)
- args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 4 * 1024)
- args.decoder_layers = getattr(args, "decoder_layers", 12)
- args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 16)
- args.decoder_normalize_before = getattr(args, "decoder_normalize_before", True)
- args.decoder_learned_pos = getattr(args, "decoder_learned_pos", True)
- args.decoder_layerdrop = getattr(args, "decoder_layerdrop", 0.0)
-
- args.adaptive_input = getattr(args, "adaptive_input", False)
-
- args.mbart_attention_dropout = getattr(args, "mbart_attention_dropout", 0.0)
- args.mbart_activation_dropout = getattr(args, "mbart_activation_dropout", 0.0)
- args.mbart_dropout = getattr(args, "mbart_dropout", 0.1)
- args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None)
- args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0)
- args.share_decoder_input_output_embed = getattr(
- args, "share_decoder_input_output_embed", True
- )
- args.no_token_positional_embeddings = getattr(
- args, "no_token_positional_embeddings", False
- )
-
- args.decoder_output_dim = getattr(
- args, "decoder_output_dim", args.decoder_embed_dim
- )
- args.decoder_input_dim = getattr(args, "decoder_input_dim", args.decoder_embed_dim)
-
- args.no_scale_embedding = getattr(args, "no_scale_embedding", False)
- args.quant_noise_pq = getattr(args, "quant_noise_pq", 0)
- args.layernorm_embedding = getattr(args, "layernorm_embedding", True)
-
- args.activation_fn = getattr(args, "activation_fn", "gelu")
- args.pooler_activation_fn = getattr(args, "pooler_activation_fn", "tanh")
- args.pooler_dropout = getattr(args, "pooler_dropout", 0.0)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/scripts/convert_model.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/scripts/convert_model.py
deleted file mode 100644
index 4923af1312b13ee54bbaaa99e536d31a053ae478..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/scripts/convert_model.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import re
-from collections import OrderedDict
-
-import torch
-
-from fairseq.file_io import PathManager
-
-
-def is_update(param_name, module_name):
- if module_name in param_name:
- return True
- return False
-
-
-def load_checkpoint(src_cpt):
-
- with PathManager.open(src_cpt, "rb") as f:
- state_src = torch.load(
- f,
- map_location=(
- lambda s, _: torch.serialization.default_restore_location(s, "cpu")
- ),
- )
-
- return state_src
-
-
-def save_checkpoint(tgt_cpt, states):
-
- with PathManager.open(tgt_cpt, "wb") as f:
- torch.save(
- states,
- f,
- )
-
-
-# convert the pre-trained model into bart model
-def main():
- parser = argparse.ArgumentParser()
- # fmt: off
- parser.add_argument('--input-model', required=True,
- help='Input checkpoint file path.')
- parser.add_argument('--output-model', required=True,
- help='output checkpoint file path.')
- # fmt: on
- args = parser.parse_args()
- print(args)
-
- states = load_checkpoint(args.input_model)
- model = states["model"]
- new_model = OrderedDict()
- for key in model.keys():
- if re.search("^encoder.text_encoder", key):
- new_key = re.sub("encoder.text_encoder", "encoder", key)
- new_model[new_key] = model[key]
- elif re.search("^decoder.text_decoder", key):
- new_key = re.sub("decoder.text_decoder", "decoder", key)
- new_model[new_key] = model[key]
- states["model"] = new_model
- save_checkpoint(args.output_model, states)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/scripts/g2p_encode.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/scripts/g2p_encode.py
deleted file mode 100644
index 9db779396f492e3f71b08d7b895beb81d8e46bc9..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/scripts/g2p_encode.py
+++ /dev/null
@@ -1,191 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import itertools
-import logging
-import re
-import time
-
-from g2p_en import G2p
-
-logger = logging.getLogger(__name__)
-
-FAIL_SENT = "FAILED_SENTENCE"
-
-
-def parse():
- parser = argparse.ArgumentParser()
- parser.add_argument("--data-path", type=str, required=True)
- parser.add_argument("--out-path", type=str, required=True)
- parser.add_argument("--lower-case", action="store_true")
- parser.add_argument("--do-filter", action="store_true")
- parser.add_argument("--use-word-start", action="store_true")
- parser.add_argument("--dup-vowel", default=1, type=int)
- parser.add_argument("--dup-consonant", default=1, type=int)
- parser.add_argument("--no-punc", action="store_true")
- parser.add_argument("--reserve-word", type=str, default="")
- parser.add_argument(
- "--reserve-first-column",
- action="store_true",
- help="first column is sentence id",
- )
- ###
- parser.add_argument("--parallel-process-num", default=1, type=int)
- parser.add_argument("--logdir", default="")
- args = parser.parse_args()
- return args
-
-
-def process_sent(sent, g2p, res_wrds, args):
- sents = pre_process_sent(sent, args.do_filter, args.lower_case, res_wrds)
- pho_seqs = [do_g2p(g2p, s, res_wrds, i == 0) for i, s in enumerate(sents)]
- pho_seq = (
- [FAIL_SENT]
- if [FAIL_SENT] in pho_seqs
- else list(itertools.chain.from_iterable(pho_seqs))
- )
- if args.no_punc:
- pho_seq = remove_punc(pho_seq)
- if args.dup_vowel > 1 or args.dup_consonant > 1:
- pho_seq = dup_pho(pho_seq, args.dup_vowel, args.dup_consonant)
- if args.use_word_start:
- pho_seq = add_word_start(pho_seq)
- return " ".join(pho_seq)
-
-
-def remove_punc(sent):
- ns = []
- regex = re.compile("[^a-zA-Z0-9 ]")
- for p in sent:
- if (not regex.search(p)) or p == FAIL_SENT:
- if p == " " and (len(ns) == 0 or ns[-1] == " "):
- continue
- ns.append(p)
- return ns
-
-
-def do_g2p(g2p, sent, res_wrds, is_first_sent):
- if sent in res_wrds:
- pho_seq = [res_wrds[sent]]
- else:
- pho_seq = g2p(sent)
- if not is_first_sent:
- pho_seq = [" "] + pho_seq # add space to separate
- return pho_seq
-
-
-def pre_process_sent(sent, do_filter, lower_case, res_wrds):
- if do_filter:
- sent = re.sub("-", " ", sent)
- sent = re.sub("—", " ", sent)
- if len(res_wrds) > 0:
- wrds = sent.split()
- wrds = ["SPLIT_ME " + w + " SPLIT_ME" if w in res_wrds else w for w in wrds]
- sents = [x.strip() for x in " ".join(wrds).split("SPLIT_ME") if x.strip() != ""]
- else:
- sents = [sent]
- if lower_case:
- sents = [s.lower() if s not in res_wrds else s for s in sents]
- return sents
-
-
-def dup_pho(sent, dup_v_num, dup_c_num):
- """
- duplicate phoneme defined as cmudict
- http://www.speech.cs.cmu.edu/cgi-bin/cmudict
- """
- if dup_v_num == 1 and dup_c_num == 1:
- return sent
- ns = []
- for p in sent:
- ns.append(p)
- if re.search(r"\d$", p):
- for i in range(1, dup_v_num):
- ns.append(f"{p}-{i}P")
- elif re.search(r"\w", p):
- for i in range(1, dup_c_num):
- ns.append(f"{p}-{i}P")
- return ns
-
-
-def add_word_start(sent):
- ns = []
- do_add = True
- ws = "▁"
- for p in sent:
- if do_add:
- p = ws + p
- do_add = False
- if p == " ":
- do_add = True
- else:
- ns.append(p)
- return ns
-
-
-def load_reserve_word(reserve_word):
- if reserve_word == "":
- return []
- with open(reserve_word, "r") as fp:
- res_wrds = [x.strip().split() for x in fp.readlines() if x.strip() != ""]
- assert sum([0 if len(x) == 2 else 1 for x in res_wrds]) == 0
- res_wrds = dict(res_wrds)
- return res_wrds
-
-
-def process_sents(sents, args):
- g2p = G2p()
- out_sents = []
- res_wrds = load_reserve_word(args.reserve_word)
- for sent in sents:
- col1 = ""
- if args.reserve_first_column:
- col1, sent = sent.split(None, 1)
- sent = process_sent(sent, g2p, res_wrds, args)
- if args.reserve_first_column and col1 != "":
- sent = f"{col1} {sent}"
- out_sents.append(sent)
- return out_sents
-
-
-def main():
- args = parse()
- out_sents = []
- with open(args.data_path, "r") as fp:
- sent_list = [x.strip() for x in fp.readlines()]
- if args.parallel_process_num > 1:
- try:
- import submitit
- except ImportError:
- logger.warn(
- "submitit is not found and only one job is used to process the data"
- )
- submitit = None
-
- if args.parallel_process_num == 1 or submitit is None:
- out_sents = process_sents(sent_list, args)
- else:
- # process sentences with parallel computation
- lsize = len(sent_list) // args.parallel_process_num + 1
- executor = submitit.AutoExecutor(folder=args.logdir)
- executor.update_parameters(timeout_min=1000, cpus_per_task=4)
- jobs = []
- for i in range(args.parallel_process_num):
- job = executor.submit(
- process_sents, sent_list[lsize * i : lsize * (i + 1)], args
- )
- jobs.append(job)
- is_running = True
- while is_running:
- time.sleep(5)
- is_running = sum([job.done() for job in jobs]) < len(jobs)
- out_sents = list(itertools.chain.from_iterable([job.result() for job in jobs]))
- with open(args.out_path, "w") as fp:
- fp.write("\n".join(out_sents) + "\n")
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/tasks/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/tasks/__init__.py
deleted file mode 100644
index 5fc5d9e21b2b5d272bd67610958efbdb1eecb158..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/tasks/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import importlib
-import os
-
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/tasks/pair_denoising.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/tasks/pair_denoising.py
deleted file mode 100644
index b13b1e5ae362e60e23bac11f1d985ae3a744b236..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/tasks/pair_denoising.py
+++ /dev/null
@@ -1,447 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import itertools
-import logging
-import os
-import re
-
-import numpy as np
-import torch
-
-from examples.speech_text_joint_to_text.data.pair_denoising_dataset import (
- LanguagePairDenoisingDataset,
-)
-from fairseq import utils
-from fairseq.data import (
- ConcatDataset,
- Dictionary,
- LanguagePairDataset,
- ResamplingDataset,
- TransformEosConcatLangPairDataset,
- TransformEosLangPairDataset,
- data_utils,
- indexed_dataset,
-)
-from fairseq.data.encoders.utils import get_whole_word_mask
-from fairseq.tasks import register_task
-from fairseq.tasks.translation import TranslationTask
-
-logger = logging.getLogger(__name__)
-
-
-def gen_whole_word_mask(args, dictionary):
- def is_beginning_of_word(i):
- if i < dictionary.nspecial:
- # special elements are always considered beginnings
- return True
- tok = dictionary[i]
- if tok.startswith("madeupword"):
- return True
-
- if tok in ["", "", "", ""]:
- return True
- return tok.startswith("\u2581")
-
- if args.use_mask_whole_words:
- mask_whole_words = torch.ByteTensor(
- list(map(is_beginning_of_word, range(len(dictionary))))
- )
- else:
- # it will mask every token as word leading token, since no bpe model is loaded for phoneme tokens
- return get_whole_word_mask(args, dictionary)
- return mask_whole_words
-
-
-@register_task("paired_denoising")
-class PairedDenoisingTask(TranslationTask):
-
- LANG_TAG_TEMPLATE = "" # Tag for language (target)
-
- @staticmethod
- def add_args(parser):
- TranslationTask.add_args(parser)
- # bart setting
- parser.add_argument(
- "--mask",
- default=0.0,
- type=float,
- help="fraction of words/subwords that will be masked",
- )
- parser.add_argument(
- "--mask-random",
- default=0.0,
- type=float,
- help="instead of using [MASK], use random token this often",
- )
- parser.add_argument(
- "--insert",
- default=0.0,
- type=float,
- help="insert this percentage of additional random tokens",
- )
- parser.add_argument(
- "--poisson-lambda",
- default=3.0,
- type=float,
- help="randomly shuffle sentences for this proportion of inputs",
- )
- parser.add_argument(
- "--mask-length",
- default="span-poisson",
- type=str,
- choices=["subword", "word", "span-poisson"],
- help="mask length to choose",
- )
- parser.add_argument(
- "--replace-length",
- default=1,
- type=int,
- help="when masking N tokens, replace with 0, 1, or N tokens (use -1 for N)",
- )
-
- # multi-lingual
- parser.add_argument(
- "--multilang-sampling-alpha",
- type=float,
- default=1.0,
- help="smoothing alpha for sample ratios across multiple datasets",
- )
- parser.add_argument(
- "--lang-pairs",
- default="",
- metavar="PAIRS",
- help="comma-separated list of language pairs (in training order): phnen-en,phnfr-fr,phnit-it. Do masking",
- )
- parser.add_argument(
- "--lang-pairs-bitext",
- default="",
- metavar="PAIRS",
- help="comma-separated list of language pairs (in training order): en-de,en-fr,de-fr. No masking",
- )
- parser.add_argument("--add-src-lang-token", default=False, action="store_true")
- parser.add_argument("--add-tgt-lang-token", default=False, action="store_true")
- parser.add_argument(
- "--no-whole-word-mask-langs",
- type=str,
- default="",
- metavar="N",
- help="languages without spacing between words dont support whole word masking",
- )
- parser.add_argument(
- "--use-mask-whole-words", default=False, action="store_true"
- )
-
- @classmethod
- def setup_task(cls, args, **kwargs):
- """Setup the task."""
- paths = args.data.split(":")
- assert len(paths) > 0
- src_dict = Dictionary.load(
- os.path.join(paths[0], "src_dict.txt")
- ) # assume all languages share a source dictionary
- tgt_dict = Dictionary.load(
- os.path.join(paths[0], "tgt_dict.txt")
- ) # assume all languages share a target dictionary
-
- lang_pairs = args.lang_pairs + "," + args.lang_pairs_bitext
- lang_pairs = re.sub(",$", "", re.sub("^,", "", lang_pairs))
- src_langs = [lp.split("-")[0] for lp in lang_pairs.split(",")]
- tgt_langs = [lp.split("-")[1] for lp in lang_pairs.split(",")]
-
- if args.add_src_lang_token:
- for lang in src_langs:
- assert (
- src_dict.index(PairedDenoisingTask.LANG_TAG_TEMPLATE.format(lang))
- != src_dict.unk()
- )
- if args.add_tgt_lang_token:
- for lang in tgt_langs:
- assert (
- tgt_dict.index(PairedDenoisingTask.LANG_TAG_TEMPLATE.format(lang))
- != tgt_dict.unk()
- )
-
- logger.info("source dictionary: {} types".format(len(src_dict)))
- logger.info("target dictionary: {} types".format(len(tgt_dict)))
- if not hasattr(args, "shuffle_instance"):
- args.shuffle_instance = False
- return cls(args, src_dict, tgt_dict)
-
- def __init__(self, args, src_dict, tgt_dict):
- super().__init__(args, src_dict, tgt_dict)
- # check mask token
- self.mask_idx = self.src_dict.index("")
- assert self.mask_idx != self.src_dict.unk()
- self.lang_pairs = args.lang_pairs
- self.lang_pairs_bitext = args.lang_pairs_bitext
- self.args = args
-
- @classmethod
- def language_pair_denoising_dataset(
- cls,
- data_path,
- do_mask,
- split,
- src,
- src_dict,
- tgt,
- tgt_dict,
- mask_idx,
- mask_whole_words,
- seed,
- args,
- dataset_impl,
- combine=False,
- left_pad_source=True,
- left_pad_target=False,
- max_source_positions=1024,
- max_target_positions=1024,
- shuffle=True,
- src_lang_id=None,
- tgt_lang_id=None,
- ):
- def split_exists(split, src, tgt, lang, data_path):
- filename = os.path.join(
- data_path, "{}.{}-{}.{}".format(split, src, tgt, lang)
- )
- return indexed_dataset.dataset_exists(filename, impl=dataset_impl)
-
- src_datasets = []
- tgt_datasets = []
-
- for k in itertools.count():
- split_k = split + (str(k) if k > 0 else "")
-
- # infer langcode
- if split_exists(split_k, src, tgt, src, data_path):
- prefix = os.path.join(data_path, "{}.{}-{}.".format(split_k, src, tgt))
- elif split_exists(split_k, tgt, src, src, data_path):
- prefix = os.path.join(data_path, "{}.{}-{}.".format(split_k, tgt, src))
- else:
- if k > 0:
- break
- else:
- raise FileNotFoundError(
- "Dataset not found: {} ({})".format(split, data_path)
- )
-
- src_dataset = data_utils.load_indexed_dataset(
- prefix + src, src_dict, dataset_impl
- )
- src_datasets.append(src_dataset)
-
- tgt_dataset = data_utils.load_indexed_dataset(
- prefix + tgt, tgt_dict, dataset_impl
- )
- if tgt_dataset is not None:
- tgt_datasets.append(tgt_dataset)
-
- logger.info(
- "{} {} {}-{} {} examples".format(
- data_path, split_k, src, tgt, len(src_datasets[-1])
- )
- )
-
- if not combine:
- break
-
- assert len(src_datasets) == len(tgt_datasets) or len(tgt_datasets) == 0
-
- if len(src_datasets) == 1:
- src_dataset = src_datasets[0]
- tgt_dataset = tgt_datasets[0] if len(tgt_datasets) > 0 else None
- else:
- sample_ratios = [1] * len(src_datasets)
- src_dataset = ConcatDataset(src_datasets, sample_ratios)
- if len(tgt_datasets) > 0:
- tgt_dataset = ConcatDataset(tgt_datasets, sample_ratios)
- else:
- tgt_dataset = None
-
- eos = None
-
- tgt_dataset_sizes = tgt_dataset.sizes if tgt_dataset is not None else None
- if not do_mask:
- return LanguagePairDataset(
- src_dataset,
- src_dataset.sizes,
- src_dict,
- tgt_dataset,
- tgt_dataset_sizes,
- tgt_dict,
- left_pad_source=left_pad_source,
- left_pad_target=left_pad_target,
- eos=eos,
- shuffle=shuffle,
- src_lang_id=src_lang_id,
- tgt_lang_id=tgt_lang_id,
- )
-
- return LanguagePairDenoisingDataset(
- src_dataset,
- src_dataset.sizes,
- src_dict,
- tgt_dataset,
- tgt_dataset_sizes,
- tgt_dict,
- mask_idx,
- mask_whole_words,
- seed,
- args,
- left_pad_source=left_pad_source,
- left_pad_target=left_pad_target,
- eos=eos,
- shuffle=shuffle,
- src_lang_id=src_lang_id,
- tgt_lang_id=tgt_lang_id,
- )
-
- def _get_sample_prob(self, dataset_lens):
- """
- Get smoothed sampling porbability by languages. This helps low resource
- languages by upsampling them.
- """
- prob = dataset_lens / dataset_lens.sum()
- smoothed_prob = prob ** self.args.multilang_sampling_alpha
- smoothed_prob = smoothed_prob / smoothed_prob.sum()
- return smoothed_prob
-
- def resample_datasets(self, lang_datasets, lang_pairs_all, epoch):
- # For train subset, additionally up or down sample languages.
- if self.args.multilang_sampling_alpha == 1.0:
- return lang_datasets
-
- dataset_lengths = np.array(
- [len(d) for d in lang_datasets],
- dtype=float,
- )
- sample_probs = self._get_sample_prob(dataset_lengths)
- logger.info(
- "Sample probability by language pair: {}".format(
- {
- lp: "{0:.4f}".format(sample_probs[id])
- for id, lp in enumerate(lang_pairs_all)
- }
- )
- )
- size_ratio = (sample_probs * dataset_lengths.sum()) / dataset_lengths
- logger.info(
- "Up/Down Sampling ratio by language: {}".format(
- {
- lp: "{0:.2f}".format(size_ratio[id])
- for id, lp in enumerate(lang_pairs_all)
- }
- )
- )
-
- resampled_lang_datasets = [
- ResamplingDataset(
- lang_datasets[i],
- size_ratio=size_ratio[i],
- seed=self.args.seed,
- epoch=epoch,
- replace=size_ratio[i] >= 1.0,
- )
- for i, d in enumerate(lang_datasets)
- ]
- return resampled_lang_datasets
-
- def load_dataset_only(
- self, split, lang_pairs, do_mask=True, epoch=1, combine=False
- ):
- paths = utils.split_paths(self.args.data)
- assert len(paths) > 0
- data_path = paths[(epoch - 1) % len(paths)]
-
- # TODO unk token will be considered as first word too, though it might be an unknown phoneme within a word
- # get_whole_word_mask returns a tensor (size V by 1 ) to indicate if a token is a word start token
- mask_whole_src_words = gen_whole_word_mask(self.args, self.src_dict)
- language_without_segmentations = self.args.no_whole_word_mask_langs.split(",")
- lang_datasets = []
- eos_bos = []
- lang_pairs = lang_pairs.split(",") if lang_pairs != "" else []
- assert len(lang_pairs) > 0
- for lp in lang_pairs:
- src, tgt = lp.split("-")
- lang_mask_whole_src_words = (
- mask_whole_src_words
- if src not in language_without_segmentations
- else None
- )
-
- end_token = (
- self.source_dictionary.index(
- PairedDenoisingTask.LANG_TAG_TEMPLATE.format(src)
- )
- if self.args.add_src_lang_token
- else None
- )
- bos_token = (
- self.target_dictionary.index(
- PairedDenoisingTask.LANG_TAG_TEMPLATE.format(tgt)
- )
- if self.args.add_tgt_lang_token
- else None
- )
- src_lang_id = None
-
- if self.args.add_src_lang_token or self.args.add_tgt_lang_token:
- eos_bos.append((end_token, bos_token))
-
- dataset = PairedDenoisingTask.language_pair_denoising_dataset(
- data_path,
- do_mask,
- split,
- src,
- self.source_dictionary,
- tgt,
- self.target_dictionary,
- self.mask_idx,
- lang_mask_whole_src_words,
- self.args.seed,
- self.args,
- self.args.dataset_impl,
- combine=combine,
- left_pad_source=utils.eval_bool(self.args.left_pad_source),
- left_pad_target=utils.eval_bool(self.args.left_pad_target),
- max_source_positions=self.args.max_source_positions,
- max_target_positions=self.args.max_target_positions,
- src_lang_id=src_lang_id,
- )
-
- lang_datasets.append(dataset)
-
- if len(lang_datasets) == 0:
- return
- elif len(lang_datasets) == 1:
- dataset = lang_datasets[0]
- if self.args.add_src_lang_token or self.args.add_tgt_lang_token:
- end_token, bos_token = eos_bos[0]
- dataset = TransformEosLangPairDataset(
- dataset,
- src_eos=self.source_dictionary.eos(),
- new_src_eos=end_token,
- tgt_bos=self.target_dictionary.eos(),
- new_tgt_bos=bos_token,
- )
- else:
- end_tokens = [item[0] for item in eos_bos if item[0] is not None]
- bos_tokens = [item[1] for item in eos_bos if item[1] is not None]
- lang_datasets = self.resample_datasets(lang_datasets, lang_pairs, epoch)
- dataset = TransformEosConcatLangPairDataset(
- lang_datasets,
- self.source_dictionary.eos(),
- self.target_dictionary.eos(),
- new_src_eos=end_tokens,
- new_tgt_bos=bos_tokens,
- )
- return dataset
-
- # split in (train, valid, test, ...)
- def load_dataset(self, split, epoch=1, combine=False, **kwargs):
- self.datasets[split] = self.load_dataset_only(
- split, self.lang_pairs, epoch=epoch, combine=combine
- )
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/tasks/speech_text_denoise_pretrain.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/tasks/speech_text_denoise_pretrain.py
deleted file mode 100644
index 3ad8e1c906342862d0dca052a1c81c85898af612..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/tasks/speech_text_denoise_pretrain.py
+++ /dev/null
@@ -1,654 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-import logging
-import os
-import re
-from argparse import Namespace
-from pathlib import Path
-
-from fairseq.data import ConcatDataset, Dictionary, encoders
-from fairseq.data.audio.multi_modality_dataset import (
- FileAudioDatasetWrapper,
- ModalityDatasetItem,
- MultiModalityDataset,
-)
-from fairseq.data.audio.speech_to_text_joint_dataset import (
- S2TJointDataConfig,
- SpeechToTextJointDatasetCreator,
-)
-from fairseq.data.iterators import GroupedEpochBatchIterator
-from fairseq.tasks import register_task
-
-from .pair_denoising import PairedDenoisingTask
-
-logger = logging.getLogger(__name__)
-
-
-@register_task("speech_text_joint_denoising")
-class SpeechTextJointDenoisingPreTask(PairedDenoisingTask):
- """
- Joint denoising training task for speech and text.
- """
-
- SIL_TOKEN = "sil"
-
- @classmethod
- def add_args(cls, parser):
- PairedDenoisingTask.add_args(parser)
- # set max tokens and position
- parser.add_argument(
- "--max-text-tokens",
- type=int,
- metavar="N",
- default=1024,
- help="maximum samples for encoder text input ",
- )
- parser.add_argument(
- "--max-speech-tokens",
- type=int,
- metavar="N",
- default=50000,
- help="maximum samples for encoder speech input ",
- )
- parser.add_argument(
- "--max-speech-positions",
- type=int,
- metavar="N",
- default=400,
- help="maximum tokens for per encoder text input ",
- )
-
- parser.add_argument(
- "--max-sample-size",
- type=int,
- metavar="N",
- default=32000,
- help="max sample size to crop to for batching (unsupervised speech) ",
- )
- parser.add_argument(
- "--min-sample-size",
- type=int,
- metavar="N",
- default=4000,
- help="min sample size to crop to for batching (unsupervised speech) ",
- )
-
- # set mini-batch ratio for different modalities/subtasks
- # s2p
- parser.add_argument(
- "--supervised-speech-sample-ratio",
- default="1",
- type=str,
- metavar="N",
- help="Multiple Ratio for speech dataset with transcripts ",
- )
- # s2t
- parser.add_argument(
- "--supervised-speech-s2s-sample-ratio",
- default="1",
- type=str,
- metavar="N",
- help="Multiple Ratio for speech dataset with transcripts ",
- )
- # ssl
- parser.add_argument(
- "--unsupervised-speech-sample-ratio",
- default="1",
- type=str,
- metavar="N",
- help="Multiple Ratio for speech dataset without transcripts ",
- )
- # t2t with monolingual data (masking)
- parser.add_argument(
- "--text-sample-ratio",
- default="1",
- type=str,
- metavar="N",
- help="Multiple Ratio for text set ",
- )
- # t2t with parallel data (no masking)
- parser.add_argument(
- "--bitext-sample-ratio",
- default="1",
- type=str,
- metavar="N",
- help="Multiple Ratio for text set (bitext) ",
- )
- # train_subset = "train", 'valid' or so
- # parallel data is loaded according to string lang_pairs and lang_pairs_no_mask from args.data
- # (un)supervised speech is loaded from args.(un)sup_speech_{train,valid}_subset
- parser.add_argument(
- "--sup-speech-data", default="", help="path to supervised speech data"
- )
- parser.add_argument(
- "--sup-speech-train-subset",
- default="",
- help="supervised speech training subsets",
- )
- parser.add_argument(
- "--sup-speech-valid-subset",
- default="",
- help="supervised speech validation subsets",
- )
- parser.add_argument(
- "--config-yaml",
- default="config.yaml",
- help="supervised speech configuration yaml file",
- )
- parser.add_argument(
- "--sup-speech-s2s-data", default="", help="path to supervised speech data"
- )
- parser.add_argument(
- "--sup-speech-s2s-train-subset",
- default="",
- help="supervised speech training subsets",
- )
- parser.add_argument(
- "--sup-speech-s2s-valid-subset",
- default="",
- help="supervised speech validation subsets",
- )
- parser.add_argument(
- "--config-s2s-yaml",
- default="config.yaml",
- help="supervised speech configuration yaml file",
- )
- parser.add_argument(
- "--unsup-speech-train-data",
- default="",
- help="path to unsupervised speech training data (tsv)",
- )
- parser.add_argument(
- "--unsup-speech-valid-data",
- default="",
- help="path to unsupervised speech valid data (tsv)",
- )
- parser.add_argument(
- "--sample-rate",
- type=int,
- metavar="N",
- default=16000,
- help="input audio sampling rate",
- )
- parser.add_argument(
- "--no-emb-update-unsup",
- default=False,
- action="store_true",
- help="no update for output embedding during unsupervised_speech mode",
- )
- parser.add_argument("--same-data-update", default=False, action="store_true")
-
- # used for sup_speech_ali
- parser.add_argument(
- "--use-sup-speech-ctc",
- default=False,
- action="store_true",
- help="use speech_sup_ctc instead of speech_sup_ali",
- )
-
- @classmethod
- def setup_task(cls, args, **kwargs):
- """Setup the task."""
- paths = args.data.split(":")
- assert len(paths) > 0
- src_dict = Dictionary.load(
- os.path.join(paths[0], "src_dict.txt")
- ) # assume all languages share a source dictionary
- tgt_dict = Dictionary.load(
- os.path.join(paths[0], "tgt_dict.txt")
- ) # assume all languages share a target dictionary
-
- lang_pairs = args.lang_pairs + "," + args.lang_pairs_bitext
- lang_pairs = re.sub(",$", "", re.sub("^,", "", lang_pairs))
- if lang_pairs != "":
- src_langs = [lp.split("-")[0] for lp in lang_pairs.split(",")]
- tgt_langs = [lp.split("-")[1] for lp in lang_pairs.split(",")]
- else:
- src_langs = []
- tgt_langs = []
-
- if args.add_src_lang_token:
- for lang in src_langs:
- assert (
- src_dict.index(PairedDenoisingTask.LANG_TAG_TEMPLATE.format(lang))
- != src_dict.unk()
- )
- if args.add_tgt_lang_token:
- for lang in tgt_langs:
- assert (
- tgt_dict.index(PairedDenoisingTask.LANG_TAG_TEMPLATE.format(lang))
- != tgt_dict.unk()
- )
-
- logger.info("source dictionary: {} types".format(len(src_dict)))
- logger.info("target dictionary: {} types".format(len(tgt_dict)))
- if not hasattr(args, "shuffle_instance"):
- args.shuffle_instance = False
- return cls(args, src_dict, tgt_dict)
-
- def __init__(self, args, src_dict, tgt_dict):
- super().__init__(args, src_dict, tgt_dict)
- self.data_cfg = S2TJointDataConfig(
- Path(args.sup_speech_data) / args.config_yaml
- )
- logger.info(
- f"load supervised speech data configure from {Path(args.sup_speech_data) / args.config_yaml}"
- )
- self.data_s2s_cfg = (
- S2TJointDataConfig(Path(args.sup_speech_s2s_data) / args.config_s2s_yaml)
- if args.sup_speech_s2s_train_subset != ""
- else None
- )
- if self.data_s2s_cfg is not None:
- logger.info(
- f"load supervised sequece to sequence speech data configure from {Path(args.sup_speech_s2s_data) / args.config_yaml}"
- )
-
- def parse_data_ratio(sample_ratio):
- ratios = sample_ratio.split(",")
- if len(ratios) == 1:
- return [float(ratios[0])]
- epoch_ratios = []
- for item in ratios:
- ep, r = item.split(":")
- ep = int(ep)
- r = float(r)
- assert ep > 0 # epoch is 1 based
- assert ep >= len(epoch_ratios)
-
- if len(epoch_ratios) == 0:
- epoch_ratios.append(
- r
- ) # epoch_ratios[0] is not used, but we still set it to the first value to make thing simple.
- while len(epoch_ratios) < ep:
- epoch_ratios.append(epoch_ratios[-1])
- epoch_ratios.append(r)
- return epoch_ratios
-
- self.sup_ratio = parse_data_ratio(args.supervised_speech_sample_ratio)
- self.sup_s2s_ratio = parse_data_ratio(args.supervised_speech_s2s_sample_ratio)
- self.text_ratio = parse_data_ratio(args.text_sample_ratio)
- self.bitext_ratio = parse_data_ratio(args.bitext_sample_ratio)
- self.unsup_ratio = parse_data_ratio(args.unsupervised_speech_sample_ratio)
- self.sample_mode = None
-
- def build_model(self, args):
- args.input_feat_per_channel = self.data_cfg.input_feat_per_channel
- args.input_channels = self.data_cfg.input_channels
- return super().build_model(args)
-
- def build_tokenizer(self, data_cfg, msg=""):
- logger.info(f"pre-tokenizer {msg}: {data_cfg.pre_tokenizer}")
- return encoders.build_tokenizer(Namespace(**data_cfg.pre_tokenizer))
-
- def build_bpe(self, data_cfg, msg=""):
- logger.info(f"tokenizer {msg}: {data_cfg.bpe_tokenizer}")
- return encoders.build_bpe(Namespace(**data_cfg.bpe_tokenizer))
-
- @classmethod
- def resolve_data_type(cls, split, use_sup_speech_ctc):
- if len(split.split("_")) == 1:
- # default case, train or valid
- is_train = split
- dtype = "text"
- else:
- is_train, dtype = split.split("_", 1)
- is_train = True if is_train == "train" else False
- if dtype == "sup_speech":
- dtype = "sup_speech_ctc" if use_sup_speech_ctc else "sup_speech_ali"
- assert dtype in (
- "text",
- "bitext",
- "sup_speech_ali",
- "sup_speech_s2s",
- "unsup_speech",
- "sup_speech_ctc",
- ), f"failed resolving {split} (it resulted into: {dtype} ; is_train={is_train})"
- return is_train, dtype
-
- def create_modalitydatasetitem(self, dtype, dataset):
- dsitem = None
- if dtype in ("text", "bitext"):
- dsitem = ModalityDatasetItem(
- dtype,
- dataset,
- (self.args.max_source_positions, self.args.max_target_positions),
- self.args.max_text_tokens,
- self.args.batch_size,
- )
- elif dtype in ("sup_speech_ctc", "sup_speech_ali", "sup_speech_s2s"):
- dsitem = ModalityDatasetItem(
- dtype,
- dataset,
- (self.args.max_speech_positions, self.args.max_target_positions),
- self.args.max_speech_tokens,
- self.args.batch_size,
- )
- elif dtype == "unsup_speech":
- dsitem = ModalityDatasetItem(
- dtype, dataset, 1e8, self.args.max_speech_tokens, self.args.batch_size
- )
- else:
- raise ValueError(f"{dtype} is not supported")
- return dsitem
-
- def load_dataset(self, split, epoch=1, combine=False, **kwargs):
- def _get_sup_src_tgt_dict(src_dict, tgt_dict, use_s2s_sup_decoder):
- if use_s2s_sup_decoder:
- return None, tgt_dict
- # use src_dict as tgt_dict here, since we use source dictionary as target for forcealignment
- return None, src_dict
-
- is_train, dtype = self.resolve_data_type(split, self.args.use_sup_speech_ctc)
-
- # Note we use --add-tgt-lang-token instead of data_cfg.prepend_tgt_lang_tag_no_change to set target language tag in the text dataset
- # Verify add_tgt_lang_token and prepend_tgt_lang_tag_no_change are same
-
- # Note we use --multilang-sampling-alpha instead of data_cfg.sampling_text_alpha to set text data sampling
- if is_train:
- msets = []
- # train split, load everything into one
- if self.lang_pairs != "":
- text_dataset = self.load_dataset_only(
- "train", self.lang_pairs, epoch=epoch, combine=combine
- )
- dsitem = self.create_modalitydatasetitem("text", text_dataset)
- msets.append(dsitem)
- if self.lang_pairs_bitext != "": # load bitext
- bitext_dataset = self.load_dataset_only(
- "train_bitext",
- self.lang_pairs_bitext,
- do_mask=False,
- epoch=epoch,
- combine=combine,
- )
- dsitem = self.create_modalitydatasetitem("bitext", bitext_dataset)
- msets.append(dsitem)
- if self.args.sup_speech_train_subset != "":
- pre_tokenizer = self.build_tokenizer(self.data_cfg)
- bpe_tokenizer = self.build_bpe(self.data_cfg)
-
- append_eos = True
- sup_speech_type = "sup_speech_ali"
- if self.args.use_sup_speech_ctc:
- # CTC mode
- sup_speech_type = "sup_speech_ctc"
- append_eos = False # CTC doesn't need eos in the target
-
- src_dict, tgt_dict = _get_sup_src_tgt_dict(
- self.src_dict, self.tgt_dict, False
- )
- sup_speech_dataset = SpeechToTextJointDatasetCreator.from_tsv(
- self.args.sup_speech_data,
- self.data_cfg,
- self.args.sup_speech_train_subset,
- tgt_dict=tgt_dict,
- src_dict=src_dict,
- pre_tokenizer=pre_tokenizer,
- bpe_tokenizer=bpe_tokenizer,
- src_pre_tokenizer=None,
- src_bpe_tokenizer=None,
- is_train_split=is_train,
- epoch=epoch,
- seed=self.args.seed,
- append_eos=append_eos,
- )
- dsitem = self.create_modalitydatasetitem(
- sup_speech_type, sup_speech_dataset
- )
- msets.append(dsitem)
-
- if self.args.sup_speech_s2s_train_subset != "":
- pre_tokenizer = self.build_tokenizer(self.data_s2s_cfg, msg="(s2s)")
- bpe_tokenizer = self.build_bpe(self.data_s2s_cfg, msg="(s2s)")
-
- # make sure self.data_cfg.prepend_tgt_lang_tag_no_change == self.args.add_tgt_lang_token
- src_dict, tgt_dict = _get_sup_src_tgt_dict(
- self.src_dict, self.tgt_dict, True
- )
- sup_speech_s2s_dataset = SpeechToTextJointDatasetCreator.from_tsv(
- self.args.sup_speech_s2s_data,
- self.data_s2s_cfg,
- self.args.sup_speech_s2s_train_subset,
- tgt_dict=tgt_dict,
- src_dict=src_dict,
- pre_tokenizer=pre_tokenizer,
- bpe_tokenizer=bpe_tokenizer,
- src_pre_tokenizer=None,
- src_bpe_tokenizer=None,
- is_train_split=is_train,
- epoch=epoch,
- seed=self.args.seed,
- )
- dsitem = self.create_modalitydatasetitem(
- "sup_speech_s2s", sup_speech_s2s_dataset
- )
- msets.append(dsitem)
- if self.args.unsup_speech_train_data != "":
- unsup_speech_dataset = FileAudioDatasetWrapper(
- self.args.unsup_speech_train_data,
- self.args.sample_rate,
- max_sample_size=self.args.max_sample_size,
- min_sample_size=self.args.min_sample_size,
- normalize=False,
- )
- dsitem = self.create_modalitydatasetitem(
- "unsup_speech", unsup_speech_dataset
- )
- msets.append(dsitem)
-
- pre_train_dataset = MultiModalityDataset(msets)
- self.datasets[split] = pre_train_dataset
- else: # validation split, load them for each type of data
- if dtype == "text":
- text_dataset = self.load_dataset_only(
- split, self.lang_pairs, epoch=epoch, combine=combine
- )
- dsitem = self.create_modalitydatasetitem("text", text_dataset)
- self.datasets[split] = MultiModalityDataset([dsitem])
- elif dtype == "bitext":
- bitext_dataset = self.load_dataset_only(
- split,
- self.lang_pairs_bitext,
- do_mask=False,
- epoch=epoch,
- combine=combine,
- )
- dsitem = self.create_modalitydatasetitem("bitext", bitext_dataset)
- self.datasets[split] = MultiModalityDataset([dsitem])
-
- elif dtype in ("sup_speech_ctc", "sup_speech_ali"):
- assert self.args.sup_speech_valid_subset != ""
- pre_tokenizer = self.build_tokenizer(self.data_cfg)
- bpe_tokenizer = self.build_bpe(self.data_cfg)
- append_eos = True
- if dtype == "sup_speech_ctc":
- # CTC mode
- append_eos = False # CTC doesn't need eos
- assert self.args.use_sup_speech_ctc
-
- datasets = []
- for split_name in self.args.sup_speech_valid_subset.split(","):
- src_dict, tgt_dict = _get_sup_src_tgt_dict(
- self.src_dict, self.tgt_dict, False
- )
- datasets.append(
- SpeechToTextJointDatasetCreator.from_tsv(
- self.args.sup_speech_data,
- self.data_cfg,
- split_name,
- tgt_dict=tgt_dict,
- src_dict=src_dict,
- pre_tokenizer=pre_tokenizer,
- bpe_tokenizer=bpe_tokenizer,
- src_pre_tokenizer=None,
- src_bpe_tokenizer=None,
- is_train_split=is_train,
- epoch=epoch,
- seed=self.args.seed,
- append_eos=append_eos,
- )
- )
-
- dset = datasets[0] if len(datasets) == 1 else ConcatDataset(datasets)
- dsitem = self.create_modalitydatasetitem(dtype, dset)
- self.datasets[split] = MultiModalityDataset([dsitem])
-
- elif dtype == "sup_speech_s2s":
- assert self.args.sup_speech_s2s_valid_subset != ""
- pre_tokenizer = self.build_tokenizer(self.data_s2s_cfg)
- bpe_tokenizer = self.build_bpe(self.data_s2s_cfg)
- datasets = []
- for split_name in self.args.sup_speech_s2s_valid_subset.split(","):
- src_dict, tgt_dict = _get_sup_src_tgt_dict(
- self.src_dict, self.tgt_dict, True
- )
- datasets.append(
- SpeechToTextJointDatasetCreator.from_tsv(
- self.args.sup_speech_s2s_data,
- self.data_s2s_cfg,
- split_name,
- tgt_dict=tgt_dict,
- src_dict=src_dict,
- pre_tokenizer=pre_tokenizer,
- bpe_tokenizer=bpe_tokenizer,
- src_pre_tokenizer=None,
- src_bpe_tokenizer=None,
- is_train_split=is_train,
- epoch=epoch,
- seed=self.args.seed,
- )
- )
-
- dset = datasets[0] if len(datasets) == 1 else ConcatDataset(datasets)
- dsitem = self.create_modalitydatasetitem("sup_speech_s2s", dset)
- self.datasets[split] = MultiModalityDataset([dsitem])
- elif dtype == "unsup_speech":
- assert self.args.unsup_speech_valid_data != ""
- unsup_speech_dataset = FileAudioDatasetWrapper(
- self.args.unsup_speech_valid_data,
- self.args.sample_rate,
- max_sample_size=self.args.max_sample_size,
- min_sample_size=self.args.min_sample_size,
- normalize=False,
- )
- dsitem = self.create_modalitydatasetitem(
- "unsup_speech", unsup_speech_dataset
- )
- self.datasets[split] = MultiModalityDataset([dsitem])
- else:
- raise ValueError(f"Unsupported type {dtype}")
-
- def get_sample_ratio(self, epoch):
- sup_ratio = (
- self.sup_ratio[epoch] if len(self.sup_ratio) > epoch else self.sup_ratio[-1]
- )
- sup_s2s_ratio = (
- self.sup_s2s_ratio[epoch]
- if len(self.sup_s2s_ratio) > epoch
- else self.sup_s2s_ratio[-1]
- )
- unsup_ratio = (
- self.unsup_ratio[epoch]
- if len(self.unsup_ratio) > epoch
- else self.unsup_ratio[-1]
- )
- text_ratio = (
- self.text_ratio[epoch]
- if len(self.text_ratio) > epoch
- else self.text_ratio[-1]
- )
- bitext_ratio = (
- self.bitext_ratio[epoch]
- if len(self.bitext_ratio) > epoch
- else self.bitext_ratio[-1]
- )
- return text_ratio, bitext_ratio, sup_ratio, sup_s2s_ratio, unsup_ratio
-
- def get_batch_iterator(
- self,
- dataset,
- max_tokens=None,
- max_sentences=None,
- max_positions=None,
- ignore_invalid_inputs=False,
- required_batch_size_multiple=1,
- seed=1,
- num_shards=1,
- shard_id=0,
- num_workers=0,
- epoch=0,
- data_buffer_size=0,
- disable_iterator_cache=False,
- skip_remainder_batch=False,
- grouped_shuffling=False,
- update_epoch_batch_itr=False,
- ):
-
- assert isinstance(dataset, MultiModalityDataset)
- if len(dataset.id_to_mode) == 1:
- max_positions = dataset.max_positions[0]
- max_tokens = dataset.max_tokens[0]
- max_sentences = dataset.max_sentences[0]
- return super().get_batch_iterator(
- dataset,
- max_tokens,
- max_sentences,
- max_positions,
- ignore_invalid_inputs,
- required_batch_size_multiple,
- seed,
- num_shards,
- shard_id,
- num_workers,
- epoch,
- data_buffer_size,
- disable_iterator_cache,
- skip_remainder_batch=skip_remainder_batch,
- )
-
- mult_ratio = []
- (
- text_ratio,
- bitext_ratio,
- sup_ratio,
- sup_s2s_ratio,
- unsup_ratio,
- ) = self.get_sample_ratio(epoch)
- for mode in dataset.id_to_mode:
- if mode in ("sup_speech_ctc", "sup_speech_ali"):
- mult_ratio.append(sup_ratio)
- elif mode == "sup_speech_s2s":
- mult_ratio.append(sup_s2s_ratio)
- elif mode == "text":
- mult_ratio.append(text_ratio)
- elif mode == "bitext":
- mult_ratio.append(bitext_ratio)
- elif mode == "unsup_speech":
- mult_ratio.append(unsup_ratio)
-
- # initialize the dataset with the correct starting epoch
- dataset.set_epoch(epoch)
-
- batch_samplers = dataset.get_batch_samplers(
- mult_ratio, required_batch_size_multiple, seed
- )
-
- # return a reusable, sharded iterator
- epoch_iter = GroupedEpochBatchIterator(
- dataset=dataset,
- collate_fn=dataset.collater,
- batch_samplers=batch_samplers,
- seed=seed,
- num_shards=num_shards,
- shard_id=shard_id,
- num_workers=num_workers,
- epoch=epoch,
- mult_rate=max(self.args.update_freq) if self.args.same_data_update else 1,
- buffer_size=data_buffer_size,
- skip_remainder_batch=skip_remainder_batch,
- )
- self.dataset_to_epoch_iter[dataset] = {} # refresh it every epoch
- return epoch_iter
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/tasks/speech_text_joint.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/tasks/speech_text_joint.py
deleted file mode 100644
index bb04f14f13d340a43ebd42c1163bc30330c54650..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_text_joint_to_text/tasks/speech_text_joint.py
+++ /dev/null
@@ -1,377 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-import logging
-import os
-from argparse import Namespace
-from pathlib import Path
-
-import torch
-from fairseq.data import (
- encoders,
- Dictionary,
- ResamplingDataset,
- TransformEosLangPairDataset,
- ConcatDataset,
-)
-from fairseq.data.iterators import GroupedEpochBatchIterator
-from fairseq.data.audio.multi_modality_dataset import (
- MultiModalityDataset,
- LangPairMaskDataset,
- ModalityDatasetItem,
-)
-from fairseq.data.audio.speech_to_text_dataset import (
- SpeechToTextDataset,
- SpeechToTextDatasetCreator,
-)
-from fairseq.data.audio.speech_to_text_joint_dataset import (
- S2TJointDataConfig,
- SpeechToTextJointDatasetCreator,
-)
-from fairseq.tasks import register_task
-from fairseq.tasks.speech_to_text import SpeechToTextTask
-from fairseq.tasks.translation import load_langpair_dataset
-
-logger = logging.getLogger(__name__)
-LANG_TAG_TEMPLATE = ""
-
-
-@register_task("speech_text_joint_to_text")
-class SpeechTextJointToTextTask(SpeechToTextTask):
- """
- Task for joint training speech and text to text.
- """
-
- @classmethod
- def add_args(cls, parser):
- """Add task-specific arguments to the parser."""
- super(SpeechTextJointToTextTask, cls).add_args(parser)
- ###
- parser.add_argument(
- "--parallel-text-data",
- default="",
- help="path to parallel text data directory",
- )
- parser.add_argument(
- "--max-tokens-text",
- type=int,
- metavar="N",
- help="maximum tokens for encoder text input ",
- )
- parser.add_argument(
- "--max-positions-text",
- type=int,
- metavar="N",
- default=400,
- help="maximum tokens for per encoder text input ",
- )
- parser.add_argument(
- "--langpairs",
- default=None,
- metavar="S",
- help='language pairs for text training, separated with ","',
- )
- parser.add_argument(
- "--speech-sample-ratio",
- default=1,
- type=float,
- metavar="N",
- help="Multiple Ratio for speech dataset with transcripts ",
- )
- parser.add_argument(
- "--text-sample-ratio",
- default=1,
- type=float,
- metavar="N",
- help="Multiple Ratio for text set ",
- )
- parser.add_argument(
- "--update-mix-data",
- action="store_true",
- help="use mixed data in one update when update-freq > 1",
- )
- parser.add_argument(
- "--load-speech-only", action="store_true", help="load speech data only",
- )
- parser.add_argument(
- "--mask-text-ratio",
- type=float,
- metavar="V",
- default=0.0,
- help="mask V source tokens for text only mode",
- )
- parser.add_argument(
- "--mask-text-type",
- default="random",
- choices=["random", "tail"],
- help="mask text typed",
- )
- parser.add_argument(
- "--noise-token",
- default="",
- help="noise token for masking src text tokens if mask-text-ratio > 0",
- )
- parser.add_argument(
- "--infer-target-lang",
- default="",
- metavar="S",
- help="target language for inference",
- )
-
- def __init__(self, args, src_dict, tgt_dict, infer_tgt_lang_id=None):
- super().__init__(args, tgt_dict)
- self.src_dict = src_dict
- self.data_cfg = S2TJointDataConfig(Path(args.data) / args.config_yaml)
- assert self.tgt_dict.pad() == self.src_dict.pad()
- assert self.tgt_dict.eos() == self.src_dict.eos()
- self.speech_only = args.load_speech_only
- self._infer_tgt_lang_id = infer_tgt_lang_id
-
- @classmethod
- def setup_task(cls, args, **kwargs):
- """Setup the task (e.g., load dictionaries)."""
- data_cfg = S2TJointDataConfig(Path(args.data) / args.config_yaml)
- tgt_dict_path = Path(args.data) / data_cfg.vocab_filename
- src_dict_path = Path(args.data) / data_cfg.src_vocab_filename
- if (not os.path.isfile(src_dict_path)) or (not os.path.isfile(tgt_dict_path)):
- raise FileNotFoundError("Dict not found: {}".format(args.data))
- src_dict = Dictionary.load(src_dict_path.as_posix())
- tgt_dict = Dictionary.load(tgt_dict_path.as_posix())
-
- print("| src dictionary: {} types".format(len(src_dict)))
- print("| tgt dictionary: {} types".format(len(tgt_dict)))
-
- if args.parallel_text_data != "":
- if not os.path.isabs(args.parallel_text_data):
- args.parallel_text_data = os.path.join(
- args.data, args.parallel_text_data
- )
-
- if args.langpairs is None:
- raise Exception(
- "Could not infer language pair, please provide it explicitly"
- )
- infer_tgt_lang_id = None
- if args.infer_target_lang != "" and data_cfg.prepend_tgt_lang_tag_no_change:
- tgt_lang_tag = SpeechToTextDataset.LANG_TAG_TEMPLATE.format(
- args.infer_target_lang
- )
- infer_tgt_lang_id = tgt_dict.index(tgt_lang_tag)
- assert infer_tgt_lang_id != tgt_dict.unk()
- return cls(args, src_dict, tgt_dict, infer_tgt_lang_id=infer_tgt_lang_id)
-
- def load_langpair_dataset(
- self, prepend_tgt_lang_tag=False, sampling_alpha=1.0, epoch=0
- ):
- lang_pairs = []
- text_dataset = None
- split = "train"
- for lp in self.args.langpairs.split(","):
- src, tgt = lp.split("-")
- text_dataset = load_langpair_dataset(
- self.args.parallel_text_data,
- split,
- src,
- self.src_dict,
- tgt,
- self.tgt_dict,
- combine=True,
- dataset_impl=None,
- upsample_primary=1,
- left_pad_source=False,
- left_pad_target=False,
- max_source_positions=self.args.max_positions_text,
- max_target_positions=self.args.max_target_positions,
- load_alignments=False,
- truncate_source=False,
- )
- if prepend_tgt_lang_tag:
- # TODO
- text_dataset = TransformEosLangPairDataset(
- text_dataset,
- src_eos=self.src_dict.eos(),
- tgt_bos=self.tgt_dict.eos(), # 'prev_output_tokens' starts with eos
- new_tgt_bos=self.tgt_dict.index(LANG_TAG_TEMPLATE.format(tgt)),
- )
- lang_pairs.append(text_dataset)
- if len(lang_pairs) > 1:
- if sampling_alpha != 1.0:
- size_ratios = SpeechToTextDatasetCreator.get_size_ratios(
- self.args.langpairs.split(","),
- [len(s) for s in lang_pairs],
- alpha=sampling_alpha,
- )
- lang_pairs = [
- ResamplingDataset(d, size_ratio=r, epoch=epoch, replace=(r >= 1.0))
- for d, r in zip(lang_pairs, size_ratios)
- ]
- return ConcatDataset(lang_pairs)
- return text_dataset
-
- def inference_step(
- self, generator, models, sample, prefix_tokens=None, constraints=None
- ):
- with torch.no_grad():
- return generator.generate(
- models,
- sample,
- prefix_tokens=prefix_tokens,
- constraints=constraints,
- bos_token=self._infer_tgt_lang_id,
- )
-
- def build_src_tokenizer(self, args):
- logger.info(f"src-pre-tokenizer: {self.data_cfg.src_pre_tokenizer}")
- return encoders.build_tokenizer(Namespace(**self.data_cfg.src_pre_tokenizer))
-
- def build_src_bpe(self, args):
- logger.info(f"tokenizer: {self.data_cfg.src_bpe_tokenizer}")
- return encoders.build_bpe(Namespace(**self.data_cfg.src_bpe_tokenizer))
-
- def load_dataset(self, split, epoch=1, combine=False, **kwargs):
- """Load a given dataset split.
-
- Args:
- split (str): name of the split (e.g., train, valid, test)
- """
- is_train_split = split.startswith("train")
- pre_tokenizer = self.build_tokenizer(self.args)
- bpe_tokenizer = self.build_bpe(self.args)
- src_pre_tokenizer = self.build_src_tokenizer(self.args)
- src_bpe_tokenizer = self.build_src_bpe(self.args)
- ast_dataset = SpeechToTextJointDatasetCreator.from_tsv(
- self.args.data,
- self.data_cfg,
- split,
- self.tgt_dict,
- src_dict=None if self.speech_only else self.src_dict,
- pre_tokenizer=pre_tokenizer,
- bpe_tokenizer=bpe_tokenizer,
- src_pre_tokenizer=src_pre_tokenizer,
- src_bpe_tokenizer=src_bpe_tokenizer,
- is_train_split=is_train_split,
- epoch=epoch,
- seed=self.args.seed,
- )
- noise_token_id = -1
- text_dataset = None
- if self.args.parallel_text_data != "" and is_train_split:
- text_dataset = self.load_langpair_dataset(
- self.data_cfg.prepend_tgt_lang_tag_no_change, 1.0, epoch=epoch,
- )
- if self.args.mask_text_ratio > 0:
- # add mask
- noise_token_id = (
- self.src_dict.unk()
- if self.args.noise_token == ""
- else self.src_dict.index(self.args.noise_token)
- )
- text_dataset = LangPairMaskDataset(
- text_dataset,
- src_bos=self.src_dict.bos(),
- src_eos=self.src_dict.eos(),
- noise_id=noise_token_id,
- mask_ratio=self.args.mask_text_ratio,
- mask_type=self.args.mask_text_type,
- )
-
- if text_dataset is not None:
- mdsets = [
- ModalityDatasetItem(
- "sup_speech",
- ast_dataset,
- (self.args.max_source_positions, self.args.max_target_positions),
- self.args.max_tokens,
- self.args.batch_size,
- ),
- ModalityDatasetItem(
- "text",
- text_dataset,
- (self.args.max_positions_text, self.args.max_target_positions),
- self.args.max_tokens_text
- if self.args.max_tokens_text is not None
- else self.args.max_tokens,
- self.args.batch_size,
- ),
- ]
- ast_dataset = MultiModalityDataset(mdsets)
- self.datasets[split] = ast_dataset
-
- @property
- def target_dictionary(self):
- """Return the :class:`~fairseq.data.Dictionary` for the language
- model."""
- return self.tgt_dict
-
- @property
- def source_dictionary(self):
- """Return the source :class:`~fairseq.data.Dictionary` (if applicable
- for this task)."""
- return None if self.speech_only else self.src_dict
-
- def get_batch_iterator(
- self,
- dataset,
- max_tokens=None,
- max_sentences=None,
- max_positions=None,
- ignore_invalid_inputs=False,
- required_batch_size_multiple=1,
- seed=1,
- num_shards=1,
- shard_id=0,
- num_workers=0,
- epoch=0,
- data_buffer_size=0,
- disable_iterator_cache=False,
- skip_remainder_batch=False,
- grouped_shuffling=False,
- update_epoch_batch_itr=False,
- ):
-
- if not isinstance(dataset, MultiModalityDataset):
- return super(SpeechTextJointToTextTask, self).get_batch_iterator(
- dataset,
- max_tokens,
- max_sentences,
- max_positions,
- ignore_invalid_inputs,
- required_batch_size_multiple,
- seed,
- num_shards,
- shard_id,
- num_workers,
- epoch,
- data_buffer_size,
- disable_iterator_cache,
- skip_remainder_batch=skip_remainder_batch,
- update_epoch_batch_itr=update_epoch_batch_itr,
- )
-
- mult_ratio = [self.args.speech_sample_ratio, self.args.text_sample_ratio]
- assert len(dataset.datasets) == 2
-
- # initialize the dataset with the correct starting epoch
- dataset.set_epoch(epoch)
-
- batch_samplers = dataset.get_batch_samplers(
- mult_ratio, required_batch_size_multiple, seed
- )
-
- # return a reusable, sharded iterator
- epoch_iter = GroupedEpochBatchIterator(
- dataset=dataset,
- collate_fn=dataset.collater,
- batch_samplers=batch_samplers,
- seed=seed,
- num_shards=num_shards,
- shard_id=shard_id,
- num_workers=num_workers,
- epoch=epoch,
- mult_rate=1 if self.args.update_mix_data else max(self.args.update_freq),
- buffer_size=data_buffer_size,
- skip_remainder_batch=skip_remainder_batch,
- )
- self.dataset_to_epoch_iter[dataset] = {} # refresh it every epoch
- return epoch_iter
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/README.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/README.md
deleted file mode 100644
index f03f6a32f8b3a0070440918b775f18e712480885..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# Speech to speech translation (S2ST)
-
-We provide the implementation and resources for the following work on speech-to-speech translation (S2ST):
-
-* [Direct speech-to-speech translation with discrete units (Lee et al. 2021)](docs/direct_s2st_discrete_units.md)
-* [Textless Speech-to-Speech Translation on Real Data (Lee et al. 2021)](docs/textless_s2st_real_data.md)
-* [Enhanced Direct Speech-to-Speech Translation Using Self-supervised Pre-training and Data Augmentation](docs/enhanced_direct_s2st_discrete_units.md)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/__init__.py
deleted file mode 100644
index 812b3c30b9d0af9616b6e7e75a334bb90934f532..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-from . import unity # noqa
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/README.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/README.md
deleted file mode 100644
index 6a7ea7fcefb1d4dacd02ce726a0a654e09bbc940..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/README.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# ASR-BLEU evaluation toolkit
-
-This toolkit provides a set of public ASR models used for evaluation of different speech-to-speech translation systems at FAIR. It enables easier score comparisons between different system's outputs.
-
-The ASRGenerator wraps different CTC-based ASR models from HuggingFace and fairseq code bases. Torchaudio CTC decoder is built on top of it to decode given audio files.
-
-Please see `asr_model_cfgs.json` for a list of languages covered currently.
-
-The high-level pipeline is simple by design: given a lang tag, script loads the ASR model, transcribes model's predicted audio, and computes the BLEU score against provided reference translations using sacrebleu.
-
-# Dependencies
-
-Please see `requirements.txt`.
-
-# Usage examples
-
-This toolkit have been used with:
-
-* Speechmatrix project: https://github.com/facebookresearch/fairseq/tree/ust/examples/speech_matrix.
-
-* Hokkien speech-to-speech translation project: https://github.com/facebookresearch/fairseq/tree/ust/examples/hokkien.
-
-# Standalone run example
-
-High-level example, please substitute arguments per your case:
-
-```bash
-python compute_asr_bleu.py --lang \
---audio_dirpath \
---reference_path \
---reference_format txt
-```
-
-For more details about arguments please see the script argparser help.
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/asr_model_cfgs.json b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/asr_model_cfgs.json
deleted file mode 100644
index d0a5f3e3aa612b8eb879d9de19ad0d2a7e047fa8..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/asr_model_cfgs.json
+++ /dev/null
@@ -1,198 +0,0 @@
-{
- "en": {
- "oct22": {
- "desc": "Wav2Vec 2.0 Large (LV-60) + Self Training from https://github.com/facebookresearch/fairseq/tree/main/examples/wav2vec#pre-trained-models",
- "ckpt_path": "https://dl.fbaipublicfiles.com/fairseq/wav2vec/wav2vec_vox_960h_pl.pt",
- "dict_path": "https://dl.fbaipublicfiles.com/fairseq/wav2vec/dict.ltr.txt",
- "model_type": "fairseq",
- "lang": "en",
- "post_process": "collapse"
- }
- },
- "hok": {
- "oct22": {
- "desc": "Hokkien ASR model, for details check [TODO add paper link]",
- "ckpt_path": "https://dl.fbaipublicfiles.com/ust_asr/hok/checkpoint_best.pt",
- "dict_path": "https://dl.fbaipublicfiles.com/ust_asr/hok/dict.ltr.txt",
- "model_type": "fairseq",
- "lang": "hok",
- "post_process": "none"
- }
- },
- "es": {
- "oct22": {
- "model_path": "jonatasgrosman/wav2vec2-large-xlsr-53-spanish",
- "model_type": "hf",
- "lang": "es",
- "post_process": "collapse"
- }
- },
- "fr": {
- "oct22": {
- "model_path": "jonatasgrosman/wav2vec2-large-fr-voxpopuli-french",
- "model_type": "hf",
- "lang": "fr",
- "post_process": "collapse"
- }
- },
- "zh": {
- "oct22": {
- "model_path": "ydshieh/wav2vec2-large-xlsr-53-chinese-zh-cn-gpt",
- "model_type": "hf",
- "lang": "zh",
- "post_process": "collapse"
- }
- },
- "tr": {
- "oct22": {
- "model_path": "cahya/wav2vec2-large-xlsr-turkish-artificial-cv",
- "model_type": "hf",
- "lang": "tr",
- "post_process": "collapse"
- }
- },
- "ar": {
- "oct22": {
- "model_path": "jonatasgrosman/wav2vec2-large-xlsr-53-arabic",
- "model_type": "hf",
- "lang": "ar",
- "post_process": "collapse"
- }
- },
- "vi": {
- "oct22": {
- "model_path": "not-tanh/wav2vec2-large-xlsr-53-vietnamese",
- "model_type": "hf",
- "lang": "vi",
- "post_process": "collapse"
- }
- },
- "de": {
- "oct22": {
- "model_path": "jonatasgrosman/wav2vec2-xls-r-1b-german",
- "model_type": "hf",
- "lang": "de",
- "post_process": "collapse"
- }
- },
- "pl": {
- "oct22": {
- "model_path": "jonatasgrosman/wav2vec2-xls-r-1b-polish",
- "model_type": "hf",
- "lang": "pl",
- "post_process": "collapse"
- }
- },
- "it": {
- "oct22": {
- "model_path": "jonatasgrosman/wav2vec2-large-xlsr-53-italian",
- "model_type": "hf",
- "lang": "it",
- "post_process": "collapse"
- }
- },
- "pt": {
- "oct22": {
- "model_path": "jonatasgrosman/wav2vec2-xls-r-1b-portuguese",
- "model_type": "hf",
- "lang": "pt",
- "post_process": "collapse"
- }
- },
- "ro": {
- "oct22": {
- "model_path": "gigant/romanian-wav2vec2",
- "model_type": "hf",
- "lang": "ro",
- "post_process": "collapse"
- }
- },
- "cs": {
- "oct22": {
- "model_path": "comodoro/wav2vec2-xls-r-300m-cs-250",
- "model_type": "hf",
- "lang": "cs",
- "post_process": "collapse"
- }
- },
- "sk": {
- "oct22": {
- "model_path": "anuragshas/wav2vec2-xls-r-300m-sk-cv8-with-lm",
- "model_type": "hf",
- "lang": "sk",
- "post_process": "collapse"
- }
- },
- "sl": {
- "oct22": {
- "model_path": "anuragshas/wav2vec2-xls-r-300m-sl-cv8-with-lm",
- "model_type": "hf",
- "lang": "sl",
- "post_process": "collapse"
- }
- },
- "fi": {
- "oct22": {
- "model_path": "jonatasgrosman/wav2vec2-large-xlsr-53-finnish",
- "model_type": "hf",
- "lang": "fi",
- "post_process": "collapse"
- }
- },
- "hu": {
- "oct22": {
- "model_path": "jonatasgrosman/wav2vec2-large-xlsr-53-hungarian",
- "model_type": "hf",
- "lang": "hu",
- "post_process": "collapse"
- }
- },
- "et": {
- "oct22": {
- "model_path": "RASMUS/wav2vec2-xlsr-1b-et",
- "model_type": "hf",
- "lang": "et",
- "post_process": "collapse"
- }
- },
- "lt": {
- "oct22": {
- "model_path": "sammy786/wav2vec2-xlsr-lithuanian",
- "model_type": "hf",
- "lang": "lt",
- "post_process": "collapse"
- }
- },
- "nl": {
- "oct22": {
- "model_path": "jonatasgrosman/wav2vec2-xls-r-1b-dutch",
- "model_type": "hf",
- "lang": "nl",
- "post_process": "collapse"
- }
- },
- "lv": {
- "oct22": {
- "model_path": "reach-vb/wav2vec2-large-xls-r-1B-common_voice7-lv-ft",
- "model_type": "hf",
- "lang": "lv",
- "post_process": "collapse"
- }
- },
- "sv": {
- "oct22": {
- "model_path": "marinone94/xls-r-300m-sv-robust",
- "model_type": "hf",
- "lang": "sv",
- "post_process": "collapse"
- }
- },
- "hr": {
- "oct22": {
- "model_path": "classla/wav2vec2-xls-r-parlaspeech-hr",
- "model_type": "hf",
- "lang": "hr",
- "post_process": "collapse"
- }
- }
-}
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/compute_asr_bleu.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/compute_asr_bleu.py
deleted file mode 100644
index d5926194c186c18c66fe5063a38c5dfa07c989ab..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/compute_asr_bleu.py
+++ /dev/null
@@ -1,244 +0,0 @@
-import os
-from typing import Dict, List
-import sacrebleu
-import pandas as pd
-from glob import glob
-from pathlib import Path
-from utils import retrieve_asr_config, ASRGenerator
-from tqdm import tqdm
-from argparse import ArgumentParser
-
-
-def merge_tailo_init_final(text):
- """
- Hokkien ASR hypothesis post-processing.
- """
- sps = text.strip().split()
- results = []
- last_syllable = ""
- for sp in sps:
- if sp == "NULLINIT" or sp == "nullinit":
- continue
- last_syllable += sp
- if sp[-1].isnumeric():
- results.append(last_syllable)
- last_syllable = ""
- if last_syllable != "":
- results.append(last_syllable)
- return " ".join(results)
-
-
-def remove_tone(text):
- """
- Used for tone-less evaluation of Hokkien
- """
- return " ".join([t[:-1] for t in text.split()])
-
-
-def extract_audio_for_eval(audio_dirpath: str, audio_format: str):
- if audio_format == "n_pred.wav":
- """
- The assumption here is that 0_pred.wav corresponds to the reference at line position 0 from the reference manifest
- """
- audio_list = []
- audio_fp_list = glob((Path(audio_dirpath) / "*_pred.wav").as_posix())
- audio_fp_list = sorted(
- audio_fp_list, key=lambda x: int(os.path.basename(x).split("_")[0])
- )
- for i in range(len(audio_fp_list)):
- try:
- audio_fp = (Path(audio_dirpath) / f"{i}_pred.wav").as_posix()
- assert (
- audio_fp in audio_fp_list
- ), f"{Path(audio_fp).name} does not exist in {audio_dirpath}"
- except AssertionError:
- # check the audio with random speaker
- audio_fp = Path(audio_dirpath) / f"{i}_spk*_pred.wav"
- audio_fp = glob(
- audio_fp.as_posix()
- ) # resolve audio filepath with random speaker
- assert len(audio_fp) == 1
- audio_fp = audio_fp[0]
-
- audio_list.append(audio_fp)
- else:
- raise NotImplementedError
-
- return audio_list
-
-
-def extract_text_for_eval(
- references_filepath: str, reference_format: str, reference_tsv_column: str = None
-):
- if reference_format == "txt":
- reference_sentences = open(references_filepath, "r").readlines()
- reference_sentences = [l.strip() for l in reference_sentences]
- elif reference_format == "tsv":
- tsv_df = pd.read_csv(references_filepath, sep="\t", quoting=3)
- reference_sentences = tsv_df[reference_tsv_column].to_list()
- reference_sentences = [l.strip() for l in reference_sentences]
- else:
- raise NotImplementedError
-
- return reference_sentences
-
-
-def compose_eval_data(
- audio_dirpath: str,
- audio_format: str,
- references_filepath: str,
- reference_format: str,
- reference_tsv_column: str = None,
- save_manifest_filepath=None,
-):
- """
- Speech matrix decoding pipeline produces audio with the following mask "N_pred.wav" where N is the order of the corresponding input sample
- """
-
- reference_sentences = extract_text_for_eval(
- references_filepath, reference_format, reference_tsv_column
- )
- predicted_audio_fp_list = extract_audio_for_eval(audio_dirpath, audio_format)
- assert len(predicted_audio_fp_list) == len(reference_sentences)
-
- audio_text_pairs = [
- (audio, reference)
- for audio, reference in zip(predicted_audio_fp_list, reference_sentences)
- ]
-
- tsv_manifest = pd.DataFrame(audio_text_pairs, columns=["prediction", "reference"])
-
- if save_manifest_filepath is not None:
- tsv_manifest.to_csv(save_manifest_filepath, sep="\t", quoting=3)
-
- return tsv_manifest
-
-
-def load_eval_data_from_tsv(eval_data_filepath: str):
- """
- We may load the result of `compose_eval_data` directly if needed
- """
- eval_df = pd.from_csv(eval_data_filepath, sep="\t")
-
- return eval_df
-
-
-def run_asr_bleu(args):
-
- asr_config = retrieve_asr_config(
- args.lang, args.asr_version, json_path="./asr_model_cfgs.json"
- )
- asr_model = ASRGenerator(asr_config)
-
- eval_manifest = compose_eval_data(
- audio_dirpath=args.audio_dirpath,
- audio_format=args.audio_format,
- references_filepath=args.reference_path,
- reference_format=args.reference_format,
- reference_tsv_column=args.reference_tsv_column,
- save_manifest_filepath=None,
- )
-
- prediction_transcripts = []
- for _, eval_pair in tqdm(
- eval_manifest.iterrows(),
- desc="Transcribing predictions",
- total=len(eval_manifest),
- ):
- transcription = asr_model.transcribe_audiofile(eval_pair.prediction)
- prediction_transcripts.append(transcription.lower())
-
- if args.lang == "hok":
- prediction_transcripts = [
- merge_tailo_init_final(text) for text in prediction_transcripts
- ]
-
- references = eval_manifest["reference"].tolist()
- bleu_score = sacrebleu.corpus_bleu(prediction_transcripts, [references])
-
- print(bleu_score)
-
- return prediction_transcripts, bleu_score
-
-
-def main():
- parser = ArgumentParser(
- description="This script computes the ASR-BLEU metric between model's generated audio and the text reference sequences."
- )
-
- parser.add_argument(
- "--lang",
- help="The target language used to initialize ASR model, see asr_model_cfgs.json for available languages",
- type=str,
- )
- parser.add_argument(
- "--asr_version",
- type=str,
- default="oct22",
- help="For future support we add and extra layer of asr versions. The current most recent version is oct22 meaning October 2022",
- )
- parser.add_argument(
- "--audio_dirpath",
- type=str,
- help="Path to the directory containing the audio predictions from the translation model",
- )
- parser.add_argument(
- "--reference_path",
- type=str,
- help="Path to the file containing reference translations in the form of normalized text (to be compared to ASR predictions",
- )
- parser.add_argument(
- "--reference_format",
- choices=["txt", "tsv"],
- help="Format of reference file. Txt means plain text format where each line represents single reference sequence",
- )
- parser.add_argument(
- "--reference_tsv_column",
- default=None,
- type=str,
- help="If format is tsv, then specify the column name which contains reference sequence",
- )
- parser.add_argument(
- "--audio_format",
- default="n_pred.wav",
- choices=["n_pred.wav"],
- help="Audio format n_pred.wav corresponds to names like 94_pred.wav or 94_spk7_pred.wav where spk7 is the speaker id",
- )
- parser.add_argument(
- "--results_dirpath",
- default=None,
- type=str,
- help="If specified, the resulting BLEU score will be written to this file path as txt file",
- )
- parser.add_argument(
- "--transcripts_path",
- default=None,
- type=str,
- help="If specified, the predicted transcripts will be written to this path as a txt file.",
- )
-
- args = parser.parse_args()
-
- prediction_transcripts, bleu_score = run_asr_bleu(args)
- result_filename = f"{args.reference_format}_{args.lang}_bleu.txt"
- if args.results_dirpath is not None:
- if not Path(args.results_dirpath).exists():
- Path(args.results_dirpath).mkdir(parents=True)
- with open(Path(args.results_dirpath) / result_filename, "w") as f:
- f.write(bleu_score.format(width=2))
-
- if args.transcripts_path is not None:
- with open(args.transcripts_path, "w") as f:
- for transcript in prediction_transcripts:
- f.write(transcript + "\n")
-
-
-if __name__ == "__main__":
- main()
-
-
-"""
-Example to load Sl audio and references, compute BLEU:
-
-export lang=fi; split=vp && python compute_asr_bleu.py --lang $lang --audio_dirpath /checkpoint/hygong/S2S/speech_matrix_release_ckpts/generated_waveform_release/en-$lang/test_$split/checkpoint.pt --audio_format n_pred.wav --reference_path /large_experiments/ust/hygong/S2S/SpeechEncoder/manifests/vp-vp/en-$lang/test_$split.$lang --reference_format txt --results_dirpath ./
-"""
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/requirements.txt b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/requirements.txt
deleted file mode 100644
index cfa90f6aeffd879c1e309ae58a2f050c943e87b6..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/requirements.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-fairseq==0.12.2
-pandas==1.4.3
-sacrebleu==2.2.0
-torch==1.12.1
-torchaudio==0.12.1
-tqdm==4.64.0
-transformers==4.21.1
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/utils.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/utils.py
deleted file mode 100644
index 0fed55a9b9032952e8cc20db36c127b8354f0478..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/asr_bleu/utils.py
+++ /dev/null
@@ -1,306 +0,0 @@
-import json
-import re
-import urllib.request
-from pathlib import Path
-
-import fairseq
-import torch
-from fairseq.data.data_utils import lengths_to_padding_mask
-from tqdm import tqdm
-
-try:
- import torchaudio
- from torchaudio.models.decoder import ctc_decoder
-except ImportError:
- raise ImportError("Upgrade torchaudio to 0.12 to enable CTC decoding")
-
-
-class DownloadProgressBar(tqdm):
- """A class to represent a download progress bar"""
-
- def update_to(self, b=1, bsize=1, tsize=None) -> None:
- """
- Update the download progress
- """
- if tsize is not None:
- self.total = tsize
- self.update(b * bsize - self.n)
-
-
-def retrieve_asr_config(lang_key: str, asr_version: str, json_path: str) -> dict:
- """
- Retrieve the asr model configs
-
- Args:
- lang_key: the lanuage type as the key name
- json_path: the path of the config json file
-
- Returns:
- Dict of all the configs in the json file
- """
-
- with open(json_path, "r") as f:
- asr_model_cfgs = json.load(f)
- return asr_model_cfgs[lang_key][asr_version]
-
-
-class ASRGenerator(object):
- """A class to represent a ASR generator"""
-
- def __init__(
- self,
- model_cfg: dict,
- cache_dirpath: str = (Path.home() / ".cache" / "ust_asr").as_posix(),
- ) -> None:
- """
- Construct all the necessary attributes of the ASRGenerator class
-
- Args:
- model_cfg: the dict of the asr model config
- cache_dirpath: the default cache path is "Path.home()/.cache/ust_asr"
- """
-
- self.cache_dirpath = Path(cache_dirpath) / model_cfg["lang"]
- self.model_cfg = model_cfg
-
- self.use_cuda = torch.cuda.is_available()
-
- torchaudio.set_audio_backend("sox_io")
-
- if self.model_cfg["model_type"] == "hf":
- self.prepare_hf_model(self.model_cfg)
- elif self.model_cfg["model_type"] == "fairseq":
- self.prepare_fairseq_model(self.model_cfg)
- else:
- raise NotImplementedError(
- f"Model type {self.model_cfg['model_type']} is not supported"
- )
-
- if self.model_cfg["post_process"] == "collapse":
- self.post_process_fn = lambda hypo: "".join(hypo).replace(
- self.sil_token, " "
- )
- elif self.model_cfg["post_process"] == "none":
- self.post_process_fn = lambda hypo: " ".join(hypo).replace(
- self.sil_token, " "
- )
- else:
- raise NotImplementedError
-
- if self.use_cuda:
- self.model.cuda()
- self.model.eval()
-
- self.decoder = ctc_decoder(
- lexicon=None,
- tokens=self.tokens,
- lm=None,
- nbest=1,
- beam_size=1,
- beam_size_token=None,
- lm_weight=0.0,
- word_score=0.0,
- unk_score=float("-inf"),
- sil_token=self.sil_token,
- sil_score=0.0,
- log_add=False,
- blank_token=self.blank_token,
- )
-
- def prepare_hf_model(self, model_cfg: dict) -> None:
- """
- Prepare the huggingface asr model
-
- Args:
- model_cfg: dict with the relevant ASR config
- """
-
- def infer_silence_token(vocab: list):
- """
- Different HF checkpoints have different notion of silence token
- such as | or " " (space)
- Important: when adding new HF asr model in, check what silence token it uses
- """
- if "|" in vocab:
- return "|"
- elif " " in vocab:
- return " "
- else:
- raise RuntimeError("Silence token is not found in the vocabulary")
-
- try:
- from transformers import (AutoFeatureExtractor, AutoTokenizer,
- Wav2Vec2ForCTC, Wav2Vec2Processor)
- except ImportError:
- raise ImportError("Install transformers to load HF wav2vec model")
-
- model_path = model_cfg["model_path"]
- self.model = Wav2Vec2ForCTC.from_pretrained(model_path)
- self.tokenizer = AutoTokenizer.from_pretrained(model_path)
- self.preprocessor = AutoFeatureExtractor.from_pretrained(model_path)
- self.processor = Wav2Vec2Processor.from_pretrained(model_path)
-
- # extra unk tokens are there to make some models work e.g. Finnish ASR has some vocab issue
- vocab_list = [
- self.tokenizer.decoder.get(i, f"{self.tokenizer.unk_token}1")
- for i in range(self.tokenizer.vocab_size)
- ]
-
- self.sampling_rate = self.preprocessor.sampling_rate
- self.normalize_input = self.preprocessor.do_normalize
- self.tokens = vocab_list
- self.sil_token = infer_silence_token(vocab_list)
- self.blank_token = self.tokenizer.pad_token
-
- def prepare_fairseq_model(self, model_cfg: dict) -> None:
- """
- Prepare the fairseq asr model
-
- Args:
- model_cfg: the specific model config dict must have: (1) ckpt_path, (2) dict_path
- """
-
- def download_file(url: str, cache_dir: Path):
- download_path = cache_dir / url.split("/")[-1]
- if not (cache_dir / url.split("/")[-1]).exists():
- with DownloadProgressBar(
- unit="B", unit_scale=True, miniters=1, desc=url.split("/")[-1]
- ) as t:
- cache_dir.mkdir(parents=True, exist_ok=True)
- urllib.request.urlretrieve(
- url, filename=download_path.as_posix(), reporthook=t.update_to
- )
- else:
- print(f"'{url}' exists in {cache_dir}")
-
- return download_path.as_posix()
-
- try:
- ckpt_path = model_cfg["ckpt_path"]
- dict_path = model_cfg["dict_path"]
- except KeyError:
- raise KeyError(
- "Fairseq model cfg must provide (1) ckpt_path, (2) dict_path"
- )
-
- if re.search("^https", ckpt_path):
- ckpt_path = download_file(ckpt_path, self.cache_dirpath)
- if re.search("^https", dict_path):
- dict_path = download_file(dict_path, self.cache_dirpath)
-
- model, saved_cfg, _ = fairseq.checkpoint_utils.load_model_ensemble_and_task(
- [ckpt_path],
- arg_overrides={
- "task": "audio_finetuning",
- "data": self.cache_dirpath.as_posix(),
- }, # data must have dict in it
- )
-
- dict_lines = open(dict_path, "r").readlines()
- tokens = [l.split()[0] for l in dict_lines]
- # adding default fairseq special tokens
- tokens = ["", "", " ", ""] + tokens
-
- self.model = model[0]
- self.tokens = tokens
-
- if "|" in tokens:
- self.sil_token = "|"
- else:
- self.sil_token = tokens[
- 2
- ] # use eos as silence token if | not presented e.g., Hok ASR model
- print(f"Inferring silence token from the dict: {self.sil_token}")
- self.blank_token = self.tokens[0]
-
- self.sampling_rate = saved_cfg.task.sample_rate
- self.normalize_input = saved_cfg.task.normalize
-
- @torch.inference_mode()
- def load_audiofile(self, audio_path: str) -> torch.Tensor:
- """
- Load the audio files and apply resampling and normalizaion
-
- Args:
- audio_path: the audio file path
-
- Returns:
- audio_waveform: the audio waveform as a torch.Tensor object
- """
-
- audio_waveform, sampling_rate = torchaudio.load(audio_path)
- if audio_waveform.dim == 2:
- audio_waveform = audio_waveform.mean(-1)
- if self.sampling_rate != sampling_rate:
- audio_waveform = torchaudio.functional.resample(
- audio_waveform, sampling_rate, self.sampling_rate
- )
- if self.normalize_input:
- # following fairseq raw audio dataset
- audio_waveform = torch.nn.functional.layer_norm(
- audio_waveform, audio_waveform.shape
- )
-
- return audio_waveform
-
- @torch.inference_mode()
- def compute_emissions(self, audio_input: torch.Tensor) -> torch.Tensor:
- """
- Compute the emissions for either fairseq or huggingface asr model
-
- Args:
- audio_path: the input audio waveform
-
- Returns:
- emissions: the logits of the encoded prediction.
- """
-
- if self.use_cuda:
- audio_input = audio_input.to("cuda")
- if isinstance(self.model, fairseq.models.wav2vec.wav2vec2_asr.Wav2VecCtc):
- padding_mask = lengths_to_padding_mask(torch.tensor([audio_input.numel()]))
- emissions = self.model.w2v_encoder(audio_input, padding_mask)[
- "encoder_out"
- ].transpose(0, 1)
- else:
- emissions = self.model(audio_input).logits
-
- return emissions
-
- def decode_emissions(self, emissions: torch.Tensor) -> str:
- """
- Decode the emissions and apply post process functions
-
- Args:
- emissions: the input Tensor object
-
- Returns:
- hypo: the str as the decoded transcriptions
- """
-
- emissions = emissions.cpu()
- results = self.decoder(emissions)
-
- # assuming the lexicon-free decoder and working with tokens
- hypo = self.decoder.idxs_to_tokens(results[0][0].tokens)
- hypo = self.post_process_fn(hypo)
-
- return hypo
-
- def transcribe_audiofile(self, audio_path: str, lower=True) -> str:
- """
- Transcribe the audio into string
-
- Args:
- audio_path: the input audio waveform
- lower: the case of the transcriptions with lowercase as the default
-
- Returns:
- hypo: the transcription result
- """
-
- asr_input = self.load_audiofile(audio_path)
- emissions = self.compute_emissions(asr_input)
- hypo = self.decode_emissions(emissions)
-
- return hypo.strip().lower() if lower else hypo.strip()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/README.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/README.md
deleted file mode 100644
index c62fe12963a20a09078d3c79c65f3ebedf1aa3f9..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/README.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# Benchmarking
-
-## Overview
-
-The goal of this framework is to support benchmarking various speech to speech translation(S2ST) models in terms of runtime, max-memory consumption and total number of floating point operations(FLOPS). It is a generic framework and can be easily extended to support any fairseq models. To accurately benchmark the performance, core inference modules are re-implemented based on fairseq_cli/generate.py (core.py/Processing) and examples/speech_to_text/generate_waveform.py(core.py/SpeechGeneration. To ensure that the end to end models and cascaded models are compared fairly, for cascaded models we only consider the performance metrics for model inference at all stages ignoring any intermediate data and io processing consumption. We run all the benchmarking runs on CPU as it is generally used in production environment and also due to lack of good benchmarking library support for GPUs.
-
-1. Runtime: Average time in seconds to run model inference on an example from a given dataset. We use [timeit](https://docs.python.org/3/library/timeit.html) library to measure the runtime.
-2. Max memory: Maximum memory in MiB averaged over by running the model inference on all examples from the given dataset. We use [memory_profiler](https://pypi.org/project/memory-profiler/) library to gather memory footprints for a code snippet and find the maximum to get the max memory used by the code. For cascaded models, we find the max of all stages to get the overall max_memory footprint.
-3. FLOPS: We compute the average number of floating point operations needed to run model inference for an example from the given dataset. We use [PAPI library](http://www.bnikolic.co.uk/blog/python/flops/2019/10/01/pytorch-count-flops.html) to benchmark the number of flops.
-
-## CLI Commands
-
-```{python}
-CUBLAS_WORKSPACE_CONFIG=:4096:8 python examples/speech_to_speech/benchmarking/get_metrics.py ‘’ --config $config
-```
-
-
-## Note:
-
-1. The npy dataset is a list of samples saved as a .npy file. Each sample is a dictionary with id, net_input.
-2. The raw dataset is a list of raw audio paths similar to wav2vec2 input tsv file
-
-```{python}
-sample: {
- "id": xx,
- "net_input": {
- "src_tokens": torch.tensor([]),
- "src_lengths": torch.tensor([])
- }
-}
-```
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/configs/2StageS2ST.yaml b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/configs/2StageS2ST.yaml
deleted file mode 100644
index 11deb42e7d63cf4783d19a6fe17fb8b8cd483aff..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/configs/2StageS2ST.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
-general:
- dataset_path: $npy_dataset
- cpu: True
- model_type: 2StageS2ST
- dataset_size: 1
-
-stage1:
- data: $data_bin_stage1
- task: speech_to_text
- path: $checkpoint_stage1
- config_yaml: config.yaml
- max_len_a: 2
- max_len_b: 500
-
-stage2:
- data: $data_bin_stage2
- task: text_to_speech
- path: $checkpoint_stage2
- config_yaml: config.yaml
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/configs/3StageS2ST.yaml b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/configs/3StageS2ST.yaml
deleted file mode 100644
index 96381361508ce5d459f9020ccaf2b18a2fc18aaa..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/configs/3StageS2ST.yaml
+++ /dev/null
@@ -1,28 +0,0 @@
-general:
- dataset_path: $npy_dataset
- cpu: True
- model_type: 3StageS2ST
- max_len_a: 2
- max_len_b: 500
- dataset_size: 1
-
-stage1:
- data: $data_bin_stage1
- task: speech_to_text
- path: $checkpoint_stage1
- config_yaml: config.yaml
- max_len_a: 2
- max_len_b: 500
-
-stage2:
- data: $data_bin_stage2
- task: translation
- path: $checkpoint_stage2
- config_yaml: config.yaml
-
-
-stage2:
- data: $data_bin_stage3
- task: text_to_speech
- path: $checkpoint_stage3
- config_yaml: config.yaml
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/configs/DirectS2U.yaml b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/configs/DirectS2U.yaml
deleted file mode 100644
index 96264cec685ba9d0371318866fcc6c82fffdc02d..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/configs/DirectS2U.yaml
+++ /dev/null
@@ -1,22 +0,0 @@
-general:
- dataset_path: $npy_dataset_path
- cpu: True
- model_type: S2UT
- dataset_size: 5
- dump_speech_waveforms_dir: $dump_waveforms_dir_path
-
-stage1:
- data: $data_bin
- task: speech_to_speech
- path: $checkpoint
- config_yaml: config.yaml
- max_len_b: 100000
- beam: 10
- target_is_code: True
- max_target_positions: 3000
- target_code_size: 100
-
-stage2:
- vocoder: $vocoder_path
- vocoder_cfg: $vocoder_cfg_json
- dur_prediction: True
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/configs/S2T.yaml b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/configs/S2T.yaml
deleted file mode 100644
index 3a106a0441007331e926870a7310e114daf598a0..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/configs/S2T.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-general:
- dataset_path: $npy_dataset
- cpu: True
- model_type: S2T
- dataset_size: 1
-
-stage1:
- data: $data_bin
- task: speech_to_text
- path: $checkpoint
- config_yaml: config.yaml
- max_len_a: 2
- max_len_b: 500
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/core.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/core.py
deleted file mode 100644
index da22a34eced5a1a286855b5856c0c1444b58e5ea..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/core.py
+++ /dev/null
@@ -1,487 +0,0 @@
-import timeit
-import logging
-import torch
-from pypapi import events, papi_high as high
-from memory_profiler import memory_usage
-from torch import nn
-from argparse import Namespace
-from fairseq.dataclass.utils import convert_namespace_to_omegaconf
-from fairseq.data import data_utils as fairseq_data_utils
-from fairseq import checkpoint_utils, tasks, utils
-from fairseq.models.text_to_speech.vocoder import CodeHiFiGANVocoder
-from examples.hubert.simple_kmeans.dump_hubert_feature import HubertFeatureReader
-from examples.hubert.simple_kmeans.dump_km_label import ApplyKmeans
-from fairseq_cli.generate import get_symbols_to_strip_from_output
-import soundfile as sf
-import ast
-import json
-
-logging.basicConfig()
-logging.root.setLevel(logging.INFO)
-logging.basicConfig(level=logging.INFO)
-logger = logging.getLogger(__name__)
-
-
-torch.manual_seed(1)
-torch.set_deterministic(True)
-
-
-class BenchmarkingBase(nn.Module):
- def __init__(self):
- nn.Module.__init__(self)
- self.s2x_task = None
-
- def warm_up(self, sample, repeat):
- """Warm up the model"""
- for _i in range(repeat):
- self.forward(sample)
- logger.info(f"Model warmed up by running inference {repeat} times")
-
- def benchmark_run_time(self, dataset, repeat):
- """Benchmark average runtime for the model by calling benchmark_run_time_single_sample function"""
- logger.info("Starting run time benchmarking")
- time_elapsed = 0
- for i, sample in enumerate(dataset):
- time_elapsed += self.benchmark_run_time_single_sample(sample, repeat=repeat)
- if i % 100 == 0:
- logger.info(f"Benchmarked run time for {i}/{len(dataset)} samples")
- total_time_elapsed = time_elapsed / len(dataset)
- return total_time_elapsed
-
- def benchmark_run_time_single_sample(self, sample, repeat):
- """Benchmark average runtime for a single sample using timeit library. Units are seconds"""
- timer = timeit.Timer(lambda: self.forward(sample))
- time_elapsed = timer.timeit(repeat)
- return time_elapsed / repeat
-
- def count_flops(
- self,
- dataset,
- repeat,
- ):
- """Use PYPAPI library to count average flops for model inference.
- Note: It only works if the model is being run on cpu"""
- logger.info("Starting flop counter")
- high.start_counters([events.PAPI_DP_OPS])
- for i, sample in enumerate(dataset):
- for _r in range(repeat):
- self.forward(sample)
- if i % 100 == 0:
- logger.info(f"Counted flops for {i}/{len(dataset)} samples")
- flops = high.stop_counters()
- flops = round(flops[0] / (repeat * len(dataset)))
- return flops
-
- def max_memory(self, dataset, repeat):
- """Compute average max memory consumed by model inference. Units are MiB"""
- logger.info("Starting memory benchmarking")
- total_memory = 0
- for i, sample in enumerate(dataset):
- for _r in range(repeat):
- total_memory += max(memory_usage((self.forward, (sample,), {})))
- if i % 100 == 0:
- logger.info(f"Benchmarked memory for {i}/{len(dataset)} samples")
- total_memory = total_memory / (repeat * len(dataset))
- return total_memory
-
- def gather_all_metrics(self, dataset, repeat):
- run_time = self.benchmark_run_time(dataset, repeat)
- max_memory = self.max_memory(dataset, repeat)
- flops = self.count_flops(dataset, repeat)
-
- return run_time, max_memory, flops
-
- def dump_final_speech_output(
- self, dataset, output_dir, resample_fn, sample_rate, prefix=None
- ):
-
- for i, sample in enumerate(dataset):
- hypo = self.forward(sample)[0]
-
- def to_np(x):
- return x.detach().cpu().numpy()
-
- try:
- wave_preds = to_np(resample_fn(hypo["waveform"]))
- sf.write(
- f"{output_dir}/{prefix}_{i}_pred.wav",
- wave_preds,
- sample_rate,
- )
- except Exception as e:
- raise Exception(
- f" Encountered {e} - Invalid waveform. Make sure the model outputs a waveform"
- )
-
-
-class Processing(BenchmarkingBase):
- """Class similar to fairseq_cli/generate.py. Supports ASR, MT and ST model inference"""
-
- def __init__(self, args):
- super().__init__()
- self.use_cuda = not getattr(args, "cpu", False)
- self.setUp(args)
- self.training = False
- self.s2x_task = self.task
-
- def setUp(self, cfg):
- if isinstance(cfg, Namespace):
- cfg = convert_namespace_to_omegaconf(cfg)
-
- self.task = tasks.setup_task(cfg.task)
- self.tgt_dict = self.task.target_dictionary
-
- # Load ensemble
- logger.info("loading model(s) from {}".format(cfg.common_eval.path))
- models, _ = checkpoint_utils.load_model_ensemble(
- utils.split_paths(cfg.common_eval.path),
- arg_overrides={},
- task=self.task,
- suffix=cfg.checkpoint.checkpoint_suffix,
- strict=False,
- num_shards=cfg.checkpoint.checkpoint_shard_count,
- )
- if len(models) > 1:
- raise Exception("Currently loading multiple models is not supported")
- self.model = models[0]
-
- # Optimize model for generation
- if cfg.common.fp16:
- self.model.half()
- if self.use_cuda:
- self.model.cuda()
- self.model.prepare_for_inference_(cfg)
-
- self.generator = self.task.build_generator(
- [self.model],
- cfg.generation,
- extra_gen_cls_kwargs={},
- )
- # Handle tokenization and BPE
- self.tokenizer = self.task.build_tokenizer(cfg.tokenizer)
- self.bpe = self.task.build_bpe(cfg.bpe)
- self.remove_bpe = cfg.common_eval.post_process
-
- def encode_source(self, src):
- """Method to generate source tokens from a string"""
- if self.tokenizer is not None:
- src = self.tokenizer.encode(src)
- if self.bpe is not None:
- src = self.bpe.encode(src)
- src_tokens = self.task.source_dictionary.encode_line(src).long()
- src_lens = src_tokens.size(0)
- return {
- "net_input": {
- "src_tokens": src_tokens.view(1, src_lens),
- "src_lengths": torch.tensor([src_lens]),
- }
- }
-
- def decode_target(self, hypos):
- """Method to decode target string from tokens"""
- hypo_str = self.tgt_dict.string(
- hypos[0][0]["tokens"].int().cpu(),
- self.remove_bpe,
- get_symbols_to_strip_from_output(self.generator),
- )
- if self.bpe is not None:
- hypo_str = self.bpe.decode(hypo_str)
- if self.tokenizer is not None:
- hypo_str = self.tokenizer.decode(hypo_str)
- return hypo_str
-
- def forward(self, sample):
- hypos = self.task.inference_step(
- self.generator,
- [self.model],
- sample,
- prefix_tokens=None,
- constraints=None,
- )
- return hypos
-
-
-class GenerateWaveformFromCode(BenchmarkingBase):
- """Class to support waveform generation from code. Currently, vocoder only supports single speaker"""
-
- def __init__(self, args):
- super().__init__()
- with open(args.vocoder_cfg) as f:
- vocoder_cfg = json.load(f)
- self.dur_prediction = args.dur_prediction
- self.vocoder = CodeHiFiGANVocoder(args.vocoder, vocoder_cfg)
-
- def format_units(self, input):
- code = torch.LongTensor(list(map(int, input.strip().split()))).view(1, -1)
- return {"code": code}
-
- def generate_vocoder_input(self, dataset):
- return [self.format_units(sample) for sample in dataset]
-
- def forward(self, sample):
- return [{"waveform": self.vocoder(sample, self.dur_prediction)}]
-
-
-class HubertUnitExtractor(BenchmarkingBase):
- def __init__(self, args):
- self.feature_reader = HubertFeatureReader(
- args.hubert_ckpt_path, args.hubert_layer
- )
- self.kmeans = ApplyKmeans(args.hubert_km_path)
-
- def forward(self, sample):
- with torch.no_grad():
- feat = []
- for start in range(0, sample.size(1), self.feature_reader.max_chunk):
- x_chunk = sample[:, start : start + self.max_chunk]
- feat_chunk, _ = self.feature_reader.model.extract_features(
- source=x_chunk,
- padding_mask=None,
- mask=False,
- output_layer=self.layer,
- )
- feat.append(feat_chunk)
- torch.cat(feat, 1).squeeze(0)
- return self.kmeans(feat).tolist()
-
-
-class SpeechGeneration(BenchmarkingBase):
- """Class similar to examples/text_to_speech/generate_waveform.py.
- Supports models with speech generation as end goal (TTS, Direct S2ST models etc)"""
-
- def __init__(self, args):
- super().__init__()
- self.use_cuda = not getattr(args, "cpu", False)
- self.setUp(args)
- self.s2x_task = self.task
-
- def setUp(self, args):
- if args.task == "speech_to_speech":
- args.normalize_waveform = False
- self.task = tasks.setup_task(args)
- self.pre_tokenizer = self.task.build_tokenizer(args)
- self.bpe_tokenizer = self.task.build_bpe(args)
- try:
- self.src_dict = self.task.src_dict
- except Exception:
- self.src_dict = None
- ensemble, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task(
- [args.path],
- arg_overrides=ast.literal_eval(args.model_overrides),
- task=self.task,
- strict=False,
- )
- self.model = ensemble[0]
- if self.use_cuda:
- self.model.cuda()
- # criterion.cuda()
- self.model.eval()
- self.generator = self.task.build_generator(
- [self.model],
- args,
- )
-
- def processTextInput(self, text):
- """Generate source tokens from text input"""
- if self.pre_tokenizer is not None:
- text = self.pre_tokenizer.encode(text)
- if self.bpe_tokenizer is not None:
- text = self.bpe_tokenizer.encode(text)
- target = self.src_dict.encode_line(
- text, add_if_not_exist=False, append_eos=True
- ).long()
- target = fairseq_data_utils.collate_tokens(
- [target],
- self.src_dict.pad(),
- self.src_dict.eos(),
- left_pad=False,
- move_eos_to_beginning=False,
- )
- src_lengths = torch.tensor([target.size(1)], dtype=torch.long)
- prev_output_tokens = None
- sample = {
- "net_input": {
- "src_tokens": target,
- "src_lengths": src_lengths,
- "prev_output_tokens": prev_output_tokens,
- }
- }
- sample = utils.move_to_cuda(sample) if self.use_cuda else sample
- return sample
-
- def forward(self, sample):
- sample["speaker"] = None
- output = self.generator.generate(self.model, sample) # , has_targ=False
- return output
-
-
-class S2UT(BenchmarkingBase):
- """Class to support S2UT models. Also supports generating waveforms from the units predicted"""
-
- def __init__(self, s2u_args, vocoder_args=None):
- super().__init__()
- self.s2u = Processing(s2u_args)
- self.vocoder = None
- if vocoder_args:
- self.vocoder = GenerateWaveformFromCode(vocoder_args)
- self.vocoder_input = None
-
- def forward(self, sample):
- s2u_hypos = self.s2u(sample)
- s2u_output = self.s2u.decode_target(s2u_hypos)
- if not self.vocoder:
- return s2u_output
- units = self.vocoder.format_units(s2u_output)
- vocoder_output = self.vocoder(units)
- return vocoder_output
-
- def generate_s2u_outputs(self, dataset):
- return [self.s2u.decode_target(self.s2u(sample)) for sample in dataset]
-
- def compute_metrics(self, metric_type, dataset, repeat=None):
- """Generic function to compute metrics ignoring the io processing time"""
- if self.vocoder and not self.vocoder_input:
- self.s2u_output = self.generate_s2u_outputs(dataset)
- self.vocoder_input = self.vocoder.generate_vocoder_input(self.s2u_output)
-
- s2u_metrics = getattr(self.s2u, metric_type)(
- dataset,
- repeat,
- )
- vocoder_metrics = 0
- if self.vocoder:
- vocoder_metrics = getattr(self.vocoder, metric_type)(
- self.vocoder_input,
- repeat,
- )
- print(
- f"metric_type = {metric_type} s2u_metrics = {s2u_metrics} \t vocoder_metrics = {vocoder_metrics}"
- )
- if metric_type == "max_memory":
- return max(s2u_metrics, vocoder_metrics)
- else:
- return s2u_metrics + vocoder_metrics
-
- def benchmark_run_time(self, dataset, repeat):
- return self.compute_metrics("benchmark_run_time", dataset, repeat)
-
- def count_flops(self, dataset, repeat):
- return self.compute_metrics("count_flops", dataset, repeat)
-
- def max_memory(self, dataset, repeat):
- return self.compute_metrics("max_memory", dataset, repeat)
-
-
-class Cascaded2StageS2ST(BenchmarkingBase):
- """ST + TTS"""
-
- def __init__(self, s2t_args, tts_args):
- super().__init__()
- self.s2t = Processing(s2t_args)
- self.s2x_task = self.s2t.task
- self.tts = SpeechGeneration(tts_args) if tts_args else None
- self.training = False
- self.tts_inputs = None
-
- def forward(self, sample):
- if not self.tts:
- raise Exception(
- "Forward function is not callable without tts. Reinitialize the class with tts_args"
- )
- s2t_hypos = self.s2t(sample)
- s2t_output = self.s2t.decode_target(s2t_hypos)
- tts_input = self.tts.processTextInput(s2t_output)
- tts_output = self.tts(tts_input)
- return tts_output
-
- def generate_s2t_outputs(self, dataset):
- """Process dataset and generate s2t outputs"""
- return [self.s2t.decode_target(self.s2t(sample)) for sample in dataset]
-
- def generate_tts_inputs(self, dataset):
- """Process dataset and generate tts inputs"""
- return [self.tts.processTextInput(sample) for sample in dataset]
-
- def compute_metrics(self, metric_type, dataset, repeat=None):
- """Generic function to compute metrics ignoring the io processing time"""
- if not self.tts_inputs:
- s2t_outputs = self.generate_s2t_outputs(dataset)
- self.tts_inputs = self.generate_tts_inputs(s2t_outputs)
-
- s2t_metrics = getattr(self.s2t, metric_type)(
- dataset,
- repeat,
- )
-
- tts_metrics = getattr(self.tts, metric_type)(
- self.tts_inputs,
- repeat,
- )
- print(
- f"metric_type = {metric_type} s2t_metrics = {s2t_metrics} \t tts_metrics = {tts_metrics}"
- )
- if metric_type == "max_memory":
- return max(s2t_metrics, tts_metrics)
- else:
- return s2t_metrics + tts_metrics
-
- def benchmark_run_time(self, dataset, repeat):
- return self.compute_metrics("benchmark_run_time", dataset, repeat)
-
- def count_flops(self, dataset, repeat):
- return self.compute_metrics("count_flops", dataset, repeat)
-
- def max_memory(self, dataset, repeat):
- return self.compute_metrics("max_memory", dataset, repeat)
-
-
-class Cascaded3StageS2ST(Cascaded2StageS2ST):
- """ASR + MT + TTS"""
-
- def __init__(self, s2t_args, tts_args, mt_args):
- super().__init__(s2t_args, tts_args)
- self.mt = Processing(mt_args)
- self.mt_inputs = []
-
- def forward(self, sample):
- s2t_hypos = self.s2t(sample)
- s2t_output = self.s2t.decode_target(s2t_hypos)
- mt_input = self.mt.encode_source(s2t_output)
- mt_hypos = self.mt(mt_input)
- mt_output = self.mt.decode_target(mt_hypos)
- tts_input = self.tts.processTextInput(mt_output)
- tts_output = self.tts(tts_input)
- return tts_output
-
- def generate_mt_inputs(self, dataset):
- """Process dataset to generate mt model inputs"""
- return [self.mt.encode_source(sample) for sample in dataset]
-
- def generate_mt_outputs(self, dataset):
- """Process dataset to generate mt model outputs"""
- return [self.mt.decode_target(self.mt(sample)) for sample in dataset]
-
- def compute_metrics(self, metric_type, dataset, repeat=None):
- """Generic function to compute metrics ignoring the io processing time"""
- if not self.tts_inputs:
- s2t_outputs = self.generate_s2t_outputs(dataset)
- self.mt_inputs = self.generate_mt_inputs(s2t_outputs)
- mt_outputs = self.generate_mt_outputs(self.mt_inputs)
- self.tts_inputs = self.generate_tts_inputs(mt_outputs)
-
- s2t_metrics = getattr(self.s2t, metric_type)(
- dataset,
- repeat,
- )
- mt_metrics = getattr(self.mt, metric_type)(self.mt_inputs, repeat)
- tts_metrics = getattr(self.tts, metric_type)(
- self.tts_inputs,
- repeat,
- )
- print(
- f"metric_type = {metric_type} s2t_metrics = {s2t_metrics} \t mt_metrics = {mt_metrics} \t tts_metrics = {tts_metrics}"
- )
- if metric_type == "max_memory":
- return max(s2t_metrics, mt_metrics, tts_metrics)
- else:
- return s2t_metrics + mt_metrics + tts_metrics
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/data_utils.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/data_utils.py
deleted file mode 100644
index c73a59951f5862c5aa8dffc901a950b5b36272f7..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/data_utils.py
+++ /dev/null
@@ -1,264 +0,0 @@
-from fairseq import tasks
-import numpy as np
-import logging
-import random
-from fairseq import options
-import torch
-import os
-import soundfile as sf
-
-from fairseq.data.audio.audio_utils import (
- get_waveform,
- parse_path,
-)
-
-logging.basicConfig()
-logging.root.setLevel(logging.INFO)
-logging.basicConfig(level=logging.INFO)
-logger = logging.getLogger(__name__)
-
-random.seed(1)
-np.random.seed(1)
-random_number_generator = np.random.RandomState(30)
-
-
-def generate_random_data_sample(T, B=1, D=80):
- """Generate random data sample given the T, B, D values"""
- net_input = {
- "src_tokens": torch.tensor(random_number_generator.randn(B, T, D)).float(),
- "src_lengths": torch.tensor([T]),
- }
- return {"net_input": net_input}
-
-
-def generate_random_dataset(T_range_min, T_range_max, B=1, D=80, dataset_size=100):
- """Generate random dataset with T values within a given range, B, D"""
- T_values = [random.randint(T_range_min, T_range_max) for i in range(dataset_size)]
- dataset = []
- for t in T_values:
- dataset.append(generate_random_data_sample(t, B, D))
- return dataset, sum(T_values) / dataset_size
-
-
-def load_dataset_npy(file_name, dataset_size=None):
- """Load dataset from a .npy file."""
- data = np.load(file_name, allow_pickle=True)
- if dataset_size:
- data = data[:dataset_size]
- return data
-
-
-def load_dataset_raw_to_waveforms(
- file_name,
- dataset_size=None,
- need_waveform=True,
- sample_rate=16000,
- read_using_soundfile=False,
-):
- """Load raw dataset from w2v tsv file. Optionally get waveforms"""
- data = []
- with open(file_name, "r") as fp:
- lines = fp.readlines()
- data = [
- os.path.join(lines[0].strip(), line.strip().split("\t")[0])
- for line in lines[1:]
- ]
-
- if dataset_size:
- data = data[:dataset_size]
-
- if not need_waveform:
- return data
-
- features = []
- if read_using_soundfile:
- for _i, d in enumerate(data):
- wav = sf.read(d)[0]
- if wav.ndim == 2:
- wav = wav.mean(-1)
- features.append(torch.from_numpy(wav).float().view(1, -1))
- else:
- for i, d in enumerate(data):
- _path, slice_ptr = parse_path(d)
- if len(slice_ptr) == 0:
- feat = get_waveform(
- _path, always_2d=True, output_sample_rate=sample_rate
- )[0]
- features.append(
- {
- "id": i,
- "net_input": {
- "src_tokens": torch.tensor(feat),
- "src_lengths": torch.tensor([feat.shape[1]]),
- },
- }
- )
- else:
- raise Exception("Currently unsupported data format")
- return features
-
-
-def load_dataset_task(
- args,
- batch_size=1,
- limit_size=None,
- ref_dataset=None,
-):
- """Loads dataset based on args by creating a task"""
- if not args.data or not args.subset or not args.task:
- raise Exception(
- "Please provide necessary arguments to load the dataset - data, subset and task"
- )
- task = tasks.setup_task(args)
-
- task.load_dataset(args.subset)
- if not limit_size:
- limit_size = len(task.dataset(args.subset))
-
- iter = task.get_batch_iterator(
- dataset=task.dataset(args.subset), max_sentences=batch_size
- ).next_epoch_itr(shuffle=False)
- dataset = []
- for i, sample in enumerate(iter):
- sample = {
- "id": task.datasets[args.subset].ids[sample["id"].item()],
- "net_input": {
- "src_tokens": sample["net_input"]["src_tokens"],
- "src_lengths": sample["net_input"]["src_lengths"],
- },
- }
- dataset.append(sample)
- if i == limit_size - 1:
- break
-
- if ref_dataset:
- try:
- ids = get_ids_from_dataset(ref_dataset)
- except Exception as e:
- raise Exception(f"{e} - Cannot extract ids from reference dataset")
-
- filtered_dataset = []
- for sample in dataset:
- if (
- sample["id"] in ids
- or sample["id"][5:] in ids
- or f"dev_{sample['id']}" in ids
- ):
- filtered_dataset.append(sample)
- dataset = filtered_dataset
-
- max_len, min_len, avg_len = get_dataset_stats(dataset)
- print(
- f"{args.subset} dataset stats : num_samples={len(dataset)} max_len = {max_len} min_len = {min_len} avg_len = {avg_len}"
- )
-
- return dataset
-
-
-def randomly_sample_subset(dataset, size=500):
- """Randomly sample subset from a dataset"""
- random_indices = [random.randint(0, len(dataset) - 1) for i in range(size)]
- return [dataset[i] for i in random_indices]
-
-
-def get_short_data_subset(dataset, size=500):
- """Get a subset of desired size by sorting based on src_lengths"""
- return sort_dataset(dataset)[:size]
-
-
-def get_long_data_subset(dataset, size=500):
- """Get a subset of desired size by sorting based on src_lengths descending"""
- return sort_dataset(dataset, reverse=True)[:size]
-
-
-def sort_dataset(dataset, reverse=False):
- return sorted(
- dataset, key=lambda x: x["net_input"]["src_lengths"].item(), reverse=reverse
- )
-
-
-def save_dataset_npy(dataset, file_name):
- """Save a dataset as .npy file"""
- np.save(file_name, dataset)
-
-
-def get_dataset_stats(dataset):
- """Get stats about dataset based on src_lengths of samples"""
- max_len = 0
- min_len = 100000
- avg_len = 0
- for d in dataset:
- max_len = max(max_len, d["net_input"]["src_lengths"].item())
- min_len = min(min_len, d["net_input"]["src_lengths"].item())
- avg_len += d["net_input"]["src_lengths"].item()
-
- return max_len, min_len, avg_len / len(dataset)
-
-
-def make_parser():
- """
- Additional args:
- 1. Provide the dataset dir path using --data.
- 2. Loading the dataset doesn't require config, provide --config-yaml to apply additional feature transforms
- """
- parser = options.get_speech_generation_parser()
- parser.add_argument(
- "--subset",
- default=None,
- type=str,
- required=True,
- help="Subset to use for dataset generation",
- )
- parser.add_argument(
- "--dataset-save-dir",
- default=None,
- type=str,
- required=False,
- help="Dir path in which the datasets are to be saved",
- )
- parser.add_argument(
- "--ref-dataset",
- default=None,
- type=str,
- required=False,
- help="If provided, the ids in the reference dataset will be used to filter the new dataset generated.",
- )
- parser.add_argument("--dataset-save-token", default="", type=str, required=False)
-
- options.add_generation_args(parser)
- return parser
-
-
-def get_ids_from_dataset(dataset):
- return {sample["id"]: 1 for sample in dataset}
-
-
-def cli_main():
- parser = make_parser()
- args = options.parse_args_and_arch(parser)
- dataset = load_dataset_task(args)
-
- random_dataset = randomly_sample_subset(dataset)
- short_dataset = get_short_data_subset(dataset)
- long_dataset = get_long_data_subset(dataset)
-
- if args.dataset_save_token:
- args.dataset_save_token = f"_{args.dataset_save_token}_"
-
- if args.dataset_save_dir:
- save_dataset_npy(
- random_dataset,
- f"{args.dataset_save_dir}/random_dataset{args.dataset_save_token}w_ids.npy",
- )
- save_dataset_npy(
- short_dataset,
- f"{args.dataset_save_dir}/short_dataset{args.dataset_save_token}w_ids.npy",
- )
- save_dataset_npy(
- long_dataset,
- f"{args.dataset_save_dir}/long_dataset{args.dataset_save_token}w_ids.npy",
- )
-
-
-if __name__ == "__main__":
- cli_main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/get_metrics.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/get_metrics.py
deleted file mode 100644
index 773257f5daa970ac73281c4328fdf977022a02f2..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/benchmarking/get_metrics.py
+++ /dev/null
@@ -1,162 +0,0 @@
-import copy
-import torch
-import logging
-from argparse import Namespace
-import yaml
-from fairseq import options
-from examples.speech_to_speech.benchmarking.core import (
- Processing,
- SpeechGeneration,
- Cascaded2StageS2ST,
- Cascaded3StageS2ST,
- S2UT,
-)
-from examples.speech_to_speech.benchmarking.data_utils import (
- load_dataset_npy,
- load_dataset_raw_to_waveforms,
-)
-
-
-logging.basicConfig()
-logging.root.setLevel(logging.INFO)
-logging.basicConfig(level=logging.INFO)
-logger = logging.getLogger(__name__)
-
-torch.manual_seed(1)
-torch.set_deterministic(True)
-
-
-def make_parser():
- """Note: As the names indicate use s2x_args(ex:ST, ASR etc) for models with speech input,
- x2s_args for models with speech output(ex:TTS) and mt_args for translation models (ex: mt, T2U etc).
- For direct S2ST models, use x2s_args to provide model details.
- """
- parser = options.get_speech_generation_parser()
- parser.add_argument("--target-is-code", action="store_true", default=False)
- parser.add_argument("--config", type=str)
- parser.add_argument(
- "--model-type",
- default="S2U",
- choices=["S2S", "TTS", "S2UT", "MT", "S2T", "2StageS2ST", "3StageS2ST"],
- help="Choose one of the models. For model inference implementation, refer to core.py",
- )
- parser.add_argument(
- "--dataset-path",
- type=str,
- help="""File to load dataset from. Assumes dataset is a list of samples.
- Each sample is a dict of format {'net_input':{'src_tokens':torch.tenor(),'src_lengths':torch.tensor()}}""",
- )
- parser.add_argument(
- "--dataset-type",
- type=str,
- default="npy",
- choices=["npy", "raw"],
- help="""Type of input dataset file""",
- )
- parser.add_argument(
- "--read-using-sf",
- type=str,
- default=False,
- help="""If sound file should be used to read the raw dataset""",
- )
- parser.add_argument(
- "--dataset-size",
- default=None,
- type=int,
- help="Dataset size to use for benchmarking",
- )
- parser.add_argument(
- "--dump-speech-waveforms-dir",
- default=None,
- type=str,
- help="Directory to dump the speech waveforms computed on the dataset.",
- )
- parser.add_argument(
- "--dump-waveform-file-prefix",
- default="",
- type=str,
- help="File name prefix for the saved speech waveforms",
- )
- parser.add_argument(
- "--feat-dim", default=80, type=int, help="Input feature dimension"
- )
- parser.add_argument(
- "--target-sr",
- default=16000,
- type=int,
- help="Target sample rate for dumping waveforms",
- )
-
- options.add_generation_args(parser)
- options.get_interactive_generation_parser(parser)
- return parser
-
-
-def cli_main():
- parser = make_parser()
- args = options.parse_args_and_arch(parser)
-
- with open(
- args.config,
- "r",
- ) as f:
- config = yaml.load(f, Loader=yaml.FullLoader)
- dict_args = vars(args)
- dict_args.update(config["general"])
- args = Namespace(**dict_args)
-
- i = 1
- stage_args = []
- while i <= 3:
- var = f"stage{i}"
- tmp_args = copy.deepcopy(dict_args)
- if var in config:
- tmp_args.update(config[var])
- stage_args.append(Namespace(**tmp_args))
- i += 1
- else:
- break
-
- if args.model_type == "S2S" or args.model_type == "TTS":
- model = SpeechGeneration(stage_args[0])
- elif args.model_type == "S2UT":
- model = S2UT(stage_args[0], stage_args[1] if len(stage_args) > 1 else None)
- elif args.model_type == "MT" or args.model_type == "S2T":
- model = Processing(stage_args[0])
- elif args.model_type == "2StageS2ST":
- model = Cascaded2StageS2ST(stage_args[0], stage_args[1])
- elif args.model_type == "3StageS2ST":
- model = Cascaded3StageS2ST(stage_args[0], stage_args[2], stage_args[1])
- else:
- raise Exception(f"Currently unsupported model type {args.model_type}")
-
- print(f"Evaluating on dataset - {args.dataset_path}\n")
-
- if args.dataset_type == "npy":
- dataset = load_dataset_npy(args.dataset_path, dataset_size=args.dataset_size)
- elif args.dataset_type == "raw":
- dataset = load_dataset_raw_to_waveforms(
- args.dataset_path,
- dataset_size=args.dataset_size,
- read_using_soundfile=args.read_using_sf,
- )
- else:
- raise Exception(f"Invalid dataset type {args.dataset_type}")
-
- model.warm_up(sample=dataset[0], repeat=2)
-
- run_time, memory, flops = model.gather_all_metrics(dataset, repeat=1)
- print(f"run_time = {run_time}sec \tmemory = {memory}MiB \tflops = {flops}")
-
- if args.dump_speech_waveforms_dir:
- model.dump_final_speech_output(
- dataset,
- args.dump_speech_waveforms_dir,
- lambda x: x,
- args.target_sr,
- prefix=args.dump_waveform_file_prefix,
- )
-
-
-if __name__ == "__main__":
- cli_main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/docs/data_augmentation.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/docs/data_augmentation.md
deleted file mode 100644
index c0c17ff2235dbfa4c90ad033a53bb7fb5080e3bd..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/docs/data_augmentation.md
+++ /dev/null
@@ -1,435 +0,0 @@
-# Noise and audio augmentation techniques
-
-The noise and data augmentation techniques were written in an effort to understand how augmenatation can affect model robustness and performance in both clean and noisy settings.
-
-All transforms discussed in this section are subclasses of `AudioFeatureTransform`, `AudioWaveformTransform`, or `AudioDatasetTransform`. Each `Audio*Transform` has unique interaction with the data. If interested in implemented one's own transforms, it is highly advisable to review the differences (see [Adding your own transforms](https://github.com/facebookresearch/fairseq/blob/main/examples/speech_to_speech/docs/data_augmentation.md#adding-your-own-transforms)). If only applying the in-built transforms, then one only needs to be mindful that the correct kind of transform is listed in the config (see [Using transforms](https://github.com/facebookresearch/fairseq/blob/main/examples/speech_to_speech/docs/data_augmentation.md#using-transforms)). These transforms can be applied to instances of `SpeechToTextDataset`.
-
-### Contents
-[In-built transforms](https://github.com/facebookresearch/fairseq/blob/main/examples/speech_to_speech/docs/data_augmentation.md#in-built-transforms)
-
-[Benchmark studies](https://github.com/facebookresearch/fairseq/blob/main/examples/speech_to_speech/docs/data_augmentation.md#benchmark-studies)
-
-[Using transforms](https://github.com/facebookresearch/fairseq/blob/main/examples/speech_to_speech/docs/data_augmentation.md#using-transforms)
-
-[Adding your own transforms](https://github.com/facebookresearch/fairseq/blob/main/examples/speech_to_speech/docs/data_augmentation.md#adding-your-own-transforms)
-
-
-## In-built transforms
-### 1. Utterance concatenation
-Utterance concatenation is a data augmenation technique introduced as ConcatAug in [Translatotron 2: High-quality direct speech-to-speech translation
-with voice preservation](https://arxiv.org/pdf/2107.08661.pdf).
-With some parameterized probability, samples are concatenated with one other randomly chosen sample from the whole dataset. In the positive (concatenation) case, accessing `dataset[i]` will return a `SpeechToTextDatasetItem` where `source=source[i]+source[j]` and `target=target[i]+target[j]`. In the negative (skip concatenation) case, accessing `dataset[i]` will return a `SpeechToTextDatasetItem` where `source=source[i]` and `target=target[i]` as usual.
-
-**Usage**: `concataugment` is an `AudioDatasetTransform` and has three configurable hyperparameters:
-- `rate`: probability that any single access will result in the positive (concatenation) case. Defaults to 0.25.
-- `max_tokens`: maximum number of tokens allowed for concatenated source sequences. This parameter is meant to limit the length of concatenated samples to avoid out-of-memory errors. Defaults to 300.
-- `attempts`: maximum number of invalid concatenation attempts before defaulting to the negative (skip concatenation) case. This parameter aims to limit excessive time spent trying to find candidate samples that are short enough to concatenate with. Defaults to 5.
-
-Please be wary of OOMs while using this augmentation technique; we used smaller batch sizes as a workaround to avoid OOMs. Batch size is determined by update frequency, batch size hyperparameter, and the number of GPU, so you may want to alter these to this end.
-
-### 2. Noise augmentation suite
-
-The four noise augmentation methods in this suite adhere to the following principle: with some parameterized probability, samples are overlayed with a noise track. The content of the noise track is specific to the method. Signal-to-noise ratio with which the noise track is overlayed is determined by choosing a value from a random uniform distribution with parameterized endpoints. The first three methods are based off data augmentation methods suggested in Section 3.3 of [X-Vectors: Robust DNN Embeddings for Speaker Recognition](https://danielpovey.com/files/2018_icassp_xvectors.pdf).
-
-#### 2.1. Music augmentation
-For music augmentation, the noise track consists of one file uniformly randomly selected from a corpus of music files. The music file is cut to size, including being repeated to fill the original sample length if necessary.
-
-**Usage**: `musicaugment` is an `AudioWaveformTransform` and has four configurable hyperparameters:
-- `samples_path`: path where background music files are saved as audios (.wav files). No default.
-- `rate`: probability that any single access will result in the positive (background music) case. Defaults to 0.25.
-- `snr_min`: lower endpoint of the range from which a signal-to-noise ratio is uniformly randomly chosen with which to add background noise to the original source. Defaults to 5.
-- `snr_max`: higher endpoint of the range from which a signal-to-noise ratio is uniformly randomly chosen with which to add background noise to the original source. Defaults to 15.
-
-#### 2.2. Babble augmentation
-For babble augmentation, the noise track consists of multiple audios uniformly randomly selected from a corpus of speech files. The number of speech audios in the background track is chosen randomly with equal probability between 3 and 7 audios.
-
-**Usage**: `babbleaugment` is an `AudioWaveformTransform` and has four configurable hyperparameters:
-- `samples_path`: path where background speech files are saved as audios (.wav files). No default.
-- `rate`: probability that any single access will result in the positive (background speech) case. Defaults to 0.25.
-- `snr_min`: lower endpoint of the range from which a signal-to-noise ratio is uniformly randomly chosen with which to add background noise to the original source. Defaults to 5.
-- `snr_max`: higher endpoint of the range from which a signal-to-noise ratio is uniformly randomly chosen with which to add background noise to the original source. Defaults to 15.
-
-#### 2.3. Sporadic noise augmentation
-For sporadic noise augmentation, the noise track is mostly silent except for intermittent short clips of noise which are added at roughly a parameterized frequency. These clips are randomly chosen and cut from a corpus of noise files to lengths according to a parameterized Gaussian distribution.
-
-**Usage**: `sporadicnoiseaugment` is an `AudioWaveformTransform` and has seven configurable hyperparameters:
-- `samples_path`: path where background noise files are saved as audios (.wav files). No default.
-- `rate`: probability that any single access will result in the positive (add a sporadic noise track) case. Defaults to 0.25.
-- `snr_min`: lower endpoint of the range from which a signal-to-noise ratio is uniformly randomly chosen with which to add background noise to the original source. Defaults to 5.
-- `snr_max`: higher endpoint of the range from which a signal-to-noise ratio is uniformly randomly chosen with which to add background noise to the original source. Defaults to 15.
-- `noise_rate`: rate in noises per second at which noise clip will be added to the original sample
-- `noise_len_mean`: mean of Gaussian normal distribution from which length of noise clip is chosen
-- `noise_len_std`: standard deviation of Gaussian normal distribution from which length of noise clip is chosen
-
-#### 2.4. Background noise augmentation
-For background noise augmentation, the noise track is a single track uniformly randomly selected from a corpus of noise files. The noise file is cut to size, including being repeated to fill the original sample length if necessary.
-
-**Usage**: `backgroundnoiseaugment` is an `AudioWaveformTransform` and has four configurable hyperparameters:
-- `samples_path`: path where background noise files are saved as audios (.wav files). No default.
-- `rate`: probability that any single access will result in the positive (background noise) case. Defaults to 0.25.
-- `snr_min`: lower endpoint of the range from which a signal-to-noise ratio is uniformly randomly chosen with which to add background noise to the original source. Defaults to 5.
-- `snr_max`: higher endpoint of the range from which a signal-to-noise ratio is uniformly randomly chosen with which to add background noise to the original source. Defaults to 15.
-
-### 3. Mixed babble and background noise augmentation with recognizable source speaker
-
-This augmentation technique is based on Algorithm 1 in [WavLM: Large-Scale Self-Supervised Pre-Training for Full Stack Speech Processing](https://arxiv.org/abs/2110.13900) and is similar to the noise augmentation suite techniques in that it has a background noise track. The noise track consists of either (1) another audio sample from the batch or (2) a background noise track. A key difference is the length of the noise track is chosen from a uniform random distribution between 0 and half of the original sample length.
-
-**Usage**: `noisyoverlapaugment` is an `AudioDatasetTransform` and has seven configurable hyperparameters:
-- `noises_path`: path where background noise files are saved as audios (.wav files). No default.
-- `rate`: probability that any single access will result in the positive (background noise) case. Defaults to 0.25.
-- `mixing_noise_rate`: probability that in a positive (background noise) case, the noise track will consist of background noise (rather than babble from the batch). Defaults to 0.1.
-- `noise_snr_min`: lower endpoint of the range from which a signal-to-noise ratio is uniformly randomly chosen with which to add background noise to the original source. Defaults to -5.
-- `noise_snr_max`: higher endpoint of the range from which a signal-to-noise ratio is uniformly randomly chosen with which to add background noise to the original source. Defaults to 5.
-- `utterance_snr_min`: lower endpoint of the range from which a signal-to-noise ratio is uniformly randomly chosen with which to add **another audio from the batch** to the original source. Defaults to -5.
-- `utterance_snr_max`: higher endpoint of the range from which a signal-to-noise ratio is uniformly randomly chosen with which to add **another audio from the batch** to the original source. Defaults to 5.
-
-## Benchmark studies
-### Evaluation on clean data
-Augmentation in training data|Hyperparameters|Training loss|BLEU (covost)|BLEU (epst)|BLEU (mtedx)
----|---|---|---|---|---
-None||3.954|24.984|23.962|24.448
-ConcatAugment|rate = 0.25, max_tokens = 3000, attempts = 5|3.940|25.322|26.124|26.19
-BabbleAugment|rate = 0.25, MUSAN speech, snr_min = (-5), snr_max = 5|3.957|24.226|23.186|22.368|
-BackgroundNoiseAugment|rate = 0.1, MUSAN noises, snr_min = (-10), snr_max = 10|3.955|24.745|23.513|23.819
-MusicAugment|rate = 0.25, MUSAN music, snr_min = 0, snr_max = 20|3.954|25.096|24.301|23.341|
-SporadicNoiseAugment|rate = 0.1, noise_rate = 0.25, MUSAN noises, snr_min = 10, snr_max = 35|3.954|24.924|23.951|23.484|
-MusicAugment + BabbleAugment + BackgroundNoiseAugment + SporadicNoiseAugment|as above, except limited rates to sum to 0.25: music (0.074), background (0.029), babble (0.074), sporadic (0.029)|3.953|24.874|23.675|24.249|
-NoisyOverlapAugment|rate = 0.25, mixing_noise_rate = 0.5, MUSAN noises, utterance_snr_min = (-10), utterance_snr_max = 0, noise_snr_min = (-5), noise_snr_max = 20|3.954|24.949|24.015|23.768|
-
-### Evaluation on data with music noise added at SNR = (-5) - 5
-Augmentation in training data|Training loss|BLEU (covost)|BLEU (epst)|BLEU (mtedx)
----|---|---|---|---
-None|3.954|15.785|21.105|16.944
-ConcatAugment|3.940|17.186|23.255|18.24
-BabbleAugment|3.957|19.158|22.064|17.116
-BackgroundNoiseAugment|3.955|17.777|22.0|17.535|
-MusicAugment|3.954|20.345|23.126|19.433|
-SporadicNoiseAugment|3.954|15.927|21.382|14.736|
-MusicAugment + BabbleAugment + BackgroundNoiseAugment + SporadicNoiseAugment|3.953|19.724|22.659|17.852|
-NoisyOverlapAugment|3.954|17.49|22.142|17.207|
-
-### Evaluation on data with babble noise added at SNR = (-5) - 5
-Augmentation in training data|Training loss|BLEU (covost)|BLEU (epst)|BLEU (mtedx)
----|---|---|---|---
-None|3.954|4.092|13.514|5.13
-ConcatAugment|3.940|5.493|15.835|6.893
-BabbleAugment|3.957|16.12|21.097|13.996
-BackgroundNoiseAugment|3.955|4.691|15.784|5.982
-MusicAugment|3.954|8.06|17.764|9.008
-SporadicNoiseAugment|3.954|4.009|13.935|4.814
-MusicAugment + BabbleAugment + BackgroundNoiseAugment + SporadicNoiseAugment|3.953|14.692|20.882|14.45
-NoisyOverlapAugment|3.954|4.032|16.434|7.284
-
-### Evaluation on data with sporadic noise added at SNR = (-5) - 5
-Augmentation in training data|Training loss|BLEU (covost)|BLEU (epst)|BLEU (mtedx)
----|---|---|---|---
-None|3.954|23.778|23.745|22.748
-ConcatAugment|3.940|24.239|25.907|25.723
-BabbleAugment|3.957|23.42|23.048|21.076
-BackgroundNoiseAugment|3.955|23.998|23.467|22.494
-MusicAugment|3.954|24.142|24.181|19.143
-SporadicNoiseAugment|3.954|23.97|23.894|22.61
-MusicAugment + BabbleAugment + BackgroundNoiseAugment + SporadicNoiseAugment|3.953|24.118|23.59|23.717
-NoisyOverlapAugment|3.954|24.265|24.103|23.167
-
-### Evaluation on data with background noise added at SNR = (-5) - 5
-Augmentation in training data|Training loss|BLEU (covost)|BLEU (epst)|BLEU (mtedx)
----|---|---|---|---
-None|3.954|20.201|22.525|19.66
-ConcatAugment|3.940|20.904|24.706|21.353
-BabbleAugment|3.957|20.687|22.374|18.907
-BackgroundNoiseAugment|3.955|21.574|22.998|20.043
-MusicAugment|3.954|21.65|23.529|19.87
-SporadicNoiseAugment|3.954|20.578|22.577|19.096
-MusicAugment + BabbleAugment + BackgroundNoiseAugment + SporadicNoiseAugment|3.953|21.811|23.144|20.986
-NoisyOverlapAugment|3.954|21.312|23.153|20.302
-
-### Evaluation on data with all four types of noises added at SNR = (-5) - 5, each applied with prob 0.5
-Augmentation in training data|Training loss|BLEU (covost)|BLEU (epst)|BLEU (mtedx)
----|---|---|---|---
-None|3.954|10.895|19.319|12.748
-ConcatAugment|3.940|13.517|21.658|15.428
-BabbleAugment|3.957|18.09|21.384|16.018
-BackgroundNoiseAugment|3.955|12.837|20.719|13.933
-MusicAugment|3.954|16.589|21.823|15.927
-SporadicNoiseAugment|3.954|11.238|19.91|13.31
-MusicAugment + BabbleAugment + BackgroundNoiseAugment + SporadicNoiseAugment|3.953|18.636|21.935|17.845
-NoisyOverlapAugment|3.954|12.829|20.856|15.048
-
-### Evaluation on data with noisy overlap augment
-Augmentation in training data|Training loss|BLEU (covost)|BLEU (epst)|BLEU (mtedx)
----|---|---|---|---
-None|3.954|21.245|22.24|20.994
-ConcatAugment|3.940|21.611|24.247|23.068
-BabbleAugment|3.957|21.867|21.987|20.099|
-BackgroundNoiseAugment|3.955|21.533|21.806|19.717|
-MusicAugment|3.954|21.823|22.643|20.847|
-SporadicNoiseAugment|3.954|21.373|22.381|20.672|
-MusicAugment + BabbleAugment + BackgroundNoiseAugment + SporadicNoiseAugment|3.953|22.206|22.414|21.375|
-NoisyOverlapAugment|3.954|23.371|23.396|22.627|
-
-## Using transforms
-Transforms are configurable.
-
-1. Please pay careful attention to the type of transform you are applying.
- - `concataugment` and `noisyoverlapaugment` are instances of `AudioDatasetTransform` and should be listed in the config under `dataset_transforms`.
- - `musicaugment`, `babbleaugment`, `sporadicnoiseaugment`, and `backgroundnoiseaugment` are instances of `AudioWaveformTransform` and should be listed under `waveform_transforms`.
- - Instances of `AudioFeatureTransform` should be listed under `feature_transforms`.
-2. Feel free to apply these augmentations in different contexts, e.g., you may use a `_train` or `_eval` flag to specify when the transform will be applied. If the dataset at hand contains `train` in its name, those transforms under the `_train` flag will be applied; else, the remaining transforms will be applied.
-
-For example, you would add this to your config to apply the musicaugment transform to a training dataset:
-```yaml
-musicaugment:
- samples_path: ${MUSIC_PATH}
- snr_min: 10
- snr_max: 15
- rate: 0.25
-waveform_transforms:
- _train:
- - musicaugment
-```
-or add this to apply the concataugment transform:
-```yaml
-concataugment:
- rate: 0.25
- max_tokens: 3000
- attempts: 5
-dataset_transforms:
- _train:
- - concataugment
- ```
-You may also want to add multiple of one type of transform; here, we add multiple `AudioWaveformTransform`s:
-```yaml
-musicaugment:
- samples_path: ${MUSIC_PATH}
- snr_min: 5
- snr_max: 20
- rate: 0.25
-backgroundnoiseaugment:
- samples_path: ${NOISES_PATH}
- snr_min: 10
- snr_max: 20
- rate: 0.1
-sporadicnoiseaugment:
- samples_path: ${NOISES_PATH}
- snr_min: 5
- snr_max: 15
- rate: 0.1
- noise_rate: 0.25
-waveform_transforms:
- _train:
- - musicaugment
- - backgroundnoiseaugment
- - sporadicnoiseaugment
-```
-
-## Adding your own transforms
-Note: We store transform implementations in `fairseq/data/audio/*_transforms` directories. You may refer to these as examples while implementing your own transform.
-
-### Step 1. Picking the right class for your transform
-The integration into SpeechToTextDataset is quite different for each kind of transform, so it is important to understand which one is best suited to your purposes.
-
-**Feature transforms**
-`AudioFeatureTransform` is a base class which allows **some transform to be applied to audio spectrograms** in the data loading step. One thing to note is that the source data is either saved as `np.ndarrays` or as audio files, and is to be returned either as features (spectrogram) or waveform. If and only if the data is to be returned as a spectrogram, then `AudioFeatureTransform`s will be applied.
-
-**Waveform transforms**
-`AudioWaveformTransform` is a base class which allows some **transform to be applied to waveforms** in the data loading step. As mentioned above, there are two source and return types to data loading for this dataset. If and only if the data is saved in audio file format, then `AudioWaveformTransform`s will be applied, whichever return type is used.
-
-**Dataset transforms**
-`AudioDatasetTransform` is a base class for transforms **based on more than one item in a dataset**, ex. concatenation of two random samples in a dataset. Rather than being applied in a consistent way, i.e., to all features or to all waveforms, the integration of a dataset transform is entirely specific. Adding a dataset transform requires actually editing the `fairseq/data/audio/speech_to_text_dataset.py` file.
-
-### Step 2. Setting up your transform (generic to all types of transforms)
-Now that you know which kind of transform you would like to use, we are ready to implement it. This step is generic for all transform types, i.e., `TRANSFORM_TYPE` may be any of `feature`, `waveform`, or `dataset`. We will show how to build utterance concatenation (an `AudioDatasetTransform`) as an example.
-
-Import the base class and registration function for your transform.
-```python
-from fairseq.data.audio.dataset_transforms import (
- AudioDatasetTransform,
- register_audio_dataset_transform
-)
-```
-
-Define the class and register the transform. The name passed into the registration function is how your transform should be named in the config.
-```python
-@register_audio_dataset_transform("concataugment")
-class ConcatAugment(AudioDatasetTransform):
-```
-
-We are now ready to add the basic important functions to our new class. In this example, `_DEFAULTS` refers to a dictionary with the default hyperparameter values that we defined. `from_config_dict` is called to instantiate the transform given hyperparameters from the config.
-```python
- @classmethod
- def from_config_dict(cls, config=None):
- _config = {} if config is None else config
- return ConcatAugment(
- _config.get("rate", _DEFAULTS["rate"]),
- _config.get("max_tokens", _DEFAULTS["max_tokens"]),
- _config.get("attempts", _DEFAULTS["attempts"]),
- )
-```
-We edit the instantiation function `__init__` to track hyperparameters and do any setup work.
-```python
- def __init__(
- self,
- rate=_DEFAULTS["rate"],
- max_tokens=_DEFAULTS["max_tokens"],
- attempts=_DEFAULTS["attempts"],
- ):
- self.rate, self.max_tokens, self.attempts = rate, max_tokens, attempts
-```
-Lastly `__repr__` gives how the transform will be reported in an output log.
-```python
- def __repr__(self):
- return (
- self.__class__.__name__
- + "("
- + ", ".join(
- [
- f"rate={self.rate}",
- f"max_tokens={self.max_tokens}",
- f"attempts={self.attempts}",
- ]
- )
- + ")"
- )
-```
-
-### Step 3. Adding the transform logic
-At this point, we are ready to implement the actual transform logic. The flow from here is different for each of the three transforms, so follow the path that is relevant to you.
-### ...for feature transforms
-The final step is implementing the `__call__` function, which applies the transform logic and **returns** the spectrogram with transform applied. This supports and should take exactly **two arguments**:
-- `self`
-- `x` (np.ndarray): the spectrogram for one source sample. (This is a positional argument, so you can use another parameter name like `spectrogram` instead of `x`.)
-
-For example, this is the `__call__` function for GlobalCMVN (cepstral mean and variance normalization).
-```python
- def __call__(self, x):
- x = np.subtract(x, self.mean)
- x = np.divide(x, self.std)
- return x
-
-```
-### ...for waveform transforms
-The final step is implementing the `__call__` function, which applies the transform logic. This supports and should take exactly **three arguments**:
-- `self`
-- `source` (numpy.ndarray or torch.Tensor): source audio 2d waveform (channels x length)
-- `sample_rate` (optional, defaults to None): sample rate of `source`
-
-`__call__` **returns**:
-- transformed audio waveform
-- sample rate of transformed audio waveform
-
-For example, this is the `__call__` function for augmentations in the Noise Augmentation Suite.
-```python
- def __call__(self, source, sample_rate=None):
- if np.random.random() > self.rate:
- return source
-
- noise = self._get_noise(
- source.shape, always_2d=True, use_sample_rate=sample_rate
- )
- return self._mix(source, noise, rand_uniform(self.snr_min, self.snr_max)), sample_rate
-```
-
-### ...for dataset transforms
-Dataset transforms are extremely flexible, and implementation involves directly integrating them into `fairseq/data/audio/speech_to_text_dataset.py` in transform-specific ways.
-There are two basic components: (1) check whether or not this transform is part of this dataset instance using `self.dataset_transforms.has_transform(TRANSFORM_CLS)`, and (2) if so, get the transform using `self.dataset_transforms.get_transform(TRANSFORM_CLS)` & apply it.
-Due to the case-by-case specificity, it is easier to demonstrate this by examples.
-
-#### Example: NoisyOverlapAugment
-This transform requires access to multiple items within the same batch at once.
-
-**Logic**: We still use the transform classes to keep away the transform logic. For example, `__call__` of `NoisyOverlapAugment` class takes a list of source tokens for items in a mini-batch, applies noise/utterance as dictated by the transform, and returns the list of transformed source tokens for items in the mini-batch.
-
-```python
- def __call__(self, sources):
- for i, source in enumerate(sources):
- if np.random.random() > self.rate:
- continue
-
- pri = source.numpy()
-
- # ... some transform code omitted
-
- pri[s_source : s_source + l] = np.add(
- pri[s_source : s_source + l], np.multiply(scl, sec[s_sec : s_sec + l])
- )
- sources[i] = torch.from_numpy(pri).float()
-
- return sources
-```
-
-**Integration**: The `collater` function for `SpeechToTextDataset` is responsible for preparing a mini-batch for training, so we integrate NOAug through adding a few lines to the top of this function:
-```python
-def collater(
- self, samples: List[SpeechToTextDatasetItem], return_order: bool = False
-) -> Dict:
- if len(samples) == 0:
- return {}
- indices = torch.tensor([x.index for x in samples], dtype=torch.long)
-
- sources = [x.source for x in samples]
-
- # NOAUG INTEGRATION BLOCK
- # (1) Check whether or not this transform is part of this dataset instance
- has_NOAug = self.dataset_transforms.has_transform(NoisyOverlapAugment)
- # (2) If so, get & apply the transform
- if has_NOAug and self.cfg.use_audio_input:
- NOAug = self.dataset_transforms.get_transform(NoisyOverlapAugment)
- sources = NOAug(sources)
-
- frames = _collate_frames(sources, self.cfg.use_audio_input)
- # sort samples by descending number of frames
- n_frames = torch.tensor([x.size(0) for x in sources], dtype=torch.long)
- n_frames, order = n_frames.sort(descending=True)
- indices = indices.index_select(0, order)
- frames = frames.index_select(0, order)
-
- # ... rest of function
-```
-
-#### Example: ConcatAugment
-This transform requires access to another item within the dataset at once.
-
-**Logic**: We abstract the logic for picking indices to concatenate by adding a `find_indices` function to the `ConcatAugment` class, which takes one index in the dataset and finds a compatible second index to concatenate source and target tokens.
-```python
- def find_indices(self, index: int, n_frames: List[int], n_samples: int):
- # skip conditions: application rate, max_tokens limit exceeded
- if np.random.random() > self.rate:
- return [index]
- if self.max_tokens and n_frames[index] > self.max_tokens:
- return [index]
-
- # pick second sample to concatenate
- for _ in range(self.attempts):
- index2 = np.random.randint(0, n_samples)
- if index2 != index and (
- not self.max_tokens
- or n_frames[index] + n_frames[index2] < self.max_tokens
- ):
- return [index, index2]
-
- return [index]
-```
-
-**Integration**: `SpeechToTextDataset` uses a custom `__getitem__(self, index)` function (called in the background when you write `dataset[i]`). We edited this function (as well as `_get_source_audio` and `get_tokenized_tgt_text`) to achieve the desired transform effect where accessing `dataset[i]` will return a `SpeechToTextDatasetItem` where `source=source[i]+source[j]` and `target=target[i]+target[j]`.
-```python
-def __getitem__(self, index: int) -> SpeechToTextDatasetItem:
-
- # CONCATAUGMENT INTEGRATION BLOCK
- # (1) Check whether or not this transform is part of this dataset instance
- has_concat = self.dataset_transforms.has_transform(ConcatAugment)
- # (2) If so, get & apply the transform
- if has_concat:
- concat = self.dataset_transforms.get_transform(ConcatAugment)
- indices = concat.find_indices(index, self.n_frames, self.n_samples)
-
- source = self._get_source_audio(indices if has_concat else index)
- source = self.pack_frames(source)
-
- target = None
- if self.tgt_texts is not None:
- tokenized = self.get_tokenized_tgt_text(indices if has_concat else index)
- target = self.tgt_dict.encode_line(
-
- # ... rest of function
-```
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/docs/direct_s2st_discrete_units.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/docs/direct_s2st_discrete_units.md
deleted file mode 100644
index 0c63ffee1cc4eff67cb3b761e4771dbf33f36e1a..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/docs/direct_s2st_discrete_units.md
+++ /dev/null
@@ -1,181 +0,0 @@
-# Direct speech-to-speech translation with discrete units
-
-We provide the implementation for speech-to-unit translation (S2UT) proposed in "[Direct speech-to-speech translation with discrete units (Lee et al. 2021)](https://arxiv.org/abs/2107.05604)" and also the transformer-based implementation of the speech-to-spectrogram translation (S2SPECT, or transformer-based [Translatotron](https://arxiv.org/abs/1904.06037)) baseline in the paper.
-
-## Pretrained Models
-
-### Unit-based HiFi-GAN Vocoder
-Unit config | Unit size | Vocoder dataset | Model
-|---|---|---|---
-[HuBERT Base, Librispeech](https://github.com/fairinternal/fairseq-py/tree/main/examples/hubert), layer 6 | 100 | [LJSpeech](https://keithito.com/LJ-Speech-Dataset/) | [ckpt](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/vocoder/code_hifigan/hubert_base_100_lj/g_00500000), [config](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/vocoder/code_hifigan/hubert_base_100_lj/config.json)
-
-
-## Data preparation
-### Target speech
-0. (optional) To prepare S2S data from a speech-to-text translation (ST) dataset, see [fairseq-S^2](https://github.com/pytorch/fairseq/tree/main/examples/speech_synthesis) for pre-trained TTS models and instructions on how to train and decode TTS models.
-1. Prepare two folders, `$SRC_AUDIO` and `$TGT_AUDIO`, with `${SPLIT}/${SAMPLE_ID}.wav` for source and target speech under each folder, separately. Note that for S2UT experiments, target audio sampling rate should be in 16,000 Hz, and for S2SPECT experiments, target audio sampling rate is recommended to be in 22,050 Hz.
-2. To prepare target discrete units for S2UT model training, see [Generative Spoken Language Modeling (speech2unit)](https://github.com/pytorch/fairseq/tree/main/examples/textless_nlp/gslm/speech2unit) for pre-trained k-means models, checkpoints, and instructions on how to decode units from speech. Set the output target unit files (`--out_quantized_file_path`) as `${TGT_AUDIO}/${SPLIT}.txt`. In [Lee et al. 2021](https://arxiv.org/abs/2107.05604), we use 100 units from the sixth layer (`--layer 6`) of the HuBERT Base model.
-
-### Formatting data
-**Speech-to-speech data**
-
-_S2UT_
- * Set `--reduce-unit` for training S2UT _reduced_ model
- * Pre-trained vocoder and config (`$VOCODER_CKPT`, `$VOCODER_CFG`) can be downloaded from the **Pretrained Models** section. They are not required if `--eval-inference` is not going to be set during model training.
-```
-# $SPLIT1, $SPLIT2, etc. are split names such as train, dev, test, etc.
-
-python examples/speech_to_speech/preprocessing/prep_s2ut_data.py \
- --source-dir $SRC_AUDIO --target-dir $TGT_AUDIO --data-split $SPLIT1 $SPLIT2 \
- --output-root $DATA_ROOT --reduce-unit \
- --vocoder-checkpoint $VOCODER_CKPT --vocoder-cfg $VOCODER_CFG
-```
-
-_S2SPECT_
-```
-# $SPLIT1, $SPLIT2, etc. are split names such as train, dev, test, etc.
-
-python examples/speech_to_speech/preprocessing/prep_s2spect_data.py \
- --source-dir $SRC_AUDIO --target-dir $TGT_AUDIO --data-split $SPLIT1 $SPLIT2 \
- --output-root $DATA_ROOT
-```
-
-**Multitask data**
- * For each multitask `$TASK_NAME`, prepare `${DATA_ROOT}/${TASK_NAME}/${SPLIT}.tsv` files for each split following the format below: (Two tab separated columns. The sample_ids should match with the sample_ids for the speech-to-speech data in `${DATA_ROOT}/${SPLIT}.tsv`.)
-```
-id tgt_text
-sample_id_0 token1 token2 token3 ...
-sample_id_1 token1 token2 token3 ...
-...
-```
- * For each multitask `$TASK_NAME`, prepare `${DATA_ROOT}/${TASK_NAME}/dict.txt`, a dictionary in fairseq format with all tokens for the targets for `$TASK_NAME`.
- * Create `config_multitask.yaml`. Below is an example of the config used for S2UT _reduced_ with Fisher experiments including two encoder multitasks (`source_letter`, `target_letter`) and one decoder CTC task (`decoder_target_ctc`).
-```
-source_letter: # $TASK_NAME
- decoder_type: transformer
- dict: ${DATA_ROOT}/source_letter/dict.txt
- data: ${DATA_ROOT}/source_letter
- encoder_layer: 6
- loss_weight: 8.0
-target_letter:
- decoder_type: transformer
- dict: ${DATA_ROOT}/target_letter/dict.txt
- data: ${DATA_ROOT}/target_letter
- encoder_layer: 8
- loss_weight: 8.0
-decoder_target_ctc:
- decoder_type: ctc
- dict: ${DATA_ROOT}/decoder_target_ctc/dict.txt
- data: ${DATA_ROOT}/decoder_target_ctc
- decoder_layer: 3
- loss_weight: 1.6
-```
-
-
-## Training
-
-**Speech-to-unit translation (S2UT)**
-
-Here's an example for training Fisher S2UT models with 100 discrete units as target:
-```
-fairseq-train $DATA_ROOT \
- --config-yaml config.yaml --multitask-config-yaml config_multitask.yaml \
- --task speech_to_speech --target-is-code --target-code-size 100 --vocoder code_hifigan \
- --criterion speech_to_unit --label-smoothing 0.2 \
- --arch s2ut_transformer_fisher --share-decoder-input-output-embed \
- --dropout 0.1 --attention-dropout 0.1 --relu-dropout 0.1 \
- --train-subset train --valid-subset dev \
- --save-dir ${MODEL_DIR} \
- --lr 0.0005 --lr-scheduler inverse_sqrt --warmup-init-lr 1e-7 --warmup-updates 10000 \
- --optimizer adam --adam-betas "(0.9,0.98)" --clip-norm 10.0 \
- --max-update 400000 --max-tokens 20000 --max-target-positions 3000 --update-freq 4 \
- --seed 1 --fp16 --num-workers 8
-```
-* Adjust `--update-freq` accordingly for different #GPUs. In the above we set `--update-freq 4` to simulate training with 4 GPUs.
-* Set `--n-frames-per-step 5` to train an S2UT _stacked_ system with reduction ratio r=5. (Use `$DATA_ROOT` prepared without `--reduce-unit`.)
-* (optional) one can turn on tracking MCD loss during training for checkpoint selection by setting `--eval-inference --eval-args '{"beam": 1, "max_len_a": 1}' --best-checkpoint-metric mcd_loss`. It is recommended to sample a smaller subset as the validation set as MCD loss computation is time-consuming.
-
-**Speech-to-spectrogram translation (S2SPECT)**
-
-Here's an example for training Fisher S2SPECT models with reduction ratio r=5:
-```
-fairseq-train $DATA_ROOT \
- --config-yaml config.yaml --multitask-config-yaml config_multitask.yaml \
- --task speech_to_speech --n-frames-per-step 5 \
- --criterion speech_to_spectrogram \
- --arch s2spect_transformer_fisher --decoder-normalize-before \
- --dropout 0.1 --attention-dropout 0.1 --relu-dropout 0.1 \
- --train-subset train --valid-subset dev \
- --save-dir ${MODEL_DIR} \
- --eval-inference --best-checkpoint-metric mcd_loss \
- --lr 0.0005 --lr-scheduler inverse_sqrt --warmup-init-lr 1e-7 --warmup-updates 10000 \
- --optimizer adam --adam-betas "(0.9,0.98)" --clip-norm 10.0 --weight-decay 1e-6 \
- --max-update 400000 --max-tokens 80000 --max-tokens-valid 30000 --required-batch-size-multiple 1 \
- --max-target-positions 3000 --update-freq 16 \
- --seed 1 --fp16 --num-workers 8
-```
-* Adjust `--update-freq` accordingly for different #GPUs. In the above we set `--update-freq 16` to simulate training with 16 GPUs.
-* We recommend turning on MCD loss during training for the best checkpoint selection.
-
-**Unit-based HiFi-GAN vocoder**
-
-The vocoder is trained with the [speech-resynthesis repo](https://github.com/facebookresearch/speech-resynthesis). See [here](https://github.com/facebookresearch/speech-resynthesis/tree/main/examples/speech_to_speech_translation) for instructions on how to train the unit-based HiFi-GAN vocoder with duration prediction. The same vocoder can support waveform generation for both _reduced_ unit sequences (with `--dur-prediction` set during inference) and original unit sequences.
-
-## Inference
-
-**Speech-to-unit translation (S2UT)**
-
-1. Follow the same inference process as in [fairseq-S2T](https://github.com/pytorch/fairseq/tree/main/examples/speech_to_text) to generate unit sequences (`${RESULTS_PATH}/generate-${GEN_SUBSET}.txt`).
-```
-fairseq-generate $DATA_ROOT \
- --config-yaml config.yaml --multitask-config-yaml config_multitask.yaml \
- --task speech_to_speech --target-is-code --target-code-size 100 --vocoder code_hifigan \
- --path $MODEL_DIR/checkpoint_best.pt --gen-subset $GEN_SUBSET \
- --max-tokens 50000 \
- --beam 10 --max-len-a 1 \
- --results-path ${RESULTS_PATH}
-```
- * Set `--beam 1 --n-frames-per-step $r` for decoding with S2UT _stacked_ models.
-
-2. Convert unit sequences to waveform.
-```
-grep "^D\-" ${RESULTS_PATH}/generate-${GEN_SUBSET}.txt | \
- sed 's/^D-//ig' | sort -nk1 | cut -f3 \
- > ${RESULTS_PATH}/generate-${GEN_SUBSET}.unit
-
-python examples/speech_to_speech/generate_waveform_from_code.py \
- --in-code-file ${RESULTS_PATH}/generate-${GEN_SUBSET}.unit \
- --vocoder $VOCODER_CKPT --vocoder-cfg $VOCODER_CFG \
- --results-path ${RESULTS_PATH} --dur-prediction
-```
- * Set `--dur-prediction` for generating audio for S2UT _reduced_ models.
-
-
-**Speech-to-spectrogram translation (S2SPECT)**
-
-Follow the same inference process as in [fairseq-S^2](https://github.com/pytorch/fairseq/tree/main/examples/speech_synthesis) to generate waveform.
-
-```
-# assume using a default Griffin-Lim vocoder
-
-python examples/speech_synthesis/generate_waveform.py $DATA_ROOT \
- --config-yaml config.yaml --multitask-config-yaml config_multitask.yaml \
- --task speech_to_speech --n-frames-per-step 5 \
- --path $MODEL_DIR/checkpoint_best.pt --gen-subset $GEN_SUBSET \
- --max-tokens 50000 \
- --results-path ${RESULTS_PATH} --dump-waveforms --output-sample-rate 16000
-```
-
-In addition to using the default Griffin-Lim vocoder, one can also finetune a HiFi-GAN vocoder for the S2SPECT model by following the instructions in the [HiFi-GAN repo](https://github.com/jik876/hifi-gan).
-
-**Multitask decoding**
-
-Coming soon.
-
-## Evaluation
-
-To evaluate speech translation output, we first apply ASR on the speech output and then compute BLEU score betweent the ASR decoded text and the references using sacreBLEU.
-
-**En**
-* ASR: We use the "[Wav2Vec 2.0 Large (LV-60) + Self Training / 960 hours / Libri-Light + Librispeech](https://dl.fbaipublicfiles.com/fairseq/wav2vec/wav2vec_vox_960h_pl.pt)" En ASR model open-sourced by the [wav2vec](https://github.com/pytorch/fairseq/tree/main/examples/wav2vec) project. See [instructions](https://github.com/pytorch/fairseq/tree/main/examples/wav2vec#evaluating-a-ctc-model) on how to run inference with a wav2vec-based ASR model. The model is also available on [Hugging Face](https://huggingface.co/facebook/wav2vec2-large-960h-lv60-self).
-* Text normalization: We use the text cleaner at [https://github.com/keithito/tacotron](https://github.com/keithito/tacotron) for pre-processing reference English text for ASR BLEU evaluation.
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/docs/enhanced_direct_s2st_discrete_units.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/docs/enhanced_direct_s2st_discrete_units.md
deleted file mode 100644
index fbfa5dd16a760e8babe039cb74c1df8b644a89fe..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/docs/enhanced_direct_s2st_discrete_units.md
+++ /dev/null
@@ -1,125 +0,0 @@
-# Speech to speech translation (S2ST)
-
-We provide the implementation for speech-to-unit translation (S2UT) proposed in [Enhanced Direct Speech-to-Speech Translation Using Self-supervised Pre-training and Data Augmentation (Popuri et al. 2022)](https://arxiv.org/abs/2204.02967) and the various pretrained models used.
-
-## Pretrained Models
-
-### Unit extraction
-
-We used the multilingual HuBERT model open sourced in [Textless S2ST with Real Data](textless_s2st_real_data.md)
-
-### Wav2vec 2.0
-
-Language | Block type | Model size | Dataset | Model |
---- | --- | --- | --- | --- |
-Es | Transformer | BASE | Voxpopuli | [ckpt](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/w2v2/es/transformer_B.pt) |
-Es | Transformer | LARGE | Voxpopuli | [ckpt](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/w2v2/es/transformer_L.pt) |
-Es | Conformer | LARGE | Voxpopuli | [ckpt](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/w2v2/es/conformer_L.pt) |
-En | Transformer | BASE | Librilight| [ckpt](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/w2v2/en/transformer_B.pt) |
-En | Conformer | LARGE | Librilight | [ckpt](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/w2v2/en/conformer_L.pt) |
-
-### Unit mBART
-
-Unit size | Dataset | Unit config | Model |
---- | --- | --- | --- |
-1000 | [Voxpopuli](https://aclanthology.org/2021.acl-long.80) En, Es unlabelled speech | [mbart_large](https://github.com/pytorch/fairseq/blob/f591cc94caa85098ccf125a4782f91125b6a086d/fairseq/models/bart/model.py#L368) |[ckpt](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/unit_mBART/checkpoint.pt) |
-
-## Data preparation
-
-1. To prepare data for S2UT finetuning, follow the steps from [Direct S2ST with Discrete Units](./direct_s2st_discrete_units.md) and format the data in the _S2UT_ format. Note that we use 1000 units from the eleventh layer (`--layer 11`) of the multilingual hubert model linked above instead
-2. Run
-
-```
-var="id\taudio\tn_frames\ttgt_text\ttgt_n_frames"
-sed -i "1s/.*/$var/" ${SPLIT}.tsv
-```
-
-## Training
-
-**Speech-to-unit translation (S2UT)**
-
-Here's an example for finetuning S2UT models with 1000 discrete units as target. You can download the sample [config](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/config.yaml) file and [vocabulary](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/dict.txt) for Es-En from here:
-
-```
-fairseq-train $DATA_ROOT \
- --config-yaml config.yaml \
- --task speech_to_text --arch xm_transformer\
- --criterion l --label-smoothing 0.2 \
- --share-decoder-input-output-embed --adaptor-n-layers 1 --normalize\
- --dropout 0.1 --attention-dropout 0.1 --relu-dropout 0.1 \
- --train-subset train --valid-subset dev \
- --load-pretrained-decoder-from ${unit_mBART} --w2v-path ${wav2vec2.0} \
- --mask-prob 0.3 --mask-channel-length 32 --mask-channel-prob 0.25\
- --save-dir ${MODEL_DIR} --checkpoint-activations --encoder-proj \
- --lr 0.0005 --dropout 0.1 --attention-dropout 0.1 --lr-scheduler inverse_sqrt\
- --warmup-init-lr 1e-7 --warmup-updates 10000 \
- --optimizer adam --adam-betas "(0.9,0.98)" --clip-norm 10.0 \
- --max-update 20000 --max-tokens 4000 --max-tokens-valid 4000 --max-source-positions 4000 \
- --max-target-positions 4000 --update-freq 120 \
- --seed 1 --fp16 --num-workers 1
-```
-
-* Adjust `--update-freq` accordingly for different #GPUs. In the above we set `--update-freq 15` to simulate training with 120 GPUs.
-* In the above setting we finetune the model end to end, corresponding to the full setup in the paper.
-* To apply LNA-E partial finetuning, add `--finetune-w2v-params layer_norm,self_attn`
-* For LNA-D partial finetuning add `--finetune-decoder-params encoder_attn,layer_norm,self_attn`. To optionally freeze the encoder by k updates, use `--freeze-finetune-updates ${K}`
-* For LNA-E,D partial finetuning add both the above options.
-
-**Unit-based HiFi-GAN vocoder**
-
-We apply the open-sourced unit-based HiFi-GAN vocoders to convert the predicted unit sequences to waveform. They are open sourced in [Textless S2ST with Real Data](textless_s2st_real_data.md)
-
-## Inference
-
-**Speech-to-unit translation (S2UT)**
-
-1. Follow the same inference process as in [fairseq-S2T](https://github.com/pytorch/fairseq/tree/main/examples/speech_to_text) to generate unit sequences (`${RESULTS_PATH}/generate-${GEN_SUBSET}.txt`).
-
-```
-fairseq-generate $DATA_ROOT \
- --config-yaml config.yaml \
- --task speech_to_text \
- --path $MODEL_DIR/checkpoint_best.pt --gen-subset $GEN_SUBSET \
- --max-tokens 10000 --max-source-positions 10000 --max-target-positions 10000\
- --beam 10 --max-len-a 1 --max-len-b 200 \
- --results-path ${RESULTS_PATH}
-```
-
-2. Convert unit sequences to waveform.
-
-```
-grep "^D\-" ${RESULTS_PATH}/generate-${GEN_SUBSET}.txt | \
- sed 's/^D-//ig' | sort -nk1 | cut -f3 \
- > ${RESULTS_PATH}/generate-${GEN_SUBSET}.unit
-
-python examples/speech_to_speech/generate_waveform_from_code.py \
- --in-code-file ${RESULTS_PATH}/generate-${GEN_SUBSET}.unit \
- --vocoder $VOCODER_CKPT --vocoder-cfg $VOCODER_CFG \
- --results-path ${RESULTS_PATH} --dur-prediction
-```
-
-## Evaluation
-
-To evaluate speech translation output, we first apply ASR on the speech output and then compute BLEU score betweent the ASR decoded text and the references using sacreBLEU.
-
-* Text normalization: We use the text cleaner at [https://github.com/keithito/tacotron](https://github.com/keithito/tacotron) for pre-processing reference English text for ASR BLEU evaluation. The text cleaner used for Spanish text normalization will be updated here shortly.
-* En ASR: We use the "[Wav2Vec 2.0 Large (LV-60) + Self Training / 960 hours / Libri-Light + Librispeech](https://dl.fbaipublicfiles.com/fairseq/wav2vec/wav2vec_vox_960h_pl.pt)" En ASR model open-sourced by the [wav2vec](https://github.com/pytorch/fairseq/tree/main/examples/wav2vec) project. The model is also available on [Hugging Face](https://huggingface.co/facebook/wav2vec2-large-960h-lv60-self).
-* Es ASR: We use the [Wav2Vec2-Large-XLSR-53-Spanish](https://huggingface.co/facebook/wav2vec2-large-xlsr-53) finetuned on spanish Common Voice Es ASR model open-sourced by Jonatasgrosman() on [Hugging Face](https://huggingface.co/jonatasgrosman/wav2vec2-large-xlsr-53-spanish).
-* See [instructions](https://github.com/pytorch/fairseq/tree/main/examples/wav2vec#evaluating-a-ctc-model) on how to run inference with a wav2vec-based ASR model.
-
-
-## Finetuned Model Checkpoints
-
-ID | En - Es | Es - En |
-| --- | --- | --- |
-**S2UT systems without pre-training**
-S2UT with multitask | [checkpoint](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/en_es//S2UT_w_multitask.pt) | [checkpoint](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/es_en//S2UT_w_multitask.pt) |
-**S2UT systems with model pre-training**
-w2v2-L | [checkpoint](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/en_es//w2v2_only.pt ) | [checkpoint](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/es_en//w2v2_only.pt) |
-w2v2-L + mBART (LNA-E) | [checkpoint](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/en_es//w2v2_mbart_LNE.pt) | [checkpoint](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/es_en//w2v2_mbart_LNE.pt) |
-w2v2-L + mBART (LNA-D) | [checkpoint](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/en_es//w2v2_mbart_LND.pt) | [checkpoint](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/es_en//w2v2_mbart_LND.pt) |
-w2v2-L + mBART (LNA-E,D) | [checkpoint](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/en_es//w2v2_mbart_LNED.pt) | [checkpoint](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/es_en//w2v2_mbart_LNED.pt) |
-**S2UT systems with model pre-training and data augmentation**
-w2v2-L + mBART (LNA-D) | [checkpoint](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/en_es//w2v2_mbart_LND_w_ASR.pt) | [checkpoint](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/s2st_finetuning/es_en//w2v2_mbart_LND_w_ASR.pt) |
-
-Note: Some of the tasks use speech_to_text_sharded task which is yet to be open sourced. So make sure to override the task to speech_to_text to use those models.
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/docs/textless_s2st_real_data.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/docs/textless_s2st_real_data.md
deleted file mode 100644
index ca6044be1ac9abf21cdcc91e1024ef64fb93cdcc..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/docs/textless_s2st_real_data.md
+++ /dev/null
@@ -1,89 +0,0 @@
-# Textless Speech-to-Speech Translation (S2ST) on Real Data
-
-We provide instructions and pre-trained models for the work "[Textless Speech-to-Speech Translation on Real Data (Lee et al. 2021)](https://arxiv.org/abs/2112.08352)".
-
-## Pre-trained Models
-
-### HuBERT
-Model | Pretraining Data | Model | Quantizer
-|---|---|---|---
-mHuBERT Base | [VoxPopuli](https://github.com/facebookresearch/voxpopuli) En, Es, Fr speech from the 100k subset | [download](https://dl.fbaipublicfiles.com/hubert/mhubert_base_vp_en_es_fr_it3.pt) | [L11 km1000](https://dl.fbaipublicfiles.com/hubert/mhubert_base_vp_en_es_fr_it3_L11_km1000.bin)
-
-
-### Unit-based HiFi-GAN vocoder
-Unit config | Unit size | Vocoder language | Dataset | Model
-|---|---|---|---|---
-mHuBERT, layer 11 | 1000 | En | [LJSpeech](https://keithito.com/LJ-Speech-Dataset/) | [ckpt](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/vocoder/code_hifigan/mhubert_vp_en_es_fr_it3_400k_layer11_km1000_lj/g_00500000), [config](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/vocoder/code_hifigan/mhubert_vp_en_es_fr_it3_400k_layer11_km1000_lj/config.json)
-mHuBERT, layer 11 | 1000 | Es | [CSS10](https://github.com/Kyubyong/css10) | [ckpt](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/vocoder/code_hifigan/mhubert_vp_en_es_fr_it3_400k_layer11_km1000_es_css10/g_00500000), [config](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/vocoder/code_hifigan/mhubert_vp_en_es_fr_it3_400k_layer11_km1000_es_css10/config.json)
-mHuBERT, layer 11 | 1000 | Fr | [CSS10](https://github.com/Kyubyong/css10) | [ckpt](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/vocoder/code_hifigan/mhubert_vp_en_es_fr_it3_400k_layer11_km1000_fr_css10/g_00500000), [config](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/vocoder/code_hifigan/mhubert_vp_en_es_fr_it3_400k_layer11_km1000_fr_css10/config.json)
-
-
-### Speech normalizer
-Language | Training data | Target unit config | Model
-|---|---|---|---
-En | 10 mins | mHuBERT, layer 11, km1000 | [download](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/speech_normalizer/en/en_10min.tar.gz)
-En | 1 hr | mHuBERT, layer 11, km1000 | [download](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/speech_normalizer/en/en_1h.tar.gz)
-En | 10 hrs | mHuBERT, layer 11, km1000 | [download](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/speech_normalizer/en/en_10h.tar.gz)
-Es | 10 mins | mHuBERT, layer 11, km1000 | [download](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/speech_normalizer/es/es_10min.tar.gz)
-Es | 1 hr | mHuBERT, layer 11, km1000 | [download](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/speech_normalizer/es/es_1h.tar.gz)
-Es | 10 hrs | mHuBERT, layer 11, km1000 | [download](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/speech_normalizer/es/es_10h.tar.gz)
-Fr | 10 mins | mHuBERT, layer 11, km1000 | [download](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/speech_normalizer/fr/fr_10min.tar.gz)
-Fr | 1 hr | mHuBERT, layer 11, km1000 | [download](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/speech_normalizer/fr/fr_1h.tar.gz)
-Fr | 10 hrs | mHuBERT, layer 11, km1000 | [download](https://dl.fbaipublicfiles.com/fairseq/speech_to_speech/speech_normalizer/fr/fr_10h.tar.gz)
-
-* Refer to the paper for the details of the training data.
-
-## Inference with Pre-trained Models
-
-### Speech normalizer
-1. Download the pre-trained models, including the dictionary, to `DATA_DIR`.
-2. Format the audio data.
-```bash
-# AUDIO_EXT: audio extension, e.g. wav, flac, etc.
-# Assume all audio files are at ${AUDIO_DIR}/*.${AUDIO_EXT}
-
-python examples/speech_to_speech/preprocessing/prep_sn_data.py \
- --audio-dir ${AUDIO_DIR} --ext ${AUIDO_EXT} \
- --data-name ${GEN_SUBSET} --output-dir ${DATA_DIR} \
- --for-inference
-```
-
-3. Run the speech normalizer and post-process the output.
-```bash
-mkdir -p ${RESULTS_PATH}
-
-python examples/speech_recognition/new/infer.py \
- --config-dir examples/hubert/config/decode/ \
- --config-name infer_viterbi \
- task.data=${DATA_DIR} \
- task.normalize=false \
- common_eval.results_path=${RESULTS_PATH}/log \
- common_eval.path=${DATA_DIR}/checkpoint_best.pt \
- dataset.gen_subset=${GEN_SUBSET} \
- '+task.labels=["unit"]' \
- +decoding.results_path=${RESULTS_PATH} \
- common_eval.post_process=none \
- +dataset.batch_size=1 \
- common_eval.quiet=True
-
-# Post-process and generate output at ${RESULTS_PATH}/${GEN_SUBSET}.txt
-python examples/speech_to_speech/preprocessing/prep_sn_output_data.py \
- --in-unit ${RESULTS_PATH}/hypo.units \
- --in-audio ${DATA_DIR}/${GEN_SUBSET}.tsv \
- --output-root ${RESULTS_PATH}
-```
-
-
-### Unit-to-waveform conversion with unit vocoder
-The pre-trained vocoders can support generating audio for both full unit sequences and reduced unit sequences (i.e. duplicating consecutive units removed). Set `--dur-prediction` for generating audio with reduced unit sequences.
-```bash
-# IN_CODE_FILE contains one unit sequence per line. Units are separated by space.
-
-python examples/speech_to_speech/generate_waveform_from_code.py \
- --in-code-file ${IN_CODE_FILE} \
- --vocoder ${VOCODER_CKPT} --vocoder-cfg ${VOCODER_CFG} \
- --results-path ${RESULTS_PATH} --dur-prediction
-```
-
-## Training new models
-To be updated.
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/generate_waveform_from_code.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/generate_waveform_from_code.py
deleted file mode 100644
index 82aa7acfb82ed6914cd04411d041503ac828ee30..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/generate_waveform_from_code.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import json
-import logging
-from pathlib import Path
-import random
-import soundfile as sf
-import torch
-
-from tqdm import tqdm
-
-from fairseq import utils
-from fairseq.models.text_to_speech.vocoder import CodeHiFiGANVocoder
-
-
-logging.basicConfig()
-logging.root.setLevel(logging.INFO)
-logging.basicConfig(level=logging.INFO)
-logger = logging.getLogger(__name__)
-
-
-def dump_result(args, sample_id, pred_wav, suffix=""):
- sf.write(
- f"{args.results_path}/{sample_id}{suffix}_pred.wav",
- pred_wav.detach().cpu().numpy(),
- 16000,
- )
-
-
-def load_code(in_file):
- with open(in_file) as f:
- out = [list(map(int, line.strip().split())) for line in f]
- return out
-
-
-def main(args):
- logger.info(args)
-
- use_cuda = torch.cuda.is_available() and not args.cpu
-
- with open(args.vocoder_cfg) as f:
- vocoder_cfg = json.load(f)
- vocoder = CodeHiFiGANVocoder(args.vocoder, vocoder_cfg)
- if use_cuda:
- vocoder = vocoder.cuda()
-
- multispkr = vocoder.model.multispkr
- if multispkr:
- logger.info("multi-speaker vocoder")
- num_speakers = vocoder_cfg.get(
- "num_speakers", 200
- ) # following the default in codehifigan to set to 200
- assert (
- args.speaker_id < num_speakers
- ), f"invalid --speaker-id ({args.speaker_id}) with total #speakers = {num_speakers}"
-
- data = load_code(args.in_code_file)
- Path(args.results_path).mkdir(exist_ok=True, parents=True)
- for i, d in tqdm(enumerate(data), total=len(data)):
- x = {
- "code": torch.LongTensor(d).view(1, -1),
- }
- suffix = ""
- if multispkr:
- spk = (
- random.randint(0, num_speakers - 1)
- if args.speaker_id == -1
- else args.speaker_id
- )
- suffix = f"_spk{spk}"
- x["spkr"] = torch.LongTensor([spk]).view(1, 1)
-
- x = utils.move_to_cuda(x) if use_cuda else x
- wav = vocoder(x, args.dur_prediction)
- dump_result(args, i, wav, suffix=suffix)
-
-
-def cli_main():
- parser = argparse.ArgumentParser()
- parser.add_argument(
- "--in-code-file", type=str, required=True, help="one unit sequence per line"
- )
- parser.add_argument(
- "--vocoder", type=str, required=True, help="path to the CodeHiFiGAN vocoder"
- )
- parser.add_argument(
- "--vocoder-cfg",
- type=str,
- required=True,
- help="path to the CodeHiFiGAN vocoder config",
- )
- parser.add_argument("--results-path", type=str, required=True)
- parser.add_argument(
- "--dur-prediction",
- action="store_true",
- help="enable duration prediction (for reduced/unique code sequences)",
- )
- parser.add_argument(
- "--speaker-id",
- type=int,
- default=-1,
- help="Speaker id (for vocoder that supports multispeaker). Set to -1 to randomly sample speakers.",
- )
- parser.add_argument("--cpu", action="store_true", help="run on CPU")
-
- args = parser.parse_args()
-
- main(args)
-
-
-if __name__ == "__main__":
- cli_main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/__init__.py
deleted file mode 100644
index 6264236915a7269a4d920ee8213004374dd86a9a..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/data_utils.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/data_utils.py
deleted file mode 100644
index a83a67f9549e79792e78d013a1dabccd78475185..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/data_utils.py
+++ /dev/null
@@ -1,88 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-from pathlib import Path
-from typing import List, Optional
-
-from examples.speech_to_text.data_utils import S2TDataConfigWriter
-
-
-def gen_config_yaml(
- manifest_root: Path,
- yaml_filename: str = "config.yaml",
- specaugment_policy: Optional[str] = "lb",
- feature_transform: Optional[List[str]] = None,
- input_channels: Optional[int] = 1,
- input_feat_per_channel: Optional[int] = 80,
- audio_root: str = "",
- vocoder_type: Optional[str] = None,
- vocoder_checkpoint: Optional[str] = None,
- vocoder_cfg: Optional[str] = None,
- extra=None,
-):
- manifest_root = manifest_root.absolute()
- writer = S2TDataConfigWriter(manifest_root / yaml_filename)
-
- if input_channels is not None:
- writer.set_input_channels(input_channels)
- if input_feat_per_channel is not None:
- writer.set_input_feat_per_channel(input_feat_per_channel)
- specaugment_setters = {
- "lb": writer.set_specaugment_lb_policy,
- "ld": writer.set_specaugment_ld_policy,
- "sm": writer.set_specaugment_sm_policy,
- "ss": writer.set_specaugment_ss_policy,
- }
- specaugment_setter = specaugment_setters.get(specaugment_policy, None)
- if specaugment_setter is not None:
- specaugment_setter()
-
- if feature_transform is None:
- feature_transform = []
- else:
- writer.set_feature_transforms("*", feature_transform)
-
- if specaugment_policy is not None:
- writer.set_feature_transforms("_train", feature_transform + ["specaugment"])
-
- if len(audio_root) > 0:
- writer.set_audio_root(audio_root)
-
- if (
- vocoder_type is not None
- and vocoder_checkpoint is not None
- and vocoder_cfg is not None
- ):
- writer.set_extra(
- {
- "vocoder": {
- "type": vocoder_type,
- "config": vocoder_cfg,
- "checkpoint": vocoder_checkpoint,
- }
- }
- )
-
- if extra is not None:
- writer.set_extra(extra)
- writer.flush()
-
-
-def load_units(in_file):
- out = {}
- with open(in_file) as f:
- for line in f:
- sample_id, units = line.strip().split("|", 1)
- out[sample_id] = units.split()
-
- return out
-
-
-def process_units(units, reduce=False):
- if not reduce:
- return units
-
- out = [u for i, u in enumerate(units) if i == 0 or u != units[i - 1]]
- return out
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/prep_s2spect_data.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/prep_s2spect_data.py
deleted file mode 100644
index 2748b37aef71d04451febd612a4fee9bf9c8a91a..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/prep_s2spect_data.py
+++ /dev/null
@@ -1,169 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import logging
-import os
-from pathlib import Path
-import shutil
-import torchaudio
-
-import soundfile as sf
-from tqdm import tqdm
-import pandas as pd
-
-from examples.speech_synthesis.data_utils import extract_logmel_spectrogram
-from examples.speech_to_speech.preprocessing.data_utils import gen_config_yaml
-from examples.speech_to_text.data_utils import create_zip, get_zip_manifest, save_df_to_tsv
-from fairseq.data.audio.audio_utils import convert_waveform
-
-
-logger = logging.getLogger(__name__)
-
-MANIFEST_COLUMNS = ["id", "src_audio", "src_n_frames", "tgt_audio", "tgt_n_frames"]
-
-
-def prepare_target_data(args, tgt_audios):
- feature_name = "logmelspec80"
- zip_path = args.output_root / f"{feature_name}.zip"
- if zip_path.exists():
- print(f"{zip_path} exists.")
- return zip_path
-
- feature_root = args.output_root / feature_name
- feature_root.mkdir(exist_ok=True)
-
- print("Extracting Mel spectrogram features...")
- for tgt_audio in tqdm(tgt_audios):
- sample_id = tgt_audio.stem
- waveform, sample_rate = torchaudio.load(tgt_audio.as_posix())
- waveform, sample_rate = convert_waveform(
- waveform, sample_rate, normalize_volume=args.normalize_volume,
- to_sample_rate=args.sample_rate
- )
- extract_logmel_spectrogram(
- waveform, sample_rate, feature_root / f"{sample_id}.npy",
- win_length=args.win_length, hop_length=args.hop_length,
- n_fft=args.n_fft, n_mels=args.n_mels, f_min=args.f_min,
- f_max=args.f_max
- )
- print("ZIPing features...")
- create_zip(feature_root, zip_path)
- shutil.rmtree(feature_root)
-
- return zip_path
-
-
-def process(args):
- os.makedirs(args.output_root, exist_ok=True)
-
- manifest = {}
- tgt_audios = []
- for split in args.data_split:
- print(f"Processing {split}...")
-
- manifest[split] = {c: [] for c in MANIFEST_COLUMNS}
- missing_tgt_audios = []
- src_audios = list(args.source_dir.glob(f"{split}/*.wav"))
- for src_audio in tqdm(src_audios):
- sample_id = src_audio.stem
-
- tgt_audio = args.target_dir / split / f"{sample_id}.wav"
- if not tgt_audio.is_file():
- missing_tgt_audios.append(sample_id)
- continue
-
- tgt_audios.append(tgt_audio)
-
- src_n_frames = sf.info(src_audio.as_posix()).frames
- manifest[split]["id"].append(sample_id)
- manifest[split]["src_audio"].append(src_audio.as_posix())
- manifest[split]["src_n_frames"].append(
- src_n_frames // 160
- ) # estimation of 10-ms frame for 16kHz audio
-
- print(f"Processed {len(manifest[split]['id'])} samples")
- if len(missing_tgt_audios) > 0:
- print(
- f"{len(missing_tgt_audios)} with missing target data (first 3 examples: {', '.join(missing_tgt_audios[:3])})"
- )
-
- # Extract features and pack features into ZIP
- zip_path = prepare_target_data(args, tgt_audios)
-
- print("Fetching ZIP manifest...")
- tgt_audio_paths, tgt_audio_lengths = get_zip_manifest(zip_path)
-
- print("Generating manifest...")
- for split in args.data_split:
- print(f"Processing {split}...")
-
- for sample_id in tqdm(manifest[split]["id"]):
- manifest[split]["tgt_audio"].append(tgt_audio_paths[sample_id])
- manifest[split]["tgt_n_frames"].append(tgt_audio_lengths[sample_id])
-
- out_manifest = args.output_root / f"{split}.tsv"
- print(f"Writing manifest to {out_manifest}...")
- save_df_to_tsv(pd.DataFrame.from_dict(manifest[split]), out_manifest)
-
- # Generate config YAML
- win_len_t = args.win_length / args.sample_rate
- hop_len_t = args.hop_length / args.sample_rate
- extra = {
- "features": {
- "type": "spectrogram+melscale+log",
- "sample_rate": args.sample_rate,
- "eps": 1e-5, "n_mels": args.n_mels, "n_fft": args.n_fft,
- "window_fn": "hann", "win_length": args.win_length,
- "hop_length": args.hop_length,
- "win_len_t": win_len_t, "hop_len_t": hop_len_t,
- "f_min": args.f_min, "f_max": args.f_max,
- "n_stft": args.n_fft // 2 + 1
- }
- }
- gen_config_yaml(
- args.output_root,
- audio_root=args.output_root.as_posix(),
- specaugment_policy="lb",
- feature_transform=["utterance_cmvn", "delta_deltas"],
- extra=extra,
- )
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument(
- "--source-dir", required=True, type=Path, help="source audio directory"
- )
- parser.add_argument(
- "--target-dir", required=True, type=Path, help="target audio directory"
- )
- parser.add_argument(
- "--data-split",
- default=["train", "valid", "test"],
- nargs="+",
- help="data split names",
- )
- parser.add_argument(
- "--output-root", required=True, type=Path, help="output directory"
- )
- # target feature related
- parser.add_argument("--win-length", type=int, default=1024)
- parser.add_argument("--hop-length", type=int, default=256)
- parser.add_argument("--n-fft", type=int, default=1024)
- parser.add_argument("--n-mels", type=int, default=80)
- parser.add_argument("--f-min", type=int, default=20)
- parser.add_argument("--f-max", type=int, default=8000)
- parser.add_argument("--sample-rate", type=int, default=22050)
- parser.add_argument("--normalize-volume", "-n", action="store_true")
-
- args = parser.parse_args()
-
- process(args)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/prep_s2ut_data.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/prep_s2ut_data.py
deleted file mode 100644
index c97c0fe9be01fac1199b24f0b20b16c526494ff2..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/prep_s2ut_data.py
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import logging
-from pathlib import Path
-
-import soundfile as sf
-from tqdm import tqdm
-import pandas as pd
-
-from examples.speech_to_speech.preprocessing.data_utils import (
- gen_config_yaml,
- load_units,
- process_units,
-)
-from examples.speech_to_text.data_utils import save_df_to_tsv
-
-logger = logging.getLogger(__name__)
-
-MANIFEST_COLUMNS = ["id", "src_audio", "src_n_frames", "tgt_audio", "tgt_n_frames"]
-
-
-def process(args):
- args.output_root.mkdir(exist_ok=True)
-
- print("Generating manifest...")
- for split in args.data_split:
- print(f"Processing {split}")
-
- # load target units
- target_unit_data = load_units(args.target_dir / f"{split}.txt")
-
- manifest = {c: [] for c in MANIFEST_COLUMNS}
- missing_tgt_audios = []
- src_audios = list(args.source_dir.glob(f"{split}/*.wav"))
- for src_audio in tqdm(src_audios):
- sample_id = src_audio.stem
-
- if sample_id not in target_unit_data:
- missing_tgt_audios.append(sample_id)
- continue
-
- src_n_frames = sf.info(src_audio.as_posix()).frames
- manifest["id"].append(sample_id)
- manifest["src_audio"].append(src_audio.as_posix())
- manifest["src_n_frames"].append(
- src_n_frames // 160
- ) # estimation of 10-ms frame for 16kHz audio
-
- target_units = process_units(target_unit_data[sample_id], args.reduce_unit)
- manifest["tgt_audio"].append(" ".join(target_units))
- manifest["tgt_n_frames"].append(len(target_units))
-
- print(f"Processed {len(manifest['id'])} samples")
- if len(missing_tgt_audios) > 0:
- print(
- f"{len(missing_tgt_audios)} with missing target data (first 3 examples: {', '.join(missing_tgt_audios[:3])})"
- )
-
- out_manifest = args.output_root / f"{split}.tsv"
- print(f"Writing manifest to {out_manifest}...")
- save_df_to_tsv(pd.DataFrame.from_dict(manifest), out_manifest)
-
- # Generate config YAML
- gen_config_yaml(
- args.output_root,
- specaugment_policy="lb",
- feature_transform=["utterance_cmvn"],
- vocoder_type="code_hifigan",
- vocoder_checkpoint=args.vocoder_checkpoint,
- vocoder_cfg=args.vocoder_cfg,
- )
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument(
- "--source-dir", required=True, type=Path, help="source audio directory"
- )
- parser.add_argument(
- "--target-dir", required=True, type=Path, help="target audio directory"
- )
- parser.add_argument(
- "--data-split",
- default=["train", "valid", "test"],
- nargs="+",
- help="data split names",
- )
- parser.add_argument(
- "--output-root", required=True, type=Path, help="output directory"
- )
- parser.add_argument(
- "--reduce-unit",
- action="store_true",
- help="reduce a target unit sequence to a unique unit sequence, i.e. '1 1 1 2 2' -> '1 2'",
- )
- parser.add_argument(
- "--vocoder-checkpoint", default=None, type=str, help="vocoder checkpoint"
- )
- parser.add_argument(
- "--vocoder-cfg", default=None, type=str, help="vocoder config file"
- )
-
- args = parser.parse_args()
-
- process(args)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/prep_sn_data.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/prep_sn_data.py
deleted file mode 100644
index ea94175634204075d645af2c35720c76c8924253..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/prep_sn_data.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-#
-# Adapted from examples/wav2vec/wav2vec_manifest.py
-"""
-Data preparation for the speech normalizer
-"""
-
-import argparse
-import glob
-import os
-
-import soundfile
-
-from examples.speech_to_speech.preprocessing.data_utils import load_units, process_units
-
-
-def process(args):
- assert (
- args.for_inference or args.target_unit is not None
- ), "missing --target-unit or --for-inference"
-
- if not os.path.exists(args.output_dir):
- os.makedirs(args.output_dir)
-
- dir_path = os.path.realpath(args.audio_dir)
- search_path = os.path.join(dir_path, "**/*." + args.ext)
-
- if args.target_unit:
- unit_data = load_units(args.target_unit)
-
- with open(os.path.join(args.output_dir, f"{args.data_name}.tsv"), "w") as o_t, open(
- os.path.join(args.output_dir, f"{args.data_name}.unit"), "w"
- ) as o_u:
- print(dir_path, file=o_t)
- for fname in glob.iglob(search_path, recursive=True):
- file_path = os.path.realpath(fname)
- frames = soundfile.info(fname).frames
- print(
- "{}\t{}".format(os.path.relpath(file_path, dir_path), frames), file=o_t
- )
-
- if args.for_inference:
- print("0", file=o_u)
- else:
- sample_id = os.path.basename(file_path)[: -len(args.ext) - 1]
- assert (
- sample_id in unit_data
- ), f'{fname} does not have unit data in {args.target_unit}. Expecting sample_id "{sample_id}".'
- target_units = process_units(unit_data[sample_id], reduce=True)
- print(" ".join(target_units), file=o_u)
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument("--audio-dir", required=True, type=str, help="audio directory")
- parser.add_argument("--ext", default="flac", type=str, help="audio extension")
- parser.add_argument(
- "--data-name",
- required=True,
- type=str,
- help="dataset name",
- )
- parser.add_argument(
- "--output-dir", required=True, type=str, help="output directory"
- )
- parser.add_argument(
- "--for-inference",
- action="store_true",
- help="set this if preparing data for running inference with a speech normalizer",
- )
- parser.add_argument(
- "--target-unit",
- default=None,
- type=str,
- help="a file containing unit sequences in the format: sample_id|u1 u2 ...",
- )
-
- args = parser.parse_args()
-
- process(args)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/prep_sn_output_data.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/prep_sn_output_data.py
deleted file mode 100644
index 06991343bd7ce9a3087a016d7e4bd04ca3a1fb97..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/preprocessing/prep_sn_output_data.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-from pathlib import Path
-
-from tqdm import tqdm
-
-
-def process(args):
- args.output_root.mkdir(exist_ok=True)
-
- # load units
- units = {}
- with open(args.in_unit) as f:
- for line in f:
- unit_seq, utt_id = line.strip().rsplit(" ", 1)
- utt_id = int(utt_id[6:-1]) # remove "(None-"
- units[utt_id] = unit_seq
-
- with open(args.in_audio) as f, open(
- args.output_root / f"{args.in_audio.stem}.txt", "w"
- ) as o:
- f.readline()
- for i, line in enumerate(tqdm(f.readlines())):
- audio, _ = line.strip().split("\t", 1)
- sample_id = Path(audio).stem
- o.write(f"{sample_id}|{units[i]}\n")
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument(
- "--in-unit",
- required=True,
- type=Path,
- help="unit file (output from the speech normalizer)",
- )
- parser.add_argument(
- "--in-audio",
- required=True,
- type=Path,
- help="tsv file (input to the normalizer)",
- )
- parser.add_argument(
- "--output-root", required=True, type=Path, help="output directory"
- )
-
- args = parser.parse_args()
-
- process(args)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/unity/__init__.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/unity/__init__.py
deleted file mode 100644
index 349db7c65e51363d75ab6386188b4eef48ec89d0..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/unity/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-from . import sequence_generator # noqa
-from . import sequence_generator_multi_decoder # noqa
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/unity/sequence_generator.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/unity/sequence_generator.py
deleted file mode 100644
index c482098feb88b1b055ffef86bb5dda4e0f5b28b0..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/unity/sequence_generator.py
+++ /dev/null
@@ -1,626 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import math
-import sys
-from typing import Dict, List, Optional
-
-import torch
-from torch import Tensor
-
-from fairseq.sequence_generator import EnsembleModel as EnsembleModelBase
-from fairseq.sequence_generator import SequenceGenerator as SequenceGeneratorBase
-
-
-class SequenceGenerator(SequenceGeneratorBase):
- def __init__(
- self,
- models,
- tgt_dict,
- beam_size=1,
- max_len_a=0,
- max_len_b=200,
- max_len=0,
- min_len=1,
- normalize_scores=True,
- len_penalty=1.0,
- unk_penalty=0.0,
- temperature=1.0,
- match_source_len=False,
- no_repeat_ngram_size=0,
- search_strategy=None,
- eos=None,
- symbols_to_strip_from_output=None,
- lm_model=None,
- lm_weight=1.0,
- tokens_to_suppress=(),
- ):
- """Generates translations of a given source sentence.
-
- Args:
- models (List[~fairseq.models.FairseqModel]): ensemble of models,
- currently support fairseq.models.TransformerModel for scripting
- beam_size (int, optional): beam width (default: 1)
- max_len_a/b (int, optional): generate sequences of maximum length
- ax + b, where x is the source length
- max_len (int, optional): the maximum length of the generated output
- (not including end-of-sentence)
- min_len (int, optional): the minimum length of the generated output
- (not including end-of-sentence)
- normalize_scores (bool, optional): normalize scores by the length
- of the output (default: True)
- len_penalty (float, optional): length penalty, where <1.0 favors
- shorter, >1.0 favors longer sentences (default: 1.0)
- unk_penalty (float, optional): unknown word penalty, where <0
- produces more unks, >0 produces fewer (default: 0.0)
- temperature (float, optional): temperature, where values
- >1.0 produce more uniform samples and values <1.0 produce
- sharper samples (default: 1.0)
- match_source_len (bool, optional): outputs should match the source
- length (default: False)
- """
- super().__init__(
- models=models,
- tgt_dict=tgt_dict,
- beam_size=beam_size,
- max_len_a=max_len_a,
- max_len_b=max_len_b,
- max_len=max_len,
- min_len=min_len,
- normalize_scores=normalize_scores,
- len_penalty=len_penalty,
- unk_penalty=unk_penalty,
- temperature=temperature,
- match_source_len=match_source_len,
- no_repeat_ngram_size=no_repeat_ngram_size,
- search_strategy=search_strategy,
- eos=eos,
- symbols_to_strip_from_output=symbols_to_strip_from_output,
- lm_model=lm_model,
- lm_weight=lm_weight,
- tokens_to_suppress=tokens_to_suppress,
- )
-
- if isinstance(models, EnsembleModel):
- self.model = models
- else:
- self.model = EnsembleModel(models)
-
- self.model.set_decoder_beam_size(self.beam_size)
- self.model.eval()
-
- def _generate(
- self,
- sample: Dict[str, Dict[str, Tensor]],
- prefix_tokens: Optional[Tensor] = None,
- constraints: Optional[Tensor] = None,
- bos_token: Optional[int] = None,
- ):
- net_input = sample["net_input"]
-
- if "src_tokens" in net_input:
- src_tokens = net_input["src_tokens"]
- # length of the source text being the character length except EndOfSentence and pad
- # if src_lengths exists in net_input (speech_to_text dataset case), then use it
- if "src_lengths" in net_input:
- src_lengths = net_input["src_lengths"]
- else:
- src_lengths = (
- (src_tokens.ne(self.eos) & src_tokens.ne(self.pad))
- .long()
- .sum(dim=1)
- )
- elif "source" in net_input:
- src_tokens = net_input["source"]
- src_lengths = (
- net_input["padding_mask"].size(-1) - net_input["padding_mask"].sum(-1)
- if net_input["padding_mask"] is not None
- else torch.tensor(src_tokens.size(-1)).to(src_tokens)
- )
- elif "features" in net_input:
- src_tokens = net_input["features"]
- src_lengths = (
- net_input["padding_mask"].size(-1) - net_input["padding_mask"].sum(-1)
- if net_input["padding_mask"] is not None
- else torch.tensor(src_tokens.size(-1)).to(src_tokens)
- )
- else:
- raise Exception(
- "expected src_tokens or source in net input. input keys: "
- + str(net_input.keys())
- )
-
- if constraints is not None and not self.search.supports_constraints:
- raise NotImplementedError(
- "Target-side constraints were provided, but search method doesn't support them"
- )
-
- # Initialize constraints, when active
- self.search.init_constraints(constraints, self.beam_size)
-
- # compute the encoder output for each beam
- with torch.autograd.profiler.record_function("EnsembleModel: forward_encoder"):
- encoder_outs = self.model.forward_encoder(net_input)
-
- finalized = self.generate_decoder(
- encoder_outs,
- src_tokens,
- src_lengths,
- sample,
- prefix_tokens,
- constraints,
- bos_token,
- )
- return finalized
-
- def generate_decoder(
- self,
- encoder_outs,
- src_tokens,
- src_lengths,
- sample: Dict[str, Dict[str, Tensor]],
- prefix_tokens: Optional[Tensor] = None,
- constraints: Optional[Tensor] = None,
- bos_token: Optional[int] = None,
- aux_task_name="",
- encoder_outs_aug: Optional[
- Tensor
- ] = None, # an additional/augmented encoder_outs
- ):
- incremental_states = torch.jit.annotate(
- List[Dict[str, Dict[str, Optional[Tensor]]]],
- [
- torch.jit.annotate(Dict[str, Dict[str, Optional[Tensor]]], {})
- for i in range(self.model.models_size)
- ],
- )
-
- # bsz: total number of sentences in beam
- # Note that src_tokens may have more than 2 dimensions (i.e. audio features)
- bsz, src_len = src_tokens.size()[:2]
- beam_size = self.beam_size
-
- decoder_name = f"{aux_task_name}_decoder" if aux_task_name else "decoder"
-
- max_len: int = -1
- if self.match_source_len:
- max_len = src_lengths.max().item()
- else:
- max_len = min(
- int(self.max_len_a * src_len + self.max_len_b),
- self.max_len - 1,
- )
- assert (
- self.min_len <= max_len
- ), "min_len cannot be larger than max_len, please adjust these!"
-
- # placeholder of indices for bsz * beam_size to hold tokens and accumulative scores
- new_order = torch.arange(bsz).view(-1, 1).repeat(1, beam_size).view(-1)
- new_order = new_order.to(src_tokens.device).long()
- encoder_outs = self.model.reorder_encoder_out(encoder_outs, new_order)
- # ensure encoder_outs is a List.
- assert encoder_outs is not None
- if encoder_outs_aug is not None:
- encoder_outs_aug = self.model.reorder_encoder_out(
- encoder_outs_aug, new_order
- )
-
- # initialize buffers
- scores = (
- torch.zeros(bsz * beam_size, max_len + 1).to(src_tokens).float()
- ) # +1 for eos; pad is never chosen for scoring
- tokens = (
- torch.zeros(bsz * beam_size, max_len + 2)
- .to(src_tokens)
- .long()
- .fill_(self.pad)
- ) # +2 for eos and pad
- tokens[:, 0] = self.eos if bos_token is None else bos_token
- attn: Optional[Tensor] = None
-
- # A list that indicates candidates that should be ignored.
- # For example, suppose we're sampling and have already finalized 2/5
- # samples. Then cands_to_ignore would mark 2 positions as being ignored,
- # so that we only finalize the remaining 3 samples.
- cands_to_ignore = (
- torch.zeros(bsz, beam_size).to(src_tokens).eq(-1)
- ) # forward and backward-compatible False mask
-
- # list of completed sentences
- finalized = torch.jit.annotate(
- List[List[Dict[str, Tensor]]],
- [torch.jit.annotate(List[Dict[str, Tensor]], []) for i in range(bsz)],
- ) # contains lists of dictionaries of infomation about the hypothesis being finalized at each step
-
- # a boolean array indicating if the sentence at the index is finished or not
- finished = [False for i in range(bsz)]
- num_remaining_sent = bsz # number of sentences remaining
-
- # number of candidate hypos per step
- cand_size = 2 * beam_size # 2 x beam size in case half are EOS
-
- # offset arrays for converting between different indexing schemes
- bbsz_offsets = (
- (torch.arange(0, bsz) * beam_size)
- .unsqueeze(1)
- .type_as(tokens)
- .to(src_tokens.device)
- )
- cand_offsets = torch.arange(0, cand_size).type_as(tokens).to(src_tokens.device)
-
- reorder_state: Optional[Tensor] = None
- batch_idxs: Optional[Tensor] = None
-
- original_batch_idxs: Optional[Tensor] = None
- if "id" in sample and isinstance(sample["id"], Tensor):
- original_batch_idxs = sample["id"]
- else:
- original_batch_idxs = torch.arange(0, bsz).type_as(tokens)
-
- for step in range(max_len + 1): # one extra step for EOS marker
- # reorder decoder internal states based on the prev choice of beams
- if reorder_state is not None:
- if batch_idxs is not None:
- # update beam indices to take into account removed sentences
- corr = batch_idxs - torch.arange(batch_idxs.numel()).type_as(
- batch_idxs
- )
- reorder_state.view(-1, beam_size).add_(
- corr.unsqueeze(-1) * beam_size
- )
- original_batch_idxs = original_batch_idxs[batch_idxs]
- self.model.reorder_incremental_state(
- incremental_states, reorder_state, decoder_name
- )
- encoder_outs = self.model.reorder_encoder_out(
- encoder_outs, reorder_state
- )
- if encoder_outs_aug is not None:
- encoder_outs_aug = self.model.reorder_encoder_out(
- encoder_outs_aug, reorder_state
- )
- with torch.autograd.profiler.record_function(
- "EnsembleModel: forward_decoder"
- ):
- lprobs, avg_attn_scores = self.model.forward_decoder(
- tokens[:, : step + 1],
- encoder_outs,
- incremental_states,
- self.temperature,
- decoder_name=decoder_name,
- encoder_outs_aug=encoder_outs_aug,
- )
-
- if self.lm_model is not None and not aux_task_name:
- lm_out = self.lm_model(tokens[:, : step + 1])
- probs = self.lm_model.get_normalized_probs(
- lm_out, log_probs=True, sample=None
- )
- probs = probs[:, -1, :] * self.lm_weight
- lprobs += probs
-
- lprobs[lprobs != lprobs] = torch.tensor(-math.inf).to(lprobs)
-
- lprobs[:, self.pad] = -math.inf # never select pad
- lprobs[:, self.unk] -= self.unk_penalty # apply unk penalty
-
- # handle max length constraint
- if step >= max_len:
- lprobs[:, : self.eos] = -math.inf
- lprobs[:, self.eos + 1 :] = -math.inf
-
- # handle prefix tokens (possibly with different lengths)
- if (
- prefix_tokens is not None
- and step < prefix_tokens.size(1)
- and step < max_len
- ):
- lprobs, tokens, scores = self._prefix_tokens(
- step, lprobs, scores, tokens, prefix_tokens, beam_size
- )
- else:
- if step < self.min_len:
- # minimum length constraint (does not apply if using prefix_tokens)
- lprobs[:, self.eos] = -math.inf
-
- if self.token_indices_to_suppress is not None:
- lprobs[:, self.token_indices_to_suppress] = -math.inf
-
- # Record attention scores, only support avg_attn_scores is a Tensor
- if avg_attn_scores is not None:
- if attn is None:
- attn = torch.empty(
- bsz * beam_size, avg_attn_scores.size(1), max_len + 2
- ).to(scores)
- attn[:, :, step + 1].copy_(avg_attn_scores)
-
- scores = scores.type_as(lprobs)
- eos_bbsz_idx = torch.empty(0).to(
- tokens
- ) # indices of hypothesis ending with eos (finished sentences)
- eos_scores = torch.empty(0).to(
- scores
- ) # scores of hypothesis ending with eos (finished sentences)
-
- if self.should_set_src_lengths:
- self.search.set_src_lengths(src_lengths)
-
- if self.repeat_ngram_blocker is not None:
- lprobs = self.repeat_ngram_blocker(tokens, lprobs, bsz, beam_size, step)
-
- # Shape: (batch, cand_size)
- cand_scores, cand_indices, cand_beams = self.search.step(
- step,
- lprobs.view(bsz, -1, self.vocab_size),
- scores.view(bsz, beam_size, -1)[:, :, :step],
- tokens[:, : step + 1],
- original_batch_idxs,
- )
-
- # cand_bbsz_idx contains beam indices for the top candidate
- # hypotheses, with a range of values: [0, bsz*beam_size),
- # and dimensions: [bsz, cand_size]
- cand_bbsz_idx = cand_beams.add(bbsz_offsets)
-
- # finalize hypotheses that end in eos
- # Shape of eos_mask: (batch size, beam size)
- eos_mask = cand_indices.eq(self.eos) & cand_scores.ne(-math.inf)
- eos_mask[:, :beam_size][cands_to_ignore] = torch.tensor(0).to(eos_mask)
-
- # only consider eos when it's among the top beam_size indices
- # Now we know what beam item(s) to finish
- # Shape: 1d list of absolute-numbered
- eos_bbsz_idx = torch.masked_select(
- cand_bbsz_idx[:, :beam_size], mask=eos_mask[:, :beam_size]
- )
-
- finalized_sents: List[int] = []
- if eos_bbsz_idx.numel() > 0:
- eos_scores = torch.masked_select(
- cand_scores[:, :beam_size], mask=eos_mask[:, :beam_size]
- )
-
- finalized_sents = self.finalize_hypos(
- step,
- eos_bbsz_idx,
- eos_scores,
- tokens,
- scores,
- finalized,
- finished,
- beam_size,
- attn,
- src_lengths,
- max_len,
- )
- num_remaining_sent -= len(finalized_sents)
-
- assert num_remaining_sent >= 0
- if num_remaining_sent == 0:
- break
- if self.search.stop_on_max_len and step >= max_len:
- break
- assert step < max_len, f"{step} < {max_len}"
-
- # Remove finalized sentences (ones for which {beam_size}
- # finished hypotheses have been generated) from the batch.
- if len(finalized_sents) > 0:
- new_bsz = bsz - len(finalized_sents)
-
- # construct batch_idxs which holds indices of batches to keep for the next pass
- batch_mask = torch.ones(
- bsz, dtype=torch.bool, device=cand_indices.device
- )
- batch_mask[finalized_sents] = False
- # TODO replace `nonzero(as_tuple=False)` after TorchScript supports it
- batch_idxs = torch.arange(
- bsz, device=cand_indices.device
- ).masked_select(batch_mask)
-
- # Choose the subset of the hypothesized constraints that will continue
- self.search.prune_sentences(batch_idxs)
-
- eos_mask = eos_mask[batch_idxs]
- cand_beams = cand_beams[batch_idxs]
- bbsz_offsets.resize_(new_bsz, 1)
- cand_bbsz_idx = cand_beams.add(bbsz_offsets)
- cand_scores = cand_scores[batch_idxs]
- cand_indices = cand_indices[batch_idxs]
-
- if prefix_tokens is not None:
- prefix_tokens = prefix_tokens[batch_idxs]
- src_lengths = src_lengths[batch_idxs]
- cands_to_ignore = cands_to_ignore[batch_idxs]
-
- scores = scores.view(bsz, -1)[batch_idxs].view(new_bsz * beam_size, -1)
- tokens = tokens.view(bsz, -1)[batch_idxs].view(new_bsz * beam_size, -1)
- if attn is not None:
- attn = attn.view(bsz, -1)[batch_idxs].view(
- new_bsz * beam_size, attn.size(1), -1
- )
- bsz = new_bsz
- else:
- batch_idxs = None
-
- # Set active_mask so that values > cand_size indicate eos hypos
- # and values < cand_size indicate candidate active hypos.
- # After, the min values per row are the top candidate active hypos
-
- # Rewrite the operator since the element wise or is not supported in torchscript.
-
- eos_mask[:, :beam_size] = ~((~cands_to_ignore) & (~eos_mask[:, :beam_size]))
- active_mask = torch.add(
- eos_mask.type_as(cand_offsets) * cand_size,
- cand_offsets[: eos_mask.size(1)],
- )
-
- # get the top beam_size active hypotheses, which are just
- # the hypos with the smallest values in active_mask.
- # {active_hypos} indicates which {beam_size} hypotheses
- # from the list of {2 * beam_size} candidates were
- # selected. Shapes: (batch size, beam size)
- new_cands_to_ignore, active_hypos = torch.topk(
- active_mask, k=beam_size, dim=1, largest=False
- )
-
- # update cands_to_ignore to ignore any finalized hypos.
- cands_to_ignore = new_cands_to_ignore.ge(cand_size)[:, :beam_size]
- # Make sure there is at least one active item for each sentence in the batch.
- assert (~cands_to_ignore).any(dim=1).all()
-
- # update cands_to_ignore to ignore any finalized hypos
-
- # {active_bbsz_idx} denotes which beam number is continued for each new hypothesis (a beam
- # can be selected more than once).
- active_bbsz_idx = torch.gather(cand_bbsz_idx, dim=1, index=active_hypos)
- active_scores = torch.gather(cand_scores, dim=1, index=active_hypos)
-
- active_bbsz_idx = active_bbsz_idx.view(-1)
- active_scores = active_scores.view(-1)
-
- # copy tokens and scores for active hypotheses
-
- # Set the tokens for each beam (can select the same row more than once)
- tokens[:, : step + 1] = torch.index_select(
- tokens[:, : step + 1], dim=0, index=active_bbsz_idx
- )
- # Select the next token for each of them
- tokens.view(bsz, beam_size, -1)[:, :, step + 1] = torch.gather(
- cand_indices, dim=1, index=active_hypos
- )
- if step > 0:
- scores[:, :step] = torch.index_select(
- scores[:, :step], dim=0, index=active_bbsz_idx
- )
- scores.view(bsz, beam_size, -1)[:, :, step] = torch.gather(
- cand_scores, dim=1, index=active_hypos
- )
-
- # Update constraints based on which candidates were selected for the next beam
- self.search.update_constraints(active_hypos)
-
- # copy attention for active hypotheses
- if attn is not None:
- attn[:, :, : step + 2] = torch.index_select(
- attn[:, :, : step + 2], dim=0, index=active_bbsz_idx
- )
-
- # reorder incremental state in decoder
- reorder_state = active_bbsz_idx
-
- # sort by score descending
- for sent in range(len(finalized)):
- scores = torch.tensor(
- [float(elem["score"].item()) for elem in finalized[sent]]
- )
- _, sorted_scores_indices = torch.sort(scores, descending=True)
- finalized[sent] = [finalized[sent][ssi] for ssi in sorted_scores_indices]
- finalized[sent] = torch.jit.annotate(
- List[Dict[str, Tensor]], finalized[sent]
- )
- return finalized
-
-
-class EnsembleModel(EnsembleModelBase):
- """A wrapper around an ensemble of models."""
-
- def __init__(self, models):
- super().__init__(models)
-
- @torch.jit.export
- def forward_decoder(
- self,
- tokens,
- encoder_outs: List[Dict[str, List[Tensor]]],
- incremental_states: List[Dict[str, Dict[str, Optional[Tensor]]]],
- temperature: float = 1.0,
- decoder_name="decoder",
- encoder_outs_aug: List[Dict[str, List[Tensor]]] = None,
- ):
- log_probs = []
- avg_attn: Optional[Tensor] = None
- encoder_out: Optional[Dict[str, List[Tensor]]] = None
- encoder_out_aug: Optional[Dict[str, List[Tensor]]] = None
- for i, model in enumerate(self.models):
- if self.has_encoder():
- encoder_out = encoder_outs[i]
- if encoder_outs_aug is not None:
- encoder_out_aug = encoder_outs_aug[i]
- # decode each model
- if self.has_incremental_states():
- if encoder_out_aug is not None:
- decoder_out = getattr(model, decoder_name).forward(
- tokens,
- encoder_out=encoder_out,
- encoder_out_aug=encoder_out_aug,
- incremental_state=incremental_states[i],
- )
- else:
- decoder_out = getattr(model, decoder_name).forward(
- tokens,
- encoder_out=encoder_out,
- incremental_state=incremental_states[i],
- )
- else:
- if hasattr(model, decoder_name):
- decoder_out = getattr(model, decoder_name).forward(
- tokens, encoder_out=encoder_out
- )
- else:
- decoder_out = model.forward(tokens)
-
- attn: Optional[Tensor] = None
- decoder_len = len(decoder_out)
- if decoder_len > 1 and decoder_out[1] is not None:
- if isinstance(decoder_out[1], Tensor):
- attn = decoder_out[1]
- else:
- attn_holder = decoder_out[1]["attn"]
- if isinstance(attn_holder, Tensor):
- attn = attn_holder
- elif attn_holder is not None:
- attn = attn_holder[0]
- if attn is not None:
- attn = attn[:, -1, :]
-
- decoder_out_tuple = (
- decoder_out[0][:, -1:, :].div_(temperature),
- None if decoder_len <= 1 else decoder_out[1],
- )
- probs = getattr(model, decoder_name).get_normalized_probs(
- decoder_out_tuple, log_probs=True, sample=None
- )
- probs = probs[:, -1, :]
- if self.models_size == 1:
- return probs, attn
-
- log_probs.append(probs)
- if attn is not None:
- if avg_attn is None:
- avg_attn = attn
- else:
- avg_attn.add_(attn)
-
- avg_probs = torch.logsumexp(torch.stack(log_probs, dim=0), dim=0) - math.log(
- self.models_size
- )
-
- if avg_attn is not None:
- avg_attn.div_(self.models_size)
- return avg_probs, avg_attn
-
- @torch.jit.export
- def reorder_incremental_state(
- self,
- incremental_states: List[Dict[str, Dict[str, Optional[Tensor]]]],
- new_order,
- decoder_name="decoder",
- ):
- if not self.has_incremental_states():
- return
- for i, model in enumerate(self.models):
- getattr(model, decoder_name).reorder_incremental_state_scripting(
- incremental_states[i], new_order
- )
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/unity/sequence_generator_multi_decoder.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/unity/sequence_generator_multi_decoder.py
deleted file mode 100644
index af99a960b8b5c6d504f68613bc4e5f8e7af0a7aa..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_speech/unity/sequence_generator_multi_decoder.py
+++ /dev/null
@@ -1,267 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-from typing import Dict, List, Optional
-
-import torch
-import torch.nn as nn
-from torch import Tensor
-
-from fairseq import search
-
-
-class MultiDecoderSequenceGenerator(nn.Module):
- def __init__(
- self,
- models,
- tgt_dict,
- tgt_dict_mt,
- beam_size=1,
- beam_size_mt=1,
- max_len_a=0,
- max_len_b=200,
- max_len_a_mt=0,
- max_len_b_mt=200,
- max_len=0,
- min_len=1,
- normalize_scores=True,
- len_penalty=1.0,
- len_penalty_mt=1.0,
- unk_penalty=0.0,
- temperature=1.0,
- match_source_len=False,
- no_repeat_ngram_size=0,
- eos=None,
- eos_mt=None,
- symbols_to_strip_from_output=None,
- lm_model=None,
- lm_weight=1.0,
- ):
- """Generates translations of a given source sentence.
-
- Args:
- models (List[~fairseq.models.FairseqModel]): ensemble of models,
- currently support fairseq.models.TransformerModel for scripting
- beam_size (int, optional): beam width (default: 1)
- max_len_a/b (int, optional): generate sequences of maximum length
- ax + b, where x is the source length for the second pass
- max_len_a_mt/b_mt (int, optional): generate sequences of maximum length
- ax + b, where x is the source length for the first pass
- max_len (int, optional): the maximum length of the generated output
- (not including end-of-sentence)
- min_len (int, optional): the minimum length of the generated output
- (not including end-of-sentence)
- normalize_scores (bool, optional): normalize scores by the length
- of the output (default: True)
- len_penalty (float, optional): length penalty in the second pass, where <1.0 favors
- shorter, >1.0 favors longer sentences (default: 1.0)
- len_penalty (float, optional): length penalty in the first pass, where <1.0 favors
- shorter, >1.0 favors longer sentences (default: 1.0)
- unk_penalty (float, optional): unknown word penalty, where <0
- produces more unks, >0 produces fewer (default: 0.0)
- temperature (float, optional): temperature, where values
- >1.0 produce more uniform samples and values <1.0 produce
- sharper samples (default: 1.0)
- match_source_len (bool, optional): outputs should match the source
- length (default: False)
- """
- super().__init__()
-
- from examples.speech_to_speech.unity.sequence_generator import SequenceGenerator
-
- self.generator = SequenceGenerator(
- models,
- tgt_dict,
- beam_size=beam_size,
- max_len_a=max_len_a,
- max_len_b=max_len_b,
- max_len=max_len,
- min_len=min_len,
- normalize_scores=normalize_scores,
- len_penalty=len_penalty,
- unk_penalty=unk_penalty,
- temperature=temperature,
- match_source_len=match_source_len,
- no_repeat_ngram_size=no_repeat_ngram_size,
- search_strategy=search.BeamSearch(tgt_dict),
- eos=eos,
- symbols_to_strip_from_output=symbols_to_strip_from_output,
- lm_model=lm_model,
- lm_weight=lm_weight,
- )
- self.eos = self.generator.eos
-
- self.generator_mt = SequenceGenerator(
- models,
- tgt_dict_mt,
- beam_size=beam_size_mt,
- max_len_a=max_len_a_mt,
- max_len_b=max_len_b_mt,
- max_len=max_len,
- min_len=min_len,
- normalize_scores=normalize_scores,
- len_penalty=len_penalty_mt,
- unk_penalty=unk_penalty,
- temperature=temperature,
- match_source_len=match_source_len,
- no_repeat_ngram_size=no_repeat_ngram_size,
- search_strategy=search.BeamSearch(tgt_dict_mt),
- eos=eos_mt,
- symbols_to_strip_from_output=symbols_to_strip_from_output,
- )
-
- @torch.no_grad()
- def generate(
- self, models, sample: Dict[str, Dict[str, Tensor]], **kwargs
- ) -> List[List[Dict[str, Tensor]]]:
- """Generate translations. Match the api of other fairseq generators.
-
- Args:
- models (List[~fairseq.models.FairseqModel]): ensemble of models
- sample (dict): batch
- prefix_tokens (torch.LongTensor, optional): force decoder to begin
- with these tokens
- constraints (torch.LongTensor, optional): force decoder to include
- the list of constraints
- bos_token (int, optional): beginning of sentence token
- (default: self.eos)
- """
- return self._generate(sample, **kwargs)
-
- def _generate(
- self,
- sample: Dict[str, Dict[str, Tensor]],
- prefix_tokens: Optional[Tensor] = None,
- constraints: Optional[Tensor] = None,
- bos_token: Optional[int] = None,
- ):
- net_input = sample["net_input"]
-
- if "src_tokens" in net_input:
- src_tokens = net_input["src_tokens"]
- # length of the source text being the character length except EndOfSentence and pad
- # if src_lengths exists in net_input (speech_to_text dataset case), then use it
- if "src_lengths" in net_input:
- src_lengths = net_input["src_lengths"]
- else:
- src_lengths = (
- (
- src_tokens.ne(self.generator.eos)
- & src_tokens.ne(self.generator.pad)
- )
- .long()
- .sum(dim=1)
- )
- else:
- raise Exception(
- "expected src_tokens or source in net input. input keys: "
- + str(net_input.keys())
- )
-
- if constraints is not None and not self.generator.search.supports_constraints:
- raise NotImplementedError(
- "Target-side constraints were provided, but search method doesn't support them"
- )
-
- # Initialize constraints, when active
- self.generator.search.init_constraints(constraints, self.generator.beam_size)
- self.generator_mt.search.init_constraints(
- constraints, self.generator_mt.beam_size
- )
-
- # compute the encoder output for each beam
- with torch.autograd.profiler.record_function("EnsembleModel: forward_encoder"):
- encoder_outs = self.generator.model.forward_encoder(net_input)
-
- single_model = self.generator.model.single_model
- mt_decoder = getattr(single_model, f"{single_model.mt_task_name}_decoder")
-
- # 1. MT decoder
- finalized_mt = self.generator_mt.generate_decoder(
- encoder_outs,
- src_tokens,
- src_lengths,
- sample,
- prefix_tokens,
- constraints,
- bos_token,
- aux_task_name=single_model.mt_task_name,
- )
-
- # extract decoder output corresponding to the best hypothesis
- max_tgt_len = max([len(hypo[0]["tokens"]) for hypo in finalized_mt])
- prev_output_tokens_mt = (
- src_tokens.new_zeros(src_tokens.shape[0], max_tgt_len)
- .fill_(mt_decoder.padding_idx)
- .int()
- ) # B x T
- for i, hypo in enumerate(finalized_mt):
- i_beam = 0
- tmp = hypo[i_beam]["tokens"].int() # hyp + eos
- prev_output_tokens_mt[i, 0] = self.generator_mt.eos
- if tmp[-1] == self.generator_mt.eos:
- tmp = tmp[:-1]
- prev_output_tokens_mt[i, 1 : len(tmp) + 1] = tmp
-
- text = "".join([self.generator_mt.tgt_dict[c] for c in tmp])
- text = text.replace("_", " ")
- text = text.replace("▁", " ")
- text = text.replace("", " ")
- text = text.replace("", "")
- text = text.replace("", "")
- if len(text) > 0 and text[0] == " ":
- text = text[1:]
- sample_id = sample["id"].tolist()[i]
- print("{} (None-{})".format(text, sample_id))
-
- x = mt_decoder(
- prev_output_tokens_mt,
- encoder_out=encoder_outs[0],
- features_only=True,
- )[0].transpose(0, 1)
-
- if getattr(single_model, "proj", None) is not None:
- x = single_model.proj(x)
-
- mt_decoder_padding_mask = None
- if prev_output_tokens_mt.eq(mt_decoder.padding_idx).any():
- mt_decoder_padding_mask = prev_output_tokens_mt.eq(mt_decoder.padding_idx)
-
- # 2. T2U encoder
- if getattr(single_model, "synthesizer_encoder", None) is not None:
- t2u_encoder_out = single_model.synthesizer_encoder(
- x,
- mt_decoder_padding_mask,
- )
- else:
- t2u_encoder_out = {
- "encoder_out": [x], # T x B x C
- "encoder_padding_mask": [mt_decoder_padding_mask]
- if mt_decoder_padding_mask is not None
- else [], # B x T
- "encoder_embedding": [],
- "encoder_states": [],
- "src_tokens": [],
- "src_lengths": [],
- }
-
- if getattr(single_model, "t2u_augmented_cross_attn", False):
- encoder_outs_aug = [t2u_encoder_out]
- else:
- encoder_outs = [t2u_encoder_out]
- encoder_outs_aug = None
-
- # 3. T2U decoder
- finalized = self.generator.generate_decoder(
- encoder_outs,
- src_tokens,
- src_lengths,
- sample,
- prefix_tokens,
- constraints,
- bos_token,
- encoder_outs_aug=encoder_outs_aug,
- )
- return finalized
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/README.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/README.md
deleted file mode 100644
index f639d300d342f8de1392c98bfc44ec8690188539..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/README.md
+++ /dev/null
@@ -1,77 +0,0 @@
-# Speech-to-Text (S2T) Modeling
-
-[https://www.aclweb.org/anthology/2020.aacl-demo.6](https://www.aclweb.org/anthology/2020.aacl-demo.6.pdf)
-
-Speech recognition (ASR) and speech-to-text translation (ST) with fairseq.
-
-## Data Preparation
-S2T modeling data consists of source speech features, target text and other optional information
-(source text, speaker id, etc.). Fairseq S2T uses per-dataset-split TSV manifest files
-to store these information. Each data field is represented by a column in the TSV file.
-
-Unlike text token embeddings, speech features (e.g. log mel-scale filter banks) are usually fixed
-during model training and can be pre-computed. The manifest file contains the path to
-either the feature file in NumPy format or the WAV/FLAC audio file. For the latter,
-features will be extracted on-the-fly by fairseq S2T. Optionally, feature/audio files can be packed
-into uncompressed ZIP files (then accessed via byte offset and length) to improve I/O performance.
-
-Fairseq S2T also employs a YAML file for data related configurations: tokenizer type and dictionary path
-for the target text, feature transforms such as CMVN (cepstral mean and variance normalization) and SpecAugment,
-temperature-based resampling, etc.
-
-## Model Training
-Fairseq S2T uses the unified `fairseq-train` interface for model training. It requires arguments `--task speech_to_text`,
- `--arch ` and `--config-yaml `.
-
-## Inference & Evaluation
-Fairseq S2T uses the unified `fairseq-generate`/`fairseq-interactive` interface for inference and evaluation. It
-requires arguments `--task speech_to_text` and `--config-yaml `. The interactive console takes
-audio paths (one per line) as inputs.
-
-
-## Examples
-- [Speech Recognition (ASR) on LibriSpeech](docs/librispeech_example.md)
-
-- [Speech-to-Text Translation (ST) on MuST-C](docs/mustc_example.md)
-
-- [Speech-to-Text Translation (ST) on CoVoST 2](docs/covost_example.md)
-
-- [Speech-to-Text Translation (ST) on Multilingual TEDx](docs/mtedx_example.md)
-- [Simultaneous Speech-to-Text Translation (SimulST) on MuST-C](docs/simulst_mustc_example.md)
-
-## Updates
-- 02/04/2021: Added interactive decoding (`fairseq-interactive`) support. Examples:
- [ASR (LibriSpeech)](docs/librispeech_example.md#interactive-decoding)
- and [ST (CoVoST 2)](docs/covost_example.md#interactive-decoding).
-- 01/08/2021: Several fixes for S2T Transformer model, inference-time de-tokenization, scorer configuration and data
- preparation scripts. We also add pre-trained models to the examples and revise the instructions.
- Breaking changes: the data preparation scripts now extract filterbank features without CMVN. CMVN is instead applied
- on-the-fly (defined in the config YAML).
-
-## What's Next
-- We are migrating the old fairseq [ASR example](../speech_recognition) into this S2T framework and
- merging the features from both sides.
-- The following papers also base their experiments on fairseq S2T. We are adding more examples for replication.
- - [Improving Cross-Lingual Transfer Learning for End-to-End Speech Recognition with Speech Translation (Wang et al., 2020)](https://arxiv.org/abs/2006.05474)
- - [Self-Supervised Representations Improve End-to-End Speech Translation (Wu et al., 2020)](https://arxiv.org/abs/2006.12124)
- - [Self-Training for End-to-End Speech Translation (Pino et al., 2020)](https://arxiv.org/abs/2006.02490)
- - [CoVoST: A Diverse Multilingual Speech-To-Text Translation Corpus (Wang et al., 2020)](https://arxiv.org/abs/2002.01320)
- - [Harnessing Indirect Training Data for End-to-End Automatic Speech Translation: Tricks of the Trade (Pino et al., 2019)](https://arxiv.org/abs/1909.06515)
-
-## Citation
-Please cite as:
-```
-@inproceedings{wang2020fairseqs2t,
- title = {fairseq S2T: Fast Speech-to-Text Modeling with fairseq},
- author = {Changhan Wang and Yun Tang and Xutai Ma and Anne Wu and Dmytro Okhonko and Juan Pino},
- booktitle = {Proceedings of the 2020 Conference of the Asian Chapter of the Association for Computational Linguistics (AACL): System Demonstrations},
- year = {2020},
-}
-
-@inproceedings{ott2019fairseq,
- title = {fairseq: A Fast, Extensible Toolkit for Sequence Modeling},
- author = {Myle Ott and Sergey Edunov and Alexei Baevski and Angela Fan and Sam Gross and Nathan Ng and David Grangier and Michael Auli},
- booktitle = {Proceedings of NAACL-HLT 2019: Demonstrations},
- year = {2019},
-}
-```
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/data_utils.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/data_utils.py
deleted file mode 100644
index b8648cb2a05e275dd55cf7a6c009c8d21c6ec9fd..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/data_utils.py
+++ /dev/null
@@ -1,383 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import csv
-from pathlib import Path
-import zipfile
-from functools import reduce
-from multiprocessing import cpu_count
-from typing import Any, Dict, List, Optional, Union
-import io
-
-import numpy as np
-import pandas as pd
-import sentencepiece as sp
-from fairseq.data.audio.audio_utils import (
- convert_waveform, _get_kaldi_fbank, _get_torchaudio_fbank, is_npy_data,
- is_sf_audio_data
-)
-import torch
-import soundfile as sf
-from tqdm import tqdm
-
-
-UNK_TOKEN, UNK_TOKEN_ID = "", 3
-BOS_TOKEN, BOS_TOKEN_ID = "", 0
-EOS_TOKEN, EOS_TOKEN_ID = "", 2
-PAD_TOKEN, PAD_TOKEN_ID = "", 1
-
-
-def gen_vocab(
- input_path: Path, output_path_prefix: Path, model_type="bpe",
- vocab_size=1000, special_symbols: Optional[List[str]] = None
-):
- # Train SentencePiece Model
- arguments = [
- f"--input={input_path.as_posix()}",
- f"--model_prefix={output_path_prefix.as_posix()}",
- f"--model_type={model_type}",
- f"--vocab_size={vocab_size}",
- "--character_coverage=1.0",
- f"--num_threads={cpu_count()}",
- f"--unk_id={UNK_TOKEN_ID}",
- f"--bos_id={BOS_TOKEN_ID}",
- f"--eos_id={EOS_TOKEN_ID}",
- f"--pad_id={PAD_TOKEN_ID}",
- ]
- if special_symbols is not None:
- _special_symbols = ",".join(special_symbols)
- arguments.append(f"--user_defined_symbols={_special_symbols}")
- sp.SentencePieceTrainer.Train(" ".join(arguments))
- # Export fairseq dictionary
- spm = sp.SentencePieceProcessor()
- spm.Load(output_path_prefix.as_posix() + ".model")
- vocab = {i: spm.IdToPiece(i) for i in range(spm.GetPieceSize())}
- assert (
- vocab.get(UNK_TOKEN_ID) == UNK_TOKEN
- and vocab.get(PAD_TOKEN_ID) == PAD_TOKEN
- and vocab.get(BOS_TOKEN_ID) == BOS_TOKEN
- and vocab.get(EOS_TOKEN_ID) == EOS_TOKEN
- )
- vocab = {
- i: s
- for i, s in vocab.items()
- if s not in {UNK_TOKEN, BOS_TOKEN, EOS_TOKEN, PAD_TOKEN}
- }
- with open(output_path_prefix.as_posix() + ".txt", "w") as f_out:
- for _, s in sorted(vocab.items(), key=lambda x: x[0]):
- f_out.write(f"{s} 1\n")
-
-
-def extract_fbank_features(
- waveform: torch.FloatTensor,
- sample_rate: int,
- output_path: Optional[Path] = None,
- n_mel_bins: int = 80,
- overwrite: bool = False,
-):
- if output_path is not None and output_path.is_file() and not overwrite:
- return
-
- _waveform, _ = convert_waveform(waveform, sample_rate, to_mono=True)
- # Kaldi compliance: 16-bit signed integers
- _waveform = _waveform * (2 ** 15)
- _waveform = _waveform.numpy()
-
- features = _get_kaldi_fbank(_waveform, sample_rate, n_mel_bins)
- if features is None:
- features = _get_torchaudio_fbank(_waveform, sample_rate, n_mel_bins)
- if features is None:
- raise ImportError(
- "Please install pyKaldi or torchaudio to enable fbank feature extraction"
- )
-
- if output_path is not None:
- np.save(output_path.as_posix(), features)
- return features
-
-
-def create_zip(data_root: Path, zip_path: Path):
- paths = list(data_root.glob("*.npy"))
- paths.extend(data_root.glob("*.flac"))
- with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_STORED) as f:
- for path in tqdm(paths):
- f.write(path, arcname=path.name)
-
-
-def get_zip_manifest(
- zip_path: Path, zip_root: Optional[Path] = None, is_audio=False
-):
- _zip_path = Path.joinpath(zip_root or Path(""), zip_path)
- with zipfile.ZipFile(_zip_path, mode="r") as f:
- info = f.infolist()
- paths, lengths = {}, {}
- for i in tqdm(info):
- utt_id = Path(i.filename).stem
- offset, file_size = i.header_offset + 30 + len(i.filename), i.file_size
- paths[utt_id] = f"{zip_path.as_posix()}:{offset}:{file_size}"
- with open(_zip_path, "rb") as f:
- f.seek(offset)
- byte_data = f.read(file_size)
- assert len(byte_data) > 1
- if is_audio:
- assert is_sf_audio_data(byte_data), i
- else:
- assert is_npy_data(byte_data), i
- byte_data_fp = io.BytesIO(byte_data)
- if is_audio:
- lengths[utt_id] = sf.info(byte_data_fp).frames
- else:
- lengths[utt_id] = np.load(byte_data_fp).shape[0]
- return paths, lengths
-
-
-def gen_config_yaml(
- manifest_root: Path,
- spm_filename: Optional[str] = None,
- vocab_name: Optional[str] = None,
- yaml_filename: str = "config.yaml",
- specaugment_policy: Optional[str] = "lb",
- prepend_tgt_lang_tag: bool = False,
- sampling_alpha: Optional[float] = None,
- input_channels: Optional[int] = 1,
- input_feat_per_channel: Optional[int] = 80,
- audio_root: str = "",
- cmvn_type: str = "utterance",
- gcmvn_path: Optional[Path] = None,
- extra=None
-):
- manifest_root = manifest_root.absolute()
- writer = S2TDataConfigWriter(manifest_root / yaml_filename)
- assert spm_filename is not None or vocab_name is not None
- vocab_name = spm_filename.replace(".model", ".txt") if vocab_name is None \
- else vocab_name
- writer.set_vocab_filename(vocab_name)
- if input_channels is not None:
- writer.set_input_channels(input_channels)
- if input_feat_per_channel is not None:
- writer.set_input_feat_per_channel(input_feat_per_channel)
- specaugment_setters = {
- "lb": writer.set_specaugment_lb_policy,
- "ld": writer.set_specaugment_ld_policy,
- "sm": writer.set_specaugment_sm_policy,
- "ss": writer.set_specaugment_ss_policy,
- }
- specaugment_setter = specaugment_setters.get(specaugment_policy, None)
- if specaugment_setter is not None:
- specaugment_setter()
- if spm_filename is not None:
- writer.set_bpe_tokenizer(
- {
- "bpe": "sentencepiece",
- "sentencepiece_model": (manifest_root / spm_filename).as_posix(),
- }
- )
- if prepend_tgt_lang_tag:
- writer.set_prepend_tgt_lang_tag(True)
- if sampling_alpha is not None:
- writer.set_sampling_alpha(sampling_alpha)
-
- if cmvn_type not in ["global", "utterance"]:
- raise NotImplementedError
-
- if specaugment_policy is not None:
- writer.set_feature_transforms(
- "_train", [f"{cmvn_type}_cmvn", "specaugment"]
- )
- writer.set_feature_transforms("*", [f"{cmvn_type}_cmvn"])
-
- if cmvn_type == "global":
- if gcmvn_path is None:
- raise ValueError("Please provide path of global cmvn file.")
- else:
- writer.set_global_cmvn(gcmvn_path.as_posix())
-
- if len(audio_root) > 0:
- writer.set_audio_root(audio_root)
-
- if extra is not None:
- writer.set_extra(extra)
- writer.flush()
-
-
-def load_df_from_tsv(path: Union[str, Path]) -> pd.DataFrame:
- _path = path if isinstance(path, str) else path.as_posix()
- return pd.read_csv(
- _path,
- sep="\t",
- header=0,
- encoding="utf-8",
- escapechar="\\",
- quoting=csv.QUOTE_NONE,
- na_filter=False,
- )
-
-
-def save_df_to_tsv(dataframe, path: Union[str, Path]):
- _path = path if isinstance(path, str) else path.as_posix()
- dataframe.to_csv(
- _path,
- sep="\t",
- header=True,
- index=False,
- encoding="utf-8",
- escapechar="\\",
- quoting=csv.QUOTE_NONE,
- )
-
-
-def load_tsv_to_dicts(path: Union[str, Path]) -> List[dict]:
- with open(path, "r") as f:
- reader = csv.DictReader(
- f,
- delimiter="\t",
- quotechar=None,
- doublequote=False,
- lineterminator="\n",
- quoting=csv.QUOTE_NONE,
- )
- rows = [dict(e) for e in reader]
- return rows
-
-
-def filter_manifest_df(
- df, is_train_split=False, extra_filters=None, min_n_frames=5, max_n_frames=3000
-):
- filters = {
- "no speech": df["audio"] == "",
- f"short speech (<{min_n_frames} frames)": df["n_frames"] < min_n_frames,
- "empty sentence": df["tgt_text"] == "",
- }
- if is_train_split:
- filters[f"long speech (>{max_n_frames} frames)"] = df["n_frames"] > max_n_frames
- if extra_filters is not None:
- filters.update(extra_filters)
- invalid = reduce(lambda x, y: x | y, filters.values())
- valid = ~invalid
- print(
- "| "
- + ", ".join(f"{n}: {f.sum()}" for n, f in filters.items())
- + f", total {invalid.sum()} filtered, {valid.sum()} remained."
- )
- return df[valid]
-
-
-def cal_gcmvn_stats(features_list):
- features = np.concatenate(features_list)
- square_sums = (features ** 2).sum(axis=0)
- mean = features.mean(axis=0)
- features = np.subtract(features, mean)
- var = square_sums / features.shape[0] - mean ** 2
- std = np.sqrt(np.maximum(var, 1e-8))
- return {"mean": mean.astype("float32"), "std": std.astype("float32")}
-
-
-class S2TDataConfigWriter(object):
- DEFAULT_VOCAB_FILENAME = "dict.txt"
- DEFAULT_INPUT_FEAT_PER_CHANNEL = 80
- DEFAULT_INPUT_CHANNELS = 1
-
- def __init__(self, yaml_path: Path):
- try:
- import yaml
- except ImportError:
- print("Please install PyYAML for S2T data config YAML files")
- self.yaml = yaml
- self.yaml_path = yaml_path
- self.config = {}
-
- def flush(self):
- with open(self.yaml_path, "w") as f:
- self.yaml.dump(self.config, f)
-
- def set_audio_root(self, audio_root=""):
- self.config["audio_root"] = audio_root
-
- def set_vocab_filename(self, vocab_filename: str = "dict.txt"):
- self.config["vocab_filename"] = vocab_filename
-
- def set_specaugment(
- self,
- time_wrap_w: int,
- freq_mask_n: int,
- freq_mask_f: int,
- time_mask_n: int,
- time_mask_t: int,
- time_mask_p: float,
- ):
- self.config["specaugment"] = {
- "time_wrap_W": time_wrap_w,
- "freq_mask_N": freq_mask_n,
- "freq_mask_F": freq_mask_f,
- "time_mask_N": time_mask_n,
- "time_mask_T": time_mask_t,
- "time_mask_p": time_mask_p,
- }
-
- def set_specaugment_lb_policy(self):
- self.set_specaugment(
- time_wrap_w=0,
- freq_mask_n=1,
- freq_mask_f=27,
- time_mask_n=1,
- time_mask_t=100,
- time_mask_p=1.0,
- )
-
- def set_specaugment_ld_policy(self):
- self.set_specaugment(
- time_wrap_w=0,
- freq_mask_n=2,
- freq_mask_f=27,
- time_mask_n=2,
- time_mask_t=100,
- time_mask_p=1.0,
- )
-
- def set_specaugment_sm_policy(self):
- self.set_specaugment(
- time_wrap_w=0,
- freq_mask_n=2,
- freq_mask_f=15,
- time_mask_n=2,
- time_mask_t=70,
- time_mask_p=0.2,
- )
-
- def set_specaugment_ss_policy(self):
- self.set_specaugment(
- time_wrap_w=0,
- freq_mask_n=2,
- freq_mask_f=27,
- time_mask_n=2,
- time_mask_t=70,
- time_mask_p=0.2,
- )
-
- def set_input_channels(self, input_channels: int = 1):
- self.config["input_channels"] = input_channels
-
- def set_input_feat_per_channel(self, input_feat_per_channel: int = 80):
- self.config["input_feat_per_channel"] = input_feat_per_channel
-
- def set_bpe_tokenizer(self, bpe_tokenizer: Dict[str, Any]):
- self.config["bpe_tokenizer"] = bpe_tokenizer
-
- def set_global_cmvn(self, stats_npz_path: str):
- self.config["global_cmvn"] = {"stats_npz_path": stats_npz_path}
-
- def set_feature_transforms(self, split: str, transforms: List[str]):
- if "transforms" not in self.config:
- self.config["transforms"] = {}
- self.config["transforms"][split] = transforms
-
- def set_prepend_tgt_lang_tag(self, flag: bool = True):
- self.config["prepend_tgt_lang_tag"] = flag
-
- def set_sampling_alpha(self, sampling_alpha: float = 1.0):
- self.config["sampling_alpha"] = sampling_alpha
-
- def set_extra(self, data):
- self.config.update(data)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/docs/covost_example.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/docs/covost_example.md
deleted file mode 100644
index 6282428b16496dbc8512da2e9cd3204a065c73a5..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/docs/covost_example.md
+++ /dev/null
@@ -1,140 +0,0 @@
-[[Back]](..)
-
-# S2T Example: ST on CoVoST
-
-We replicate the experiments in
-[CoVoST 2 and Massively Multilingual Speech-to-Text Translation (Wang et al., 2020)](https://arxiv.org/abs/2007.10310).
-
-## Data Preparation
-
-[Download](https://commonvoice.mozilla.org/en/datasets) and unpack Common Voice v4 to a path
-`${COVOST_ROOT}/${SOURCE_LANG_ID}`, then preprocess it with
-
-```bash
-# additional Python packages for S2T data processing/model training
-pip install pandas torchaudio sentencepiece
-
-# En ASR
-python examples/speech_to_text/prep_covost_data.py \
- --data-root ${COVOST_ROOT} --vocab-type char --src-lang en
-# ST
-python examples/speech_to_text/prep_covost_data.py \
- --data-root ${COVOST_ROOT} --vocab-type char \
- --src-lang fr --tgt-lang en
-```
-
-The generated files (manifest, features, vocabulary and data configuration) will be added to
-`${COVOST_ROOT}/${SOURCE_LANG_ID}`.
-
-Download our vocabulary files if you want to use our pre-trained models:
-
-- ASR: [En](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_en_asr_vocab_char.zip)
-- ST: [Fr-En](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_fr_en_st_vocab_char.zip), [De-En](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_de_en_st_vocab_char.zip), [Es-En](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_es_en_st_vocab_char.zip), [Ca-En](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_ca_en_st_vocab_char.zip), [En-De](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_en_de_st_vocab_char.zip), [En-Ca](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_en_ca_st_vocab_char.zip), [En-Fa](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_en_fa_st_vocab_char.zip), [En-Et](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_en_et_st_vocab_char.zip)
-
-## ASR
-
-#### Training
-
-We train an En ASR model for encoder pre-training some of the ST models.
-
-```bash
-fairseq-train ${COVOST_ROOT}/en \
- --config-yaml config_asr_en.yaml --train-subset train_asr_en --valid-subset dev_asr_en \
- --save-dir ${ASR_SAVE_DIR} --num-workers 4 --max-tokens 50000 --max-update 60000 \
- --task speech_to_text --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \
- --report-accuracy --arch s2t_transformer_s --dropout 0.15 --optimizer adam --lr 2e-3 \
- --lr-scheduler inverse_sqrt --warmup-updates 10000 --clip-norm 10.0 --seed 1 --update-freq 8 \
- --attn-type None --pos-enc-type ${POS_ENC_TYPE}
-```
-
-where `ASR_SAVE_DIR` is the checkpoint root path and `POS_ENC_TYPE` refers to positional encoding to be used in the conformer encoder.
-Set it to `abs`, `rope` or `rel_pos` to use the absolute positional encoding, rotary positional encoding or relative positional encoding in the conformer layer respectively.
-Transformer encoder only supports absolute positional encoding and by default, the transformer encoder will be used.
-To switch to conformer, set `--attn-type espnet` and `--POS_ENC_TYPE`. We set `--update-freq 8` to simulate 8 GPUs with 1 GPU. You may want to update it accordingly when using more than 1 GPU.
-
-#### Inference & Evaluation
-
-```bash
-CHECKPOINT_FILENAME=avg_last_10_checkpoint.pt
-python scripts/average_checkpoints.py \
- --inputs ${ASR_SAVE_DIR} --num-epoch-checkpoints 10 \
- --output "${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME}"
-fairseq-generate ${COVOST_ROOT}/en \
- --config-yaml config_asr_en.yaml --gen-subset test_asr_en --task speech_to_text \
- --path ${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME} --max-tokens 50000 --beam 5 \
- --scoring wer --wer-tokenizer 13a --wer-lowercase --wer-remove-punct
-```
-
-#### Results
-
-| --arch | --pos-enc-type | Params | En | Model |
-|---|---|---|---|---|
-| s2t_transformer_s | - | 31M | 25.6 | [Download](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_en_asr_transformer_s.pt) |
-| s2t_conformer | rel_pos | 42.9M | 23.18| [Download](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_asr/rel_pos_asr_checkpoint_best.pt) |
-| s2t_conformer | rope | 42.1M | 23.8| [Download](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_asr/rope_pos_asr_checkpoint_best.pt) |
-| s2t_conformer | abs | 42.1M | 23.8| [Download](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_asr/abs_asr_checkpoint_best.pt) |
-
-## ST
-
-#### Training
-
-Fr-En as example:
-
-```bash
-fairseq-train ${COVOST_ROOT}/fr \
- --config-yaml config_st_fr_en.yaml --train-subset train_st_fr_en --valid-subset dev_st_fr_en \
- --save-dir ${ST_SAVE_DIR} --num-workers 4 --max-update 30000 --max-tokens 40000 \ # --max-tokens 50000 for en-*
- --task speech_to_text --criterion label_smoothed_cross_entropy --label-smoothing 0.1 --report-accuracy \
- --arch s2t_transformer_s --encoder-freezing-updates 1000 --optimizer adam --lr 2e-3 \
- --lr-scheduler inverse_sqrt --warmup-updates 10000 --clip-norm 10.0 --seed 1 --update-freq 8 \
- --attn-type None --pos-enc-type ${POS_ENC_TYPE} \
- --load-pretrained-encoder-from ${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME}
-```
-
-where `ST_SAVE_DIR` is the checkpoint root path and `POS_ENC_TYPE` refers to positional encoding to be used in the conformer encoder.
-Set it to `abs`, `rope` or `rel_pos` to use the absolute positional encoding, rotary positional encoding or relative positional encoding in the conformer layer respectively.
-Transformer encoder only supports absolute positional encoding and by default, the transformer encoder will be used.
-To switch to conformer, set `--attn-type espnet` and `--POS_ENC_TYPE`. Optionally load the pre-trained En ASR encoder for faster training and better
-performance: `--load-pretrained-encoder-from `. We set `--update-freq 8` to simulate 8 GPUs with 1 GPU.
-You may want to update it accordingly when using more than 1 GPU.
-
-#### Inference & Evaluation
-
-Average the last 10 checkpoints and evaluate on test split:
-
-```bash
-CHECKPOINT_FILENAME=avg_last_10_checkpoint.pt
-python scripts/average_checkpoints.py \
- --inputs ${ST_SAVE_DIR} --num-epoch-checkpoints 10 \
- --output "${ST_SAVE_DIR}/${CHECKPOINT_FILENAME}"
-fairseq-generate ${COVOST_ROOT}/fr \
- --config-yaml config_st_fr_en.yaml --gen-subset test_st_fr_en --task speech_to_text \
- --path ${ST_SAVE_DIR}/${CHECKPOINT_FILENAME} \
- --max-tokens 50000 --beam 5 --scoring sacrebleu
-```
-
-## Interactive Decoding
-
-Launch the interactive console via
-
-```bash
-fairseq-interactive ${COVOST_ROOT}/fr --config-yaml config_st_fr_en.yaml \
- --task speech_to_text --path ${SAVE_DIR}/${CHECKPOINT_FILENAME} \
- --max-tokens 50000 --beam 5
-```
-
-Type in WAV/FLAC/OGG audio paths (one per line) after the prompt.
-
-#### Results
-
-| --arch | --pos-enc-type | Params | ASR PT | Fr-En | De-En | Es-En | Ca-En | En-De | En-Ca | En-Fa | En-Et | Model |
-|---|---|---|---|---|---|---|---|---|---|---|---|---|
-| s2t_transformer | - | 31M | Yes | [27.2](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_fr_en_st_transformer_s.pt) | [17.7](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_de_en_st_transformer_s.pt) | [23.1](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_es_en_st_transformer_s.pt) | [19.3](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_ca_en_st_transformer_s.pt) | [16.1](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_en_de_st_transformer_s.pt) | [21.6](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_en_ca_st_transformer_s.pt) | [12.9](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_en_fa_st_transformer_s.pt) | [12.8](https://dl.fbaipublicfiles.com/fairseq/s2t/covost2_en_et_st_transformer_s.pt) | (<-Download) |
-| s2t_conformer | rel_pos | 42.9M | No | [28.32](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/fr_en/rel_pos_from_scratch_avg_last_10_checkpoint.pt) | [18.21](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/de_en/rel_pos_from_scratch_avg_last_10_checkpoint.pt) | [25.98](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/es_en/rel_pos_from_scratch_avg_last_10_checkpoint.pt) | [21.13](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/ca_en/rel_pos_from_scratch_avg_last_10_checkpoint.pt) | [20.37](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_de/rel_pos_from_scratch_avg_last_10_checkpoint.pt) | [25.89](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_ca/rel_pos_from_scratch_avg_last_10_checkpoint.pt) | [15.59](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_fa/rel_pos_from_scratch_avg_last_10_checkpoint.pt) | [14.49](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_et/rel_pos_from_scratch_avg_last_10_checkpoint.pt) | (<-Download) |
-| s2t_conformer | rel_pos | 42.9M | Yes| [27.15](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/fr_en/rel_pos_asr_pt_avg_last_10_checkpoint.pt) | [18.22](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/de_en/rel_pos_asr_pt_avg_last_10_checkpoint.pt) | [25.14](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/es_en/rel_pos_asr_pt_avg_last_10_checkpoint.pt) | [21.68](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/ca_en/rel_pos_asr_pt_avg_last_10_checkpoint.pt) | [20.35](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_de/rel_pos_asr_pt_avg_last_10_checkpoint.pt) | [25.92](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_ca/rel_pos_asr_pt_avg_last_10_checkpoint.pt) | [15.76](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_fa/rel_pos_asr_pt_avg_last_10_checkpoint.pt) | [16.52](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_et/rel_pos_asr_pt_avg_last_10_checkpoint.pt) | (<-Download) |
-| s2t_conformer | rope | 42.1M | No | [27.61](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/fr_en/rope_from_scratch_avg_last_10_checkpoint.pt) | [17.6](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/de_en/rope_from_scratch_avg_last_10_checkpoint.pt) | [24.91](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/es_en/rope_from_scratch_avg_last_10_checkpoint.pt) | [20.78](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/ca_en/rope_from_scratch_avg_last_10_checkpoint.pt) | [19.7](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_de/rope_from_scratch_avg_last_10_checkpoint.pt) | [25.13](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_ca/rope_from_scratch_avg_last_10_checkpoint.pt) | [15.22](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_fa/rope_from_scratch_avg_last_10_checkpoint.pt) | [15.87](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_et/rope_from_scratch_avg_last_10_checkpoint.pt) | (<-Download) |
-| s2t_conformer | rope | 42.1M | Yes | [26.99](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/fr_en/rope_asr_pt_avg_last_10_checkpoint.pt) | [17.71](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/de_en/rope_asr_pt_avg_last_10_checkpoint.pt) | [24.24](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/es_en/rope_asr_pt_avg_last_10_checkpoint.pt) | [21.24](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/ca_en/rope_asr_pt_avg_last_10_checkpoint.pt) | [19.9](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_de/rope_asr_pt_avg_last_10_checkpoint.pt) | [25.25](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_ca/rope_asr_pt_avg_last_10_checkpoint.pt) | [15.58](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_fa/rope_asr_pt_avg_last_10_checkpoint.pt) | [15.97](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_et/rope_asr_pt_avg_last_10_checkpoint.pt) | (<-Download) |
-| s2t_conformer | abs | 42.1M | No | [27.45](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/fr_en/abs_from_scratch_avg_last_10_checkpoint.pt) | [17.25](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/de_en/abs_from_scratch_avg_last_10_checkpoint.pt) | [25.01](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/es_en/abs_from_scratch_avg_last_10_checkpoint.pt) | [20.26](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/ca_en/abs_from_scratch_avg_last_10_checkpoint.pt) | [19.86](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_de/abs_from_scratch_avg_last_10_checkpoint.pt) | [25.25](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_ca/abs_from_scratch_avg_last_10_checkpoint.pt) | [15.46](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_fa/abs_from_scratch_avg_last_10_checkpoint.pt) | [15.81](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_et/abs_from_scratch_avg_last_10_checkpoint.pt) | (<-Download) |
-| s2t_conforme | abs | 42.1M | Yes| [26.52](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/fr_en/abs_asr_pt_avg_last_10_checkpoint.pt) | [17.37](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/de_en/abs_asr_pt_avg_last_10_checkpoint.pt) | [25.40](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/es_en/abs_asr_pt_avg_last_10_checkpoint.pt) | [20.45](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/ca_en/abs_asr_pt_avg_last_10_checkpoint.pt) | [19.57](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_de/abs_asr_pt_avg_last_10_checkpoint.pt) | [25.40](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_ca/abs_asr_pt_avg_last_10_checkpoint.pt) | [15.17](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_fa/abs_asr_pt_avg_last_10_checkpoint.pt) | [15.83](https://dl.fbaipublicfiles.com/fairseq/conformer/covost2/en_et/abs_asr_pt_avg_last_10_checkpoint.pt) | (<-Download) |
-
-[[Back]](..)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/docs/librispeech_example.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/docs/librispeech_example.md
deleted file mode 100644
index 4040fda9426027537036ba987d087a43e734bfd9..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/docs/librispeech_example.md
+++ /dev/null
@@ -1,69 +0,0 @@
-[[Back]](..)
-
-# S2T Example: Speech Recognition (ASR) on LibriSpeech
-[LibriSpeech](https://www.danielpovey.com/files/2015_icassp_librispeech.pdf) is a de-facto standard English ASR
-benchmark. We provide competitive
-vanilla [Transformer](https://papers.nips.cc/paper/2017/file/3f5ee243547dee91fbd053c1c4a845aa-Paper.pdf) baselines.
-
-## Data preparation
-Download and preprocess LibriSpeech data with
-```bash
-# additional Python packages for S2T data processing/model training
-pip install pandas torchaudio sentencepiece
-
-python examples/speech_to_text/prep_librispeech_data.py \
- --output-root ${LS_ROOT} --vocab-type unigram --vocab-size 10000
-```
-where `LS_ROOT` is the root path for downloaded data as well as generated files (manifest, features, vocabulary and
-data configuration).
-
-[Download](https://dl.fbaipublicfiles.com/fairseq/s2t/librispeech_vocab_unigram10000.zip) our vocabulary files
-if you want to use our pre-trained models.
-
-## Training
-```bash
-fairseq-train ${LS_ROOT} --save-dir ${SAVE_DIR} \
- --config-yaml config.yaml --train-subset train-clean-100,train-clean-360,train-other-500 --valid-subset dev-clean,dev-other \
- --num-workers 4 --max-tokens 40000 --max-update 300000 \
- --task speech_to_text --criterion label_smoothed_cross_entropy --label-smoothing 0.1 --report-accuracy \
- --arch s2t_transformer_s --share-decoder-input-output-embed \
- --optimizer adam --lr 2e-3 --lr-scheduler inverse_sqrt --warmup-updates 10000 \
- --clip-norm 10.0 --seed 1 --update-freq 8
-```
-where `SAVE_DIR` is the checkpoint root path. Here we use `--arch s2t_transformer_s` (31M parameters) as example.
-For better performance, you may switch to `s2t_transformer_m` (71M, with `--lr 1e-3`) or `s2t_transformer_l`
-(268M, with `--lr 5e-4`). We set `--update-freq 8` to simulate 8 GPUs with 1 GPU. You may want to update it accordingly
-when using more than 1 GPU.
-
-## Inference & Evaluation
-Average the last 10 checkpoints and evaluate on the 4 splits
-(`dev-clean`, `dev-other`, `test-clean` and `test-other`):
-```bash
-CHECKPOINT_FILENAME=avg_last_10_checkpoint.pt
-python scripts/average_checkpoints.py --inputs ${SAVE_DIR} \
- --num-epoch-checkpoints 10 \
- --output "${SAVE_DIR}/${CHECKPOINT_FILENAME}"
-for SUBSET in dev-clean dev-other test-clean test-other; do
- fairseq-generate ${LS_ROOT} --config-yaml config.yaml --gen-subset ${SUBSET} \
- --task speech_to_text --path ${SAVE_DIR}/${CHECKPOINT_FILENAME} \
- --max-tokens 50000 --beam 5 --scoring wer
-done
-```
-
-## Interactive Decoding
-Launch the interactive console via
-```bash
-fairseq-interactive ${LS_ROOT} --config-yaml config.yaml --task speech_to_text \
- --path ${SAVE_DIR}/${CHECKPOINT_FILENAME} --max-tokens 50000 --beam 5
-```
-Type in WAV/FLAC/OGG audio paths (one per line) after the prompt.
-
-## Results
-
-| --arch | Params | dev-clean | dev-other | test-clean | test-other | Model |
-|---|---|---|---|---|---|---|
-| s2t_transformer_s | 30M | 3.8 | 8.9 | 4.4 | 9.0 | [Download](https://dl.fbaipublicfiles.com/fairseq/s2t/librispeech_transformer_s.pt) |
-| s2t_transformer_m | 71M | 3.2 | 8.0 | 3.4 | 7.9 | [Download](https://dl.fbaipublicfiles.com/fairseq/s2t/librispeech_transformer_m.pt) |
-| s2t_transformer_l | 268M | 3.0 | 7.5 | 3.2 | 7.5 | [Download](https://dl.fbaipublicfiles.com/fairseq/s2t/librispeech_transformer_l.pt) |
-
-[[Back]](..)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/docs/mtedx_example.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/docs/mtedx_example.md
deleted file mode 100644
index 7e3d7595579363adf455bd5b55f5d0685de3a9e9..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/docs/mtedx_example.md
+++ /dev/null
@@ -1,201 +0,0 @@
-[[Back]](..)
-
-# S2T Example: Speech Translation (ST) on Multilingual TEDx
-
-[Multilingual TEDx](https://arxiv.org/abs/2102.01757) is multilingual corpus for speech recognition and
-speech translation. The data is derived from TEDx talks in 8 source languages
-with translations to a subset of 5 target languages.
-
-## Data Preparation
-[Download](http://openslr.org/100/) and unpack Multilingual TEDx data to a path
-`${MTEDX_ROOT}/${LANG_PAIR}`, then preprocess it with
-```bash
-# additional Python packages for S2T data processing/model training
-pip install pandas torchaudio soundfile sentencepiece
-
-# Generate TSV manifests, features, vocabulary
-# and configuration for each language
-python examples/speech_to_text/prep_mtedx_data.py \
- --data-root ${MTEDX_ROOT} --task asr \
- --vocab-type unigram --vocab-size 1000
-python examples/speech_to_text/prep_mtedx_data.py \
- --data-root ${MTEDX_ROOT} --task st \
- --vocab-type unigram --vocab-size 1000
-
-# Add vocabulary and configuration for joint data
-# (based on the manifests and features generated above)
-python examples/speech_to_text/prep_mtedx_data.py \
- --data-root ${MTEDX_ROOT} --task asr --joint \
- --vocab-type unigram --vocab-size 8000
-python examples/speech_to_text/prep_mtedx_data.py \
- --data-root ${MTEDX_ROOT} --task st --joint \
- --vocab-type unigram --vocab-size 8000
-```
-The generated files (manifest, features, vocabulary and data configuration) will be added to
-`${MTEDX_ROOT}/${LANG_PAIR}` (per-language data) and `MTEDX_ROOT` (joint data).
-
-
-## ASR
-#### Training
-Spanish as example:
-```bash
-fairseq-train ${MTEDX_ROOT}/es-es \
- --config-yaml config_asr.yaml --train-subset train_asr --valid-subset valid_asr \
- --save-dir ${ASR_SAVE_DIR} --num-workers 4 --max-tokens 40000 --max-epoch 200 \
- --task speech_to_text --criterion label_smoothed_cross_entropy --report-accuracy \
- --arch s2t_transformer_xs --optimizer adam --lr 2e-3 --lr-scheduler inverse_sqrt \
- --warmup-updates 10000 --clip-norm 10.0 --seed 1 --dropout 0.3 --label-smoothing 0.1 \
- --load-pretrained-encoder-from ${PRETRAINED_ENCODER} \
- --skip-invalid-size-inputs-valid-test \
- --keep-last-epochs 10 --update-freq 8 --patience 10
-```
-For joint model (using ASR data from all 8 languages):
-```bash
-fairseq-train ${MTEDX_ROOT} \
- --config-yaml config_asr.yaml \
- --train-subset train_es-es_asr,train_fr-fr_asr,train_pt-pt_asr,train_it-it_asr,train_ru-ru_asr,train_el-el_asr,train_ar-ar_asr,train_de-de_asr \
- --valid-subset valid_es-es_asr,valid_fr-fr_asr,valid_pt-pt_asr,valid_it-it_asr,valid_ru-ru_asr,valid_el-el_asr,valid_ar-ar_asr,valid_de-de_asr \
- --save-dir ${MULTILINGUAL_ASR_SAVE_DIR} --num-workers 4 --max-tokens 40000 --max-epoch 200 \
- --task speech_to_text --criterion label_smoothed_cross_entropy --report-accuracy \
- --arch s2t_transformer_s --optimizer adam --lr 2e-3 --lr-scheduler inverse_sqrt \
- --warmup-updates 10000 --clip-norm 10.0 --seed 1 --dropout 0.3 --label-smoothing 0.1 \
- --skip-invalid-size-inputs-valid-test \
- --keep-last-epochs 10 --update-freq 8 --patience 10 \
- --ignore-prefix-size 1
-```
-where `MULTILINGUAL_ASR_SAVE_DIR` is the checkpoint root path. We set `--update-freq 8` to simulate 8 GPUs
-with 1 GPU. You may want to update it accordingly when using more than 1 GPU.
-For multilingual models, we prepend target language ID token as target BOS, which should be excluded from
-the training loss via `--ignore-prefix-size 1`.
-
-#### Inference & Evaluation
-```bash
-CHECKPOINT_FILENAME=avg_last_10_checkpoint.pt
-python scripts/average_checkpoints.py \
- --inputs ${ASR_SAVE_DIR} --num-epoch-checkpoints 10 \
- --output "${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME}"
-
-fairseq-generate ${MTEDX_ROOT}/es-es \
- --config-yaml config_asr.yaml --gen-subset test --task speech_to_text \
- --path ${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME} --max-tokens 50000 --beam 5 \
- --skip-invalid-size-inputs-valid-test \
- --scoring wer --wer-tokenizer 13a --wer-lowercase --wer-remove-punct --remove-bpe
-
-# For models trained on joint data
-CHECKPOINT_FILENAME=avg_last_10_checkpoint.pt
-python scripts/average_checkpoints.py \
- --inputs ${MULTILINGUAL_ASR_SAVE_DIR} --num-epoch-checkpoints 10 \
- --output "${MULTILINGUAL_ASR_SAVE_DIR}/${CHECKPOINT_FILENAME}"
-
-for LANG in es fr pt it ru el ar de; do
- fairseq-generate ${MTEDX_ROOT} \
- --config-yaml config_asr.yaml --gen-subset test_${LANG}-${LANG}_asr --task speech_to_text \
- --prefix-size 1 --path ${MULTILINGUAL_ASR_SAVE_DIR}/${CHECKPOINT_FILENAME} \
- --max-tokens 40000 --beam 5 \
- --skip-invalid-size-inputs-valid-test \
- --scoring wer --wer-tokenizer 13a --wer-lowercase --wer-remove-punct --remove-bpe
-done
-```
-#### Results
-| Data | --arch | Params | Es | Fr | Pt | It | Ru | El | Ar | De |
-|--------------|--------------------|--------|------|------|------|------|------|-------|-------|-------|
-| Monolingual | s2t_transformer_xs | 10M | 46.4 | 45.6 | 54.8 | 48.0 | 74.7 | 109.5 | 104.4 | 111.1 |
-
-
-## ST
-#### Training
-Es-En as example:
-```bash
-fairseq-train ${MTEDX_ROOT}/es-en \
- --config-yaml config_st.yaml --train-subset train_st --valid-subset valid_st \
- --save-dir ${ST_SAVE_DIR} --num-workers 4 --max-tokens 40000 --max-epoch 200 \
- --task speech_to_text --criterion label_smoothed_cross_entropy --report-accuracy \
- --arch s2t_transformer_xs --optimizer adam --lr 2e-3 --lr-scheduler inverse_sqrt \
- --warmup-updates 10000 --clip-norm 10.0 --seed 1 --dropout 0.3 --label-smoothing 0.1 \
- --load-pretrained-encoder-from ${PRETRAINED_ENCODER} \
- --skip-invalid-size-inputs-valid-test \
- --keep-last-epochs 10 --update-freq 8 --patience 10
-```
-For multilingual model (all 12 directions):
-```bash
-fairseq-train ${MTEDX_ROOT} \
- --config-yaml config_st.yaml \
- --train-subset train_el-en_st,train_es-en_st,train_es-fr_st,train_es-it_st,train_es-pt_st,train_fr-en_st,train_fr-es_st,train_fr-pt_st,train_it-en_st,train_it-es_st,train_pt-en_st,train_pt-es_st,train_ru-en_st \
- --valid-subset valid_el-en_st,valid_es-en_st,valid_es-fr_st,valid_es-it_st,valid_es-pt_st,valid_fr-en_st,valid_fr-es_st,valid_fr-pt_st,valid_it-en_st,valid_it-es_st,valid_pt-en_st,valid_pt-es_st,valid_ru-en_st \
- --save-dir ${MULTILINGUAL_ST_SAVE_DIR} --num-workers 4 --max-tokens 40000 --max-epoch 200 \
- --task speech_to_text --criterion label_smoothed_cross_entropy --report-accuracy \
- --arch s2t_transformer_s --optimizer adam --lr 2e-3 --lr-scheduler inverse_sqrt \
- --warmup-updates 10000 --clip-norm 10.0 --seed 1 --dropout 0.3 --label-smoothing 0.1 \
- --skip-invalid-size-inputs-valid-test \
- --keep-last-epochs 10 --update-freq 8 --patience 10 \
- --ignore-prefix-size 1 \
- --load-pretrained-encoder-from ${PRETRAINED_ENCODER}
-```
-where `ST_SAVE_DIR` (`MULTILINGUAL_ST_SAVE_DIR`) is the checkpoint root path. The ST encoder is pre-trained by ASR
-for faster training and better performance: `--load-pretrained-encoder-from <(JOINT_)ASR checkpoint path>`. We set
-`--update-freq 8` to simulate 8 GPUs with 1 GPU. You may want to update it accordingly when using more than 1 GPU.
-For multilingual models, we prepend target language ID token as target BOS, which should be excluded from
-the training loss via `--ignore-prefix-size 1`.
-
-#### Inference & Evaluation
-Average the last 10 checkpoints and evaluate on the `test` split:
-```bash
-CHECKPOINT_FILENAME=avg_last_10_checkpoint.pt
-python scripts/average_checkpoints.py \
- --inputs ${ST_SAVE_DIR} --num-epoch-checkpoints 10 \
- --output "${ST_SAVE_DIR}/${CHECKPOINT_FILENAME}"
-
-fairseq-generate ${MTEDX_ROOT}/es-en \
- --config-yaml config_st.yaml --gen-subset test --task speech_to_text \
- --path ${ST_SAVE_DIR}/${CHECKPOINT_FILENAME} \
- --max-tokens 50000 --beam 5 --scoring sacrebleu --remove-bpe
-
-# For multilingual models
-python scripts/average_checkpoints.py \
- --inputs ${MULTILINGUAL_ST_SAVE_DIR} --num-epoch-checkpoints 10 \
- --output "${MULTILINGUAL_ST_SAVE_DIR}/${CHECKPOINT_FILENAME}"
-
-for LANGPAIR in es-en es-fr es-pt fr-en fr-es fr-pt pt-en pt-es it-en it-es ru-en el-en; do
- fairseq-generate ${MTEDX_ROOT} \
- --config-yaml config_st.yaml --gen-subset test_${LANGPAIR}_st --task speech_to_text \
- --prefix-size 1 --path ${MULTILINGUAL_ST_SAVE_DIR}/${CHECKPOINT_FILENAME} \
- --max-tokens 40000 --beam 5 \
- --skip-invalid-size-inputs-valid-test \
- --scoring sacrebleu --remove-bpe
-done
-```
-For multilingual models, we force decoding from the target language ID token (as BOS) via `--prefix-size 1`.
-
-#### Results
-| Data | --arch | Params | Es-En | Es-Pt | Es-Fr | Fr-En | Fr-Es | Fr-Pt | Pt-En | Pt-Es | It-En | It-Es | Ru-En | El-En |
-|--------------|--------------------|-----|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
-| Bilingual | s2t_transformer_xs | 10M | 7.0 | 12.2 | 1.7 | 8.9 | 10.6 | 7.9 | 8.1 | 8.7 | 6.4 | 1.0 | 0.7 | 0.6 |
-| Multilingual | s2t_transformer_s | 31M | 12.3 | 17.4 | 6.1 | 12.0 | 13.6 | 13.2 | 12.0 | 13.7 | 10.7 | 13.1 | 0.6 | 0.8 |
-
-
-## Citation
-Please cite as:
-```
-@inproceedings{salesky2021mtedx,
- title={Multilingual TEDx Corpus for Speech Recognition and Translation},
- author={Elizabeth Salesky and Matthew Wiesner and Jacob Bremerman and Roldano Cattoni and Matteo Negri and Marco Turchi and Douglas W. Oard and Matt Post},
- booktitle={Proceedings of Interspeech},
- year={2021},
-}
-
-@inproceedings{wang2020fairseqs2t,
- title = {fairseq S2T: Fast Speech-to-Text Modeling with fairseq},
- author = {Changhan Wang and Yun Tang and Xutai Ma and Anne Wu and Dmytro Okhonko and Juan Pino},
- booktitle = {Proceedings of the 2020 Conference of the Asian Chapter of the Association for Computational Linguistics (AACL): System Demonstrations},
- year = {2020},
-}
-
-@inproceedings{ott2019fairseq,
- title = {fairseq: A Fast, Extensible Toolkit for Sequence Modeling},
- author = {Myle Ott and Sergey Edunov and Alexei Baevski and Angela Fan and Sam Gross and Nathan Ng and David Grangier and Michael Auli},
- booktitle = {Proceedings of NAACL-HLT 2019: Demonstrations},
- year = {2019},
-}
-```
-
-[[Back]](..)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/docs/mustc_example.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/docs/mustc_example.md
deleted file mode 100644
index c95ef3e15660107c3384f87c1680f005044e7f3b..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/docs/mustc_example.md
+++ /dev/null
@@ -1,155 +0,0 @@
-[[Back]](..)
-
-# S2T Example: Speech Translation (ST) on MuST-C
-
-[MuST-C](https://www.aclweb.org/anthology/N19-1202) is multilingual speech-to-text translation corpus with
-8-language translations on English TED talks. We match the state-of-the-art performance in
-[ESPNet-ST](https://arxiv.org/pdf/2004.10234.pdf) with a simpler model training pipeline.
-
-## Data Preparation
-[Download](https://ict.fbk.eu/must-c) and unpack MuST-C data to a path
-`${MUSTC_ROOT}/en-${TARGET_LANG_ID}`, then preprocess it with
-```bash
-# additional Python packages for S2T data processing/model training
-pip install pandas torchaudio soundfile sentencepiece
-
-# Generate TSV manifests, features, vocabulary
-# and configuration for each language
-python examples/speech_to_text/prep_mustc_data.py \
- --data-root ${MUSTC_ROOT} --task asr \
- --vocab-type unigram --vocab-size 5000
-python examples/speech_to_text/prep_mustc_data.py \
- --data-root ${MUSTC_ROOT} --task st \
- --vocab-type unigram --vocab-size 8000
-
-# Add vocabulary and configuration for joint data
-# (based on the manifests and features generated above)
-python examples/speech_to_text/prep_mustc_data.py \
- --data-root ${MUSTC_ROOT} --task asr --joint \
- --vocab-type unigram --vocab-size 10000
-python examples/speech_to_text/prep_mustc_data.py \
- --data-root ${MUSTC_ROOT} --task st --joint \
- --vocab-type unigram --vocab-size 10000
-```
-The generated files (manifest, features, vocabulary and data configuration) will be added to
-`${MUSTC_ROOT}/en-${TARGET_LANG_ID}` (per-language data) and `MUSTC_ROOT` (joint data).
-
-Download our vocabulary files if you want to use our pre-trained models:
-- ASR: [En-De](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_de_asr_vocab_unigram5000.zip), [En-Nl](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_nl_asr_vocab_unigram5000.zip), [En-Es](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_es_asr_vocab_unigram5000.zip), [En-Fr](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_fr_asr_vocab_unigram5000.zip), [En-It](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_it_asr_vocab_unigram5000.zip), [En-Pt](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_pt_asr_vocab_unigram5000.zip), [En-Ro](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_ro_asr_vocab_unigram5000.zip), [En-Ru](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_ru_asr_vocab_unigram5000.zip), [Joint](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_joint_asr_vocab_unigram10000.zip)
-- ST: [En-De](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_de_st_vocab_unigram8000.zip), [En-Nl](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_nl_st_vocab_unigram8000.zip), [En-Es](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_es_st_vocab_unigram8000.zip), [En-Fr](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_fr_st_vocab_unigram8000.zip), [En-It](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_it_st_vocab_unigram8000.zip), [En-Pt](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_pt_st_vocab_unigram8000.zip), [En-Ro](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_ro_st_vocab_unigram8000.zip), [En-Ru](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_ru_st_vocab_unigram8000.zip), [Multilingual](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_multilingual_st_vocab_unigram10000.zip)
-
-## ASR
-#### Training
-En-De as example:
-```bash
-fairseq-train ${MUSTC_ROOT}/en-de \
- --config-yaml config_asr.yaml --train-subset train_asr --valid-subset dev_asr \
- --save-dir ${ASR_SAVE_DIR} --num-workers 4 --max-tokens 40000 --max-update 100000 \
- --task speech_to_text --criterion label_smoothed_cross_entropy --label-smoothing 0.1 --report-accuracy \
- --arch s2t_transformer_s --optimizer adam --lr 1e-3 --lr-scheduler inverse_sqrt \
- --warmup-updates 10000 --clip-norm 10.0 --seed 1 --update-freq 8
-```
-For joint model (using ASR data from all 8 directions):
-```bash
-fairseq-train ${MUSTC_ROOT} \
- --config-yaml config_asr.yaml \
- --train-subset train_de_asr,train_nl_asr,train_es_asr,train_fr_asr,train_it_asr,train_pt_asr,train_ro_asr,train_ru_asr \
- --valid-subset dev_de_asr,dev_nl_asr,dev_es_asr,dev_fr_asr,dev_it_asr,dev_pt_asr,dev_ro_asr,dev_ru_asr \
- --save-dir ${JOINT_ASR_SAVE_DIR} --num-workers 4 --max-tokens 40000 --max-update 100000 \
- --task speech_to_text --criterion label_smoothed_cross_entropy --label-smoothing 0.1 --report-accuracy \
- --arch s2t_transformer_s --optimizer adam --lr 1e-3 --lr-scheduler inverse_sqrt \
- --warmup-updates 10000 --clip-norm 10.0 --seed 1 --update-freq 8
-```
-where `ASR_SAVE_DIR` (`JOINT_ASR_SAVE_DIR`) is the checkpoint root path. We set `--update-freq 8` to simulate 8 GPUs
-with 1 GPU. You may want to update it accordingly when using more than 1 GPU.
-
-#### Inference & Evaluation
-```bash
-CHECKPOINT_FILENAME=avg_last_10_checkpoint.pt
-python scripts/average_checkpoints.py \
- --inputs ${ASR_SAVE_DIR} --num-epoch-checkpoints 10 \
- --output "${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME}"
-fairseq-generate ${MUSTC_ROOT}/en-de \
- --config-yaml config_asr.yaml --gen-subset tst-COMMON_asr --task speech_to_text \
- --path ${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME} --max-tokens 50000 --beam 5 \
- --scoring wer --wer-tokenizer 13a --wer-lowercase --wer-remove-punct
-
-# For models trained on joint data
-python scripts/average_checkpoints.py \
- --inputs ${JOINT_ASR_SAVE_DIR} --num-epoch-checkpoints 10 \
- --output "${JOINT_ASR_SAVE_DIR}/${CHECKPOINT_FILENAME}"
-for LANG in de nl es fr it pt ro ru; do
- fairseq-generate ${MUSTC_ROOT} \
- --config-yaml config_asr.yaml --gen-subset tst-COMMON_${LANG}_asr --task speech_to_text \
- --path ${JOINT_ASR_SAVE_DIR}/${CHECKPOINT_FILENAME} --max-tokens 50000 --beam 5 \
- --scoring wer --wer-tokenizer 13a --wer-lowercase --wer-remove-punct
-done
-```
-#### Results
-| Data | --arch | Params | En-De | En-Nl | En-Es | En-Fr | En-It | En-Pt | En-Ro | En-Ru | Model |
-|---|---|---|---|---|---|---|---|---|---|---|---|
-| Single | s2t_transformer_s | 31M | [18.2](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_de_asr_transformer_s.pt) | [17.6](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_nl_asr_transformer_s.pt) | [17.7](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_es_asr_transformer_s.pt) | [17.2](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_fr_asr_transformer_s.pt) | [17.9](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_it_asr_transformer_s.pt) | [19.1](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_pt_asr_transformer_s.pt) | [18.1](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_ro_asr_transformer_s.pt) | [17.7](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_ru_asr_transformer_s.pt) | (<-Download) |
-| Joint | s2t_transformer_m | 76M | 16.8 | 16.7 | 16.9 | 16.9 | 17.0 | 17.4 | 17.0 | 16.9 | [Download](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_joint_asr_transformer_m.pt) |
-
-## ST
-#### Training
-En-De as example:
-```bash
-fairseq-train ${MUSTC_ROOT}/en-de \
- --config-yaml config_st.yaml --train-subset train_st --valid-subset dev_st \
- --save-dir ${ST_SAVE_DIR} --num-workers 4 --max-tokens 40000 --max-update 100000 \
- --task speech_to_text --criterion label_smoothed_cross_entropy --label-smoothing 0.1 --report-accuracy \
- --arch s2t_transformer_s --optimizer adam --lr 2e-3 --lr-scheduler inverse_sqrt \
- --warmup-updates 10000 --clip-norm 10.0 --seed 1 --update-freq 8 \
- --load-pretrained-encoder-from ${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME}
-```
-For multilingual model (all 8 directions):
-```bash
-fairseq-train ${MUSTC_ROOT} \
- --config-yaml config_st.yaml \
- --train-subset train_de_st,train_nl_st,train_es_st,train_fr_st,train_it_st,train_pt_st,train_ro_st,train_ru_st \
- --valid-subset dev_de_st,dev_nl_st,dev_es_st,dev_fr_st,dev_it_st,dev_pt_st,dev_ro_st,dev_ru_st \
- --save-dir ${MULTILINGUAL_ST_SAVE_DIR} --num-workers 4 --max-tokens 40000 --max-update 100000 \
- --task speech_to_text --criterion label_smoothed_cross_entropy --label-smoothing 0.1 --report-accuracy \
- --arch s2t_transformer_s --ignore-prefix-size 1 --optimizer adam --lr 2e-3 --lr-scheduler inverse_sqrt \
- --warmup-updates 10000 --clip-norm 10.0 --seed 1 --update-freq 8 \
- --load-pretrained-encoder-from ${JOINT_ASR_SAVE_DIR}/${CHECKPOINT_FILENAME}
-```
-where `ST_SAVE_DIR` (`MULTILINGUAL_ST_SAVE_DIR`) is the checkpoint root path. The ST encoder is pre-trained by ASR
-for faster training and better performance: `--load-pretrained-encoder-from <(JOINT_)ASR checkpoint path>`. We set
-`--update-freq 8` to simulate 8 GPUs with 1 GPU. You may want to update it accordingly when using more than 1 GPU.
-For multilingual models, we prepend target language ID token as target BOS, which should be excluded from
-the training loss via `--ignore-prefix-size 1`.
-
-#### Inference & Evaluation
-Average the last 10 checkpoints and evaluate on the `tst-COMMON` split:
-```bash
-CHECKPOINT_FILENAME=avg_last_10_checkpoint.pt
-python scripts/average_checkpoints.py \
- --inputs ${ST_SAVE_DIR} --num-epoch-checkpoints 10 \
- --output "${ST_SAVE_DIR}/${CHECKPOINT_FILENAME}"
-fairseq-generate ${MUSTC_ROOT}/en-de \
- --config-yaml config_st.yaml --gen-subset tst-COMMON_st --task speech_to_text \
- --path ${ST_SAVE_DIR}/${CHECKPOINT_FILENAME} \
- --max-tokens 50000 --beam 5 --scoring sacrebleu
-
-# For multilingual models
-python scripts/average_checkpoints.py \
- --inputs ${MULTILINGUAL_ST_SAVE_DIR} --num-epoch-checkpoints 10 \
- --output "${MULTILINGUAL_ST_SAVE_DIR}/${CHECKPOINT_FILENAME}"
-for LANG in de nl es fr it pt ro ru; do
- fairseq-generate ${MUSTC_ROOT} \
- --config-yaml config_st.yaml --gen-subset tst-COMMON_${LANG}_st --task speech_to_text \
- --prefix-size 1 --path ${MULTILINGUAL_ST_SAVE_DIR}/${CHECKPOINT_FILENAME} \
- --max-tokens 50000 --beam 5 --scoring sacrebleu
-done
-```
-For multilingual models, we force decoding from the target language ID token (as BOS) via `--prefix-size 1`.
-
-#### Results
-| Data | --arch | Params | En-De | En-Nl | En-Es | En-Fr | En-It | En-Pt | En-Ro | En-Ru | Model |
-|---|---|---|---|---|---|---|---|---|---|---|---|
-| Bilingual | s2t_transformer_s | 31M | [22.7](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_de_st_transformer_s.pt) | [27.3](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_nl_st_transformer_s.pt) | [27.2](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_es_st_transformer_s.pt) | [32.9](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_fr_st_transformer_s.pt) | [22.7](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_it_st_transformer_s.pt) | [28.1](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_pt_st_transformer_s.pt) | [21.9](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_ro_st_transformer_s.pt) | [15.3](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_ru_st_transformer_s.pt) | (<-Download) |
-| Multilingual | s2t_transformer_m | 76M | 24.5 | 28.6 | 28.2 | 34.9 | 24.6 | 31.1 | 23.8 | 16.0 | [Download](https://dl.fbaipublicfiles.com/fairseq/s2t/mustc_multilingual_st_transformer_m.pt) |
-
-[[Back]](..)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/docs/simulst_mustc_example.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/docs/simulst_mustc_example.md
deleted file mode 100644
index f3b5a413a27bbe2700da3f418460aa0a7c41abdd..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/docs/simulst_mustc_example.md
+++ /dev/null
@@ -1,190 +0,0 @@
-# Simultaneous Speech Translation (SimulST) on MuST-C
-
-This is a tutorial of training and evaluating a transformer *wait-k* simultaneous model on MUST-C English-Germen Dataset, from [SimulMT to SimulST: Adapting Simultaneous Text Translation to End-to-End Simultaneous Speech Translation](https://www.aclweb.org/anthology/2020.aacl-main.58.pdf).
-
-[MuST-C](https://www.aclweb.org/anthology/N19-1202) is multilingual speech-to-text translation corpus with 8-language translations on English TED talks.
-
-## Data Preparation
-This section introduces the data preparation for training and evaluation.
-If you only want to evaluate the model, please jump to [Inference & Evaluation](#inference--evaluation)
-
-[Download](https://ict.fbk.eu/must-c) and unpack MuST-C data to a path
-`${MUSTC_ROOT}/en-${TARGET_LANG_ID}`, then preprocess it with
-```bash
-# Additional Python packages for S2T data processing/model training
-pip install pandas torchaudio sentencepiece
-
-# Generate TSV manifests, features, vocabulary,
-# global cepstral and mean estimation,
-# and configuration for each language
-cd fairseq
-
-python examples/speech_to_text/prep_mustc_data.py \
- --data-root ${MUSTC_ROOT} --task asr \
- --vocab-type unigram --vocab-size 10000 \
- --cmvn-type global
-
-python examples/speech_to_text/prep_mustc_data.py \
- --data-root ${MUSTC_ROOT} --task st \
- --vocab-type unigram --vocab-size 10000 \
- --cmvn-type global
-```
-
-## ASR Pretraining
-We need a pretrained offline ASR model. Assuming the save directory of the ASR model is `${ASR_SAVE_DIR}`.
-The following command (and the subsequent training commands in this tutorial) assume training on 1 GPU (you can also train on 8 GPUs and remove the `--update-freq 8` option).
-```
-fairseq-train ${MUSTC_ROOT}/en-de \
- --config-yaml config_asr.yaml --train-subset train_asr --valid-subset dev_asr \
- --save-dir ${ASR_SAVE_DIR} --num-workers 4 --max-tokens 40000 --max-update 100000 \
- --task speech_to_text --criterion label_smoothed_cross_entropy --report-accuracy \
- --arch convtransformer_espnet --optimizer adam --lr 0.0005 --lr-scheduler inverse_sqrt \
- --warmup-updates 10000 --clip-norm 10.0 --seed 1 --update-freq 8
-```
-A pretrained ASR checkpoint can be downloaded [here](https://dl.fbaipublicfiles.com/simultaneous_translation/must_c_v1_en_de_pretrained_asr)
-
-## Simultaneous Speech Translation Training
-
-### Wait-K with fixed pre-decision module
-Fixed pre-decision indicates that the model operate simultaneous policy on the boundaries of fixed chunks.
-Here is a example of fixed pre-decision ratio 7 (the simultaneous decision is made every 7 encoder states) and
-a wait-3 policy model. Assuming the save directory is `${ST_SAVE_DIR}`
-```bash
- fairseq-train ${MUSTC_ROOT}/en-de \
- --config-yaml config_st.yaml --train-subset train_st --valid-subset dev_st \
- --save-dir ${ST_SAVE_DIR} --num-workers 8 \
- --optimizer adam --lr 0.0001 --lr-scheduler inverse_sqrt --clip-norm 10.0 \
- --criterion label_smoothed_cross_entropy \
- --warmup-updates 4000 --max-update 100000 --max-tokens 40000 --seed 2 \
- --load-pretrained-encoder-from ${ASR_SAVE_DIR}/checkpoint_best.pt \
- --task speech_to_text \
- --arch convtransformer_simul_trans_espnet \
- --simul-type waitk_fixed_pre_decision \
- --waitk-lagging 3 \
- --fixed-pre-decision-ratio 7 \
- --update-freq 8
-
-```
-### Monotonic multihead attention with fixed pre-decision module
-```
- fairseq-train ${MUSTC_ROOT}/en-de \
- --config-yaml config_st.yaml --train-subset train_st --valid-subset dev_st \
- --save-dir ${ST_SAVE_DIR} --num-workers 8 \
- --optimizer adam --lr 0.0001 --lr-scheduler inverse_sqrt --clip-norm 10.0 \
- --warmup-updates 4000 --max-update 100000 --max-tokens 40000 --seed 2 \
- --load-pretrained-encoder-from ${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME} \
- --task speech_to_text \
- --criterion latency_augmented_label_smoothed_cross_entropy \
- --latency-weight-avg 0.1 \
- --arch convtransformer_simul_trans_espnet \
- --simul-type infinite_lookback_fixed_pre_decision \
- --fixed-pre-decision-ratio 7 \
- --update-freq 8
-```
-## Inference & Evaluation
-[SimulEval](https://github.com/facebookresearch/SimulEval) is used for evaluation.
-The following command is for evaluation.
-
-```
-git clone https://github.com/facebookresearch/SimulEval.git
-cd SimulEval
-pip install -e .
-
-simuleval \
- --agent ${FAIRSEQ}/examples/speech_to_text/simultaneous_translation/agents/fairseq_simul_st_agent.py
- --source ${SRC_LIST_OF_AUDIO}
- --target ${TGT_FILE}
- --data-bin ${MUSTC_ROOT}/en-de \
- --config config_st.yaml \
- --model-path ${ST_SAVE_DIR}/${CHECKPOINT_FILENAME} \
- --output ${OUTPUT} \
- --scores
-```
-
-The source file `${SRC_LIST_OF_AUDIO}` is a list of paths of audio files. Assuming your audio files stored at `/home/user/data`,
-it should look like this
-
-```bash
-/home/user/data/audio-1.wav
-/home/user/data/audio-2.wav
-```
-
-Each line of target file `${TGT_FILE}` is the translation for each audio file input.
-```bash
-Translation_1
-Translation_2
-```
-The evaluation runs on the original MUSTC segmentation.
-The following command will generate the wav list and text file for a evaluation set `${SPLIT}` (chose from `dev`, `tst-COMMON` and `tst-HE`) in MUSTC to `${EVAL_DATA}`.
-```bash
-python ${FAIRSEQ}/examples/speech_to_text/seg_mustc_data.py \
- --data-root ${MUSTC_ROOT} --lang de \
- --split ${SPLIT} --task st \
- --output ${EVAL_DATA}
-```
-
-The `--data-bin` and `--config` should be the same in previous section if you prepare the data from the scratch.
-If only for evaluation, a prepared data directory can be found [here](https://dl.fbaipublicfiles.com/simultaneous_translation/must_c_v1.0_en_de_databin.tgz). It contains
-- `spm_unigram10000_st.model`: a sentencepiece model binary.
-- `spm_unigram10000_st.txt`: the dictionary file generated by the sentencepiece model.
-- `gcmvn.npz`: the binary for global cepstral mean and variance.
-- `config_st.yaml`: the config yaml file. It looks like this.
-You will need to set the absolute paths for `sentencepiece_model` and `stats_npz_path` if the data directory is downloaded.
-```yaml
-bpe_tokenizer:
- bpe: sentencepiece
- sentencepiece_model: ABS_PATH_TO_SENTENCEPIECE_MODEL
-global_cmvn:
- stats_npz_path: ABS_PATH_TO_GCMVN_FILE
-input_channels: 1
-input_feat_per_channel: 80
-sampling_alpha: 1.0
-specaugment:
- freq_mask_F: 27
- freq_mask_N: 1
- time_mask_N: 1
- time_mask_T: 100
- time_mask_p: 1.0
- time_wrap_W: 0
-transforms:
- '*':
- - global_cmvn
- _train:
- - global_cmvn
- - specaugment
-vocab_filename: spm_unigram10000_st.txt
-```
-
-Notice that once a `--data-bin` is set, the `--config` is the base name of the config yaml, not the full path.
-
-Set `--model-path` to the model checkpoint.
-A pretrained checkpoint can be downloaded from [here](https://dl.fbaipublicfiles.com/simultaneous_translation/convtransformer_wait5_pre7), which is a wait-5 model with a pre-decision of 280 ms.
-
-The result of this model on `tst-COMMON` is:
-```bash
-{
- "Quality": {
- "BLEU": 13.94974229366959
- },
- "Latency": {
- "AL": 1751.8031870037803,
- "AL_CA": 2338.5911762796536,
- "AP": 0.7931395378788959,
- "AP_CA": 0.9405103863210942,
- "DAL": 1987.7811616943081,
- "DAL_CA": 2425.2751560926167
- }
-}
-```
-
-If `--output ${OUTPUT}` option is used, the detailed log and scores will be stored under the `${OUTPUT}` directory.
-
-
-The quality is measured by detokenized BLEU. So make sure that the predicted words sent to the server are detokenized.
-
-The latency metrics are
-* Average Proportion
-* Average Lagging
-* Differentiable Average Lagging
-
-Again they will also be evaluated on detokenized text.
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/prep_covost_data.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/prep_covost_data.py
deleted file mode 100644
index 411e9b55152ea4a8e345e8c2d18431958c4f4c07..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/prep_covost_data.py
+++ /dev/null
@@ -1,279 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import logging
-from pathlib import Path
-import shutil
-from tempfile import NamedTemporaryFile
-from typing import Optional, Tuple
-
-import pandas as pd
-import torchaudio
-from examples.speech_to_text.data_utils import (
- create_zip,
- extract_fbank_features,
- filter_manifest_df,
- gen_config_yaml,
- gen_vocab,
- get_zip_manifest,
- load_df_from_tsv,
- save_df_to_tsv,
-)
-from torch import Tensor
-from torch.utils.data import Dataset
-from torchaudio.datasets.utils import download_url, extract_archive
-from tqdm import tqdm
-
-
-log = logging.getLogger(__name__)
-
-
-MANIFEST_COLUMNS = ["id", "audio", "n_frames", "tgt_text", "speaker"]
-
-
-class CoVoST(Dataset):
- """Create a Dataset for CoVoST (https://github.com/facebookresearch/covost).
-
- Args:
- root (str): root path to the dataset and generated manifests/features
- source_language (str): source (audio) language
- target_language (str, optional): target (text) language,
- None for no translation (default: None)
- version (int, optional): CoVoST version. (default: 2)
- download (bool, optional): Whether to download the dataset if it is not
- found at root path. (default: ``False``).
- """
-
- COVOST_URL_TEMPLATE = (
- "https://dl.fbaipublicfiles.com/covost/"
- "covost_v2.{src_lang}_{tgt_lang}.tsv.tar.gz"
- )
-
- VERSIONS = {2}
- SPLITS = ["train", "dev", "test"]
-
- XX_EN_LANGUAGES = {
- 1: ["fr", "de", "nl", "ru", "es", "it", "tr", "fa", "sv-SE", "mn", "zh-CN"],
- 2: [
- "fr",
- "de",
- "es",
- "ca",
- "it",
- "ru",
- "zh-CN",
- "pt",
- "fa",
- "et",
- "mn",
- "nl",
- "tr",
- "ar",
- "sv-SE",
- "lv",
- "sl",
- "ta",
- "ja",
- "id",
- "cy",
- ],
- }
- EN_XX_LANGUAGES = {
- 1: [],
- 2: [
- "de",
- "tr",
- "fa",
- "sv-SE",
- "mn",
- "zh-CN",
- "cy",
- "ca",
- "sl",
- "et",
- "id",
- "ar",
- "ta",
- "lv",
- "ja",
- ],
- }
-
- def __init__(
- self,
- root: str,
- split: str,
- source_language: str,
- target_language: Optional[str] = None,
- version: int = 2,
- ) -> None:
- assert version in self.VERSIONS and split in self.SPLITS
- assert source_language is not None
- self.no_translation = target_language is None
- if not self.no_translation:
- assert "en" in {source_language, target_language}
- if source_language == "en":
- assert target_language in self.EN_XX_LANGUAGES[version]
- else:
- assert source_language in self.XX_EN_LANGUAGES[version]
- else:
- # Hack here so that we can get "split" column from CoVoST TSV.
- # Note that we use CoVoST train split for ASR which is an extension
- # to Common Voice train split.
- target_language = "de" if source_language == "en" else "en"
-
- self.root: Path = Path(root)
-
- cv_tsv_path = self.root / "validated.tsv"
- assert cv_tsv_path.is_file()
-
- covost_url = self.COVOST_URL_TEMPLATE.format(
- src_lang=source_language, tgt_lang=target_language
- )
- covost_archive = self.root / Path(covost_url).name
- if not covost_archive.is_file():
- download_url(covost_url, self.root.as_posix(), hash_value=None)
- extract_archive(covost_archive.as_posix())
-
- cv_tsv = load_df_from_tsv(cv_tsv_path)
- covost_tsv = load_df_from_tsv(
- self.root / Path(covost_url).name.replace(".tar.gz", "")
- )
- df = pd.merge(
- left=cv_tsv[["path", "sentence", "client_id"]],
- right=covost_tsv[["path", "translation", "split"]],
- how="inner",
- on="path",
- )
- if split == "train":
- df = df[(df["split"] == split) | (df["split"] == f"{split}_covost")]
- else:
- df = df[df["split"] == split]
- data = df.to_dict(orient="index").items()
- data = [v for k, v in sorted(data, key=lambda x: x[0])]
- self.data = []
- for e in data:
- try:
- path = self.root / "clips" / e["path"]
- _ = torchaudio.info(path.as_posix())
- self.data.append(e)
- except RuntimeError:
- pass
-
- def __getitem__(
- self, n: int
- ) -> Tuple[Tensor, int, str, str, Optional[str], str, str]:
- """Load the n-th sample from the dataset.
-
- Args:
- n (int): The index of the sample to be loaded
-
- Returns:
- tuple: ``(waveform, sample_rate, sentence, translation, speaker_id,
- sample_id)``
- """
- data = self.data[n]
- path = self.root / "clips" / data["path"]
- waveform, sample_rate = torchaudio.load(path)
- sentence = data["sentence"]
- translation = None if self.no_translation else data["translation"]
- speaker_id = data["client_id"]
- _id = data["path"].replace(".mp3", "")
- return waveform, sample_rate, sentence, translation, speaker_id, _id
-
- def __len__(self) -> int:
- return len(self.data)
-
-
-def process(args):
- root = Path(args.data_root).absolute() / args.src_lang
- if not root.is_dir():
- raise NotADirectoryError(f"{root} does not exist")
- # Extract features
- feature_root = root / "fbank80"
- feature_root.mkdir(exist_ok=True)
- for split in CoVoST.SPLITS:
- print(f"Fetching split {split}...")
- dataset = CoVoST(root, split, args.src_lang, args.tgt_lang)
- print("Extracting log mel filter bank features...")
- for waveform, sample_rate, _, _, _, utt_id in tqdm(dataset):
- extract_fbank_features(
- waveform, sample_rate, feature_root / f"{utt_id}.npy"
- )
- # Pack features into ZIP
- zip_path = root / "fbank80.zip"
- print("ZIPing features...")
- create_zip(feature_root, zip_path)
- print("Fetching ZIP manifest...")
- audio_paths, audio_lengths = get_zip_manifest(zip_path)
- # Generate TSV manifest
- print("Generating manifest...")
- train_text = []
- task = f"asr_{args.src_lang}"
- if args.tgt_lang is not None:
- task = f"st_{args.src_lang}_{args.tgt_lang}"
- for split in CoVoST.SPLITS:
- manifest = {c: [] for c in MANIFEST_COLUMNS}
- dataset = CoVoST(root, split, args.src_lang, args.tgt_lang)
- for _, _, src_utt, tgt_utt, speaker_id, utt_id in tqdm(dataset):
- manifest["id"].append(utt_id)
- manifest["audio"].append(audio_paths[utt_id])
- manifest["n_frames"].append(audio_lengths[utt_id])
- manifest["tgt_text"].append(src_utt if args.tgt_lang is None else tgt_utt)
- manifest["speaker"].append(speaker_id)
- is_train_split = split.startswith("train")
- if is_train_split:
- train_text.extend(manifest["tgt_text"])
- df = pd.DataFrame.from_dict(manifest)
- df = filter_manifest_df(df, is_train_split=is_train_split)
- save_df_to_tsv(df, root / f"{split}_{task}.tsv")
- # Generate vocab
- vocab_size_str = "" if args.vocab_type == "char" else str(args.vocab_size)
- spm_filename_prefix = f"spm_{args.vocab_type}{vocab_size_str}_{task}"
- with NamedTemporaryFile(mode="w") as f:
- for t in train_text:
- f.write(t + "\n")
- gen_vocab(
- Path(f.name),
- root / spm_filename_prefix,
- args.vocab_type,
- args.vocab_size
- )
- # Generate config YAML
- gen_config_yaml(
- root,
- spm_filename=spm_filename_prefix + ".model",
- yaml_filename=f"config_{task}.yaml",
- specaugment_policy="lb",
- )
- # Clean up
- shutil.rmtree(feature_root)
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument(
- "--data-root", "-d", required=True, type=str,
- help="data root with sub-folders for each language /"
- )
- parser.add_argument(
- "--vocab-type",
- default="unigram",
- required=True,
- type=str,
- choices=["bpe", "unigram", "char"],
- ),
- parser.add_argument("--vocab-size", default=1000, type=int)
- parser.add_argument("--src-lang", "-s", required=True, type=str)
- parser.add_argument("--tgt-lang", "-t", type=str)
- args = parser.parse_args()
-
- process(args)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/prep_librispeech_data.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/prep_librispeech_data.py
deleted file mode 100644
index f379fa7bf195f48ad6b2ed3dbd93a5fbeb7abf79..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/prep_librispeech_data.py
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import logging
-from pathlib import Path
-import shutil
-from tempfile import NamedTemporaryFile
-
-import pandas as pd
-from examples.speech_to_text.data_utils import (
- create_zip,
- extract_fbank_features,
- gen_config_yaml,
- gen_vocab,
- get_zip_manifest,
- save_df_to_tsv,
-)
-from torchaudio.datasets import LIBRISPEECH
-from tqdm import tqdm
-
-
-log = logging.getLogger(__name__)
-
-SPLITS = [
- "train-clean-100",
- "train-clean-360",
- "train-other-500",
- "dev-clean",
- "dev-other",
- "test-clean",
- "test-other",
-]
-
-MANIFEST_COLUMNS = ["id", "audio", "n_frames", "tgt_text", "speaker"]
-
-
-def process(args):
- out_root = Path(args.output_root).absolute()
- out_root.mkdir(exist_ok=True)
- # Extract features
- feature_root = out_root / "fbank80"
- feature_root.mkdir(exist_ok=True)
- for split in SPLITS:
- print(f"Fetching split {split}...")
- dataset = LIBRISPEECH(out_root.as_posix(), url=split, download=True)
- print("Extracting log mel filter bank features...")
- for wav, sample_rate, _, spk_id, chapter_no, utt_no in tqdm(dataset):
- sample_id = f"{spk_id}-{chapter_no}-{utt_no}"
- extract_fbank_features(
- wav, sample_rate, feature_root / f"{sample_id}.npy"
- )
- # Pack features into ZIP
- zip_path = out_root / "fbank80.zip"
- print("ZIPing features...")
- create_zip(feature_root, zip_path)
- print("Fetching ZIP manifest...")
- audio_paths, audio_lengths = get_zip_manifest(zip_path)
- # Generate TSV manifest
- print("Generating manifest...")
- train_text = []
- for split in SPLITS:
- manifest = {c: [] for c in MANIFEST_COLUMNS}
- dataset = LIBRISPEECH(out_root.as_posix(), url=split)
- for _, _, utt, spk_id, chapter_no, utt_no in tqdm(dataset):
- sample_id = f"{spk_id}-{chapter_no}-{utt_no}"
- manifest["id"].append(sample_id)
- manifest["audio"].append(audio_paths[sample_id])
- manifest["n_frames"].append(audio_lengths[sample_id])
- manifest["tgt_text"].append(utt.lower())
- manifest["speaker"].append(spk_id)
- save_df_to_tsv(
- pd.DataFrame.from_dict(manifest), out_root / f"{split}.tsv"
- )
- if split.startswith("train"):
- train_text.extend(manifest["tgt_text"])
- # Generate vocab
- vocab_size = "" if args.vocab_type == "char" else str(args.vocab_size)
- spm_filename_prefix = f"spm_{args.vocab_type}{vocab_size}"
- with NamedTemporaryFile(mode="w") as f:
- for t in train_text:
- f.write(t + "\n")
- gen_vocab(
- Path(f.name),
- out_root / spm_filename_prefix,
- args.vocab_type,
- args.vocab_size,
- )
- # Generate config YAML
- gen_config_yaml(
- out_root,
- spm_filename=spm_filename_prefix + ".model",
- specaugment_policy="ld"
- )
- # Clean up
- shutil.rmtree(feature_root)
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument("--output-root", "-o", required=True, type=str)
- parser.add_argument(
- "--vocab-type",
- default="unigram",
- required=True,
- type=str,
- choices=["bpe", "unigram", "char"],
- ),
- parser.add_argument("--vocab-size", default=10000, type=int)
- args = parser.parse_args()
-
- process(args)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/prep_mtedx_data.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/prep_mtedx_data.py
deleted file mode 100644
index 2dfd6317631f56b7fd1e31da98f29f79681ba972..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/prep_mtedx_data.py
+++ /dev/null
@@ -1,271 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import logging
-import os
-from pathlib import Path
-import shutil
-from itertools import groupby
-from tempfile import NamedTemporaryFile
-from typing import Tuple
-
-import pandas as pd
-import soundfile as sf
-from examples.speech_to_text.data_utils import (
- create_zip,
- extract_fbank_features,
- filter_manifest_df,
- gen_config_yaml,
- gen_vocab,
- get_zip_manifest,
- load_df_from_tsv,
- save_df_to_tsv,
-)
-import torch
-from torch.utils.data import Dataset
-from tqdm import tqdm
-
-from fairseq.data.audio.audio_utils import get_waveform, convert_waveform
-
-
-log = logging.getLogger(__name__)
-
-
-MANIFEST_COLUMNS = [
- "id", "audio", "n_frames", "tgt_text", "speaker", "tgt_lang"
-]
-
-
-class mTEDx(Dataset):
- """
- Create a Dataset for Multilingual TEDx.
- Each item is a tuple of the form: waveform, sample_rate, source utterance,
- target utterance, speaker_id, utterance_id
- """
-
- SPLITS = ["train", "valid", "test"]
- LANGPAIRS = ["es-es", "fr-fr", "pt-pt", "it-it", "ru-ru", "el-el", "ar-ar",
- "de-de", "es-en", "es-fr", "es-pt", "es-it", "fr-en", "fr-es",
- "fr-pt", "pt-en", "pt-es", "it-en", "it-es", "ru-en", "el-en"]
-
- def __init__(self, root: str, lang: str, split: str) -> None:
- assert split in self.SPLITS and lang in self.LANGPAIRS
- _root = Path(root) / f"{lang}" / "data" / split
- wav_root, txt_root = _root / "wav", _root / "txt"
- assert _root.is_dir() and wav_root.is_dir() and txt_root.is_dir()
- # Load audio segments
- try:
- import yaml
- except ImportError:
- print(
- "Please install PyYAML to load the Multilingual TEDx YAML files"
- )
- with open(txt_root / f"{split}.yaml") as f:
- segments = yaml.load(f, Loader=yaml.BaseLoader)
- # Load source and target utterances
- src, tgt = lang.split("-")
- for _lang in [src, tgt]:
- with open(txt_root / f"{split}.{_lang}") as f:
- utterances = [r.strip() for r in f]
- assert len(segments) == len(utterances)
- for i, u in enumerate(utterances):
- segments[i][_lang] = u
- # Gather info
- self.data = []
- for wav_filename, _seg_group in groupby(segments, lambda x: x["wav"]):
- wav_filename = wav_filename.replace(".wav", ".flac")
- wav_path = wav_root / wav_filename
- sample_rate = sf.info(wav_path.as_posix()).samplerate
- seg_group = sorted(_seg_group, key=lambda x: float(x["offset"]))
- for i, segment in enumerate(seg_group):
- offset = int(float(segment["offset"]) * sample_rate)
- n_frames = int(float(segment["duration"]) * sample_rate)
- _id = f"{wav_path.stem}_{i}"
- self.data.append(
- (
- wav_path.as_posix(),
- offset,
- n_frames,
- sample_rate,
- segment[src],
- segment[tgt],
- segment["speaker_id"],
- tgt,
- _id,
- )
- )
-
- def __getitem__(
- self, n: int
- ) -> Tuple[torch.Tensor, int, str, str, str, str, str]:
- wav_path, offset, n_frames, sr, src_utt, tgt_utt, spk_id, tgt_lang, \
- utt_id = self.data[n]
- waveform, _ = get_waveform(wav_path, frames=n_frames, start=offset)
- waveform = torch.from_numpy(waveform)
- return waveform, sr, src_utt, tgt_utt, spk_id, tgt_lang, utt_id
-
- def __len__(self) -> int:
- return len(self.data)
-
-
-def process(args):
- root = Path(args.data_root).absolute()
- for lang in mTEDx.LANGPAIRS:
- cur_root = root / f"{lang}"
- if not cur_root.is_dir():
- print(f"{cur_root.as_posix()} does not exist. Skipped.")
- continue
- # Extract features
- audio_root = cur_root / ("flac" if args.use_audio_input else "fbank80")
- audio_root.mkdir(exist_ok=True)
- for split in mTEDx.SPLITS:
- print(f"Fetching split {split}...")
- dataset = mTEDx(root.as_posix(), lang, split)
- if args.use_audio_input:
- print("Converting audios...")
- for waveform, sample_rate, _, _, _, utt_id in tqdm(dataset):
- tgt_sample_rate = 16_000
- _wavform, _ = convert_waveform(
- waveform, sample_rate, to_mono=True,
- to_sample_rate=tgt_sample_rate
- )
- sf.write(
- (audio_root / f"{utt_id}.flac").as_posix(),
- _wavform.numpy(), tgt_sample_rate
- )
- else:
- print("Extracting log mel filter bank features...")
- for waveform, sample_rate, _, _, _, _, utt_id in tqdm(dataset):
- extract_fbank_features(
- waveform, sample_rate, audio_root / f"{utt_id}.npy"
- )
- # Pack features into ZIP
- zip_path = cur_root / f"{audio_root.name}.zip"
- print("ZIPing audios/features...")
- create_zip(audio_root, zip_path)
- print("Fetching ZIP manifest...")
- audio_paths, audio_lengths = get_zip_manifest(zip_path)
- # Generate TSV manifest
- print("Generating manifest...")
- train_text = []
- for split in mTEDx.SPLITS:
- is_train_split = split.startswith("train")
- manifest = {c: [] for c in MANIFEST_COLUMNS}
- ds = mTEDx(args.data_root, lang, split)
- for _, _, src_utt, tgt_utt, spk_id, tgt_lang, utt_id in tqdm(ds):
- manifest["id"].append(utt_id)
- manifest["audio"].append(audio_paths[utt_id])
- manifest["n_frames"].append(audio_lengths[utt_id])
- manifest["tgt_text"].append(
- src_utt if args.task == "asr" else tgt_utt
- )
- manifest["speaker"].append(spk_id)
- manifest["tgt_lang"].append(tgt_lang)
- if is_train_split:
- train_text.extend(manifest["tgt_text"])
- df = pd.DataFrame.from_dict(manifest)
- df = filter_manifest_df(df, is_train_split=is_train_split)
- save_df_to_tsv(df, cur_root / f"{split}_{args.task}.tsv")
- # Generate vocab
- v_size_str = "" if args.vocab_type == "char" else str(args.vocab_size)
- spm_filename_prefix = f"spm_{args.vocab_type}{v_size_str}_{args.task}"
- with NamedTemporaryFile(mode="w") as f:
- for t in train_text:
- f.write(t + "\n")
- gen_vocab(
- Path(f.name),
- cur_root / spm_filename_prefix,
- args.vocab_type,
- args.vocab_size,
- )
- # Generate config YAML
- if args.use_audio_input:
- gen_config_yaml(
- cur_root,
- spm_filename=spm_filename_prefix + ".model",
- yaml_filename=f"config_{args.task}.yaml",
- specaugment_policy=None,
- extra={"use_audio_input": True}
- )
- else:
- gen_config_yaml(
- cur_root,
- spm_filename=spm_filename_prefix + ".model",
- yaml_filename=f"config_{args.task}.yaml",
- specaugment_policy="lb",
- )
- # Clean up
- shutil.rmtree(audio_root)
-
-
-def process_joint(args):
- cur_root = Path(args.data_root)
- assert all((cur_root / f"{lang}").is_dir() for lang in mTEDx.LANGPAIRS), \
- "do not have downloaded data available for all languages"
- # Generate vocab
- vocab_size_str = "" if args.vocab_type == "char" else str(args.vocab_size)
- spm_filename_prefix = f"spm_{args.vocab_type}{vocab_size_str}_{args.task}"
- with NamedTemporaryFile(mode="w") as f:
- for lang in mTEDx.LANGPAIRS:
- tsv_path = cur_root / f"{lang}" / f"train_{args.task}.tsv"
- df = load_df_from_tsv(tsv_path)
- for t in df["tgt_text"]:
- f.write(t + "\n")
- special_symbols = None
- if args.joint:
- # Add tgt_lang tags to dict
- special_symbols = list(
- {f'' for lang in mTEDx.LANGPAIRS}
- )
- gen_vocab(
- Path(f.name),
- cur_root / spm_filename_prefix,
- args.vocab_type,
- args.vocab_size,
- special_symbols=special_symbols
- )
- # Generate config YAML
- gen_config_yaml(
- cur_root,
- spm_filename=spm_filename_prefix + ".model",
- yaml_filename=f"config_{args.task}.yaml",
- specaugment_policy="ld",
- prepend_tgt_lang_tag=(args.joint),
- )
- # Make symbolic links to manifests
- for lang in mTEDx.LANGPAIRS:
- for split in mTEDx.SPLITS:
- src_path = cur_root / f"{lang}" / f"{split}_{args.task}.tsv"
- desc_path = cur_root / f"{split}_{lang}_{args.task}.tsv"
- if not desc_path.is_symlink():
- os.symlink(src_path, desc_path)
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument("--data-root", "-d", required=True, type=str)
- parser.add_argument(
- "--vocab-type",
- default="unigram",
- required=True,
- type=str,
- choices=["bpe", "unigram", "char"],
- ),
- parser.add_argument("--vocab-size", default=8000, type=int)
- parser.add_argument("--task", type=str, choices=["asr", "st"])
- parser.add_argument("--joint", action="store_true", help="")
- parser.add_argument("--use-audio-input", action="store_true")
- args = parser.parse_args()
-
- if args.joint:
- process_joint(args)
- else:
- process(args)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/prep_mustc_data.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/prep_mustc_data.py
deleted file mode 100644
index c2362f76fa0fd58e59fb4d790ba174bfa0d97e03..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/prep_mustc_data.py
+++ /dev/null
@@ -1,294 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import logging
-import os
-from pathlib import Path
-import shutil
-from itertools import groupby
-from tempfile import NamedTemporaryFile
-from typing import Tuple
-
-import numpy as np
-import pandas as pd
-import soundfile as sf
-from examples.speech_to_text.data_utils import (
- create_zip,
- extract_fbank_features,
- filter_manifest_df,
- gen_config_yaml,
- gen_vocab,
- get_zip_manifest,
- load_df_from_tsv,
- save_df_to_tsv,
- cal_gcmvn_stats,
-)
-import torch
-from torch.utils.data import Dataset
-from tqdm import tqdm
-
-from fairseq.data.audio.audio_utils import get_waveform, convert_waveform
-
-
-log = logging.getLogger(__name__)
-
-
-MANIFEST_COLUMNS = ["id", "audio", "n_frames", "tgt_text", "speaker"]
-
-
-class MUSTC(Dataset):
- """
- Create a Dataset for MuST-C. Each item is a tuple of the form:
- waveform, sample_rate, source utterance, target utterance, speaker_id,
- utterance_id
- """
-
- SPLITS = ["train", "dev", "tst-COMMON", "tst-HE"]
- LANGUAGES = ["de", "es", "fr", "it", "nl", "pt", "ro", "ru"]
-
- def __init__(self, root: str, lang: str, split: str) -> None:
- assert split in self.SPLITS and lang in self.LANGUAGES
- _root = Path(root) / f"en-{lang}" / "data" / split
- wav_root, txt_root = _root / "wav", _root / "txt"
- assert _root.is_dir() and wav_root.is_dir() and txt_root.is_dir()
- # Load audio segments
- try:
- import yaml
- except ImportError:
- print("Please install PyYAML to load the MuST-C YAML files")
- with open(txt_root / f"{split}.yaml") as f:
- segments = yaml.load(f, Loader=yaml.BaseLoader)
- # Load source and target utterances
- for _lang in ["en", lang]:
- with open(txt_root / f"{split}.{_lang}") as f:
- utterances = [r.strip() for r in f]
- assert len(segments) == len(utterances)
- for i, u in enumerate(utterances):
- segments[i][_lang] = u
- # Gather info
- self.data = []
- for wav_filename, _seg_group in groupby(segments, lambda x: x["wav"]):
- wav_path = wav_root / wav_filename
- sample_rate = sf.info(wav_path.as_posix()).samplerate
- seg_group = sorted(_seg_group, key=lambda x: x["offset"])
- for i, segment in enumerate(seg_group):
- offset = int(float(segment["offset"]) * sample_rate)
- n_frames = int(float(segment["duration"]) * sample_rate)
- _id = f"{wav_path.stem}_{i}"
- self.data.append(
- (
- wav_path.as_posix(),
- offset,
- n_frames,
- sample_rate,
- segment["en"],
- segment[lang],
- segment["speaker_id"],
- _id,
- )
- )
-
- def __getitem__(
- self, n: int
- ) -> Tuple[torch.Tensor, int, str, str, str, str]:
- wav_path, offset, n_frames, sr, src_utt, tgt_utt, spk_id, \
- utt_id = self.data[n]
- waveform, _ = get_waveform(wav_path, frames=n_frames, start=offset)
- waveform = torch.from_numpy(waveform)
- return waveform, sr, src_utt, tgt_utt, spk_id, utt_id
-
- def __len__(self) -> int:
- return len(self.data)
-
-
-def process(args):
- root = Path(args.data_root).absolute()
- for lang in MUSTC.LANGUAGES:
- cur_root = root / f"en-{lang}"
- if not cur_root.is_dir():
- print(f"{cur_root.as_posix()} does not exist. Skipped.")
- continue
- # Extract features
- audio_root = cur_root / ("flac" if args.use_audio_input else "fbank80")
- audio_root.mkdir(exist_ok=True)
-
- for split in MUSTC.SPLITS:
- print(f"Fetching split {split}...")
- dataset = MUSTC(root.as_posix(), lang, split)
- if args.use_audio_input:
- print("Converting audios...")
- for waveform, sample_rate, _, _, _, utt_id in tqdm(dataset):
- tgt_sample_rate = 16_000
- _wavform, _ = convert_waveform(
- waveform, sample_rate, to_mono=True,
- to_sample_rate=tgt_sample_rate
- )
- sf.write(
- (audio_root / f"{utt_id}.flac").as_posix(),
- _wavform.T.numpy(), tgt_sample_rate
- )
- else:
- print("Extracting log mel filter bank features...")
- gcmvn_feature_list = []
- if split == 'train' and args.cmvn_type == "global":
- print("And estimating cepstral mean and variance stats...")
-
- for waveform, sample_rate, _, _, _, utt_id in tqdm(dataset):
- features = extract_fbank_features(
- waveform, sample_rate, audio_root / f"{utt_id}.npy"
- )
- if split == 'train' and args.cmvn_type == "global":
- if len(gcmvn_feature_list) < args.gcmvn_max_num:
- gcmvn_feature_list.append(features)
-
- if split == 'train' and args.cmvn_type == "global":
- # Estimate and save cmv
- stats = cal_gcmvn_stats(gcmvn_feature_list)
- with open(cur_root / "gcmvn.npz", "wb") as f:
- np.savez(f, mean=stats["mean"], std=stats["std"])
-
- # Pack features into ZIP
- zip_path = cur_root / f"{audio_root.name}.zip"
- print("ZIPing audios/features...")
- create_zip(audio_root, zip_path)
- print("Fetching ZIP manifest...")
- audio_paths, audio_lengths = get_zip_manifest(
- zip_path,
- is_audio=args.use_audio_input,
- )
- # Generate TSV manifest
- print("Generating manifest...")
- train_text = []
- for split in MUSTC.SPLITS:
- is_train_split = split.startswith("train")
- manifest = {c: [] for c in MANIFEST_COLUMNS}
- dataset = MUSTC(args.data_root, lang, split)
- for _, _, src_utt, tgt_utt, speaker_id, utt_id in tqdm(dataset):
- manifest["id"].append(utt_id)
- manifest["audio"].append(audio_paths[utt_id])
- manifest["n_frames"].append(audio_lengths[utt_id])
- manifest["tgt_text"].append(
- src_utt if args.task == "asr" else tgt_utt
- )
- manifest["speaker"].append(speaker_id)
- if is_train_split:
- train_text.extend(manifest["tgt_text"])
- df = pd.DataFrame.from_dict(manifest)
- df = filter_manifest_df(df, is_train_split=is_train_split)
- save_df_to_tsv(df, cur_root / f"{split}_{args.task}.tsv")
- # Generate vocab
- v_size_str = "" if args.vocab_type == "char" else str(args.vocab_size)
- spm_filename_prefix = f"spm_{args.vocab_type}{v_size_str}_{args.task}"
- with NamedTemporaryFile(mode="w") as f:
- for t in train_text:
- f.write(t + "\n")
- gen_vocab(
- Path(f.name),
- cur_root / spm_filename_prefix,
- args.vocab_type,
- args.vocab_size,
- )
- # Generate config YAML
- if args.use_audio_input:
- gen_config_yaml(
- cur_root,
- spm_filename=spm_filename_prefix + ".model",
- yaml_filename=f"config_{args.task}.yaml",
- specaugment_policy=None,
- extra={"use_audio_input": True}
- )
- else:
- gen_config_yaml(
- cur_root,
- spm_filename=spm_filename_prefix + ".model",
- yaml_filename=f"config_{args.task}.yaml",
- specaugment_policy="lb",
- cmvn_type=args.cmvn_type,
- gcmvn_path=(
- cur_root / "gcmvn.npz" if args.cmvn_type == "global"
- else None
- ),
- )
- # Clean up
- shutil.rmtree(audio_root)
-
-
-def process_joint(args):
- cur_root = Path(args.data_root)
- assert all(
- (cur_root / f"en-{lang}").is_dir() for lang in MUSTC.LANGUAGES
- ), "do not have downloaded data available for all 8 languages"
- # Generate vocab
- vocab_size_str = "" if args.vocab_type == "char" else str(args.vocab_size)
- spm_filename_prefix = f"spm_{args.vocab_type}{vocab_size_str}_{args.task}"
- with NamedTemporaryFile(mode="w") as f:
- for lang in MUSTC.LANGUAGES:
- tsv_path = cur_root / f"en-{lang}" / f"train_{args.task}.tsv"
- df = load_df_from_tsv(tsv_path)
- for t in df["tgt_text"]:
- f.write(t + "\n")
- special_symbols = None
- if args.task == 'st':
- special_symbols = [f'' for lang in MUSTC.LANGUAGES]
- gen_vocab(
- Path(f.name),
- cur_root / spm_filename_prefix,
- args.vocab_type,
- args.vocab_size,
- special_symbols=special_symbols
- )
- # Generate config YAML
- gen_config_yaml(
- cur_root,
- spm_filename=spm_filename_prefix + ".model",
- yaml_filename=f"config_{args.task}.yaml",
- specaugment_policy="ld",
- prepend_tgt_lang_tag=(args.task == "st"),
- )
- # Make symbolic links to manifests
- for lang in MUSTC.LANGUAGES:
- for split in MUSTC.SPLITS:
- src_path = cur_root / f"en-{lang}" / f"{split}_{args.task}.tsv"
- desc_path = cur_root / f"{split}_{lang}_{args.task}.tsv"
- if not desc_path.is_symlink():
- os.symlink(src_path, desc_path)
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument("--data-root", "-d", required=True, type=str)
- parser.add_argument(
- "--vocab-type",
- default="unigram",
- required=True,
- type=str,
- choices=["bpe", "unigram", "char"],
- ),
- parser.add_argument("--vocab-size", default=8000, type=int)
- parser.add_argument("--task", type=str, choices=["asr", "st"])
- parser.add_argument("--joint", action="store_true", help="")
- parser.add_argument(
- "--cmvn-type", default="utterance",
- choices=["global", "utterance"],
- help="The type of cepstral mean and variance normalization"
- )
- parser.add_argument(
- "--gcmvn-max-num", default=150000, type=int,
- help="Maximum number of sentences to use to estimate global mean and "
- "variance"
- )
- parser.add_argument("--use-audio-input", action="store_true")
- args = parser.parse_args()
-
- if args.joint:
- process_joint(args)
- else:
- process(args)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/seg_mustc_data.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/seg_mustc_data.py
deleted file mode 100644
index 1ee665d6399729afe17d790d872eff34de124900..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/seg_mustc_data.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-import logging
-from pathlib import Path
-import soundfile as sf
-from examples.speech_to_text.prep_mustc_data import (
- MUSTC
-)
-
-from tqdm import tqdm
-
-log = logging.getLogger(__name__)
-
-
-def main(args):
- root = Path(args.data_root).absolute()
- lang = args.lang
- split = args.split
-
- cur_root = root / f"en-{lang}"
- assert cur_root.is_dir(), (
- f"{cur_root.as_posix()} does not exist. Skipped."
- )
-
- dataset = MUSTC(root.as_posix(), lang, split)
- output = Path(args.output).absolute()
- output.mkdir(exist_ok=True)
- f_text = open(output / f"{split}.{lang}", "w")
- f_wav_list = open(output / f"{split}.wav_list", "w")
- for waveform, sample_rate, _, text, _, utt_id in tqdm(dataset):
- sf.write(
- output / f"{utt_id}.wav",
- waveform.squeeze(0).numpy(),
- samplerate=int(sample_rate)
- )
- f_text.write(text + "\n")
- f_wav_list.write(str(output / f"{utt_id}.wav") + "\n")
-
-
-if __name__ == "__main__":
- parser = argparse.ArgumentParser()
- parser.add_argument("--data-root", "-d", required=True, type=str)
- parser.add_argument("--task", required=True, type=str, choices=["asr", "st"])
- parser.add_argument("--lang", required=True, type=str)
- parser.add_argument("--output", required=True, type=str)
- parser.add_argument("--split", required=True, choices=MUSTC.SPLITS)
- args = parser.parse_args()
-
- main(args)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/simultaneous_translation/agents/fairseq_simul_st_agent.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/simultaneous_translation/agents/fairseq_simul_st_agent.py
deleted file mode 100644
index 61617a1739ce196abba1e9a6f9ad9e9f4b37b9c1..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/speech_to_text/simultaneous_translation/agents/fairseq_simul_st_agent.py
+++ /dev/null
@@ -1,363 +0,0 @@
-import math
-import os
-import json
-import numpy as np
-import torch
-import torchaudio.compliance.kaldi as kaldi
-import yaml
-from fairseq import checkpoint_utils, tasks
-from fairseq.file_io import PathManager
-
-try:
- from simuleval import READ_ACTION, WRITE_ACTION, DEFAULT_EOS
- from simuleval.agents import SpeechAgent
- from simuleval.states import ListEntry, SpeechStates
-except ImportError:
- print("Please install simuleval 'pip install simuleval'")
-
-SHIFT_SIZE = 10
-WINDOW_SIZE = 25
-SAMPLE_RATE = 16000
-FEATURE_DIM = 80
-BOW_PREFIX = "\u2581"
-
-
-class OnlineFeatureExtractor:
- """
- Extract speech feature on the fly.
- """
-
- def __init__(self, args):
- self.shift_size = args.shift_size
- self.window_size = args.window_size
- assert self.window_size >= self.shift_size
-
- self.sample_rate = args.sample_rate
- self.feature_dim = args.feature_dim
- self.num_samples_per_shift = int(self.shift_size * self.sample_rate / 1000)
- self.num_samples_per_window = int(self.window_size * self.sample_rate / 1000)
- self.len_ms_to_samples = lambda x: x * self.sample_rate / 1000
- self.previous_residual_samples = []
- self.global_cmvn = args.global_cmvn
-
- def clear_cache(self):
- self.previous_residual_samples = []
-
- def __call__(self, new_samples):
- samples = self.previous_residual_samples + new_samples
- if len(samples) < self.num_samples_per_window:
- self.previous_residual_samples = samples
- return
-
- # num_frames is the number of frames from the new segment
- num_frames = math.floor(
- (len(samples) - self.len_ms_to_samples(self.window_size - self.shift_size))
- / self.num_samples_per_shift
- )
-
- # the number of frames used for feature extraction
- # including some part of thte previous segment
- effective_num_samples = int(
- num_frames * self.len_ms_to_samples(self.shift_size)
- + self.len_ms_to_samples(self.window_size - self.shift_size)
- )
-
- input_samples = samples[:effective_num_samples]
- self.previous_residual_samples = samples[
- num_frames * self.num_samples_per_shift:
- ]
-
- torch.manual_seed(1)
- output = kaldi.fbank(
- torch.FloatTensor(input_samples).unsqueeze(0),
- num_mel_bins=self.feature_dim,
- frame_length=self.window_size,
- frame_shift=self.shift_size,
- ).numpy()
-
- output = self.transform(output)
-
- return torch.from_numpy(output)
-
- def transform(self, input):
- if self.global_cmvn is None:
- return input
-
- mean = self.global_cmvn["mean"]
- std = self.global_cmvn["std"]
-
- x = np.subtract(input, mean)
- x = np.divide(x, std)
- return x
-
-
-class TensorListEntry(ListEntry):
- """
- Data structure to store a list of tensor.
- """
-
- def append(self, value):
-
- if len(self.value) == 0:
- self.value = value
- return
-
- self.value = torch.cat([self.value] + [value], dim=0)
-
- def info(self):
- return {
- "type": str(self.new_value_type),
- "length": self.__len__(),
- "value": "" if type(self.value) is list else self.value.size(),
- }
-
-
-class FairseqSimulSTAgent(SpeechAgent):
-
- speech_segment_size = 40 # in ms, 4 pooling ratio * 10 ms step size
-
- def __init__(self, args):
- super().__init__(args)
-
- self.eos = DEFAULT_EOS
-
- self.gpu = getattr(args, "gpu", False)
-
- self.args = args
-
- self.load_model_vocab(args)
-
- if getattr(
- self.model.decoder.layers[0].encoder_attn,
- 'pre_decision_ratio',
- None
- ) is not None:
- self.speech_segment_size *= (
- self.model.decoder.layers[0].encoder_attn.pre_decision_ratio
- )
-
- args.global_cmvn = None
- if args.config:
- with open(os.path.join(args.data_bin, args.config), "r") as f:
- config = yaml.load(f, Loader=yaml.BaseLoader)
-
- if "global_cmvn" in config:
- args.global_cmvn = np.load(config["global_cmvn"]["stats_npz_path"])
-
- if args.global_stats:
- with PathManager.open(args.global_stats, "r") as f:
- global_cmvn = json.loads(f.read())
- self.global_cmvn = {"mean": global_cmvn["mean"], "std": global_cmvn["stddev"]}
-
- self.feature_extractor = OnlineFeatureExtractor(args)
-
- self.max_len = args.max_len
-
- self.force_finish = args.force_finish
-
- torch.set_grad_enabled(False)
-
- def build_states(self, args, client, sentence_id):
- # Initialize states here, for example add customized entry to states
- # This function will be called at beginning of every new sentence
- states = SpeechStates(args, client, sentence_id, self)
- self.initialize_states(states)
- return states
-
- def to_device(self, tensor):
- if self.gpu:
- return tensor.cuda()
- else:
- return tensor.cpu()
-
- @staticmethod
- def add_args(parser):
- # fmt: off
- parser.add_argument('--model-path', type=str, required=True,
- help='path to your pretrained model.')
- parser.add_argument("--data-bin", type=str, required=True,
- help="Path of data binary")
- parser.add_argument("--config", type=str, default=None,
- help="Path to config yaml file")
- parser.add_argument("--global-stats", type=str, default=None,
- help="Path to json file containing cmvn stats")
- parser.add_argument("--tgt-splitter-type", type=str, default="SentencePiece",
- help="Subword splitter type for target text")
- parser.add_argument("--tgt-splitter-path", type=str, default=None,
- help="Subword splitter model path for target text")
- parser.add_argument("--user-dir", type=str, default="examples/simultaneous_translation",
- help="User directory for simultaneous translation")
- parser.add_argument("--max-len", type=int, default=200,
- help="Max length of translation")
- parser.add_argument("--force-finish", default=False, action="store_true",
- help="Force the model to finish the hypothsis if the source is not finished")
- parser.add_argument("--shift-size", type=int, default=SHIFT_SIZE,
- help="Shift size of feature extraction window.")
- parser.add_argument("--window-size", type=int, default=WINDOW_SIZE,
- help="Window size of feature extraction window.")
- parser.add_argument("--sample-rate", type=int, default=SAMPLE_RATE,
- help="Sample rate")
- parser.add_argument("--feature-dim", type=int, default=FEATURE_DIM,
- help="Acoustic feature dimension.")
-
- # fmt: on
- return parser
-
- def load_model_vocab(self, args):
-
- filename = args.model_path
- if not os.path.exists(filename):
- raise IOError("Model file not found: {}".format(filename))
-
- state = checkpoint_utils.load_checkpoint_to_cpu(filename)
-
- task_args = state["cfg"]["task"]
- task_args.data = args.data_bin
-
- if args.config is not None:
- task_args.config_yaml = args.config
-
- task = tasks.setup_task(task_args)
-
- # build model for ensemble
- state["cfg"]["model"].load_pretrained_encoder_from = None
- state["cfg"]["model"].load_pretrained_decoder_from = None
- self.model = task.build_model(state["cfg"]["model"])
- self.model.load_state_dict(state["model"], strict=True)
- self.model.eval()
- self.model.share_memory()
-
- if self.gpu:
- self.model.cuda()
-
- # Set dictionary
- self.dict = {}
- self.dict["tgt"] = task.target_dictionary
-
- def initialize_states(self, states):
- self.feature_extractor.clear_cache()
- states.units.source = TensorListEntry()
- states.units.target = ListEntry()
- states.incremental_states = dict()
-
- def segment_to_units(self, segment, states):
- # Convert speech samples to features
- features = self.feature_extractor(segment)
- if features is not None:
- return [features]
- else:
- return []
-
- def units_to_segment(self, units, states):
- # Merge sub word to full word.
- if self.model.decoder.dictionary.eos() == units[0]:
- return DEFAULT_EOS
-
- segment = []
- if None in units.value:
- units.value.remove(None)
-
- for index in units:
- if index is None:
- units.pop()
- token = self.model.decoder.dictionary.string([index])
- if token.startswith(BOW_PREFIX):
- if len(segment) == 0:
- segment += [token.replace(BOW_PREFIX, "")]
- else:
- for j in range(len(segment)):
- units.pop()
-
- string_to_return = ["".join(segment)]
-
- if self.model.decoder.dictionary.eos() == units[0]:
- string_to_return += [DEFAULT_EOS]
-
- return string_to_return
- else:
- segment += [token.replace(BOW_PREFIX, "")]
-
- if (
- len(units) > 0
- and self.model.decoder.dictionary.eos() == units[-1]
- or len(states.units.target) > self.max_len
- ):
- tokens = [self.model.decoder.dictionary.string([unit]) for unit in units]
- return ["".join(tokens).replace(BOW_PREFIX, "")] + [DEFAULT_EOS]
-
- return None
-
- def update_model_encoder(self, states):
- if len(states.units.source) == 0:
- return
- src_indices = self.to_device(
- states.units.source.value.unsqueeze(0)
- )
- src_lengths = self.to_device(
- torch.LongTensor([states.units.source.value.size(0)])
- )
-
- states.encoder_states = self.model.encoder(src_indices, src_lengths)
- torch.cuda.empty_cache()
-
- def update_states_read(self, states):
- # Happens after a read action.
- self.update_model_encoder(states)
-
- def policy(self, states):
- if not getattr(states, "encoder_states", None):
- return READ_ACTION
-
- tgt_indices = self.to_device(
- torch.LongTensor(
- [self.model.decoder.dictionary.eos()]
- + [x for x in states.units.target.value if x is not None]
- ).unsqueeze(0)
- )
-
- states.incremental_states["steps"] = {
- "src": states.encoder_states["encoder_out"][0].size(0),
- "tgt": 1 + len(states.units.target),
- }
-
- states.incremental_states["online"] = {"only": torch.tensor(not states.finish_read())}
-
- x, outputs = self.model.decoder.forward(
- prev_output_tokens=tgt_indices,
- encoder_out=states.encoder_states,
- incremental_state=states.incremental_states,
- )
-
- states.decoder_out = x
-
- states.decoder_out_extra = outputs
-
- torch.cuda.empty_cache()
-
- if outputs.action == 0:
- return READ_ACTION
- else:
- return WRITE_ACTION
-
- def predict(self, states):
- decoder_states = states.decoder_out
-
- lprobs = self.model.get_normalized_probs(
- [decoder_states[:, -1:]], log_probs=True
- )
-
- index = lprobs.argmax(dim=-1)
-
- index = index[0, 0].item()
-
- if (
- self.force_finish
- and index == self.model.decoder.dictionary.eos()
- and not states.finish_read()
- ):
- # If we want to force finish the translation
- # (don't stop before finish reading), return a None
- # self.model.decoder.clear_cache(states.incremental_states)
- index = None
-
- return index
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/stories/README.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/stories/README.md
deleted file mode 100644
index 588941eddc5f0280f5254affd40ef49de874c885..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/stories/README.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# Hierarchical Neural Story Generation (Fan et al., 2018)
-
-The following commands provide an example of pre-processing data, training a model, and generating text for story generation with the WritingPrompts dataset.
-
-## Pre-trained models
-
-Description | Dataset | Model | Test set(s)
----|---|---|---
-Stories with Convolutional Model
([Fan et al., 2018](https://arxiv.org/abs/1805.04833)) | [WritingPrompts](https://dl.fbaipublicfiles.com/fairseq/data/writingPrompts.tar.gz) | [download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/models/stories_checkpoint.tar.bz2) | [download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/stories_test.tar.bz2)
-
-We provide sample stories generated by the [convolutional seq2seq model](https://dl.fbaipublicfiles.com/fairseq/data/seq2seq_stories.txt) and [fusion model](https://dl.fbaipublicfiles.com/fairseq/data/fusion_stories.txt) from [Fan et al., 2018](https://arxiv.org/abs/1805.04833). The corresponding prompts for the fusion model can be found [here](https://dl.fbaipublicfiles.com/fairseq/data/fusion_prompts.txt). Note that there are unk in the file, as we modeled a small full vocabulary (no BPE or pre-training). We did not use these unk prompts for human evaluation.
-
-## Dataset
-
-The dataset can be downloaded like this:
-
-```bash
-cd examples/stories
-curl https://dl.fbaipublicfiles.com/fairseq/data/writingPrompts.tar.gz | tar xvzf -
-```
-
-and contains a train, test, and valid split. The dataset is described here: https://arxiv.org/abs/1805.04833. We model only the first 1000 words of each story, including one newLine token.
-
-## Example usage
-
-First we will preprocess the dataset. Note that the dataset release is the full data, but the paper models the first 1000 words of each story. Here is example code that trims the dataset to the first 1000 words of each story:
-```python
-data = ["train", "test", "valid"]
-for name in data:
- with open(name + ".wp_target") as f:
- stories = f.readlines()
- stories = [" ".join(i.split()[0:1000]) for i in stories]
- with open(name + ".wp_target", "w") as o:
- for line in stories:
- o.write(line.strip() + "\n")
-```
-
-Once we've trimmed the data we can binarize it and train our model:
-```bash
-# Binarize the dataset:
-export TEXT=examples/stories/writingPrompts
-fairseq-preprocess --source-lang wp_source --target-lang wp_target \
- --trainpref $TEXT/train --validpref $TEXT/valid --testpref $TEXT/test \
- --destdir data-bin/writingPrompts --padding-factor 1 --thresholdtgt 10 --thresholdsrc 10
-
-# Train the model:
-fairseq-train data-bin/writingPrompts -a fconv_self_att_wp --lr 0.25 --optimizer nag --clip-norm 0.1 --max-tokens 1500 --lr-scheduler reduce_lr_on_plateau --decoder-attention True --encoder-attention False --criterion label_smoothed_cross_entropy --weight-decay .0000001 --label-smoothing 0 --source-lang wp_source --target-lang wp_target --gated-attention True --self-attention True --project-input True --pretrained False
-
-# Train a fusion model:
-# add the arguments: --pretrained True --pretrained-checkpoint path/to/checkpoint
-
-# Generate:
-# Note: to load the pretrained model at generation time, you need to pass in a model-override argument to communicate to the fusion model at generation time where you have placed the pretrained checkpoint. By default, it will load the exact path of the fusion model's pretrained model from training time. You should use model-override if you have moved the pretrained model (or are using our provided models). If you are generating from a non-fusion model, the model-override argument is not necessary.
-
-fairseq-generate data-bin/writingPrompts --path /path/to/trained/model/checkpoint_best.pt --batch-size 32 --beam 1 --sampling --sampling-topk 10 --temperature 0.8 --nbest 1 --model-overrides "{'pretrained_checkpoint':'/path/to/pretrained/model/checkpoint'}"
-```
-
-## Citation
-```bibtex
-@inproceedings{fan2018hierarchical,
- title = {Hierarchical Neural Story Generation},
- author = {Fan, Angela and Lewis, Mike and Dauphin, Yann},
- booktitle = {Conference of the Association for Computational Linguistics (ACL)},
- year = 2018,
-}
-```
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/README.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/README.md
deleted file mode 100644
index 917dbb2765501ff1a78eb6e272ab3dab6a793f04..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/README.md
+++ /dev/null
@@ -1,183 +0,0 @@
-# Generative Spoken Dialogue Language Modeling
-[[paper]](https://arxiv.org/abs/2203.16502) [[demo samples]](https://speechbot.github.io/dgslm/index.html) [[blog]](https://ai.facebook.com/blog/generating-chit-chat-including-laughs-yawns-ums-and-other-nonverbal-cues-from-raw-audio/)
-
-This repo contains the code and pre-trained models for the paper _Generative Spoken Dialogue Language Modeling_.
-
- Paper abstract
-
-> We introduce dGSLM, the first "textless" model able to generate audio samples of naturalistic spoken dialogues. It uses recent work on unsupervised spoken unit discovery coupled with a dual-tower transformer architecture with cross-attention trained on 2000 hours of two-channel raw conversational audio (Fisher dataset) without any text or labels. We show that our model is able to generate speech, laughter and other paralinguistic signals in the two channels simultaneously and reproduces more naturalistic and fluid turn taking compared to a text-based cascaded model.
-
-
-
-## [Speech-to-Unit Encoder for dGSLM: The Fisher HuBERT model](hubert_fisher/)
-The [hubert_fisher](hubert_fisher/) repository contains the pre-trained models and recipies to produce discrete units for the dGSLM model.
-
-## [Unit-to-Speech Decoder for dGSLM](vocoder_hifigan/)
-The [vocoder_hifigan](vocoder_hifigan/) repo contains the vocoder and recipies to synthesize the waveform from the discrete units.
-
-## Spoken Dialogue Transformer Language Model (SpeechDLM)
-### Pre-trained model
-We share the pre-trained model checkpoint for the best configuration in the paper (DLM-5 model, with Edge Unit Prediction & Delayed Duration Prediction objectives), dubbed as `SpeechDLM`, trained on the 2000 hours of Fisher dataset :
-| Pre-trained SpeechDLM model trained on Fisher dataset |
-|-----------------------------------------------|
-|[model checkpoint](https://dl.fbaipublicfiles.com/textless_nlp/dgslm/checkpoints/speech_dlm/speech_dlm_base.pt) - [dictionary 1](https://dl.fbaipublicfiles.com/textless_nlp/dgslm/checkpoints/speech_dlm/dict.unitA.txt) - [dictionary 2](https://dl.fbaipublicfiles.com/textless_nlp/dgslm/checkpoints/speech_dlm/dict.unitB.txt)|
-the two dictionary files correspond to the two channels, and actually have the same content.
-
-### Sample from a trained model
-You can sample from a trained SpeechDLM model interactively :
-```python
-from fairseq.models.speech_dlm import SpeechDLM
-
-# Load SpeechDLM model
-speech_dlm = SpeechDLM.from_pretrained(
- model_name_or_path='/path/to/model/dir',
- checkpoint_file='speech_dlm_base.pt',
- data_name_or_path='/path/to/data/dir'
- )
-# Disable dropout
-speech_dlm.eval()
-# Move model to GPU
-speech_dlm.cuda()
-
-# Define the input sequences
-input_sequences = [{
- 'unitA': '7 376 376 133 178 486 486 486 486 486 486 486 486 2 486',
- 'unitB': '7 499 415 177 7 7 7 7 7 7 136 136 289 289 408'
- }]
-
-# Sample from the SpeechDLM model
-generated_units = speech_dlm.sample(
- input_sequences,
- max_len_a = 0,
- max_len_b = 500,
- sampling=True,
- beam=5,
- )
-# >> {'unitA': '7 376 376 133 178 486 486 486 486 486 486 486 486 2 486 486 178 486 486 2 2 376 376 486 486 486 376 376 387 387 ...',
-# >> 'unitB': '7 499 415 177 7 7 7 7 7 7 136 136 289 289 408 32 428 95 356 141 331 439 350 350 192 331 445 202 104 104 ...'}
-```
-
-Or using the `sample_speech_dlm.py` script :
-```bash
-python sample_speech_dlm.py \
- --in-file $INPUT_CODE_FILE --out-file $OUTPUT_FILE \
- --ckpt $CHECKPOINT_PATH --data $DATA_DIR
-```
-where each line of INPUT_CODE_FILE is a dictionary with keys `'audio', 'unitA', 'unitB'` as follows :
-```
-{'audio': 'file_1', 'unitA': '8 8 ... 352 352', 'unitB': '217 8 ... 8 8'}
-{'audio': 'file_2', 'unitA': '5 5 ... 65 65', 'unitB': '6 35 ... 8 9'}
-...
-```
-This code file can be created with the script `create_input_code.py` (using the outputs of `quantize_with_kmeans.py` [here](hubert_fisher/#encode-audio-to-discrete-units)) :
-```bash
-python examples/textless_nlp/dgslm/vocoder_hifigan/create_input_code.py \
- $CHANNEL1_UNITS $CHANNEL2_UNITS $OUTPUT_CODE_FILE
-```
-
-### Training a SpeechDLM model
-#### 1) Data preparation
-First, you need to prepare the raw dataset. For each `split` (train, valid), you need two files corresponding to two channels (namely `unitA` and `unitB` for example) containing the units from each channel separately. Make sure that 2 files have the same number of lines and each corresponding line has the same number of units.
-
-Here is an example of `.unitA` file :
-```
-7 376 376 133 178
-486 486 486
-486 376
-```
-and the corresponding `.unitB` file :
-```
-7 499 415 177 7
-7 7 136
-331 445
-```
-These two files can be obtained using the [example command](hubert_fisher/#encode-audio-to-discrete-units) of hubert fisher, with the `--hide-fname` option added.
-
-The raw dataset directory should contain the following files :
-```
-train.unitA valid.unitA
-train.unitB valid.unitB
-```
-
-Next preprocess/binarize the data with `fairseq-preprocess`, but make sure to preprocess each channel separately, and **rename** the preprocessed files under the following format `${split}.${channel}.{bin, idx}`. Each channel also needs a separate dictionary file under the name `dict.${channel}.txt` .
-
-Here is an example pre-processing code :
-
-```bash
-# Preprocess the first channel (unitA)
-fairseq-preprocess --source-lang unitA \
- --only-source \
- --trainpref $RAW_DATA_DIR/train \
- --validpref $RAW_DATA_DIR/valid \
- --destdir $BIN_DATA_DIR \
- --workers 20
-
-# Preprocess the second channel (unitB) and reuse the dictionary from the first channel
-fairseq-preprocess --source-lang unitB \
- --srcdict $BIN_DATA_DIR/dict.unitA.txt \
- --only-source \
- --trainpref $RAW_DATA_DIR/train \
- --validpref $RAW_DATA_DIR/valid \
- --destdir $BIN_DATA_DIR \
- --workers 20
-
-# Rename the bin & index files
-for channel in unitA unitB; do
- for split in train valid; do
- mv $BIN_DATA_DIR/${split}.${channel}-None.${channel}.bin $BIN_DATA_DIR/${split}.${channel}.bin
- mv $BIN_DATA_DIR/${split}.${channel}-None.${channel}.idx $BIN_DATA_DIR/${split}.${channel}.idx
- done
-done
-```
-Finally, the preprocessed (bin) dataset directory should contain the following files :
-```
-dict.unitA.txt train.unitA.idx train.unitA.bin valid.unitA.idx valid.unitA.bin
-dict.unitB.txt train.unitB.idx train.unitB.bin valid.unitB.idx valid.unitB.bin
-```
-
-#### 2) Train the model
-To train the SpeechDLM (with the configuration as the pre-trained model) on 2 GPUs :
-```bash
-fairseq-train $BIN_DATA_DIR \
- --save-dir $CHECKPOINT_DIR \
- --tensorboard-logdir $CHECKPOINT_DIR \
- --task speech_dlm_task --channels unitA,unitB \
- --next-unit-prediction "False" --edge-unit-prediction "True" \
- --duration-prediction "True" --delayed-duration-target "True" \
- --criterion speech_dlm_criterion \
- --arch speech_dlm --decoder-cross-layers 4 \
- --share-decoder-input-output-embed \
- --dropout 0.1 --attention-dropout 0.1 \
- --optimizer adam --adam-betas "(0.9, 0.98)" --clip-norm 1.0 \
- --lr 0.0005 --lr-scheduler inverse_sqrt --warmup-init-lr 1e-07 \
- --max-tokens 18432 --tokens-per-sample 6144 --sample-break-mode none \
- --update-freq 16 --num-workers 4 --skip-invalid-size-inputs-valid-test \
- --max-update 250000 --warmup-updates 20000 \
- --save-interval-updates 10000 --keep-last-epochs 1 --no-epoch-checkpoints \
- --log-interval 50 --seed 100501 \
- --fp16 --checkpoint-activations
-```
-
-#### 3) Validate
-The model can be validated via the `fairseq-validate` command :
-```bash
-fairseq-validate $BIN_DATA_DIR \
- --task speech_dlm_task \
- --path $CHECKPOINT_PATH \
- --max-tokens 6144
-```
-
-## Reference
-
-If you find our work useful in your research, please consider citing our paper:
-
-```bibtex
-@article{nguyen2022dgslm,
- title = {Generative Spoken Dialogue Language Modeling},
- author = {Nguyen, Tu Anh and Kharitonov, Eugene and Copet, Jade and Adi, Yossi and Hsu, Wei-Ning and Elkahky, Ali and Tomasello, Paden and Algayres, Robin and Sagot, Benoit and Mohamed, Abdelrahman and Dupoux, Emmanuel},
- eprint={2203.16502},
- archivePrefix={arXiv},
- primaryClass={cs.CL},
- year={2022}
-}
-```
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/create_code_file.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/create_code_file.py
deleted file mode 100644
index d10f9484ad26e21ff1cac0909a1337b65194cfb6..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/create_code_file.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import argparse
-
-
-def main():
- """
- Create code file with the following format:
- {'audio': 'file1', 'unitA': 'file1_chnl1_units', 'unitB': 'file1_chnl2_units'}
- {'audio': 'file2', 'unitA': 'file2_chnl1_units', 'unitB': 'file2_chnl2_units'}
- ...
-
- Given the input units files
- - channel1_units_file:
- file1|file1_chnl1_units
- file2|file2_chnl1_units
- ...
- - channel2_units_file:
- file1|file1_chnl2_units
- file2|file2_chnl2_units
- ...
- """
-
- parser = argparse.ArgumentParser()
- parser.add_argument(
- "channel1_units_file",
- type=str,
- help="Units of the first channel.",
- )
- parser.add_argument(
- "channel2_units_file",
- type=str,
- help="Units of the second channel.",
- )
- parser.add_argument(
- "output_file",
- type=str,
- help="Output file.",
- )
- parser.add_argument(
- "--channels",
- type=str,
- default='unitA,unitB',
- help="Comma-separated list of the channel names to create in the code"
- "(Default: 'unitA,unitB').",
- )
-
- args = parser.parse_args()
-
- channel_names = args.channels.split(',')
-
- with open(args.channel1_units_file) as funit1, \
- open(args.channel2_units_file) as funit2, \
- open(args.output_file, 'w') as fout:
- for line1, line2 in zip(funit1, funit2):
- fname1, units1 = line1.strip().split('|')
- fname2, units2 = line2.strip().split('|')
- assert len(units1.split()) == len(units2.split()), \
- f"Mismatch units length ({len(units1.split())} vs {len(units2.split())})"
- base_fname1 = fname1[:-9]
- base_fname2 = fname2[:-9]
- assert base_fname1 == base_fname2, \
- f"Mismatch filenames ({base_fname1} vs {base_fname2}). " \
- f"Expected $filename-channel1 and $filename-channel2 in two files"
- code = {
- "audio" : base_fname1,
- channel_names[0] : units1,
- channel_names[1] : units2,
- }
- fout.write(str(code))
- fout.write("\n")
- print(f"Codes written to {args.output_file}")
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/dgslm_utils.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/dgslm_utils.py
deleted file mode 100644
index 8049d4979311b1fa3807da89144dab65a40ee7c7..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/dgslm_utils.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import numpy as np
-import torch
-import json
-
-from fairseq import utils
-from fairseq.models.text_to_speech.vocoder import CodeHiFiGANVocoder
-
-# from examples.hubert.simple_kmeans.dump_hubert_feature import HubertFeatureReader
-from examples.textless_nlp.gslm.speech2unit.pretrained.hubert_feature_reader import HubertFeatureReader
-from examples.hubert.simple_kmeans.dump_km_label import ApplyKmeans
-
-
-# Hubert tokenizer
-class HubertTokenizer:
- def __init__(
- self,
- hubert_path,
- hubert_layer,
- km_path,
- use_cuda=True,
- ):
- self.feature_extractor = HubertFeatureReader(hubert_path, hubert_layer, use_cuda=use_cuda)
- self.quantizer = ApplyKmeans(km_path)
- if not use_cuda:
- self.quantizer.C = self.quantizer.C.cpu()
- self.quantizer.Cnorm = self.quantizer.Cnorm.cpu()
-
- def wav2code(self, path, channel_id=1):
- feat = self.feature_extractor.get_feats(path, channel_id=channel_id)
- code = self.quantizer(feat)
- return ' '.join(map(str, code))
-
- def wav2codes(self, path):
- codes = [
- self.wav2code(path, channel_id=1),
- self.wav2code(path, channel_id=2)
- ]
- return codes
-
-
-# Vocoder
-class HifiganVocoder:
- def __init__(
- self,
- vocoder_path,
- vocoder_cfg_path,
- use_cuda=True,
- ):
- with open(vocoder_cfg_path) as f:
- cfg = json.load(f)
- self.vocoder = CodeHiFiGANVocoder(vocoder_path, cfg).eval()
- self.use_cuda = use_cuda
- if self.use_cuda:
- self.vocoder.cuda()
-
- def code2wav(self, code, speaker_id=0, pred_dur=False):
- if isinstance(code, str):
- code = list(map(int, code.split()))
- inp = {"code": torch.LongTensor(code).view(1, -1)}
- if self.vocoder.model.multispkr:
- inp["spkr"] = torch.LongTensor([speaker_id]).view(1, 1)
- if self.use_cuda:
- inp = utils.move_to_cuda(inp)
- return self.vocoder(inp, pred_dur).detach().cpu().numpy()
-
- def codes2wav(self, codes, speaker_ids=[0, 4], pred_dur=False):
- if isinstance(codes, dict):
- codes = list(codes.values())
- assert len(codes) == 2
- wav1 = self.code2wav(codes[0], speaker_ids[0], pred_dur)
- wav2 = self.code2wav(codes[1], speaker_ids[1], pred_dur)
- wav = np.stack([wav1, wav2])
- return wav
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/hubert_fisher/README.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/hubert_fisher/README.md
deleted file mode 100644
index 52c528fa1e40e4af290c486bd22d59dbc7aabcea..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/hubert_fisher/README.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# Dialogue Speech-to-Unit Encoder for dGSLM: The Fisher HuBERT model
-For the speech2unit encoder, we train a [HuBERT model](https://arxiv.org/pdf/2106.07447.pdf) on the [Fisher dataset](http://www.lrec-conf.org/proceedings/lrec2004/pdf/767.pdf) for 3 iterations (see [our paper](https://arxiv.org/pdf/2203.16502.pdf) for more details) and train a k-means model with 500 units on the layer 12 features of the HuBERT model.
-
-## Model checkpoints
-The pre-trained HuBERT and k-means model checkpoints can be found here:
-
-| Fisher HuBERT model | k-means model |
-|---------------------|---------------|
-|[download](https://dl.fbaipublicfiles.com/textless_nlp/dgslm/checkpoints/hubert/hubert_fisher.pt)|[download](https://dl.fbaipublicfiles.com/textless_nlp/dgslm/checkpoints/hubert/hubert_fisher_km_500.bin)|
-
-
-## Encode audio to discrete units
-Below is an example command to encode a stereo dataset to discrete units using the pre-trained model checkpoints :
-```bash
-for CHANNEL_ID in 1 2; do
- python examples/textless_nlp/gslm/speech2unit/clustering/quantize_with_kmeans.py \
- --feature_type hubert \
- --kmeans_model_path path/to/hubert_fisher_km_500.bin \
- --acoustic_model_path path/to/hubert_fisher.pt \
- --layer 12 \
- --manifest_path $MANIFEST_FILE \
- --out_quantized_file_path ${OUTPUT_FILE}-channel${CHANNEL_ID} \
- --extension $EXTENSION \
- --channel_id $CHANNEL_ID
-done
-```
-where MANIFEST_FILE is the output of [wav2vec manifest script](https://github.com/facebookresearch/fairseq/blob/main/examples/wav2vec/wav2vec_manifest.py), which can be obtained through the following command :
-```
-python examples/wav2vec/wav2vec_manifest.py --valid-percent=0.0 $AUDIO_DIR --dest=$OUTPUT_DIR --ext=$EXTENSION
-```
-
-Otherwise, you can encode an audio file in python interactively with the HubertTokenizer class :
-```python
-# Load the Hubert tokenizer
-from examples.textless_nlp.dgslm.dgslm_utils import HubertTokenizer
-encoder = HubertTokenizer(
- hubert_path = "/path/to/hubert_ckpt.pt",
- hubert_layer = 12,
- km_path = "path/to/km.bin"
-)
-
-# Encode the audio to units
-path = "/path/to/stereo/audio.wav"
-codes = encoder.wav2codes(path)
-# > ['7 376 376 133 178 486 486 486 486 486 486 486 486 2 486',
-# > '7 499 415 177 7 7 7 7 7 7 136 136 289 289 408']
-```
\ No newline at end of file
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/sample_speech_dlm.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/sample_speech_dlm.py
deleted file mode 100644
index 484cbabd3e6c91368ad8d65d71877af795a52b2c..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/sample_speech_dlm.py
+++ /dev/null
@@ -1,202 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import os
-import ast
-import argparse
-import logging
-import torch
-
-from fairseq import utils
-from fairseq.models.speech_dlm import SpeechDLM
-
-logging.basicConfig()
-logging.root.setLevel(logging.INFO)
-logging.basicConfig(level=logging.INFO)
-logger = logging.getLogger(__name__)
-
-
-def load_data(in_file):
- with open(in_file) as f:
- data = [ast.literal_eval(line.strip()) for line in f]
- return data
-
-
-def write_data(out_file, data):
- with open(out_file, 'w') as f:
- for d in data:
- f.write(str(d))
- f.write('\n')
-
-
-def limit(codes, n):
- new_codes = {}
- for k, v in codes.items():
- new_codes[k] = ' '.join(v.split()[:n])
- return new_codes
-
-
-def main(args):
- logger.info(args)
-
- use_cuda = torch.cuda.is_available()
-
- # Load the data
- data = load_data(args.in_file)
- channels = args.channels.split(',')
- unit_sequences = [{
- channels[0]: d[channels[0]],
- channels[1]: d[channels[1]],
- } for d in data]
- fnames = [d['audio'] for d in data]
- print(f"Found {len(data)} sequences from {args.in_file}")
-
- # Limit the prefix size
- if args.prefix_size is not None:
- print(f"Limit the prefix size to {args.prefix_size}")
- unit_sequences = [limit(codes, args.prefix_size) for codes in unit_sequences]
-
- # Load model from ckpt
- print(f"Loading the SpeechDLM model from {args.ckpt}")
- model = SpeechDLM.from_pretrained(
- model_name_or_path=os.path.dirname(args.ckpt),
- checkpoint_file=os.path.basename(args.ckpt),
- data_name_or_path=args.data
- )
- model.eval()
- if use_cuda:
- model.cuda()
-
- # Set batch sizes
- model.cfg.dataset.max_tokens = args.batch_max_tokens
- model.max_positions = args.batch_max_positions
- if args.batch_max_sentences is not None:
- model.cfg.dataset.batch_size = args.batch_max_sentences
-
- # Set seed (if needed)
- if args.seed is not None:
- utils.set_torch_seed(args.seed)
-
- # Sample from the SpeechDLM model
- print(f"Generating {len(unit_sequences)} sequences with SpeechDLM model...\n"
- f"Generation args: sampling={(not args.beam_search)}, "
- f"sampling_topk={args.sampling_topk}, sampling_topp={args.sampling_topp}, "
- f"beam={args.beam_size}, min_len={args.min_len}, "
- f"max_len_a={args.max_len_a}, max_len_b={args.max_len_b}, "
- f"temperature={args.temperature}, dur_temperature={args.dur_temperature}, "
- f"seed={args.seed}")
- generated_units = model.sample(
- unit_sequences,
- sampling=(not args.beam_search),
- sampling_topk=args.sampling_topk,
- sampling_topp=args.sampling_topp,
- beam=args.beam_size,
- max_len_a=args.max_len_a,
- max_len_b=args.max_len_b,
- min_len=args.min_len,
- temperature=args.temperature,
- duration_temperature=args.dur_temperature,
- verbose=args.verbose,
- skip_invalid_size_inputs=args.skip_invalid_size_batch,
- )
-
- # Create the generated sequences
- generated_data = []
- for fname, gen_units in zip(fnames, generated_units):
- d = {
- "audio" : fname+'-generated',
- **gen_units
- }
- generated_data.append(d)
-
- # Write the generated sequences
- print(f"Write the generated units to {args.out_file}")
- if args.out_file:
- os.makedirs(os.path.dirname(args.out_file), exist_ok=True)
- write_data(args.out_file, generated_data)
-
-
-def cli_main():
- parser = argparse.ArgumentParser()
- parser.add_argument(
- "--in-file",
- type=str,
- required=True,
- help="Input file following the same format of the output from create_input.py",
- )
- parser.add_argument(
- "--ckpt",
- type=str,
- required=True,
- help="Path to the model checkpoint."
- )
- parser.add_argument(
- "--data",
- type=str,
- required=True,
- help="path to the model data dir (containing dict files)",
- )
- parser.add_argument(
- "--out-file",
- type=str,
- required=True,
- help="Path of the output file.",
- )
- parser.add_argument(
- "--channels",
- type=str,
- default='unitA,unitB',
- help="Comma-separated list of the channel names"
- "(Default: 'unitA,unitB').",
- )
- parser.add_argument("--prefix-size", type=int, default=None,
- help='Limit the prefix size')
-
- # Batch sizes
- parser.add_argument("--batch-max-tokens", type=int, default=9216,
- help='maximum number of tokens considered in a batch')
- parser.add_argument("--batch-max-positions", type=int, default=6144,
- help='maximum number of tokens allowed for a sentence in a batch')
- parser.add_argument("--batch-max-sentences", type=int, default=None,
- help='maximum number of sentences considered in a batch')
- parser.add_argument("--skip-invalid-size-batch", action='store_true',
- help='skip sentences with more tokens than --batch-max-positions')
-
- # Generation args
- parser.add_argument("--beam-search", action='store_true',
- help='perform beam search instead of sampling')
- parser.add_argument("--beam-size", type=int, default=5,
- help="beam width (used in both sampling and beam search mode) "
- "(default: 5)")
- parser.add_argument("--sampling-topk", type=int, default=-1,
- help="only sample from top-k candidates (default: -1, non applied)")
- parser.add_argument("--sampling-topp", type=float, default=-1.0,
- help="only sample among the smallest set of elements whose cumulative "
- "probability mass exceeds p (default: -1.0, non applied)")
- parser.add_argument("--max-len-a", type=int, default=0,
- help="generate sequences of maximum length ax + b, "
- "where x is the source length (default: 0)")
- parser.add_argument("--max-len-b", type=int, default=500,
- help="generate sequences of maximum length ax + b, "
- "where x is the source length (default: 500 ~ 10s)")
- parser.add_argument("--min-len", type=int, default=1,
- help="generate sequences of maximum length ax + b, "
- "where x is the source length (default: 1)")
- parser.add_argument("--temperature", type=float, default=1.0,
- help="temperature when generating unit tokens (default: 1.0)")
- parser.add_argument("--dur-temperature", type=float, default=1.0,
- help="temperature when generating duration tokens (default: 1.0)")
- parser.add_argument("--verbose", action='store_true',
- help="print the scores given by the model to generated sequences")
- parser.add_argument("--seed", type=int, default=123,
- help="seed of the generation model")
-
- args = parser.parse_args()
-
- main(args)
-
-
-if __name__ == "__main__":
- cli_main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/vocoder_hifigan/README.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/vocoder_hifigan/README.md
deleted file mode 100644
index 5d4a59a9acfaaeae616354e25ce031c387857909..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/vocoder_hifigan/README.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# Dialogue Unit-to-Speech Decoder for dGSLM
-For the unit2speech decoder, we train a [discrete unit-based HiFi-GAN vocoder](https://arxiv.org/pdf/2104.00355.pdf) on the [Fisher dataset](http://www.lrec-conf.org/proceedings/lrec2004/pdf/767.pdf).
-
-## Model checkpoint
-The pre-trained model checkpoint can be found here :
-
-| HiFi-GAN vocoder based on HuBERT Fisher Units |
-|-----------------------------------------------|
-|[model checkpoint](https://dl.fbaipublicfiles.com/textless_nlp/dgslm/checkpoints/hifigan/hifigan_vocoder) - [config](https://dl.fbaipublicfiles.com/textless_nlp/dgslm/checkpoints/hifigan/config.json) |
-
-## Decode discrete units to audio
-To create waveform from discrete units, use the script `generate_stereo_waveform.py` :
-```bash
-python examples/textless_nlp/dgslm/vocoder_hifigan/generate_stereo_waveform.py \
- --in-file $INPUT_CODE_FILE \
- --vocoder $VOCODER_PATH \
- --vocoder-cfg $VOCODER_CONFIG \
- --results-path $OUTPUT_DIR
-```
-where INPUT_CODE_FILE is expected to have the following format :
-```
-{'audio': 'file_1', 'unitA': '8 8 ... 352 352', 'unitB': '217 8 ... 8 8'}
-{'audio': 'file_2', 'unitA': '5 5 ... 65 65', 'unitB': '6 35 ... 8 9'}
-...
-```
-
-You can also use the HifiganVocoder class to generate waveform from the codes interactively :
-```python
-# Load the Hifigan vocoder
-from examples.textless_nlp.dgslm.dgslm_utils import HifiganVocoder
-decoder = HifiganVocoder(
- vocoder_path = "/path/to/hifigan_vocoder",
- vocoder_cfg_path = "/path/to/config.json",
-)
-
-# Decode the units to waveform
-codes = [
- '7 376 376 133 178 486 486 486 486 486 486 486 486 2 486',
- '7 499 415 177 7 7 7 7 7 7 136 136 289 289 408',
-]
-wav = decoder.codes2wav(codes)
-# > array of shape (2, 4800)
-
-# Play the waveform
-import IPython.display as ipd
-ipd.Audio(wav, rate=16_000)
-```
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/vocoder_hifigan/generate_stereo_waveform.py b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/vocoder_hifigan/generate_stereo_waveform.py
deleted file mode 100644
index 1e15f4324104016e04e69899d610c41295c2ea18..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/dgslm/vocoder_hifigan/generate_stereo_waveform.py
+++ /dev/null
@@ -1,137 +0,0 @@
-# Copyright (c) Facebook, Inc. and its affiliates.
-#
-# This source code is licensed under the MIT license found in the
-# LICENSE file in the root directory of this source tree.
-
-import ast
-import argparse
-import json
-import logging
-from pathlib import Path
-import soundfile as sf
-import torch
-
-from tqdm import tqdm
-
-from fairseq import utils
-from fairseq.models.text_to_speech.vocoder import CodeHiFiGANVocoder
-
-
-logging.basicConfig()
-logging.root.setLevel(logging.INFO)
-logging.basicConfig(level=logging.INFO)
-logger = logging.getLogger(__name__)
-
-
-def dump_result(args, data, sample_id, pred_wav):
- assert "audio" in data or args.results_path is not None
- if args.results_path:
- fname = Path(data["audio"]).stem + ".wav" if "audio" in data else f"{sample_id}_pred.wav"
- out_file = Path(args.results_path) / fname
-
- sf.write(
- out_file.as_posix(),
- pred_wav.detach().cpu().numpy(),
- args.sample_rate,
- )
-
-
-def load_data(in_file):
- with open(in_file) as f:
- data = [ast.literal_eval(line.strip()) for line in f]
-
- return data
-
-
-def load_vocoder(vocoder_path, vocoder_cfg_path, use_cuda=True):
- with open(vocoder_cfg_path) as f:
- cfg = json.load(f)
- vocoder = CodeHiFiGANVocoder(vocoder_path, cfg).eval()
- if use_cuda:
- vocoder = vocoder.cuda()
- return vocoder
-
-
-def code2wav(vocoder, code, speaker_id, use_cuda=True):
- if isinstance(code, str):
- code = list(map(int, code.split()))
- inp = dict()
- inp["code"] = torch.LongTensor(code).view(1, -1)
- if vocoder.model.multispkr:
- inp["spkr"] = torch.LongTensor([speaker_id]).view(1, 1)
- if use_cuda:
- inp = utils.move_to_cuda(inp)
- return vocoder(inp)
-
-
-def main(args):
- logger.info(args)
-
- use_cuda = torch.cuda.is_available() and not args.cpu
-
- vocoder = load_vocoder(args.vocoder, args.vocoder_cfg, use_cuda)
-
- data = load_data(args.in_file)
-
- if args.results_path:
- Path(args.results_path).mkdir(exist_ok=True, parents=True)
-
- channels = args.channels.split(',')
- speakers = [args.channel1_spk, args.channel2_spk]
-
- for i, d in tqdm(enumerate(data), total=len(data)):
- wavs = []
- for key, speaker_id in zip(channels, speakers):
- wav = code2wav(vocoder, d[key], speaker_id, use_cuda=use_cuda)
- wavs.append(wav)
-
- wav = torch.stack(wavs, dim=-1)
- if args.mix:
- wav = torch.mean(wav, dim=-1)
-
- dump_result(args, d, i, wav)
-
-
-def cli_main():
- parser = argparse.ArgumentParser()
- parser.add_argument(
- "--in-file",
- type=str,
- required=True,
- help="Input file following the same format of the output from create_input.py",
- )
- parser.add_argument(
- "--vocoder", type=str, required=True, help="path to the vocoder"
- )
- parser.add_argument(
- "--vocoder-cfg",
- type=str,
- required=True,
- help="path to the vocoder config",
- )
- parser.add_argument(
- "--channels",
- type=str,
- default='unitA,unitB',
- help="Comma-separated list of the channel names"
- "(Default: 'unitA,unitB').",
- )
- parser.add_argument("--sample-rate", type=int, default=16_000)
- parser.add_argument(
- "--results-path",
- type=str,
- default=None,
- help="Output directory. If not set, the audios will be stored following the 'audio' field specified in the input file",
- )
- parser.add_argument("--channel1-spk", type=int, default=0, help="Speaker of the first channel",)
- parser.add_argument("--channel2-spk", type=int, default=4, help="Speaker of the second channel",)
- parser.add_argument("--mix", action="store_true", help="Mix the two channels to create output mono files")
- parser.add_argument("--cpu", action="store_true", help="run on CPU")
-
- args = parser.parse_args()
-
- main(args)
-
-
-if __name__ == "__main__":
- cli_main()
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/gslm/README.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/gslm/README.md
deleted file mode 100644
index 7a76ffd57c066c20af94aa3fca24c18e2ba4c3dd..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/gslm/README.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Generative Spoken Language Modeling
-
-* [Paper](https://arxiv.org/abs/2102.01192)
-* [Demo](https://speechbot.github.io/gslm/index.html)
-
-We build and evaluate generative speech2speech systems using [Log Mel Filtebank](https://pytorch.org/audio/stable/compliance.kaldi.html#fbank), [Modified CPC](https://github.com/facebookresearch/CPC_audio), [HuBERT Base](https://github.com/pytorch/fairseq/tree/main/examples/hubert) and [Wav2Vec 2.0 Large](https://github.com/pytorch/fairseq/tree/main/examples/wav2vec). Our system is composed of three components, namely, *speech2unit*, *ulm* and *unit2speech*. We explain about models and usage of these components in their respective sub-directories. See the links below.
-
-## Speech to Unit Model (speech2unit)
-Speech to unit model is used for quantizing raw speech into learned discrete speech units. [More details](speech2unit)
-
-## Unit Language Model (ulm)
-Unit Language Model is a generative language model trained on discrete speech units. [More details](ulm)
-
-## Unit to Speech Model (unit2speech)
-Unit to speech model is used for synthesizing speech from discrete speech units. [More details](unit2speech)
-
-## Metrics
-We show how to compute ASR based metrics as well as zero-shot metrics proposed in our paper [here](metrics).
-
-## Tools
-We share two tools to resynthesize a given spoken utterance, and generate novel spoken language given a spoken prompt. [More detail](tools)
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/gslm/metrics/README.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/gslm/metrics/README.md
deleted file mode 100644
index 0a63e2f0d844ce157f9502c82738aac2a0de3f0c..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/gslm/metrics/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# GSLM Metrics
-
-## ASR Metrics
-The suite of metrics here uses an ASR model to transcribe the synthesized speech into text, and then uses text-based metrics. We also use word error rate from ASR transcription itself as one of the metrics. [More details](asr_metrics)
-
-## ABX Metrics
-We use [ABX](https://www.semanticscholar.org/paper/ABX-Discriminability-Measures-and-Applications-Schatz/13d3537228f728c1063cc83743cb118bba3367a0) to evaluate how well-separated phonetic categories are with quantized representations. [More details](abx_metrics)
-
-## sWUGGY and sBLIMP
-We refer to [ZeroSpeech challenge](https://www.zerospeech.com/2021/track_s.html#scoring-based-metrics) for details on the sWUGGY and sBLIMP metrics.
diff --git a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/gslm/metrics/abx_metrics/README.md b/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/gslm/metrics/abx_metrics/README.md
deleted file mode 100644
index aa2560f0453403fb5846c387848c78b037c79cb2..0000000000000000000000000000000000000000
--- a/src/third_party/MuQ/src/recipes/pretrain/fairseq/examples/textless_nlp/gslm/metrics/abx_metrics/README.md
+++ /dev/null
@@ -1,77 +0,0 @@
-# ABX-based evaluation
-
-ABX is used to evaluate the quality of the obtained discrete units.
-
-The life cycle of the ABX-based evaluation for the Speech-to-Unit contains the following steps:
-1. Training an acoustic model (or use an existing acoustic model) ([description](./../..))
-2. Perform quantization of speech by learning a K-means clustering model ([description](./../..))
-3. Compute discrete features for ABX computation using the learned clusters
-4. Compute the ABX score over the discrete features taking advantage of [libri-light's ABX evaluation script][ll-abx]
-
-Here we assume that you already went throught the first two steps and focus solely on extracting features and computing ABX scores.
-
-## Libri-light setup
-
-Follow [libri-light's instructions][ll-instructions] for installation and [ABX evaluation setup][ll-abx] (including the download of the data items required for ABX computation).
-
-## Computing ABX
-
-### Dumping quantized features
-
-The first step for the ABX computation is to dump the quantized representations corresponding to the test files.
-
-```shell
-TYPE="hubert"
-LAYER=6
-CKPT_PATH=""
-KM_MODEL_PATH=""
-
-SUBSET="dev-clean"
-MANIFEST=""
-DATA_DIR="