flosstradamus commited on
Commit
afe1a07
1 Parent(s): 943654e

Upload 194 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. FluxMusic_jupyter.ipynb +190 -0
  2. README.md +59 -12
  3. __pycache__/constants.cpython-310.pyc +0 -0
  4. __pycache__/model.cpython-310.pyc +0 -0
  5. __pycache__/train.cpython-310.pyc +0 -0
  6. __pycache__/utils.cpython-310.pyc +0 -0
  7. audioldm2/.DS_Store +0 -0
  8. audioldm2/__init__.py +2 -0
  9. audioldm2/__main__.py +183 -0
  10. audioldm2/__pycache__/__init__.cpython-310.pyc +0 -0
  11. audioldm2/__pycache__/pipeline.cpython-310.pyc +0 -0
  12. audioldm2/__pycache__/utils.cpython-310.pyc +0 -0
  13. audioldm2/audiomae_gen/__init__.py +1 -0
  14. audioldm2/audiomae_gen/__pycache__/__init__.cpython-310.pyc +0 -0
  15. audioldm2/audiomae_gen/__pycache__/sequence_input.cpython-310.pyc +0 -0
  16. audioldm2/audiomae_gen/sequence_input.py +429 -0
  17. audioldm2/audiomae_gen/utils.py +27 -0
  18. audioldm2/clap/__init__.py +0 -0
  19. audioldm2/clap/__pycache__/__init__.cpython-310.pyc +0 -0
  20. audioldm2/clap/open_clip/__init__.py +25 -0
  21. audioldm2/clap/open_clip/__pycache__/__init__.cpython-310.pyc +0 -0
  22. audioldm2/clap/open_clip/__pycache__/factory.cpython-310.pyc +0 -0
  23. audioldm2/clap/open_clip/__pycache__/feature_fusion.cpython-310.pyc +0 -0
  24. audioldm2/clap/open_clip/__pycache__/htsat.cpython-310.pyc +0 -0
  25. audioldm2/clap/open_clip/__pycache__/loss.cpython-310.pyc +0 -0
  26. audioldm2/clap/open_clip/__pycache__/model.cpython-310.pyc +0 -0
  27. audioldm2/clap/open_clip/__pycache__/openai.cpython-310.pyc +0 -0
  28. audioldm2/clap/open_clip/__pycache__/pann_model.cpython-310.pyc +0 -0
  29. audioldm2/clap/open_clip/__pycache__/pretrained.cpython-310.pyc +0 -0
  30. audioldm2/clap/open_clip/__pycache__/tokenizer.cpython-310.pyc +0 -0
  31. audioldm2/clap/open_clip/__pycache__/transform.cpython-310.pyc +0 -0
  32. audioldm2/clap/open_clip/__pycache__/utils.cpython-310.pyc +0 -0
  33. audioldm2/clap/open_clip/bpe_simple_vocab_16e6.txt.gz +3 -0
  34. audioldm2/clap/open_clip/factory.py +276 -0
  35. audioldm2/clap/open_clip/feature_fusion.py +192 -0
  36. audioldm2/clap/open_clip/htsat.py +1304 -0
  37. audioldm2/clap/open_clip/loss.py +397 -0
  38. audioldm2/clap/open_clip/model.py +931 -0
  39. audioldm2/clap/open_clip/model_configs/HTSAT-base.json +23 -0
  40. audioldm2/clap/open_clip/model_configs/HTSAT-large.json +23 -0
  41. audioldm2/clap/open_clip/model_configs/HTSAT-tiny-win-1536.json +23 -0
  42. audioldm2/clap/open_clip/model_configs/HTSAT-tiny.json +23 -0
  43. audioldm2/clap/open_clip/model_configs/PANN-10.json +23 -0
  44. audioldm2/clap/open_clip/model_configs/PANN-14-fmax-18k.json +23 -0
  45. audioldm2/clap/open_clip/model_configs/PANN-14-fmax-8k-20s.json +23 -0
  46. audioldm2/clap/open_clip/model_configs/PANN-14-tiny-transformer.json +23 -0
  47. audioldm2/clap/open_clip/model_configs/PANN-14-win-1536.json +23 -0
  48. audioldm2/clap/open_clip/model_configs/PANN-14.json +23 -0
  49. audioldm2/clap/open_clip/model_configs/PANN-6.json +23 -0
  50. audioldm2/clap/open_clip/model_configs/RN101-quickgelu.json +22 -0
FluxMusic_jupyter.ipynb ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "metadata": {
7
+ "id": "VjYy0F2gZIPR"
8
+ },
9
+ "outputs": [],
10
+ "source": [
11
+ "%cd /content\n",
12
+ "!git clone -b dev https://github.com/camenduru/FluxMusic\n",
13
+ "%cd C:/Users/Curt/Developer/AItools/AIaudio/AudioCreation/FluxMusicJupyter/FluxMusic\n",
14
+ "\n",
15
+ "!apt -y install -qq aria2\n",
16
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/audo/FluxMusic/resolve/main/musicflow_b.pt -d C:/Users/Curt/Developer/AItools/AIaudio/AudioCreation/FluxMusicJupyter/FluxMusic -o musicflow_b.pt\n",
17
+ "\n",
18
+ "!pip install transformers diffusers accelerate einops soundfile progressbar unidecode phonemizer torchlibrosa ftfy pandas timm matplotlib numpy==1.26.4 thop flash-attn==2.6.3 sentencepiece"
19
+ ]
20
+ },
21
+ {
22
+ "cell_type": "code",
23
+ "execution_count": null,
24
+ "metadata": {
25
+ "id": "NoTEt9Wto70D"
26
+ },
27
+ "outputs": [],
28
+ "source": [
29
+ "%cd C:/Users/Curt/Developer/AItools/AIaudio/AudioCreation/FluxMusicJupyter\n",
30
+ "\n",
31
+ "import os\n",
32
+ "import torch\n",
33
+ "import argparse\n",
34
+ "import math\n",
35
+ "from einops import rearrange, repeat\n",
36
+ "from PIL import Image\n",
37
+ "from diffusers import AutoencoderKL\n",
38
+ "from transformers import SpeechT5HifiGan\n",
39
+ "\n",
40
+ "from utils import load_t5, load_clap, load_ae\n",
41
+ "from train import RF\n",
42
+ "from constants import build_model\n",
43
+ "\n",
44
+ "def prepare(t5, clip, img, prompt):\n",
45
+ " bs, c, h, w = img.shape\n",
46
+ " if bs == 1 and not isinstance(prompt, str):\n",
47
+ " bs = len(prompt)\n",
48
+ "\n",
49
+ " img = rearrange(img, \"b c (h ph) (w pw) -> b (h w) (c ph pw)\", ph=2, pw=2)\n",
50
+ " if img.shape[0] == 1 and bs > 1:\n",
51
+ " img = repeat(img, \"1 ... -> bs ...\", bs=bs)\n",
52
+ "\n",
53
+ " img_ids = torch.zeros(h // 2, w // 2, 3)\n",
54
+ " img_ids[..., 1] = img_ids[..., 1] + torch.arange(h // 2)[:, None]\n",
55
+ " img_ids[..., 2] = img_ids[..., 2] + torch.arange(w // 2)[None, :]\n",
56
+ " img_ids = repeat(img_ids, \"h w c -> b (h w) c\", b=bs)\n",
57
+ "\n",
58
+ " if isinstance(prompt, str):\n",
59
+ " prompt = [prompt]\n",
60
+ " txt = t5(prompt)\n",
61
+ " if txt.shape[0] == 1 and bs > 1:\n",
62
+ " txt = repeat(txt, \"1 ... -> bs ...\", bs=bs)\n",
63
+ " txt_ids = torch.zeros(bs, txt.shape[1], 3)\n",
64
+ "\n",
65
+ " vec = clip(prompt)\n",
66
+ " if vec.shape[0] == 1 and bs > 1:\n",
67
+ " vec = repeat(vec, \"1 ... -> bs ...\", bs=bs)\n",
68
+ "\n",
69
+ " print(img_ids.size(), txt.size(), vec.size())\n",
70
+ " return img, {\n",
71
+ " \"img_ids\": img_ids.to(img.device),\n",
72
+ " \"txt\": txt.to(img.device),\n",
73
+ " \"txt_ids\": txt_ids.to(img.device),\n",
74
+ " \"y\": vec.to(img.device),\n",
75
+ " }\n",
76
+ "\n",
77
+ "version=\"base\"\n",
78
+ "seed=2024\n",
79
+ "prompt_file=\"C:/Users/Curt/Developer/AItools/AIaudio/AudioCreation/FluxMusicJupyter/config/example.txt\"\n",
80
+ "\n",
81
+ "print('generate with MusicFlux')\n",
82
+ "torch.manual_seed(seed)\n",
83
+ "torch.set_grad_enabled(False)\n",
84
+ "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
85
+ "\n",
86
+ "latent_size = (256, 16)\n",
87
+ "\n",
88
+ "model = build_model(version).to(device)\n",
89
+ "local_path = 'C:/Users/Curt/Developer/AItools/AIaudio/AudioCreation/FluxMusicJupyter/musicflow_b.pt'\n",
90
+ "state_dict = torch.load(local_path, map_location=lambda storage, loc: storage, weights_only=True)\n",
91
+ "model.load_state_dict(state_dict['ema'])\n",
92
+ "model.eval() # important!\n",
93
+ "diffusion = RF()"
94
+ ]
95
+ },
96
+ {
97
+ "cell_type": "code",
98
+ "execution_count": null,
99
+ "metadata": {
100
+ "id": "B5ebyTmto70D"
101
+ },
102
+ "outputs": [],
103
+ "source": [
104
+ "t5 = load_t5(device, max_length=256)\n",
105
+ "clap = load_clap(device, max_length=256)\n",
106
+ "\n",
107
+ "vae = AutoencoderKL.from_pretrained('cvssp/audioldm2', subfolder=\"vae\").to(device)\n",
108
+ "vocoder = SpeechT5HifiGan.from_pretrained('cvssp/audioldm2', subfolder=\"vocoder\").to(device)"
109
+ ]
110
+ },
111
+ {
112
+ "cell_type": "code",
113
+ "execution_count": null,
114
+ "metadata": {
115
+ "id": "xqG8Px6xo70D"
116
+ },
117
+ "outputs": [],
118
+ "source": [
119
+ "prompt_file=\"C:/Users/Curt/Developer/AItools/AIaudio/AudioCreation/FluxMusicJupyter/config/example.txt\"\n",
120
+ "\n",
121
+ "with open(prompt_file, 'r') as f:\n",
122
+ " conds_txt = f.readlines()\n",
123
+ "L = len(conds_txt)\n",
124
+ "unconds_txt = [\"low quality, gentle\"] * L\n",
125
+ "print(L, conds_txt, unconds_txt)\n",
126
+ "\n",
127
+ "init_noise = torch.randn(L, 8, latent_size[0], latent_size[1]).cuda()\n",
128
+ "\n",
129
+ "STEPSIZE = 50\n",
130
+ "img, conds = prepare(t5, clap, init_noise, conds_txt)\n",
131
+ "_, unconds = prepare(t5, clap, init_noise, unconds_txt)\n",
132
+ "with torch.autocast(device_type='cuda'):\n",
133
+ " images = diffusion.sample_with_xps(model, img, conds=conds, null_cond=unconds, sample_steps = STEPSIZE, cfg = 7.0)\n",
134
+ "\n",
135
+ "print(images[-1].size(), )\n",
136
+ "\n",
137
+ "images = rearrange(\n",
138
+ " images[-1],\n",
139
+ " \"b (h w) (c ph pw) -> b c (h ph) (w pw)\",\n",
140
+ " h=128,\n",
141
+ " w=8,\n",
142
+ " ph=2,\n",
143
+ " pw=2,)\n",
144
+ "# print(images.size())\n",
145
+ "latents = 1 / vae.config.scaling_factor * images\n",
146
+ "mel_spectrogram = vae.decode(latents).sample\n",
147
+ "print(mel_spectrogram.size())"
148
+ ]
149
+ },
150
+ {
151
+ "cell_type": "code",
152
+ "execution_count": null,
153
+ "metadata": {
154
+ "id": "ytAXlAEdo70D"
155
+ },
156
+ "outputs": [],
157
+ "source": [
158
+ "!mkdir C:/Users/Curt/Developer/AItools/AIaudio/AudioCreation/FluxMusicJupyter/FluxMusic/b_output\n",
159
+ "\n",
160
+ "for i in range(L):\n",
161
+ " x_i = mel_spectrogram[i]\n",
162
+ " if x_i.dim() == 4:\n",
163
+ " x_i = x_i.squeeze(1)\n",
164
+ " waveform = vocoder(x_i)\n",
165
+ " waveform = waveform[0].cpu().float().detach().numpy()\n",
166
+ " print(waveform.shape)\n",
167
+ " # import soundfile as sf\n",
168
+ " # sf.write('reconstruct.wav', waveform, samplerate=16000)\n",
169
+ " from scipy.io import wavfile\n",
170
+ " wavfile.write('C:/Users/Curt/Developer/AItools/AIaudio/AudioCreation/FluxMusicJupyter/FluxMusic/b_output/sample_' + str(i) + '.wav', 16000, waveform)"
171
+ ]
172
+ }
173
+ ],
174
+ "metadata": {
175
+ "accelerator": "GPU",
176
+ "colab": {
177
+ "gpuType": "T4",
178
+ "provenance": []
179
+ },
180
+ "kernelspec": {
181
+ "display_name": "Python 3",
182
+ "name": "python3"
183
+ },
184
+ "language_info": {
185
+ "name": "python"
186
+ }
187
+ },
188
+ "nbformat": 4,
189
+ "nbformat_minor": 0
190
+ }
README.md CHANGED
@@ -1,12 +1,59 @@
1
- ---
2
- title: FluxMusicGUI
3
- emoji: 🏢
4
- colorFrom: pink
5
- colorTo: purple
6
- sdk: gradio
7
- sdk_version: 4.42.0
8
- app_file: app.py
9
- pinned: false
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## FluxMusic: Text-to-Music Generation with Rectified Flow Transformer <br><sub>GUI Implementation</sub>
2
+
3
+ <a href="https://arxiv.org/abs/2409.00587"><img src="https://img.shields.io/static/v1?label=Paper&message=FluxMusic&color=purple&logo=arxiv"></a> &ensp;
4
+ <a href="https://huggingface.co/feizhengcong/fluxmusic"><img src="https://img.shields.io/static/v1?label=Models&message=HuggingFace&color=yellow"></a> &ensp;
5
+
6
+ This repo contains a Graphical User Interface (GUI) implementation of the FluxMusic model, based on the paper *Flux that plays music*. It explores a simple extension of diffusion-based rectified flow Transformers for text-to-music generation.
7
+
8
+ ### FluxMusic GUI
9
+
10
+ We have created a user-friendly GUI for FluxMusic using Gradio. This interface allows users to easily generate music based on text prompts without needing to interact with command-line interfaces.
11
+
12
+ #### Features:
13
+
14
+ 1. **Model Selection**: Users can choose from different FluxMusic models (small, base, large, giant) via a dropdown menu.
15
+
16
+ 2. **Text Prompt**: Enter your desired text prompt to guide the music generation.
17
+
18
+ 3. **Sliders and Inputs**:
19
+ - **Seed**: Set a seed for reproducibility (0 for random).
20
+ - **CFG Scale**: Adjust the Classifier-Free Guidance scale (1-40).
21
+ - **Steps**: Set the number of diffusion steps (10-200).
22
+ - **Duration**: Specify the length of the generated audio in seconds (10-300).
23
+
24
+ 4. **File Management**:
25
+ - **Models Folder**: Place your FluxMusic model files (`.pt`) in the `models` folder.
26
+ - **Generations Folder**: Generated audio files are saved in the `generations` folder.
27
+
28
+ 5. **File Naming System**: Generated files are named using the format: `[prompt]_[seed]_[model]_[counter].wav`
29
+
30
+ ### Setup and Running
31
+
32
+ 1. Install the required dependencies:
33
+ ```
34
+ pip install -r requirements.txt
35
+ ```
36
+
37
+ 2. Place your FluxMusic model files in the `models` folder.
38
+
39
+ 3. Run the GUI:
40
+ ```
41
+ python fluxGUI.py
42
+ ```
43
+
44
+ 4. Use the interface to generate music based on your prompts and preferences.
45
+
46
+ ### Model Information
47
+
48
+ FluxMusic comes in four sizes: Small, Base, Large, and Giant. You can download these models from the following links:
49
+
50
+ | Model | Url |
51
+ |---------------|------------------|
52
+ | FluxMusic-Small | [link](https://huggingface.co/feizhengcong/FluxMusic/blob/main/musicflow_s.pt) |
53
+ | FluxMusic-Base | [link](https://huggingface.co/feizhengcong/FluxMusic/blob/main/musicflow_b.pt) |
54
+ | FluxMusic-Large | [link](https://huggingface.co/feizhengcong/FluxMusic/blob/main/musicflow_l.pt) |
55
+ | FluxMusic-Giant | [link](https://huggingface.co/feizhengcong/FluxMusic/blob/main/musicflow_g.pt) |
56
+
57
+ ### Acknowledgments
58
+
59
+ The codebase is based on the awesome [Flux](https://github.com/black-forest-labs/flux) and [AudioLDM2](https://github.com/haoheliu/AudioLDM2) repos.
__pycache__/constants.cpython-310.pyc ADDED
Binary file (974 Bytes). View file
 
__pycache__/model.cpython-310.pyc ADDED
Binary file (3.15 kB). View file
 
__pycache__/train.cpython-310.pyc ADDED
Binary file (10.7 kB). View file
 
__pycache__/utils.cpython-310.pyc ADDED
Binary file (1.51 kB). View file
 
audioldm2/.DS_Store ADDED
Binary file (6.15 kB). View file
 
audioldm2/__init__.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ from .utils import seed_everything, save_wave, get_time, get_duration, read_list
2
+ from .pipeline import *
audioldm2/__main__.py ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!D:\GitDownload\SupThirdParty\audioldm2\venv\Scripts\python.exe
2
+ import os
3
+ import torch
4
+ import logging
5
+ from audioldm2 import text_to_audio, build_model, save_wave, get_time, read_list
6
+ import argparse
7
+
8
+ os.environ["TOKENIZERS_PARALLELISM"] = "true"
9
+ matplotlib_logger = logging.getLogger('matplotlib')
10
+ matplotlib_logger.setLevel(logging.WARNING)
11
+
12
+ parser = argparse.ArgumentParser()
13
+
14
+ parser.add_argument(
15
+ "-t",
16
+ "--text",
17
+ type=str,
18
+ required=False,
19
+ default="",
20
+ help="Text prompt to the model for audio generation",
21
+ )
22
+
23
+ parser.add_argument(
24
+ "--transcription",
25
+ type=str,
26
+ required=False,
27
+ default="",
28
+ help="Transcription for Text-to-Speech",
29
+ )
30
+
31
+ parser.add_argument(
32
+ "-tl",
33
+ "--text_list",
34
+ type=str,
35
+ required=False,
36
+ default="",
37
+ help="A file that contains text prompt to the model for audio generation",
38
+ )
39
+
40
+ parser.add_argument(
41
+ "-s",
42
+ "--save_path",
43
+ type=str,
44
+ required=False,
45
+ help="The path to save model output",
46
+ default="./output",
47
+ )
48
+
49
+ parser.add_argument(
50
+ "--model_name",
51
+ type=str,
52
+ required=False,
53
+ help="The checkpoint you gonna use",
54
+ default="audioldm_48k",
55
+ choices=["audioldm_48k", "audioldm_16k_crossattn_t5", "audioldm2-full", "audioldm2-music-665k",
56
+ "audioldm2-full-large-1150k", "audioldm2-speech-ljspeech", "audioldm2-speech-gigaspeech"]
57
+ )
58
+
59
+ parser.add_argument(
60
+ "-d",
61
+ "--device",
62
+ type=str,
63
+ required=False,
64
+ help="The device for computation. If not specified, the script will automatically choose the device based on your environment.",
65
+ default="auto",
66
+ )
67
+
68
+ parser.add_argument(
69
+ "-b",
70
+ "--batchsize",
71
+ type=int,
72
+ required=False,
73
+ default=1,
74
+ help="Generate how many samples at the same time",
75
+ )
76
+
77
+ parser.add_argument(
78
+ "--ddim_steps",
79
+ type=int,
80
+ required=False,
81
+ default=200,
82
+ help="The sampling step for DDIM",
83
+ )
84
+
85
+ parser.add_argument(
86
+ "-gs",
87
+ "--guidance_scale",
88
+ type=float,
89
+ required=False,
90
+ default=3.5,
91
+ help="Guidance scale (Large => better quality and relavancy to text; Small => better diversity)",
92
+ )
93
+
94
+ parser.add_argument(
95
+ "-dur",
96
+ "--duration",
97
+ type=float,
98
+ required=False,
99
+ default=10.0,
100
+ help="The duration of the samples",
101
+ )
102
+
103
+ parser.add_argument(
104
+ "-n",
105
+ "--n_candidate_gen_per_text",
106
+ type=int,
107
+ required=False,
108
+ default=3,
109
+ help="Automatic quality control. This number control the number of candidates (e.g., generate three audios and choose the best to show you). A Larger value usually lead to better quality with heavier computation",
110
+ )
111
+
112
+ parser.add_argument(
113
+ "--seed",
114
+ type=int,
115
+ required=False,
116
+ default=0,
117
+ help="Change this value (any integer number) will lead to a different generation result.",
118
+ )
119
+
120
+ args = parser.parse_args()
121
+
122
+ torch.set_float32_matmul_precision("high")
123
+
124
+ save_path = os.path.join(args.save_path, get_time())
125
+
126
+ text = args.text
127
+ random_seed = args.seed
128
+ duration = args.duration
129
+ sample_rate = 16000
130
+
131
+ if ("audioldm2" in args.model_name):
132
+ print(
133
+ "Warning: For AudioLDM2 we currently only support 10s of generation. Please use audioldm_48k or audioldm_16k_crossattn_t5 if you want a different duration.")
134
+ duration = 10
135
+ if ("48k" in args.model_name):
136
+ sample_rate = 48000
137
+
138
+ guidance_scale = args.guidance_scale
139
+ n_candidate_gen_per_text = args.n_candidate_gen_per_text
140
+ transcription = args.transcription
141
+
142
+ if (transcription):
143
+ if "speech" not in args.model_name:
144
+ print(
145
+ "Warning: You choose to perform Text-to-Speech by providing the transcription.However you do not choose the correct model name (audioldm2-speech-gigaspeech or audioldm2-speech-ljspeech).")
146
+ print("Warning: We will use audioldm2-speech-gigaspeech by default")
147
+ args.model_name = "audioldm2-speech-gigaspeech"
148
+ if (not text):
149
+ print(
150
+ "Warning: You should provide text as a input to describe the speaker. Use default (A male reporter is speaking)")
151
+ text = "A female reporter is speaking full of emotion"
152
+
153
+ os.makedirs(save_path, exist_ok=True)
154
+ audioldm2 = build_model(model_name=args.model_name, device=args.device)
155
+
156
+ if (args.text_list):
157
+ print("Generate audio based on the text prompts in %s" % args.text_list)
158
+ prompt_todo = read_list(args.text_list)
159
+ else:
160
+ prompt_todo = [text]
161
+
162
+ for text in prompt_todo:
163
+ if ("|" in text):
164
+ text, name = text.split("|")
165
+ else:
166
+ name = text[:128]
167
+
168
+ if (transcription):
169
+ name += "-TTS-%s" % transcription
170
+
171
+ waveform = text_to_audio(
172
+ audioldm2,
173
+ text,
174
+ transcription=transcription, # To avoid the model to ignore the last vocab
175
+ seed=random_seed,
176
+ duration=duration,
177
+ guidance_scale=guidance_scale,
178
+ ddim_steps=args.ddim_steps,
179
+ n_candidate_gen_per_text=n_candidate_gen_per_text,
180
+ batchsize=args.batchsize,
181
+ )
182
+
183
+ save_wave(waveform, save_path, name=name, samplerate=sample_rate)
audioldm2/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (337 Bytes). View file
 
audioldm2/__pycache__/pipeline.cpython-310.pyc ADDED
Binary file (4.59 kB). View file
 
audioldm2/__pycache__/utils.cpython-310.pyc ADDED
Binary file (12 kB). View file
 
audioldm2/audiomae_gen/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .sequence_input import Sequence2AudioMAE
audioldm2/audiomae_gen/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (254 Bytes). View file
 
audioldm2/audiomae_gen/__pycache__/sequence_input.cpython-310.pyc ADDED
Binary file (9.38 kB). View file
 
audioldm2/audiomae_gen/sequence_input.py ADDED
@@ -0,0 +1,429 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ from audioldm2.latent_diffusion.util import (
4
+ instantiate_from_config,
5
+ )
6
+
7
+ # from latent_diffusion.modules.encoders.modules import CLAPAudioEmbeddingClassifierFreev2
8
+ from transformers import GPT2Config, GPT2Model
9
+ import torch.optim.lr_scheduler as lr_scheduler
10
+
11
+ class Sequence2AudioMAE(nn.Module):
12
+ def __init__(
13
+ self,
14
+ base_learning_rate,
15
+ sequence_gen_length,
16
+ sequence_input_key,
17
+ sequence_input_embed_dim,
18
+ cond_stage_config,
19
+ optimizer_type="AdamW",
20
+ use_warmup=True,
21
+ use_ar_gen_loss=False,
22
+ use_audiomae_linear=False,
23
+ target_tokens_mask_ratio=0.0,
24
+ random_mask_ratio=False,
25
+ **kwargs
26
+ ):
27
+ super().__init__()
28
+ assert use_audiomae_linear == False
29
+ self.random_mask_ratio = random_mask_ratio
30
+ self.learning_rate = base_learning_rate
31
+ self.cond_stage_config = cond_stage_config
32
+ self.use_audiomae_linear = use_audiomae_linear
33
+ self.optimizer_type = optimizer_type
34
+ self.use_warmup = use_warmup
35
+ self.use_ar_gen_loss = use_ar_gen_loss
36
+ # Even though the LDM can be conditioned on mutliple pooling rate
37
+ # Our model always predict the higest pooling rate
38
+
39
+ # self.time_pool = max(self.cond_stage_config["crossattn_audiomae_pooled"]["params"]["time_pooling_factors"])
40
+ # self.freq_pool = max(self.cond_stage_config["crossattn_audiomae_pooled"]["params"]["freq_pooling_factors"])
41
+ # self.mae_token_num = int(512/(self.time_pool*self.freq_pool))
42
+
43
+ self.mae_token_num = sequence_gen_length
44
+ self.sequence_input_key = sequence_input_key
45
+ self.sequence_input_embed_dim = sequence_input_embed_dim
46
+ self.target_tokens_mask_ratio = target_tokens_mask_ratio
47
+
48
+ self.start_of_sequence_tokens = nn.Embedding(32, 768)
49
+ self.end_of_sequence_tokens = nn.Embedding(32, 768)
50
+
51
+ self.input_sequence_embed_linear = nn.ModuleList([])
52
+ self.initial_learning_rate = None
53
+
54
+ for dim in self.sequence_input_embed_dim:
55
+ self.input_sequence_embed_linear.append(nn.Linear(dim, 768))
56
+
57
+ self.cond_stage_models = nn.ModuleList([])
58
+ self.instantiate_cond_stage(cond_stage_config)
59
+ self.initialize_param_check_toolkit()
60
+
61
+ # configuration = GPT2Config(n_layer=1) # TODO
62
+ # self.model=GPT2Model(configuration)
63
+ ###################
64
+ # self.model=nn.Linear(768,768, bias=False) # TODO change the model
65
+ # with torch.no_grad():
66
+ # self.model.weight.copy_(torch.eye(768))
67
+ ###################
68
+ self.model = GPT2Model(GPT2Config.from_pretrained("gpt2"))
69
+ ###################
70
+ # self.model = nn.LSTM(input_size=768, hidden_size=768, num_layers=1,bias=False) # TODO
71
+
72
+ # self.loss_fn = nn.MSELoss()
73
+ self.loss_fn = nn.L1Loss()
74
+
75
+ self.logger_save_dir = None
76
+ self.logger_exp_name = None
77
+ self.logger_exp_group_name = None
78
+ self.logger_version = None
79
+
80
+ def set_log_dir(self, save_dir, exp_group_name, exp_name):
81
+ self.logger_save_dir = save_dir
82
+ self.logger_exp_group_name = exp_group_name
83
+ self.logger_exp_name = exp_name
84
+
85
+ def cfg_uncond(self, batch_size):
86
+ unconditional_conditioning = {}
87
+ for key in self.cond_stage_model_metadata:
88
+ model_idx = self.cond_stage_model_metadata[key]["model_idx"]
89
+ unconditional_conditioning[key] = self.cond_stage_models[
90
+ model_idx
91
+ ].get_unconditional_condition(batch_size)
92
+ assert (
93
+ "crossattn_audiomae_pooled" in unconditional_conditioning.keys()
94
+ ), "The module is not initialized with AudioMAE"
95
+ unconditional_conditioning[
96
+ "crossattn_clap_to_audiomae_feature"
97
+ ] = unconditional_conditioning["crossattn_audiomae_pooled"]
98
+ return unconditional_conditioning
99
+
100
+ def configure_optimizers(self):
101
+ lr = float(self.learning_rate)
102
+ # params = list(self.model.parameters()) + list(self.input_sequence_embed_linear.parameters())
103
+ params = list(self.parameters())
104
+
105
+ # opt = torch.optim.Adam(params, lr=lr, betas=(0.9, 0.98), eps=1e-9)
106
+ opt = eval(self.optimizer_type)(params, lr=lr)
107
+ scheduler = lr_scheduler.StepLR(opt, step_size=10, gamma=0.8)
108
+ return [opt], [scheduler]
109
+
110
+ def add_sos_eos_tokens(self, _id, sequence, attn_mask):
111
+ batchsize = sequence.size(0)
112
+
113
+ new_attn_mask_step = torch.ones((batchsize, 1)).to(sequence.device)
114
+ key_id = torch.tensor([_id]).to(sequence.device)
115
+
116
+ # Add two more steps to attn mask
117
+ new_attn_mask = torch.cat(
118
+ [new_attn_mask_step, attn_mask, new_attn_mask_step], dim=1
119
+ )
120
+
121
+ # Add two more tokens in the sequence
122
+ sos_token = self.start_of_sequence_tokens(key_id).expand(batchsize, 1, -1)
123
+ eos_token = self.end_of_sequence_tokens(key_id).expand(batchsize, 1, -1)
124
+ new_sequence = torch.cat([sos_token, sequence, eos_token], dim=1)
125
+ return new_sequence, new_attn_mask
126
+
127
+ def truncate_sequence_and_mask(self, sequence, mask, max_len=512):
128
+ if sequence.size(1) > max_len:
129
+ print(
130
+ "The input sequence length to GPT-2 model is too long:",
131
+ sequence.size(1),
132
+ )
133
+ return sequence[:, :max_len], mask[:, :max_len]
134
+ else:
135
+ return sequence, mask
136
+
137
+ def get_input_sequence_and_mask(self, cond_dict):
138
+ input_embeds = None
139
+ input_embeds_attn_mask = None
140
+ for _id, sequence_key in enumerate(self.sequence_input_key):
141
+ assert sequence_key in cond_dict.keys(), (
142
+ "Invalid sequence key %s" % sequence_key
143
+ )
144
+ cond_embed = cond_dict[sequence_key]
145
+ if isinstance(cond_embed, list):
146
+ assert (
147
+ len(cond_embed) == 2
148
+ ), "The crossattn returned list should have length 2, including embed and attn_mask"
149
+ item_input_embeds, item_attn_mask = cond_embed
150
+
151
+ item_input_embeds = self.input_sequence_embed_linear[_id](
152
+ item_input_embeds
153
+ )
154
+
155
+ item_input_embeds, item_attn_mask = self.add_sos_eos_tokens(
156
+ _id, item_input_embeds, item_attn_mask
157
+ )
158
+
159
+ if input_embeds is None and input_embeds_attn_mask is None:
160
+ input_embeds, input_embeds_attn_mask = (
161
+ item_input_embeds,
162
+ item_attn_mask,
163
+ )
164
+ else:
165
+ input_embeds = torch.cat(
166
+ [input_embeds, item_input_embeds], dim=1
167
+ ) # The 1-st dimension is time steps
168
+ input_embeds_attn_mask = torch.cat(
169
+ [input_embeds_attn_mask, item_attn_mask], dim=1
170
+ ) # The 1-st dimension is time steps
171
+ else:
172
+ assert isinstance(cond_embed, torch.Tensor)
173
+ cond_embed = self.input_sequence_embed_linear[_id](cond_embed)
174
+ attn_mask = torch.ones((cond_embed.size(0), cond_embed.size(1))).to(
175
+ cond_embed.device
176
+ )
177
+
178
+ item_input_embeds, item_attn_mask = self.add_sos_eos_tokens(
179
+ _id, cond_embed, attn_mask
180
+ )
181
+
182
+ if input_embeds is None and input_embeds_attn_mask is None:
183
+ input_embeds, input_embeds_attn_mask = (
184
+ item_input_embeds,
185
+ item_attn_mask,
186
+ )
187
+ else:
188
+ input_embeds, input_embeds_attn_mask = torch.cat(
189
+ [input_embeds, item_input_embeds], dim=1
190
+ ), torch.cat([input_embeds_attn_mask, item_attn_mask], dim=1)
191
+
192
+ assert input_embeds is not None and input_embeds_attn_mask is not None
193
+
194
+ input_embeds, input_embeds_attn_mask = self.truncate_sequence_and_mask(
195
+ input_embeds, input_embeds_attn_mask, int(1024 - self.mae_token_num)
196
+ )
197
+ cond_sequence_end_time_idx = input_embeds.size(
198
+ 1
199
+ ) # The index that we start to collect the output embeds
200
+
201
+ return input_embeds, input_embeds_attn_mask, cond_sequence_end_time_idx
202
+
203
+ def warmup_step(self):
204
+ if self.initial_learning_rate is None:
205
+ self.initial_learning_rate = float(self.learning_rate)
206
+
207
+ # Only the first parameter group
208
+ if self.global_step <= 1000:
209
+ if self.global_step == 0:
210
+ print(
211
+ "Warming up learning rate start with %s"
212
+ % self.initial_learning_rate
213
+ )
214
+ self.trainer.optimizers[0].param_groups[0]["lr"] = (
215
+ self.global_step / 1000
216
+ ) * self.initial_learning_rate
217
+ else:
218
+ # TODO set learning rate here
219
+ self.trainer.optimizers[0].param_groups[0][
220
+ "lr"
221
+ ] = self.initial_learning_rate
222
+
223
+ def mask_target_sequence(self, target_embeds, target_embeds_attn_mask):
224
+ time_seq_mask = None
225
+ if self.target_tokens_mask_ratio > 1e-4:
226
+ batchsize, time_seq_len, embed_dim = target_embeds.size()
227
+ _, time_seq_len = target_embeds_attn_mask.size()
228
+ # Generate random mask
229
+ if self.random_mask_ratio:
230
+ mask_ratio = torch.rand(1).item() * self.target_tokens_mask_ratio
231
+ else:
232
+ mask_ratio = self.target_tokens_mask_ratio
233
+
234
+ time_seq_mask = (torch.rand((batchsize, time_seq_len)) > mask_ratio).to(
235
+ target_embeds.device
236
+ )
237
+ # Mask the target embedding
238
+ target_embeds = target_embeds * time_seq_mask.unsqueeze(-1)
239
+ target_embeds_attn_mask = target_embeds_attn_mask * time_seq_mask
240
+ return target_embeds, target_embeds_attn_mask, time_seq_mask
241
+
242
+ def generate_partial(self, batch, cond_dict=None, no_grad=False):
243
+ if cond_dict is None:
244
+ cond_dict = self.get_input(batch)
245
+
246
+ print("Generate partially prompted audio with in-context learning")
247
+ # self.model.train()
248
+ # assert self.model.training==True
249
+
250
+ target_embeds, target_embeds_attn_mask = (
251
+ cond_dict["crossattn_audiomae_pooled"][0],
252
+ cond_dict["crossattn_audiomae_pooled"][1],
253
+ )
254
+
255
+ target_time_steps = target_embeds.size(1)
256
+
257
+ (
258
+ input_embeds,
259
+ input_embeds_attn_mask,
260
+ cond_sequence_end_time_idx,
261
+ ) = self.get_input_sequence_and_mask(cond_dict)
262
+
263
+ model_input = torch.cat(
264
+ [input_embeds, target_embeds[:, : target_time_steps // 4, :]], dim=1
265
+ )
266
+ model_input_mask = torch.cat(
267
+ [
268
+ input_embeds_attn_mask,
269
+ target_embeds_attn_mask[:, : target_time_steps // 4],
270
+ ],
271
+ dim=1,
272
+ )
273
+
274
+ steps = self.mae_token_num
275
+
276
+ for _ in range(3 * steps // 4):
277
+ output = self.model(
278
+ inputs_embeds=model_input, attention_mask=model_input_mask
279
+ )["last_hidden_state"]
280
+ # Update the model input
281
+ model_input = torch.cat([model_input, output[:, -1:, :]], dim=1)
282
+ # Update the attention mask
283
+ attention_mask_new_step = torch.ones((model_input_mask.size(0), 1)).to(
284
+ model_input.device
285
+ )
286
+ model_input_mask = torch.cat(
287
+ [model_input_mask, attention_mask_new_step], dim=1
288
+ )
289
+
290
+ output = model_input[:, cond_sequence_end_time_idx:]
291
+
292
+ return output, cond_dict
293
+
294
+ def generate(self, batch, cond_dict=None, no_grad=False):
295
+ if cond_dict is None:
296
+ cond_dict = self.get_input(batch)
297
+
298
+ # self.model.train()
299
+ # print("!!!!!!!!!!!!!train")
300
+
301
+ (
302
+ input_embeds,
303
+ input_embeds_attn_mask,
304
+ cond_sequence_end_time_idx,
305
+ ) = self.get_input_sequence_and_mask(cond_dict)
306
+ model_input = input_embeds
307
+ model_input_mask = input_embeds_attn_mask
308
+
309
+ steps = self.mae_token_num
310
+
311
+ for _ in range(steps):
312
+ output = self.model(
313
+ inputs_embeds=model_input, attention_mask=model_input_mask
314
+ )["last_hidden_state"]
315
+ # Update the model input
316
+ model_input = torch.cat([model_input, output[:, -1:, :]], dim=1)
317
+ # Update the attention mask
318
+ attention_mask_new_step = torch.ones((model_input_mask.size(0), 1)).to(
319
+ model_input.device
320
+ )
321
+ model_input_mask = torch.cat(
322
+ [model_input_mask, attention_mask_new_step], dim=1
323
+ )
324
+
325
+ return model_input[:, cond_sequence_end_time_idx:], cond_dict
326
+
327
+ def get_input_item(self, batch, k):
328
+ fname, text, waveform, stft, fbank = (
329
+ batch["fname"],
330
+ batch["text"],
331
+ batch["waveform"],
332
+ batch["stft"],
333
+ batch["log_mel_spec"],
334
+ )
335
+ ret = {}
336
+
337
+ ret["fbank"] = (
338
+ fbank.unsqueeze(1).to(memory_format=torch.contiguous_format).float()
339
+ )
340
+ ret["stft"] = stft.to(memory_format=torch.contiguous_format).float()
341
+ # ret["clip_label"] = clip_label.to(memory_format=torch.contiguous_format).float()
342
+ ret["waveform"] = waveform.to(memory_format=torch.contiguous_format).float()
343
+ ret["text"] = list(text)
344
+ ret["fname"] = fname
345
+
346
+ for key in batch.keys():
347
+ if key not in ret.keys():
348
+ ret[key] = batch[key]
349
+
350
+ return ret[k]
351
+
352
+ def get_input(self, batch):
353
+ cond_dict = {}
354
+ if len(self.cond_stage_model_metadata.keys()) > 0:
355
+ unconditional_cfg = False
356
+
357
+ for cond_model_key in self.cond_stage_model_metadata.keys():
358
+ cond_stage_key = self.cond_stage_model_metadata[cond_model_key][
359
+ "cond_stage_key"
360
+ ]
361
+
362
+ # if(not self.training):
363
+ # if(isinstance(self.cond_stage_models[self.cond_stage_model_metadata[cond_model_key]["model_idx"]], CLAPAudioEmbeddingClassifierFreev2)):
364
+ # assert cond_stage_key == "text" # CLAP model should use text for evaluation
365
+
366
+ # The original data for conditioning
367
+ xc = self.get_input_item(batch, cond_stage_key)
368
+ if type(xc) == torch.Tensor:
369
+ xc = xc.to(self.device)
370
+
371
+ c = self.get_learned_conditioning(
372
+ xc, key=cond_model_key, unconditional_cfg=unconditional_cfg
373
+ )
374
+ cond_dict[cond_model_key] = c
375
+
376
+ return cond_dict
377
+
378
+ def instantiate_cond_stage(self, config):
379
+ self.cond_stage_model_metadata = {}
380
+
381
+ for i, cond_model_key in enumerate(config.keys()):
382
+ model = instantiate_from_config(config[cond_model_key])
383
+ self.cond_stage_models.append(model)
384
+ self.cond_stage_model_metadata[cond_model_key] = {
385
+ "model_idx": i,
386
+ "cond_stage_key": config[cond_model_key]["cond_stage_key"],
387
+ "conditioning_key": config[cond_model_key]["conditioning_key"],
388
+ }
389
+
390
+ def get_learned_conditioning(self, c, key, unconditional_cfg):
391
+ assert key in self.cond_stage_model_metadata.keys()
392
+
393
+ # Classifier-free guidance
394
+ if not unconditional_cfg:
395
+ c = self.cond_stage_models[
396
+ self.cond_stage_model_metadata[key]["model_idx"]
397
+ ](c)
398
+ else:
399
+ if isinstance(c, torch.Tensor):
400
+ batchsize = c.size(0)
401
+ elif isinstance(c, list):
402
+ batchsize = len(c)
403
+ else:
404
+ raise NotImplementedError()
405
+ c = self.cond_stage_models[
406
+ self.cond_stage_model_metadata[key]["model_idx"]
407
+ ].get_unconditional_condition(batchsize)
408
+
409
+ return c
410
+
411
+ def initialize_param_check_toolkit(self):
412
+ self.tracked_steps = 0
413
+ self.param_dict = {}
414
+
415
+ def statistic_require_grad_tensor_number(self, module, name=None):
416
+ requires_grad_num = 0
417
+ total_num = 0
418
+ require_grad_tensor = None
419
+ for p in module.parameters():
420
+ if p.requires_grad:
421
+ requires_grad_num += 1
422
+ if require_grad_tensor is None:
423
+ require_grad_tensor = p
424
+ total_num += 1
425
+ print(
426
+ "Module: [%s] have %s trainable parameters out of %s total parameters (%.2f)"
427
+ % (name, requires_grad_num, total_num, requires_grad_num / total_num)
428
+ )
429
+ return require_grad_tensor
audioldm2/audiomae_gen/utils.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch.nn as nn
2
+
3
+
4
+ class Prenet(nn.Module):
5
+ def __init__(self, in_dim, sizes=[256, 128], dropout_rate=0.5):
6
+ super(Prenet, self).__init__()
7
+ in_sizes = [in_dim] + sizes[:-1]
8
+ self.layers = nn.ModuleList(
9
+ [
10
+ nn.Linear(in_size, out_size)
11
+ for (in_size, out_size) in zip(in_sizes, sizes)
12
+ ]
13
+ )
14
+ self.relu = nn.ReLU()
15
+ self.dropout = nn.Dropout(dropout_rate)
16
+
17
+ def forward(self, inputs):
18
+ for linear in self.layers:
19
+ inputs = self.dropout(self.relu(linear(inputs)))
20
+ return inputs
21
+
22
+
23
+ if __name__ == "__main__":
24
+ model = Prenet(in_dim=128, sizes=[256, 256, 128])
25
+ import ipdb
26
+
27
+ ipdb.set_trace()
audioldm2/clap/__init__.py ADDED
File without changes
audioldm2/clap/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (190 Bytes). View file
 
audioldm2/clap/open_clip/__init__.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .factory import (
2
+ list_models,
3
+ create_model,
4
+ create_model_and_transforms,
5
+ add_model_config,
6
+ )
7
+ from .loss import ClipLoss, gather_features, LPLoss, lp_gather_features, LPMetrics
8
+ from .model import (
9
+ CLAP,
10
+ CLAPTextCfg,
11
+ CLAPVisionCfg,
12
+ CLAPAudioCfp,
13
+ convert_weights_to_fp16,
14
+ trace_model,
15
+ )
16
+ from .openai import load_openai_model, list_openai_models
17
+ from .pretrained import (
18
+ list_pretrained,
19
+ list_pretrained_tag_models,
20
+ list_pretrained_model_tags,
21
+ get_pretrained_url,
22
+ download_pretrained,
23
+ )
24
+ from .tokenizer import SimpleTokenizer, tokenize
25
+ from .transform import image_transform
audioldm2/clap/open_clip/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (996 Bytes). View file
 
audioldm2/clap/open_clip/__pycache__/factory.cpython-310.pyc ADDED
Binary file (6.67 kB). View file
 
audioldm2/clap/open_clip/__pycache__/feature_fusion.cpython-310.pyc ADDED
Binary file (4.15 kB). View file
 
audioldm2/clap/open_clip/__pycache__/htsat.cpython-310.pyc ADDED
Binary file (30.8 kB). View file
 
audioldm2/clap/open_clip/__pycache__/loss.cpython-310.pyc ADDED
Binary file (7.95 kB). View file
 
audioldm2/clap/open_clip/__pycache__/model.cpython-310.pyc ADDED
Binary file (23.7 kB). View file
 
audioldm2/clap/open_clip/__pycache__/openai.cpython-310.pyc ADDED
Binary file (4.56 kB). View file
 
audioldm2/clap/open_clip/__pycache__/pann_model.cpython-310.pyc ADDED
Binary file (13.1 kB). View file
 
audioldm2/clap/open_clip/__pycache__/pretrained.cpython-310.pyc ADDED
Binary file (5.07 kB). View file
 
audioldm2/clap/open_clip/__pycache__/tokenizer.cpython-310.pyc ADDED
Binary file (7.39 kB). View file
 
audioldm2/clap/open_clip/__pycache__/transform.cpython-310.pyc ADDED
Binary file (1.01 kB). View file
 
audioldm2/clap/open_clip/__pycache__/utils.cpython-310.pyc ADDED
Binary file (9.75 kB). View file
 
audioldm2/clap/open_clip/bpe_simple_vocab_16e6.txt.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:924691ac288e54409236115652ad4aa250f48203de50a9e4722a6ecd48d6804a
3
+ size 1356917
audioldm2/clap/open_clip/factory.py ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import logging
3
+ import os
4
+ import re
5
+ from copy import deepcopy
6
+ from pathlib import Path
7
+
8
+ import torch
9
+
10
+ from .model import CLAP, convert_weights_to_fp16
11
+ from .openai import load_openai_model
12
+ from .pretrained import get_pretrained_url, download_pretrained
13
+ from .transform import image_transform
14
+
15
+ _MODEL_CONFIG_PATHS = [Path(__file__).parent / f"model_configs/"]
16
+ _MODEL_CONFIGS = {} # directory (model_name: config) of model architecture configs
17
+
18
+
19
+ def _natural_key(string_):
20
+ return [int(s) if s.isdigit() else s for s in re.split(r"(\d+)", string_.lower())]
21
+
22
+
23
+ def _rescan_model_configs():
24
+ global _MODEL_CONFIGS
25
+
26
+ config_ext = (".json",)
27
+ config_files = []
28
+ for config_path in _MODEL_CONFIG_PATHS:
29
+ if config_path.is_file() and config_path.suffix in config_ext:
30
+ config_files.append(config_path)
31
+ elif config_path.is_dir():
32
+ for ext in config_ext:
33
+ config_files.extend(config_path.glob(f"*{ext}"))
34
+
35
+ for cf in config_files:
36
+ if os.path.basename(cf)[0] == ".":
37
+ continue # Ignore hidden files
38
+
39
+ with open(cf, "r") as f:
40
+ model_cfg = json.load(f)
41
+ if all(a in model_cfg for a in ("embed_dim", "audio_cfg", "text_cfg")):
42
+ _MODEL_CONFIGS[cf.stem] = model_cfg
43
+
44
+ _MODEL_CONFIGS = {
45
+ k: v
46
+ for k, v in sorted(_MODEL_CONFIGS.items(), key=lambda x: _natural_key(x[0]))
47
+ }
48
+
49
+
50
+ _rescan_model_configs() # initial populate of model config registry
51
+
52
+
53
+ def load_state_dict(checkpoint_path: str, map_location="cpu", skip_params=True):
54
+ checkpoint = torch.load(checkpoint_path, map_location=map_location)
55
+ if isinstance(checkpoint, dict) and "state_dict" in checkpoint:
56
+ state_dict = checkpoint["state_dict"]
57
+ else:
58
+ state_dict = checkpoint
59
+ if skip_params:
60
+ if next(iter(state_dict.items()))[0].startswith("module"):
61
+ state_dict = {k[7:]: v for k, v in state_dict.items()}
62
+ # for k in state_dict:
63
+ # if k.startswith('transformer'):
64
+ # v = state_dict.pop(k)
65
+ # state_dict['text_branch.' + k[12:]] = v
66
+ return state_dict
67
+
68
+
69
+ def create_model(
70
+ amodel_name: str,
71
+ tmodel_name: str,
72
+ pretrained: str = "",
73
+ precision: str = "fp32",
74
+ device: torch.device = torch.device("cpu"),
75
+ jit: bool = False,
76
+ force_quick_gelu: bool = False,
77
+ openai_model_cache_dir: str = os.path.expanduser("~/.cache/clip"),
78
+ skip_params=True,
79
+ pretrained_audio: str = "",
80
+ pretrained_text: str = "",
81
+ enable_fusion: bool = False,
82
+ fusion_type: str = "None"
83
+ # pretrained_image: bool = False,
84
+ ):
85
+ amodel_name = amodel_name.replace(
86
+ "/", "-"
87
+ ) # for callers using old naming with / in ViT names
88
+ pretrained_orig = pretrained
89
+ pretrained = pretrained.lower()
90
+ if pretrained == "openai":
91
+ if amodel_name in _MODEL_CONFIGS:
92
+ logging.info(f"Loading {amodel_name} model config.")
93
+ model_cfg = deepcopy(_MODEL_CONFIGS[amodel_name])
94
+ else:
95
+ logging.error(
96
+ f"Model config for {amodel_name} not found; available models {list_models()}."
97
+ )
98
+ raise RuntimeError(f"Model config for {amodel_name} not found.")
99
+
100
+ logging.info(f"Loading pretrained ViT-B-16 text encoder from OpenAI.")
101
+ # Hard Code in model name
102
+ model_cfg["text_cfg"]["model_type"] = tmodel_name
103
+ model = load_openai_model(
104
+ "ViT-B-16",
105
+ model_cfg,
106
+ device=device,
107
+ jit=jit,
108
+ cache_dir=openai_model_cache_dir,
109
+ enable_fusion=enable_fusion,
110
+ fusion_type=fusion_type,
111
+ )
112
+ # See https://discuss.pytorch.org/t/valueerror-attemting-to-unscale-fp16-gradients/81372
113
+ if precision == "amp" or precision == "fp32":
114
+ model = model.float()
115
+ else:
116
+ if amodel_name in _MODEL_CONFIGS:
117
+ logging.info(f"Loading {amodel_name} model config.")
118
+ model_cfg = deepcopy(_MODEL_CONFIGS[amodel_name])
119
+ else:
120
+ logging.error(
121
+ f"Model config for {amodel_name} not found; available models {list_models()}."
122
+ )
123
+ raise RuntimeError(f"Model config for {amodel_name} not found.")
124
+
125
+ if force_quick_gelu:
126
+ # override for use of QuickGELU on non-OpenAI transformer models
127
+ model_cfg["quick_gelu"] = True
128
+
129
+ # if pretrained_image:
130
+ # if 'timm_amodel_name' in model_cfg.get('vision_cfg', {}):
131
+ # # pretrained weight loading for timm models set via vision_cfg
132
+ # model_cfg['vision_cfg']['timm_model_pretrained'] = True
133
+ # else:
134
+ # assert False, 'pretrained image towers currently only supported for timm models'
135
+ model_cfg["text_cfg"]["model_type"] = tmodel_name
136
+ model_cfg["enable_fusion"] = enable_fusion
137
+ model_cfg["fusion_type"] = fusion_type
138
+ model = CLAP(**model_cfg)
139
+
140
+ if pretrained:
141
+ checkpoint_path = ""
142
+ url = get_pretrained_url(amodel_name, pretrained)
143
+ if url:
144
+ checkpoint_path = download_pretrained(url, root=openai_model_cache_dir)
145
+ elif os.path.exists(pretrained_orig):
146
+ checkpoint_path = pretrained_orig
147
+ if checkpoint_path:
148
+ logging.info(
149
+ f"Loading pretrained {amodel_name}-{tmodel_name} weights ({pretrained})."
150
+ )
151
+ ckpt = load_state_dict(checkpoint_path, skip_params=True)
152
+ model.load_state_dict(ckpt)
153
+ param_names = [n for n, p in model.named_parameters()]
154
+ # for n in param_names:
155
+ # print(n, "\t", "Loaded" if n in ckpt else "Unloaded")
156
+ else:
157
+ logging.warning(
158
+ f"Pretrained weights ({pretrained}) not found for model {amodel_name}."
159
+ )
160
+ raise RuntimeError(
161
+ f"Pretrained weights ({pretrained}) not found for model {amodel_name}."
162
+ )
163
+
164
+ if pretrained_audio:
165
+ if amodel_name.startswith("PANN"):
166
+ if "Cnn14_mAP" in pretrained_audio: # official checkpoint
167
+ audio_ckpt = torch.load(pretrained_audio, map_location="cpu")
168
+ audio_ckpt = audio_ckpt["model"]
169
+ keys = list(audio_ckpt.keys())
170
+ for key in keys:
171
+ if (
172
+ "spectrogram_extractor" not in key
173
+ and "logmel_extractor" not in key
174
+ ):
175
+ v = audio_ckpt.pop(key)
176
+ audio_ckpt["audio_branch." + key] = v
177
+ elif os.path.basename(pretrained_audio).startswith(
178
+ "PANN"
179
+ ): # checkpoint trained via HTSAT codebase
180
+ audio_ckpt = torch.load(pretrained_audio, map_location="cpu")
181
+ audio_ckpt = audio_ckpt["state_dict"]
182
+ keys = list(audio_ckpt.keys())
183
+ for key in keys:
184
+ if key.startswith("sed_model"):
185
+ v = audio_ckpt.pop(key)
186
+ audio_ckpt["audio_branch." + key[10:]] = v
187
+ elif os.path.basename(pretrained_audio).startswith(
188
+ "finetuned"
189
+ ): # checkpoint trained via linear probe codebase
190
+ audio_ckpt = torch.load(pretrained_audio, map_location="cpu")
191
+ else:
192
+ raise ValueError("Unknown audio checkpoint")
193
+ elif amodel_name.startswith("HTSAT"):
194
+ if "HTSAT_AudioSet_Saved" in pretrained_audio: # official checkpoint
195
+ audio_ckpt = torch.load(pretrained_audio, map_location="cpu")
196
+ audio_ckpt = audio_ckpt["state_dict"]
197
+ keys = list(audio_ckpt.keys())
198
+ for key in keys:
199
+ if key.startswith("sed_model") and (
200
+ "spectrogram_extractor" not in key
201
+ and "logmel_extractor" not in key
202
+ ):
203
+ v = audio_ckpt.pop(key)
204
+ audio_ckpt["audio_branch." + key[10:]] = v
205
+ elif os.path.basename(pretrained_audio).startswith(
206
+ "HTSAT"
207
+ ): # checkpoint trained via HTSAT codebase
208
+ audio_ckpt = torch.load(pretrained_audio, map_location="cpu")
209
+ audio_ckpt = audio_ckpt["state_dict"]
210
+ keys = list(audio_ckpt.keys())
211
+ for key in keys:
212
+ if key.startswith("sed_model"):
213
+ v = audio_ckpt.pop(key)
214
+ audio_ckpt["audio_branch." + key[10:]] = v
215
+ elif os.path.basename(pretrained_audio).startswith(
216
+ "finetuned"
217
+ ): # checkpoint trained via linear probe codebase
218
+ audio_ckpt = torch.load(pretrained_audio, map_location="cpu")
219
+ else:
220
+ raise ValueError("Unknown audio checkpoint")
221
+ else:
222
+ raise f"this audio encoder pretrained checkpoint is not support"
223
+
224
+ model.load_state_dict(audio_ckpt, strict=False)
225
+ logging.info(
226
+ f"Loading pretrained {amodel_name} weights ({pretrained_audio})."
227
+ )
228
+ param_names = [n for n, p in model.named_parameters()]
229
+ for n in param_names:
230
+ print(n, "\t", "Loaded" if n in audio_ckpt else "Unloaded")
231
+
232
+ model.to(device=device)
233
+ if precision == "fp16":
234
+ assert device.type != "cpu"
235
+ convert_weights_to_fp16(model)
236
+
237
+ if jit:
238
+ model = torch.jit.script(model)
239
+
240
+ return model, model_cfg
241
+
242
+
243
+ def create_model_and_transforms(
244
+ model_name: str,
245
+ pretrained: str = "",
246
+ precision: str = "fp32",
247
+ device: torch.device = torch.device("cpu"),
248
+ jit: bool = False,
249
+ force_quick_gelu: bool = False,
250
+ # pretrained_image: bool = False,
251
+ ):
252
+ model = create_model(
253
+ model_name,
254
+ pretrained,
255
+ precision,
256
+ device,
257
+ jit,
258
+ force_quick_gelu=force_quick_gelu,
259
+ # pretrained_image=pretrained_image
260
+ )
261
+ preprocess_train = image_transform(model.visual.image_size, is_train=True)
262
+ preprocess_val = image_transform(model.visual.image_size, is_train=False)
263
+ return model, preprocess_train, preprocess_val
264
+
265
+
266
+ def list_models():
267
+ """enumerate available model architectures based on config files"""
268
+ return list(_MODEL_CONFIGS.keys())
269
+
270
+
271
+ def add_model_config(path):
272
+ """add model config path or file and update registry"""
273
+ if not isinstance(path, Path):
274
+ path = Path(path)
275
+ _MODEL_CONFIG_PATHS.append(path)
276
+ _rescan_model_configs()
audioldm2/clap/open_clip/feature_fusion.py ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Feature Fusion for Varible-Length Data Processing
3
+ AFF/iAFF is referred and modified from https://github.com/YimianDai/open-aff/blob/master/aff_pytorch/aff_net/fusion.py
4
+ According to the paper: Yimian Dai et al, Attentional Feature Fusion, IEEE Winter Conference on Applications of Computer Vision, WACV 2021
5
+ """
6
+
7
+ import torch
8
+ import torch.nn as nn
9
+
10
+
11
+ class DAF(nn.Module):
12
+ """
13
+ 直接相加 DirectAddFuse
14
+ """
15
+
16
+ def __init__(self):
17
+ super(DAF, self).__init__()
18
+
19
+ def forward(self, x, residual):
20
+ return x + residual
21
+
22
+
23
+ class iAFF(nn.Module):
24
+ """
25
+ 多特征融合 iAFF
26
+ """
27
+
28
+ def __init__(self, channels=64, r=4, type="2D"):
29
+ super(iAFF, self).__init__()
30
+ inter_channels = int(channels // r)
31
+
32
+ if type == "1D":
33
+ # 本地注意力
34
+ self.local_att = nn.Sequential(
35
+ nn.Conv1d(channels, inter_channels, kernel_size=1, stride=1, padding=0),
36
+ nn.BatchNorm1d(inter_channels),
37
+ nn.ReLU(inplace=True),
38
+ nn.Conv1d(inter_channels, channels, kernel_size=1, stride=1, padding=0),
39
+ nn.BatchNorm1d(channels),
40
+ )
41
+
42
+ # 全局注意力
43
+ self.global_att = nn.Sequential(
44
+ nn.AdaptiveAvgPool1d(1),
45
+ nn.Conv1d(channels, inter_channels, kernel_size=1, stride=1, padding=0),
46
+ nn.BatchNorm1d(inter_channels),
47
+ nn.ReLU(inplace=True),
48
+ nn.Conv1d(inter_channels, channels, kernel_size=1, stride=1, padding=0),
49
+ nn.BatchNorm1d(channels),
50
+ )
51
+
52
+ # 第二次本地注意力
53
+ self.local_att2 = nn.Sequential(
54
+ nn.Conv1d(channels, inter_channels, kernel_size=1, stride=1, padding=0),
55
+ nn.BatchNorm1d(inter_channels),
56
+ nn.ReLU(inplace=True),
57
+ nn.Conv1d(inter_channels, channels, kernel_size=1, stride=1, padding=0),
58
+ nn.BatchNorm1d(channels),
59
+ )
60
+ # 第二次全局注意力
61
+ self.global_att2 = nn.Sequential(
62
+ nn.AdaptiveAvgPool1d(1),
63
+ nn.Conv1d(channels, inter_channels, kernel_size=1, stride=1, padding=0),
64
+ nn.BatchNorm1d(inter_channels),
65
+ nn.ReLU(inplace=True),
66
+ nn.Conv1d(inter_channels, channels, kernel_size=1, stride=1, padding=0),
67
+ nn.BatchNorm1d(channels),
68
+ )
69
+ elif type == "2D":
70
+ # 本地注意力
71
+ self.local_att = nn.Sequential(
72
+ nn.Conv2d(channels, inter_channels, kernel_size=1, stride=1, padding=0),
73
+ nn.BatchNorm2d(inter_channels),
74
+ nn.ReLU(inplace=True),
75
+ nn.Conv2d(inter_channels, channels, kernel_size=1, stride=1, padding=0),
76
+ nn.BatchNorm2d(channels),
77
+ )
78
+
79
+ # 全局注意力
80
+ self.global_att = nn.Sequential(
81
+ nn.AdaptiveAvgPool2d(1),
82
+ nn.Conv2d(channels, inter_channels, kernel_size=1, stride=1, padding=0),
83
+ nn.BatchNorm2d(inter_channels),
84
+ nn.ReLU(inplace=True),
85
+ nn.Conv2d(inter_channels, channels, kernel_size=1, stride=1, padding=0),
86
+ nn.BatchNorm2d(channels),
87
+ )
88
+
89
+ # 第二次本地注意力
90
+ self.local_att2 = nn.Sequential(
91
+ nn.Conv2d(channels, inter_channels, kernel_size=1, stride=1, padding=0),
92
+ nn.BatchNorm2d(inter_channels),
93
+ nn.ReLU(inplace=True),
94
+ nn.Conv2d(inter_channels, channels, kernel_size=1, stride=1, padding=0),
95
+ nn.BatchNorm2d(channels),
96
+ )
97
+ # 第二次全局注意力
98
+ self.global_att2 = nn.Sequential(
99
+ nn.AdaptiveAvgPool2d(1),
100
+ nn.Conv2d(channels, inter_channels, kernel_size=1, stride=1, padding=0),
101
+ nn.BatchNorm2d(inter_channels),
102
+ nn.ReLU(inplace=True),
103
+ nn.Conv2d(inter_channels, channels, kernel_size=1, stride=1, padding=0),
104
+ nn.BatchNorm2d(channels),
105
+ )
106
+ else:
107
+ raise f"the type is not supported"
108
+
109
+ self.sigmoid = nn.Sigmoid()
110
+
111
+ def forward(self, x, residual):
112
+ flag = False
113
+ xa = x + residual
114
+ if xa.size(0) == 1:
115
+ xa = torch.cat([xa, xa], dim=0)
116
+ flag = True
117
+ xl = self.local_att(xa)
118
+ xg = self.global_att(xa)
119
+ xlg = xl + xg
120
+ wei = self.sigmoid(xlg)
121
+ xi = x * wei + residual * (1 - wei)
122
+
123
+ xl2 = self.local_att2(xi)
124
+ xg2 = self.global_att(xi)
125
+ xlg2 = xl2 + xg2
126
+ wei2 = self.sigmoid(xlg2)
127
+ xo = x * wei2 + residual * (1 - wei2)
128
+ if flag:
129
+ xo = xo[0].unsqueeze(0)
130
+ return xo
131
+
132
+
133
+ class AFF(nn.Module):
134
+ """
135
+ 多特征融合 AFF
136
+ """
137
+
138
+ def __init__(self, channels=64, r=4, type="2D"):
139
+ super(AFF, self).__init__()
140
+ inter_channels = int(channels // r)
141
+
142
+ if type == "1D":
143
+ self.local_att = nn.Sequential(
144
+ nn.Conv1d(channels, inter_channels, kernel_size=1, stride=1, padding=0),
145
+ nn.BatchNorm1d(inter_channels),
146
+ nn.ReLU(inplace=True),
147
+ nn.Conv1d(inter_channels, channels, kernel_size=1, stride=1, padding=0),
148
+ nn.BatchNorm1d(channels),
149
+ )
150
+ self.global_att = nn.Sequential(
151
+ nn.AdaptiveAvgPool1d(1),
152
+ nn.Conv1d(channels, inter_channels, kernel_size=1, stride=1, padding=0),
153
+ nn.BatchNorm1d(inter_channels),
154
+ nn.ReLU(inplace=True),
155
+ nn.Conv1d(inter_channels, channels, kernel_size=1, stride=1, padding=0),
156
+ nn.BatchNorm1d(channels),
157
+ )
158
+ elif type == "2D":
159
+ self.local_att = nn.Sequential(
160
+ nn.Conv2d(channels, inter_channels, kernel_size=1, stride=1, padding=0),
161
+ nn.BatchNorm2d(inter_channels),
162
+ nn.ReLU(inplace=True),
163
+ nn.Conv2d(inter_channels, channels, kernel_size=1, stride=1, padding=0),
164
+ nn.BatchNorm2d(channels),
165
+ )
166
+ self.global_att = nn.Sequential(
167
+ nn.AdaptiveAvgPool2d(1),
168
+ nn.Conv2d(channels, inter_channels, kernel_size=1, stride=1, padding=0),
169
+ nn.BatchNorm2d(inter_channels),
170
+ nn.ReLU(inplace=True),
171
+ nn.Conv2d(inter_channels, channels, kernel_size=1, stride=1, padding=0),
172
+ nn.BatchNorm2d(channels),
173
+ )
174
+ else:
175
+ raise f"the type is not supported."
176
+
177
+ self.sigmoid = nn.Sigmoid()
178
+
179
+ def forward(self, x, residual):
180
+ flag = False
181
+ xa = x + residual
182
+ if xa.size(0) == 1:
183
+ xa = torch.cat([xa, xa], dim=0)
184
+ flag = True
185
+ xl = self.local_att(xa)
186
+ xg = self.global_att(xa)
187
+ xlg = xl + xg
188
+ wei = self.sigmoid(xlg)
189
+ xo = 2 * x * wei + 2 * residual * (1 - wei)
190
+ if flag:
191
+ xo = xo[0].unsqueeze(0)
192
+ return xo
audioldm2/clap/open_clip/htsat.py ADDED
@@ -0,0 +1,1304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ke Chen
2
3
+ # HTS-AT: A HIERARCHICAL TOKEN-SEMANTIC AUDIO TRANSFORMER FOR SOUND CLASSIFICATION AND DETECTION
4
+ # Some layers designed on the model
5
+ # below codes are based and referred from https://github.com/microsoft/Swin-Transformer
6
+ # Swin Transformer for Computer Vision: https://arxiv.org/pdf/2103.14030.pdf
7
+
8
+ import torch
9
+ import torch.nn as nn
10
+ from itertools import repeat
11
+ import collections.abc
12
+ import math
13
+ import warnings
14
+
15
+ from torch.nn.init import _calculate_fan_in_and_fan_out
16
+ import torch.utils.checkpoint as checkpoint
17
+
18
+ import random
19
+
20
+ from torchlibrosa.stft import Spectrogram, LogmelFilterBank
21
+ from torchlibrosa.augmentation import SpecAugmentation
22
+
23
+ from itertools import repeat
24
+ from .utils import do_mixup, interpolate
25
+
26
+ from .feature_fusion import iAFF, AFF, DAF
27
+
28
+
29
+ # from PyTorch internals
30
+ def _ntuple(n):
31
+ def parse(x):
32
+ if isinstance(x, collections.abc.Iterable):
33
+ return x
34
+ return tuple(repeat(x, n))
35
+
36
+ return parse
37
+
38
+
39
+ to_1tuple = _ntuple(1)
40
+ to_2tuple = _ntuple(2)
41
+ to_3tuple = _ntuple(3)
42
+ to_4tuple = _ntuple(4)
43
+ to_ntuple = _ntuple
44
+
45
+
46
+ def drop_path(x, drop_prob: float = 0.0, training: bool = False):
47
+ """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks).
48
+ This is the same as the DropConnect impl I created for EfficientNet, etc networks, however,
49
+ the original name is misleading as 'Drop Connect' is a different form of dropout in a separate paper...
50
+ See discussion: https://github.com/tensorflow/tpu/issues/494#issuecomment-532968956 ... I've opted for
51
+ changing the layer and argument names to 'drop path' rather than mix DropConnect as a layer name and use
52
+ 'survival rate' as the argument.
53
+ """
54
+ if drop_prob == 0.0 or not training:
55
+ return x
56
+ keep_prob = 1 - drop_prob
57
+ shape = (x.shape[0],) + (1,) * (
58
+ x.ndim - 1
59
+ ) # work with diff dim tensors, not just 2D ConvNets
60
+ random_tensor = keep_prob + torch.rand(shape, dtype=x.dtype, device=x.device)
61
+ random_tensor.floor_() # binarize
62
+ output = x.div(keep_prob) * random_tensor
63
+ return output
64
+
65
+
66
+ class DropPath(nn.Module):
67
+ """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks)."""
68
+
69
+ def __init__(self, drop_prob=None):
70
+ super(DropPath, self).__init__()
71
+ self.drop_prob = drop_prob
72
+
73
+ def forward(self, x):
74
+ return drop_path(x, self.drop_prob, self.training)
75
+
76
+
77
+ class PatchEmbed(nn.Module):
78
+ """2D Image to Patch Embedding"""
79
+
80
+ def __init__(
81
+ self,
82
+ img_size=224,
83
+ patch_size=16,
84
+ in_chans=3,
85
+ embed_dim=768,
86
+ norm_layer=None,
87
+ flatten=True,
88
+ patch_stride=16,
89
+ enable_fusion=False,
90
+ fusion_type="None",
91
+ ):
92
+ super().__init__()
93
+ img_size = to_2tuple(img_size)
94
+ patch_size = to_2tuple(patch_size)
95
+ patch_stride = to_2tuple(patch_stride)
96
+ self.img_size = img_size
97
+ self.patch_size = patch_size
98
+ self.patch_stride = patch_stride
99
+ self.grid_size = (
100
+ img_size[0] // patch_stride[0],
101
+ img_size[1] // patch_stride[1],
102
+ )
103
+ self.num_patches = self.grid_size[0] * self.grid_size[1]
104
+ self.flatten = flatten
105
+ self.in_chans = in_chans
106
+ self.embed_dim = embed_dim
107
+
108
+ self.enable_fusion = enable_fusion
109
+ self.fusion_type = fusion_type
110
+
111
+ padding = (
112
+ (patch_size[0] - patch_stride[0]) // 2,
113
+ (patch_size[1] - patch_stride[1]) // 2,
114
+ )
115
+
116
+ if (self.enable_fusion) and (self.fusion_type == "channel_map"):
117
+ self.proj = nn.Conv2d(
118
+ in_chans * 4,
119
+ embed_dim,
120
+ kernel_size=patch_size,
121
+ stride=patch_stride,
122
+ padding=padding,
123
+ )
124
+ else:
125
+ self.proj = nn.Conv2d(
126
+ in_chans,
127
+ embed_dim,
128
+ kernel_size=patch_size,
129
+ stride=patch_stride,
130
+ padding=padding,
131
+ )
132
+ self.norm = norm_layer(embed_dim) if norm_layer else nn.Identity()
133
+
134
+ if (self.enable_fusion) and (
135
+ self.fusion_type in ["daf_2d", "aff_2d", "iaff_2d"]
136
+ ):
137
+ self.mel_conv2d = nn.Conv2d(
138
+ in_chans,
139
+ embed_dim,
140
+ kernel_size=(patch_size[0], patch_size[1] * 3),
141
+ stride=(patch_stride[0], patch_stride[1] * 3),
142
+ padding=padding,
143
+ )
144
+ if self.fusion_type == "daf_2d":
145
+ self.fusion_model = DAF()
146
+ elif self.fusion_type == "aff_2d":
147
+ self.fusion_model = AFF(channels=embed_dim, type="2D")
148
+ elif self.fusion_type == "iaff_2d":
149
+ self.fusion_model = iAFF(channels=embed_dim, type="2D")
150
+
151
+ def forward(self, x, longer_idx=None):
152
+ if (self.enable_fusion) and (
153
+ self.fusion_type in ["daf_2d", "aff_2d", "iaff_2d"]
154
+ ):
155
+ global_x = x[:, 0:1, :, :]
156
+
157
+ # global processing
158
+ B, C, H, W = global_x.shape
159
+ assert (
160
+ H == self.img_size[0] and W == self.img_size[1]
161
+ ), f"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]})."
162
+ global_x = self.proj(global_x)
163
+ TW = global_x.size(-1)
164
+ if len(longer_idx) > 0:
165
+ # local processing
166
+ local_x = x[longer_idx, 1:, :, :].contiguous()
167
+ B, C, H, W = local_x.shape
168
+ local_x = local_x.view(B * C, 1, H, W)
169
+ local_x = self.mel_conv2d(local_x)
170
+ local_x = local_x.view(
171
+ B, C, local_x.size(1), local_x.size(2), local_x.size(3)
172
+ )
173
+ local_x = local_x.permute((0, 2, 3, 1, 4)).contiguous().flatten(3)
174
+ TB, TC, TH, _ = local_x.size()
175
+ if local_x.size(-1) < TW:
176
+ local_x = torch.cat(
177
+ [
178
+ local_x,
179
+ torch.zeros(
180
+ (TB, TC, TH, TW - local_x.size(-1)),
181
+ device=global_x.device,
182
+ ),
183
+ ],
184
+ dim=-1,
185
+ )
186
+ else:
187
+ local_x = local_x[:, :, :, :TW]
188
+
189
+ global_x[longer_idx] = self.fusion_model(global_x[longer_idx], local_x)
190
+ x = global_x
191
+ else:
192
+ B, C, H, W = x.shape
193
+ assert (
194
+ H == self.img_size[0] and W == self.img_size[1]
195
+ ), f"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]})."
196
+ x = self.proj(x)
197
+
198
+ if self.flatten:
199
+ x = x.flatten(2).transpose(1, 2) # BCHW -> BNC
200
+ x = self.norm(x)
201
+ return x
202
+
203
+
204
+ class Mlp(nn.Module):
205
+ """MLP as used in Vision Transformer, MLP-Mixer and related networks"""
206
+
207
+ def __init__(
208
+ self,
209
+ in_features,
210
+ hidden_features=None,
211
+ out_features=None,
212
+ act_layer=nn.GELU,
213
+ drop=0.0,
214
+ ):
215
+ super().__init__()
216
+ out_features = out_features or in_features
217
+ hidden_features = hidden_features or in_features
218
+ self.fc1 = nn.Linear(in_features, hidden_features)
219
+ self.act = act_layer()
220
+ self.fc2 = nn.Linear(hidden_features, out_features)
221
+ self.drop = nn.Dropout(drop)
222
+
223
+ def forward(self, x):
224
+ x = self.fc1(x)
225
+ x = self.act(x)
226
+ x = self.drop(x)
227
+ x = self.fc2(x)
228
+ x = self.drop(x)
229
+ return x
230
+
231
+
232
+ def _no_grad_trunc_normal_(tensor, mean, std, a, b):
233
+ # Cut & paste from PyTorch official master until it's in a few official releases - RW
234
+ # Method based on https://people.sc.fsu.edu/~jburkardt/presentations/truncated_normal.pdf
235
+ def norm_cdf(x):
236
+ # Computes standard normal cumulative distribution function
237
+ return (1.0 + math.erf(x / math.sqrt(2.0))) / 2.0
238
+
239
+ if (mean < a - 2 * std) or (mean > b + 2 * std):
240
+ warnings.warn(
241
+ "mean is more than 2 std from [a, b] in nn.init.trunc_normal_. "
242
+ "The distribution of values may be incorrect.",
243
+ stacklevel=2,
244
+ )
245
+
246
+ with torch.no_grad():
247
+ # Values are generated by using a truncated uniform distribution and
248
+ # then using the inverse CDF for the normal distribution.
249
+ # Get upper and lower cdf values
250
+ l = norm_cdf((a - mean) / std)
251
+ u = norm_cdf((b - mean) / std)
252
+
253
+ # Uniformly fill tensor with values from [l, u], then translate to
254
+ # [2l-1, 2u-1].
255
+ tensor.uniform_(2 * l - 1, 2 * u - 1)
256
+
257
+ # Use inverse cdf transform for normal distribution to get truncated
258
+ # standard normal
259
+ tensor.erfinv_()
260
+
261
+ # Transform to proper mean, std
262
+ tensor.mul_(std * math.sqrt(2.0))
263
+ tensor.add_(mean)
264
+
265
+ # Clamp to ensure it's in the proper range
266
+ tensor.clamp_(min=a, max=b)
267
+ return tensor
268
+
269
+
270
+ def trunc_normal_(tensor, mean=0.0, std=1.0, a=-2.0, b=2.0):
271
+ # type: (Tensor, float, float, float, float) -> Tensor
272
+ r"""Fills the input Tensor with values drawn from a truncated
273
+ normal distribution. The values are effectively drawn from the
274
+ normal distribution :math:`\mathcal{N}(\text{mean}, \text{std}^2)`
275
+ with values outside :math:`[a, b]` redrawn until they are within
276
+ the bounds. The method used for generating the random values works
277
+ best when :math:`a \leq \text{mean} \leq b`.
278
+ Args:
279
+ tensor: an n-dimensional `torch.Tensor`
280
+ mean: the mean of the normal distribution
281
+ std: the standard deviation of the normal distribution
282
+ a: the minimum cutoff value
283
+ b: the maximum cutoff value
284
+ Examples:
285
+ >>> w = torch.empty(3, 5)
286
+ >>> nn.init.trunc_normal_(w)
287
+ """
288
+ return _no_grad_trunc_normal_(tensor, mean, std, a, b)
289
+
290
+
291
+ def variance_scaling_(tensor, scale=1.0, mode="fan_in", distribution="normal"):
292
+ fan_in, fan_out = _calculate_fan_in_and_fan_out(tensor)
293
+ if mode == "fan_in":
294
+ denom = fan_in
295
+ elif mode == "fan_out":
296
+ denom = fan_out
297
+ elif mode == "fan_avg":
298
+ denom = (fan_in + fan_out) / 2
299
+
300
+ variance = scale / denom
301
+
302
+ if distribution == "truncated_normal":
303
+ # constant is stddev of standard normal truncated to (-2, 2)
304
+ trunc_normal_(tensor, std=math.sqrt(variance) / 0.87962566103423978)
305
+ elif distribution == "normal":
306
+ tensor.normal_(std=math.sqrt(variance))
307
+ elif distribution == "uniform":
308
+ bound = math.sqrt(3 * variance)
309
+ tensor.uniform_(-bound, bound)
310
+ else:
311
+ raise ValueError(f"invalid distribution {distribution}")
312
+
313
+
314
+ def lecun_normal_(tensor):
315
+ variance_scaling_(tensor, mode="fan_in", distribution="truncated_normal")
316
+
317
+
318
+ def window_partition(x, window_size):
319
+ """
320
+ Args:
321
+ x: (B, H, W, C)
322
+ window_size (int): window size
323
+ Returns:
324
+ windows: (num_windows*B, window_size, window_size, C)
325
+ """
326
+ B, H, W, C = x.shape
327
+ x = x.view(B, H // window_size, window_size, W // window_size, window_size, C)
328
+ windows = (
329
+ x.permute(0, 1, 3, 2, 4, 5).contiguous().view(-1, window_size, window_size, C)
330
+ )
331
+ return windows
332
+
333
+
334
+ def window_reverse(windows, window_size, H, W):
335
+ """
336
+ Args:
337
+ windows: (num_windows*B, window_size, window_size, C)
338
+ window_size (int): Window size
339
+ H (int): Height of image
340
+ W (int): Width of image
341
+ Returns:
342
+ x: (B, H, W, C)
343
+ """
344
+ B = int(windows.shape[0] / (H * W / window_size / window_size))
345
+ x = windows.view(
346
+ B, H // window_size, W // window_size, window_size, window_size, -1
347
+ )
348
+ x = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(B, H, W, -1)
349
+ return x
350
+
351
+
352
+ class WindowAttention(nn.Module):
353
+ r"""Window based multi-head self attention (W-MSA) module with relative position bias.
354
+ It supports both of shifted and non-shifted window.
355
+ Args:
356
+ dim (int): Number of input channels.
357
+ window_size (tuple[int]): The height and width of the window.
358
+ num_heads (int): Number of attention heads.
359
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
360
+ qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set
361
+ attn_drop (float, optional): Dropout ratio of attention weight. Default: 0.0
362
+ proj_drop (float, optional): Dropout ratio of output. Default: 0.0
363
+ """
364
+
365
+ def __init__(
366
+ self,
367
+ dim,
368
+ window_size,
369
+ num_heads,
370
+ qkv_bias=True,
371
+ qk_scale=None,
372
+ attn_drop=0.0,
373
+ proj_drop=0.0,
374
+ ):
375
+ super().__init__()
376
+ self.dim = dim
377
+ self.window_size = window_size # Wh, Ww
378
+ self.num_heads = num_heads
379
+ head_dim = dim // num_heads
380
+ self.scale = qk_scale or head_dim**-0.5
381
+
382
+ # define a parameter table of relative position bias
383
+ self.relative_position_bias_table = nn.Parameter(
384
+ torch.zeros((2 * window_size[0] - 1) * (2 * window_size[1] - 1), num_heads)
385
+ ) # 2*Wh-1 * 2*Ww-1, nH
386
+
387
+ # get pair-wise relative position index for each token inside the window
388
+ coords_h = torch.arange(self.window_size[0])
389
+ coords_w = torch.arange(self.window_size[1])
390
+ coords = torch.stack(torch.meshgrid([coords_h, coords_w])) # 2, Wh, Ww
391
+ coords_flatten = torch.flatten(coords, 1) # 2, Wh*Ww
392
+ relative_coords = (
393
+ coords_flatten[:, :, None] - coords_flatten[:, None, :]
394
+ ) # 2, Wh*Ww, Wh*Ww
395
+ relative_coords = relative_coords.permute(
396
+ 1, 2, 0
397
+ ).contiguous() # Wh*Ww, Wh*Ww, 2
398
+ relative_coords[:, :, 0] += self.window_size[0] - 1 # shift to start from 0
399
+ relative_coords[:, :, 1] += self.window_size[1] - 1
400
+ relative_coords[:, :, 0] *= 2 * self.window_size[1] - 1
401
+ relative_position_index = relative_coords.sum(-1) # Wh*Ww, Wh*Ww
402
+ self.register_buffer("relative_position_index", relative_position_index)
403
+
404
+ self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
405
+ self.attn_drop = nn.Dropout(attn_drop)
406
+ self.proj = nn.Linear(dim, dim)
407
+ self.proj_drop = nn.Dropout(proj_drop)
408
+
409
+ trunc_normal_(self.relative_position_bias_table, std=0.02)
410
+ self.softmax = nn.Softmax(dim=-1)
411
+
412
+ def forward(self, x, mask=None):
413
+ """
414
+ Args:
415
+ x: input features with shape of (num_windows*B, N, C)
416
+ mask: (0/-inf) mask with shape of (num_windows, Wh*Ww, Wh*Ww) or None
417
+ """
418
+ B_, N, C = x.shape
419
+ qkv = (
420
+ self.qkv(x)
421
+ .reshape(B_, N, 3, self.num_heads, C // self.num_heads)
422
+ .permute(2, 0, 3, 1, 4)
423
+ )
424
+ q, k, v = (
425
+ qkv[0],
426
+ qkv[1],
427
+ qkv[2],
428
+ ) # make torchscript happy (cannot use tensor as tuple)
429
+
430
+ q = q * self.scale
431
+ attn = q @ k.transpose(-2, -1)
432
+
433
+ relative_position_bias = self.relative_position_bias_table[
434
+ self.relative_position_index.view(-1)
435
+ ].view(
436
+ self.window_size[0] * self.window_size[1],
437
+ self.window_size[0] * self.window_size[1],
438
+ -1,
439
+ ) # Wh*Ww,Wh*Ww,nH
440
+ relative_position_bias = relative_position_bias.permute(
441
+ 2, 0, 1
442
+ ).contiguous() # nH, Wh*Ww, Wh*Ww
443
+ attn = attn + relative_position_bias.unsqueeze(0)
444
+
445
+ if mask is not None:
446
+ nW = mask.shape[0]
447
+ attn = attn.view(B_ // nW, nW, self.num_heads, N, N) + mask.unsqueeze(
448
+ 1
449
+ ).unsqueeze(0)
450
+ attn = attn.view(-1, self.num_heads, N, N)
451
+ attn = self.softmax(attn)
452
+ else:
453
+ attn = self.softmax(attn)
454
+
455
+ attn = self.attn_drop(attn)
456
+
457
+ x = (attn @ v).transpose(1, 2).reshape(B_, N, C)
458
+ x = self.proj(x)
459
+ x = self.proj_drop(x)
460
+ return x, attn
461
+
462
+ def extra_repr(self):
463
+ return f"dim={self.dim}, window_size={self.window_size}, num_heads={self.num_heads}"
464
+
465
+
466
+ # We use the model based on Swintransformer Block, therefore we can use the swin-transformer pretrained model
467
+ class SwinTransformerBlock(nn.Module):
468
+ r"""Swin Transformer Block.
469
+ Args:
470
+ dim (int): Number of input channels.
471
+ input_resolution (tuple[int]): Input resulotion.
472
+ num_heads (int): Number of attention heads.
473
+ window_size (int): Window size.
474
+ shift_size (int): Shift size for SW-MSA.
475
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.
476
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
477
+ qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set.
478
+ drop (float, optional): Dropout rate. Default: 0.0
479
+ attn_drop (float, optional): Attention dropout rate. Default: 0.0
480
+ drop_path (float, optional): Stochastic depth rate. Default: 0.0
481
+ act_layer (nn.Module, optional): Activation layer. Default: nn.GELU
482
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
483
+ """
484
+
485
+ def __init__(
486
+ self,
487
+ dim,
488
+ input_resolution,
489
+ num_heads,
490
+ window_size=7,
491
+ shift_size=0,
492
+ mlp_ratio=4.0,
493
+ qkv_bias=True,
494
+ qk_scale=None,
495
+ drop=0.0,
496
+ attn_drop=0.0,
497
+ drop_path=0.0,
498
+ act_layer=nn.GELU,
499
+ norm_layer=nn.LayerNorm,
500
+ norm_before_mlp="ln",
501
+ ):
502
+ super().__init__()
503
+ self.dim = dim
504
+ self.input_resolution = input_resolution
505
+ self.num_heads = num_heads
506
+ self.window_size = window_size
507
+ self.shift_size = shift_size
508
+ self.mlp_ratio = mlp_ratio
509
+ self.norm_before_mlp = norm_before_mlp
510
+ if min(self.input_resolution) <= self.window_size:
511
+ # if window size is larger than input resolution, we don't partition windows
512
+ self.shift_size = 0
513
+ self.window_size = min(self.input_resolution)
514
+ assert (
515
+ 0 <= self.shift_size < self.window_size
516
+ ), "shift_size must in 0-window_size"
517
+
518
+ self.norm1 = norm_layer(dim)
519
+ self.attn = WindowAttention(
520
+ dim,
521
+ window_size=to_2tuple(self.window_size),
522
+ num_heads=num_heads,
523
+ qkv_bias=qkv_bias,
524
+ qk_scale=qk_scale,
525
+ attn_drop=attn_drop,
526
+ proj_drop=drop,
527
+ )
528
+
529
+ self.drop_path = DropPath(drop_path) if drop_path > 0.0 else nn.Identity()
530
+ if self.norm_before_mlp == "ln":
531
+ self.norm2 = nn.LayerNorm(dim)
532
+ elif self.norm_before_mlp == "bn":
533
+ self.norm2 = lambda x: nn.BatchNorm1d(dim)(x.transpose(1, 2)).transpose(
534
+ 1, 2
535
+ )
536
+ else:
537
+ raise NotImplementedError
538
+ mlp_hidden_dim = int(dim * mlp_ratio)
539
+ self.mlp = Mlp(
540
+ in_features=dim,
541
+ hidden_features=mlp_hidden_dim,
542
+ act_layer=act_layer,
543
+ drop=drop,
544
+ )
545
+
546
+ if self.shift_size > 0:
547
+ # calculate attention mask for SW-MSA
548
+ H, W = self.input_resolution
549
+ img_mask = torch.zeros((1, H, W, 1)) # 1 H W 1
550
+ h_slices = (
551
+ slice(0, -self.window_size),
552
+ slice(-self.window_size, -self.shift_size),
553
+ slice(-self.shift_size, None),
554
+ )
555
+ w_slices = (
556
+ slice(0, -self.window_size),
557
+ slice(-self.window_size, -self.shift_size),
558
+ slice(-self.shift_size, None),
559
+ )
560
+ cnt = 0
561
+ for h in h_slices:
562
+ for w in w_slices:
563
+ img_mask[:, h, w, :] = cnt
564
+ cnt += 1
565
+
566
+ mask_windows = window_partition(
567
+ img_mask, self.window_size
568
+ ) # nW, window_size, window_size, 1
569
+ mask_windows = mask_windows.view(-1, self.window_size * self.window_size)
570
+ attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2)
571
+ attn_mask = attn_mask.masked_fill(
572
+ attn_mask != 0, float(-100.0)
573
+ ).masked_fill(attn_mask == 0, float(0.0))
574
+ else:
575
+ attn_mask = None
576
+
577
+ self.register_buffer("attn_mask", attn_mask)
578
+
579
+ def forward(self, x):
580
+ # pdb.set_trace()
581
+ H, W = self.input_resolution
582
+ # print("H: ", H)
583
+ # print("W: ", W)
584
+ # pdb.set_trace()
585
+ B, L, C = x.shape
586
+ # assert L == H * W, "input feature has wrong size"
587
+
588
+ shortcut = x
589
+ x = self.norm1(x)
590
+ x = x.view(B, H, W, C)
591
+
592
+ # cyclic shift
593
+ if self.shift_size > 0:
594
+ shifted_x = torch.roll(
595
+ x, shifts=(-self.shift_size, -self.shift_size), dims=(1, 2)
596
+ )
597
+ else:
598
+ shifted_x = x
599
+
600
+ # partition windows
601
+ x_windows = window_partition(
602
+ shifted_x, self.window_size
603
+ ) # nW*B, window_size, window_size, C
604
+ x_windows = x_windows.view(
605
+ -1, self.window_size * self.window_size, C
606
+ ) # nW*B, window_size*window_size, C
607
+
608
+ # W-MSA/SW-MSA
609
+ attn_windows, attn = self.attn(
610
+ x_windows, mask=self.attn_mask
611
+ ) # nW*B, window_size*window_size, C
612
+
613
+ # merge windows
614
+ attn_windows = attn_windows.view(-1, self.window_size, self.window_size, C)
615
+ shifted_x = window_reverse(attn_windows, self.window_size, H, W) # B H' W' C
616
+
617
+ # reverse cyclic shift
618
+ if self.shift_size > 0:
619
+ x = torch.roll(
620
+ shifted_x, shifts=(self.shift_size, self.shift_size), dims=(1, 2)
621
+ )
622
+ else:
623
+ x = shifted_x
624
+ x = x.view(B, H * W, C)
625
+
626
+ # FFN
627
+ x = shortcut + self.drop_path(x)
628
+ x = x + self.drop_path(self.mlp(self.norm2(x)))
629
+
630
+ return x, attn
631
+
632
+ def extra_repr(self):
633
+ return (
634
+ f"dim={self.dim}, input_resolution={self.input_resolution}, num_heads={self.num_heads}, "
635
+ f"window_size={self.window_size}, shift_size={self.shift_size}, mlp_ratio={self.mlp_ratio}"
636
+ )
637
+
638
+
639
+ class PatchMerging(nn.Module):
640
+ r"""Patch Merging Layer.
641
+ Args:
642
+ input_resolution (tuple[int]): Resolution of input feature.
643
+ dim (int): Number of input channels.
644
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
645
+ """
646
+
647
+ def __init__(self, input_resolution, dim, norm_layer=nn.LayerNorm):
648
+ super().__init__()
649
+ self.input_resolution = input_resolution
650
+ self.dim = dim
651
+ self.reduction = nn.Linear(4 * dim, 2 * dim, bias=False)
652
+ self.norm = norm_layer(4 * dim)
653
+
654
+ def forward(self, x):
655
+ """
656
+ x: B, H*W, C
657
+ """
658
+ H, W = self.input_resolution
659
+ B, L, C = x.shape
660
+ assert L == H * W, "input feature has wrong size"
661
+ assert H % 2 == 0 and W % 2 == 0, f"x size ({H}*{W}) are not even."
662
+
663
+ x = x.view(B, H, W, C)
664
+
665
+ x0 = x[:, 0::2, 0::2, :] # B H/2 W/2 C
666
+ x1 = x[:, 1::2, 0::2, :] # B H/2 W/2 C
667
+ x2 = x[:, 0::2, 1::2, :] # B H/2 W/2 C
668
+ x3 = x[:, 1::2, 1::2, :] # B H/2 W/2 C
669
+ x = torch.cat([x0, x1, x2, x3], -1) # B H/2 W/2 4*C
670
+ x = x.view(B, -1, 4 * C) # B H/2*W/2 4*C
671
+
672
+ x = self.norm(x)
673
+ x = self.reduction(x)
674
+
675
+ return x
676
+
677
+ def extra_repr(self):
678
+ return f"input_resolution={self.input_resolution}, dim={self.dim}"
679
+
680
+
681
+ class BasicLayer(nn.Module):
682
+ """A basic Swin Transformer layer for one stage.
683
+ Args:
684
+ dim (int): Number of input channels.
685
+ input_resolution (tuple[int]): Input resolution.
686
+ depth (int): Number of blocks.
687
+ num_heads (int): Number of attention heads.
688
+ window_size (int): Local window size.
689
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.
690
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
691
+ qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set.
692
+ drop (float, optional): Dropout rate. Default: 0.0
693
+ attn_drop (float, optional): Attention dropout rate. Default: 0.0
694
+ drop_path (float | tuple[float], optional): Stochastic depth rate. Default: 0.0
695
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
696
+ downsample (nn.Module | None, optional): Downsample layer at the end of the layer. Default: None
697
+ use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False.
698
+ """
699
+
700
+ def __init__(
701
+ self,
702
+ dim,
703
+ input_resolution,
704
+ depth,
705
+ num_heads,
706
+ window_size,
707
+ mlp_ratio=4.0,
708
+ qkv_bias=True,
709
+ qk_scale=None,
710
+ drop=0.0,
711
+ attn_drop=0.0,
712
+ drop_path=0.0,
713
+ norm_layer=nn.LayerNorm,
714
+ downsample=None,
715
+ use_checkpoint=False,
716
+ norm_before_mlp="ln",
717
+ ):
718
+ super().__init__()
719
+ self.dim = dim
720
+ self.input_resolution = input_resolution
721
+ self.depth = depth
722
+ self.use_checkpoint = use_checkpoint
723
+
724
+ # build blocks
725
+ self.blocks = nn.ModuleList(
726
+ [
727
+ SwinTransformerBlock(
728
+ dim=dim,
729
+ input_resolution=input_resolution,
730
+ num_heads=num_heads,
731
+ window_size=window_size,
732
+ shift_size=0 if (i % 2 == 0) else window_size // 2,
733
+ mlp_ratio=mlp_ratio,
734
+ qkv_bias=qkv_bias,
735
+ qk_scale=qk_scale,
736
+ drop=drop,
737
+ attn_drop=attn_drop,
738
+ drop_path=drop_path[i]
739
+ if isinstance(drop_path, list)
740
+ else drop_path,
741
+ norm_layer=norm_layer,
742
+ norm_before_mlp=norm_before_mlp,
743
+ )
744
+ for i in range(depth)
745
+ ]
746
+ )
747
+
748
+ # patch merging layer
749
+ if downsample is not None:
750
+ self.downsample = downsample(
751
+ input_resolution, dim=dim, norm_layer=norm_layer
752
+ )
753
+ else:
754
+ self.downsample = None
755
+
756
+ def forward(self, x):
757
+ attns = []
758
+ for blk in self.blocks:
759
+ if self.use_checkpoint:
760
+ x = checkpoint.checkpoint(blk, x)
761
+ else:
762
+ x, attn = blk(x)
763
+ if not self.training:
764
+ attns.append(attn.unsqueeze(0))
765
+ if self.downsample is not None:
766
+ x = self.downsample(x)
767
+ if not self.training:
768
+ attn = torch.cat(attns, dim=0)
769
+ attn = torch.mean(attn, dim=0)
770
+ return x, attn
771
+
772
+ def extra_repr(self):
773
+ return f"dim={self.dim}, input_resolution={self.input_resolution}, depth={self.depth}"
774
+
775
+
776
+ # The Core of HTSAT
777
+ class HTSAT_Swin_Transformer(nn.Module):
778
+ r"""HTSAT based on the Swin Transformer
779
+ Args:
780
+ spec_size (int | tuple(int)): Input Spectrogram size. Default 256
781
+ patch_size (int | tuple(int)): Patch size. Default: 4
782
+ path_stride (iot | tuple(int)): Patch Stride for Frequency and Time Axis. Default: 4
783
+ in_chans (int): Number of input image channels. Default: 1 (mono)
784
+ num_classes (int): Number of classes for classification head. Default: 527
785
+ embed_dim (int): Patch embedding dimension. Default: 96
786
+ depths (tuple(int)): Depth of each HTSAT-Swin Transformer layer.
787
+ num_heads (tuple(int)): Number of attention heads in different layers.
788
+ window_size (int): Window size. Default: 8
789
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim. Default: 4
790
+ qkv_bias (bool): If True, add a learnable bias to query, key, value. Default: True
791
+ qk_scale (float): Override default qk scale of head_dim ** -0.5 if set. Default: None
792
+ drop_rate (float): Dropout rate. Default: 0
793
+ attn_drop_rate (float): Attention dropout rate. Default: 0
794
+ drop_path_rate (float): Stochastic depth rate. Default: 0.1
795
+ norm_layer (nn.Module): Normalization layer. Default: nn.LayerNorm.
796
+ ape (bool): If True, add absolute position embedding to the patch embedding. Default: False
797
+ patch_norm (bool): If True, add normalization after patch embedding. Default: True
798
+ use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False
799
+ config (module): The configuration Module from config.py
800
+ """
801
+
802
+ def __init__(
803
+ self,
804
+ spec_size=256,
805
+ patch_size=4,
806
+ patch_stride=(4, 4),
807
+ in_chans=1,
808
+ num_classes=527,
809
+ embed_dim=96,
810
+ depths=[2, 2, 6, 2],
811
+ num_heads=[4, 8, 16, 32],
812
+ window_size=8,
813
+ mlp_ratio=4.0,
814
+ qkv_bias=True,
815
+ qk_scale=None,
816
+ drop_rate=0.0,
817
+ attn_drop_rate=0.0,
818
+ drop_path_rate=0.1,
819
+ norm_layer=nn.LayerNorm,
820
+ ape=False,
821
+ patch_norm=True,
822
+ use_checkpoint=False,
823
+ norm_before_mlp="ln",
824
+ config=None,
825
+ enable_fusion=False,
826
+ fusion_type="None",
827
+ **kwargs,
828
+ ):
829
+ super(HTSAT_Swin_Transformer, self).__init__()
830
+
831
+ self.config = config
832
+ self.spec_size = spec_size
833
+ self.patch_stride = patch_stride
834
+ self.patch_size = patch_size
835
+ self.window_size = window_size
836
+ self.embed_dim = embed_dim
837
+ self.depths = depths
838
+ self.ape = ape
839
+ self.in_chans = in_chans
840
+ self.num_classes = num_classes
841
+ self.num_heads = num_heads
842
+ self.num_layers = len(self.depths)
843
+ self.num_features = int(self.embed_dim * 2 ** (self.num_layers - 1))
844
+
845
+ self.drop_rate = drop_rate
846
+ self.attn_drop_rate = attn_drop_rate
847
+ self.drop_path_rate = drop_path_rate
848
+
849
+ self.qkv_bias = qkv_bias
850
+ self.qk_scale = None
851
+
852
+ self.patch_norm = patch_norm
853
+ self.norm_layer = norm_layer if self.patch_norm else None
854
+ self.norm_before_mlp = norm_before_mlp
855
+ self.mlp_ratio = mlp_ratio
856
+
857
+ self.use_checkpoint = use_checkpoint
858
+
859
+ self.enable_fusion = enable_fusion
860
+ self.fusion_type = fusion_type
861
+
862
+ # process mel-spec ; used only once
863
+ self.freq_ratio = self.spec_size // self.config.mel_bins
864
+ window = "hann"
865
+ center = True
866
+ pad_mode = "reflect"
867
+ ref = 1.0
868
+ amin = 1e-10
869
+ top_db = None
870
+ self.interpolate_ratio = 32 # Downsampled ratio
871
+ # Spectrogram extractor
872
+ self.spectrogram_extractor = Spectrogram(
873
+ n_fft=config.window_size,
874
+ hop_length=config.hop_size,
875
+ win_length=config.window_size,
876
+ window=window,
877
+ center=center,
878
+ pad_mode=pad_mode,
879
+ freeze_parameters=True,
880
+ )
881
+ # Logmel feature extractor
882
+ self.logmel_extractor = LogmelFilterBank(
883
+ sr=config.sample_rate,
884
+ n_fft=config.window_size,
885
+ n_mels=config.mel_bins,
886
+ fmin=config.fmin,
887
+ fmax=config.fmax,
888
+ ref=ref,
889
+ amin=amin,
890
+ top_db=top_db,
891
+ freeze_parameters=True,
892
+ )
893
+ # Spec augmenter
894
+ self.spec_augmenter = SpecAugmentation(
895
+ time_drop_width=64,
896
+ time_stripes_num=2,
897
+ freq_drop_width=8,
898
+ freq_stripes_num=2,
899
+ ) # 2 2
900
+ self.bn0 = nn.BatchNorm2d(self.config.mel_bins)
901
+
902
+ # split spctrogram into non-overlapping patches
903
+ self.patch_embed = PatchEmbed(
904
+ img_size=self.spec_size,
905
+ patch_size=self.patch_size,
906
+ in_chans=self.in_chans,
907
+ embed_dim=self.embed_dim,
908
+ norm_layer=self.norm_layer,
909
+ patch_stride=patch_stride,
910
+ enable_fusion=self.enable_fusion,
911
+ fusion_type=self.fusion_type,
912
+ )
913
+
914
+ num_patches = self.patch_embed.num_patches
915
+ patches_resolution = self.patch_embed.grid_size
916
+ self.patches_resolution = patches_resolution
917
+
918
+ # absolute position embedding
919
+ if self.ape:
920
+ self.absolute_pos_embed = nn.Parameter(
921
+ torch.zeros(1, num_patches, self.embed_dim)
922
+ )
923
+ trunc_normal_(self.absolute_pos_embed, std=0.02)
924
+
925
+ self.pos_drop = nn.Dropout(p=self.drop_rate)
926
+
927
+ # stochastic depth
928
+ dpr = [
929
+ x.item() for x in torch.linspace(0, self.drop_path_rate, sum(self.depths))
930
+ ] # stochastic depth decay rule
931
+
932
+ # build layers
933
+ self.layers = nn.ModuleList()
934
+ for i_layer in range(self.num_layers):
935
+ layer = BasicLayer(
936
+ dim=int(self.embed_dim * 2**i_layer),
937
+ input_resolution=(
938
+ patches_resolution[0] // (2**i_layer),
939
+ patches_resolution[1] // (2**i_layer),
940
+ ),
941
+ depth=self.depths[i_layer],
942
+ num_heads=self.num_heads[i_layer],
943
+ window_size=self.window_size,
944
+ mlp_ratio=self.mlp_ratio,
945
+ qkv_bias=self.qkv_bias,
946
+ qk_scale=self.qk_scale,
947
+ drop=self.drop_rate,
948
+ attn_drop=self.attn_drop_rate,
949
+ drop_path=dpr[
950
+ sum(self.depths[:i_layer]) : sum(self.depths[: i_layer + 1])
951
+ ],
952
+ norm_layer=self.norm_layer,
953
+ downsample=PatchMerging if (i_layer < self.num_layers - 1) else None,
954
+ use_checkpoint=use_checkpoint,
955
+ norm_before_mlp=self.norm_before_mlp,
956
+ )
957
+ self.layers.append(layer)
958
+
959
+ self.norm = self.norm_layer(self.num_features)
960
+ self.avgpool = nn.AdaptiveAvgPool1d(1)
961
+ self.maxpool = nn.AdaptiveMaxPool1d(1)
962
+
963
+ SF = (
964
+ self.spec_size
965
+ // (2 ** (len(self.depths) - 1))
966
+ // self.patch_stride[0]
967
+ // self.freq_ratio
968
+ )
969
+ self.tscam_conv = nn.Conv2d(
970
+ in_channels=self.num_features,
971
+ out_channels=self.num_classes,
972
+ kernel_size=(SF, 3),
973
+ padding=(0, 1),
974
+ )
975
+ self.head = nn.Linear(num_classes, num_classes)
976
+
977
+ if (self.enable_fusion) and (
978
+ self.fusion_type in ["daf_1d", "aff_1d", "iaff_1d"]
979
+ ):
980
+ self.mel_conv1d = nn.Sequential(
981
+ nn.Conv1d(64, 64, kernel_size=5, stride=3, padding=2),
982
+ nn.BatchNorm1d(64),
983
+ )
984
+ if self.fusion_type == "daf_1d":
985
+ self.fusion_model = DAF()
986
+ elif self.fusion_type == "aff_1d":
987
+ self.fusion_model = AFF(channels=64, type="1D")
988
+ elif self.fusion_type == "iaff_1d":
989
+ self.fusion_model = iAFF(channels=64, type="1D")
990
+
991
+ self.apply(self._init_weights)
992
+
993
+ def _init_weights(self, m):
994
+ if isinstance(m, nn.Linear):
995
+ trunc_normal_(m.weight, std=0.02)
996
+ if isinstance(m, nn.Linear) and m.bias is not None:
997
+ nn.init.constant_(m.bias, 0)
998
+ elif isinstance(m, nn.LayerNorm):
999
+ nn.init.constant_(m.bias, 0)
1000
+ nn.init.constant_(m.weight, 1.0)
1001
+
1002
+ @torch.jit.ignore
1003
+ def no_weight_decay(self):
1004
+ return {"absolute_pos_embed"}
1005
+
1006
+ @torch.jit.ignore
1007
+ def no_weight_decay_keywords(self):
1008
+ return {"relative_position_bias_table"}
1009
+
1010
+ def forward_features(self, x, longer_idx=None):
1011
+ # A deprecated optimization for using a hierarchical output from different blocks
1012
+
1013
+ frames_num = x.shape[2]
1014
+ x = self.patch_embed(x, longer_idx=longer_idx)
1015
+ if self.ape:
1016
+ x = x + self.absolute_pos_embed
1017
+ x = self.pos_drop(x)
1018
+ for i, layer in enumerate(self.layers):
1019
+ x, attn = layer(x)
1020
+ # for x
1021
+ x = self.norm(x)
1022
+ B, N, C = x.shape
1023
+ SF = frames_num // (2 ** (len(self.depths) - 1)) // self.patch_stride[0]
1024
+ ST = frames_num // (2 ** (len(self.depths) - 1)) // self.patch_stride[1]
1025
+ x = x.permute(0, 2, 1).contiguous().reshape(B, C, SF, ST)
1026
+ B, C, F, T = x.shape
1027
+ # group 2D CNN
1028
+ c_freq_bin = F // self.freq_ratio
1029
+ x = x.reshape(B, C, F // c_freq_bin, c_freq_bin, T)
1030
+ x = x.permute(0, 1, 3, 2, 4).contiguous().reshape(B, C, c_freq_bin, -1)
1031
+ # get latent_output
1032
+ fine_grained_latent_output = torch.mean(x, dim=2)
1033
+ fine_grained_latent_output = interpolate(
1034
+ fine_grained_latent_output.permute(0, 2, 1).contiguous(),
1035
+ 8 * self.patch_stride[1],
1036
+ )
1037
+
1038
+ latent_output = self.avgpool(torch.flatten(x, 2))
1039
+ latent_output = torch.flatten(latent_output, 1)
1040
+
1041
+ # display the attention map, if needed
1042
+
1043
+ x = self.tscam_conv(x)
1044
+ x = torch.flatten(x, 2) # B, C, T
1045
+
1046
+ fpx = interpolate(
1047
+ torch.sigmoid(x).permute(0, 2, 1).contiguous(), 8 * self.patch_stride[1]
1048
+ )
1049
+
1050
+ x = self.avgpool(x)
1051
+ x = torch.flatten(x, 1)
1052
+
1053
+ output_dict = {
1054
+ "framewise_output": fpx, # already sigmoided
1055
+ "clipwise_output": torch.sigmoid(x),
1056
+ "fine_grained_embedding": fine_grained_latent_output,
1057
+ "embedding": latent_output,
1058
+ }
1059
+
1060
+ return output_dict
1061
+
1062
+ def crop_wav(self, x, crop_size, spe_pos=None):
1063
+ time_steps = x.shape[2]
1064
+ tx = torch.zeros(x.shape[0], x.shape[1], crop_size, x.shape[3]).to(x.device)
1065
+ for i in range(len(x)):
1066
+ if spe_pos is None:
1067
+ crop_pos = random.randint(0, time_steps - crop_size - 1)
1068
+ else:
1069
+ crop_pos = spe_pos
1070
+ tx[i][0] = x[i, 0, crop_pos : crop_pos + crop_size, :]
1071
+ return tx
1072
+
1073
+ # Reshape the wavform to a img size, if you want to use the pretrained swin transformer model
1074
+ def reshape_wav2img(self, x):
1075
+ B, C, T, F = x.shape
1076
+ target_T = int(self.spec_size * self.freq_ratio)
1077
+ target_F = self.spec_size // self.freq_ratio
1078
+ assert (
1079
+ T <= target_T and F <= target_F
1080
+ ), "the wav size should less than or equal to the swin input size"
1081
+ # to avoid bicubic zero error
1082
+ if T < target_T:
1083
+ x = nn.functional.interpolate(
1084
+ x, (target_T, x.shape[3]), mode="bicubic", align_corners=True
1085
+ )
1086
+ if F < target_F:
1087
+ x = nn.functional.interpolate(
1088
+ x, (x.shape[2], target_F), mode="bicubic", align_corners=True
1089
+ )
1090
+ x = x.permute(0, 1, 3, 2).contiguous()
1091
+ x = x.reshape(
1092
+ x.shape[0],
1093
+ x.shape[1],
1094
+ x.shape[2],
1095
+ self.freq_ratio,
1096
+ x.shape[3] // self.freq_ratio,
1097
+ )
1098
+ # print(x.shape)
1099
+ x = x.permute(0, 1, 3, 2, 4).contiguous()
1100
+ x = x.reshape(x.shape[0], x.shape[1], x.shape[2] * x.shape[3], x.shape[4])
1101
+ return x
1102
+
1103
+ # Repeat the wavform to a img size, if you want to use the pretrained swin transformer model
1104
+ def repeat_wat2img(self, x, cur_pos):
1105
+ B, C, T, F = x.shape
1106
+ target_T = int(self.spec_size * self.freq_ratio)
1107
+ target_F = self.spec_size // self.freq_ratio
1108
+ assert (
1109
+ T <= target_T and F <= target_F
1110
+ ), "the wav size should less than or equal to the swin input size"
1111
+ # to avoid bicubic zero error
1112
+ if T < target_T:
1113
+ x = nn.functional.interpolate(
1114
+ x, (target_T, x.shape[3]), mode="bicubic", align_corners=True
1115
+ )
1116
+ if F < target_F:
1117
+ x = nn.functional.interpolate(
1118
+ x, (x.shape[2], target_F), mode="bicubic", align_corners=True
1119
+ )
1120
+ x = x.permute(0, 1, 3, 2).contiguous() # B C F T
1121
+ x = x[:, :, :, cur_pos : cur_pos + self.spec_size]
1122
+ x = x.repeat(repeats=(1, 1, 4, 1))
1123
+ return x
1124
+
1125
+ def forward(
1126
+ self, x: torch.Tensor, mixup_lambda=None, infer_mode=False, device=None
1127
+ ): # out_feat_keys: List[str] = None):
1128
+ if self.enable_fusion and x["longer"].sum() == 0:
1129
+ # if no audio is longer than 10s, then randomly select one audio to be longer
1130
+ x["longer"][torch.randint(0, x["longer"].shape[0], (1,))] = True
1131
+
1132
+ if not self.enable_fusion:
1133
+ x = x["waveform"].to(device=device, non_blocking=True)
1134
+ x = self.spectrogram_extractor(x) # (batch_size, 1, time_steps, freq_bins)
1135
+ x = self.logmel_extractor(x) # (batch_size, 1, time_steps, mel_bins)
1136
+ x = x.transpose(1, 3)
1137
+ x = self.bn0(x)
1138
+ x = x.transpose(1, 3)
1139
+ if self.training:
1140
+ x = self.spec_augmenter(x)
1141
+
1142
+ if self.training and mixup_lambda is not None:
1143
+ x = do_mixup(x, mixup_lambda)
1144
+
1145
+ x = self.reshape_wav2img(x)
1146
+ output_dict = self.forward_features(x)
1147
+ else:
1148
+ longer_list = x["longer"].to(device=device, non_blocking=True)
1149
+ x = x["mel_fusion"].to(device=device, non_blocking=True)
1150
+ x = x.transpose(1, 3)
1151
+ x = self.bn0(x)
1152
+ x = x.transpose(1, 3)
1153
+ longer_list_idx = torch.where(longer_list)[0]
1154
+ if self.fusion_type in ["daf_1d", "aff_1d", "iaff_1d"]:
1155
+ new_x = x[:, 0:1, :, :].clone().contiguous()
1156
+ if len(longer_list_idx) > 0:
1157
+ # local processing
1158
+ fusion_x_local = x[longer_list_idx, 1:, :, :].clone().contiguous()
1159
+ FB, FC, FT, FF = fusion_x_local.size()
1160
+ fusion_x_local = fusion_x_local.view(FB * FC, FT, FF)
1161
+ fusion_x_local = torch.permute(
1162
+ fusion_x_local, (0, 2, 1)
1163
+ ).contiguous()
1164
+ fusion_x_local = self.mel_conv1d(fusion_x_local)
1165
+ fusion_x_local = fusion_x_local.view(
1166
+ FB, FC, FF, fusion_x_local.size(-1)
1167
+ )
1168
+ fusion_x_local = (
1169
+ torch.permute(fusion_x_local, (0, 2, 1, 3))
1170
+ .contiguous()
1171
+ .flatten(2)
1172
+ )
1173
+ if fusion_x_local.size(-1) < FT:
1174
+ fusion_x_local = torch.cat(
1175
+ [
1176
+ fusion_x_local,
1177
+ torch.zeros(
1178
+ (FB, FF, FT - fusion_x_local.size(-1)),
1179
+ device=device,
1180
+ ),
1181
+ ],
1182
+ dim=-1,
1183
+ )
1184
+ else:
1185
+ fusion_x_local = fusion_x_local[:, :, :FT]
1186
+ # 1D fusion
1187
+ new_x = new_x.squeeze(1).permute((0, 2, 1)).contiguous()
1188
+ new_x[longer_list_idx] = self.fusion_model(
1189
+ new_x[longer_list_idx], fusion_x_local
1190
+ )
1191
+ x = new_x.permute((0, 2, 1)).contiguous()[:, None, :, :]
1192
+ else:
1193
+ x = new_x
1194
+
1195
+ elif self.fusion_type in ["daf_2d", "aff_2d", "iaff_2d", "channel_map"]:
1196
+ x = x # no change
1197
+
1198
+ if self.training:
1199
+ x = self.spec_augmenter(x)
1200
+ if self.training and mixup_lambda is not None:
1201
+ x = do_mixup(x, mixup_lambda)
1202
+
1203
+ x = self.reshape_wav2img(x)
1204
+ output_dict = self.forward_features(x, longer_idx=longer_list_idx)
1205
+
1206
+ # if infer_mode:
1207
+ # # in infer mode. we need to handle different length audio input
1208
+ # frame_num = x.shape[2]
1209
+ # target_T = int(self.spec_size * self.freq_ratio)
1210
+ # repeat_ratio = math.floor(target_T / frame_num)
1211
+ # x = x.repeat(repeats=(1,1,repeat_ratio,1))
1212
+ # x = self.reshape_wav2img(x)
1213
+ # output_dict = self.forward_features(x)
1214
+ # else:
1215
+ # if x.shape[2] > self.freq_ratio * self.spec_size:
1216
+ # if self.training:
1217
+ # x = self.crop_wav(x, crop_size=self.freq_ratio * self.spec_size)
1218
+ # x = self.reshape_wav2img(x)
1219
+ # output_dict = self.forward_features(x)
1220
+ # else:
1221
+ # # Change: Hard code here
1222
+ # overlap_size = (x.shape[2] - 1) // 4
1223
+ # output_dicts = []
1224
+ # crop_size = (x.shape[2] - 1) // 2
1225
+ # for cur_pos in range(0, x.shape[2] - crop_size - 1, overlap_size):
1226
+ # tx = self.crop_wav(x, crop_size = crop_size, spe_pos = cur_pos)
1227
+ # tx = self.reshape_wav2img(tx)
1228
+ # output_dicts.append(self.forward_features(tx))
1229
+ # clipwise_output = torch.zeros_like(output_dicts[0]["clipwise_output"]).float().to(x.device)
1230
+ # framewise_output = torch.zeros_like(output_dicts[0]["framewise_output"]).float().to(x.device)
1231
+ # for d in output_dicts:
1232
+ # clipwise_output += d["clipwise_output"]
1233
+ # framewise_output += d["framewise_output"]
1234
+ # clipwise_output = clipwise_output / len(output_dicts)
1235
+ # framewise_output = framewise_output / len(output_dicts)
1236
+ # output_dict = {
1237
+ # 'framewise_output': framewise_output,
1238
+ # 'clipwise_output': clipwise_output
1239
+ # }
1240
+ # else: # this part is typically used, and most easy one
1241
+ # x = self.reshape_wav2img(x)
1242
+ # output_dict = self.forward_features(x)
1243
+ # x = self.head(x)
1244
+
1245
+ # We process the data in the dataloader part, in that here we only consider the input_T < fixed_T
1246
+
1247
+ return output_dict
1248
+
1249
+
1250
+ def create_htsat_model(audio_cfg, enable_fusion=False, fusion_type="None"):
1251
+ try:
1252
+ assert audio_cfg.model_name in [
1253
+ "tiny",
1254
+ "base",
1255
+ "large",
1256
+ ], "model name for HTS-AT is wrong!"
1257
+ if audio_cfg.model_name == "tiny":
1258
+ model = HTSAT_Swin_Transformer(
1259
+ spec_size=256,
1260
+ patch_size=4,
1261
+ patch_stride=(4, 4),
1262
+ num_classes=audio_cfg.class_num,
1263
+ embed_dim=96,
1264
+ depths=[2, 2, 6, 2],
1265
+ num_heads=[4, 8, 16, 32],
1266
+ window_size=8,
1267
+ config=audio_cfg,
1268
+ enable_fusion=enable_fusion,
1269
+ fusion_type=fusion_type,
1270
+ )
1271
+ elif audio_cfg.model_name == "base":
1272
+ model = HTSAT_Swin_Transformer(
1273
+ spec_size=256,
1274
+ patch_size=4,
1275
+ patch_stride=(4, 4),
1276
+ num_classes=audio_cfg.class_num,
1277
+ embed_dim=128,
1278
+ depths=[2, 2, 12, 2],
1279
+ num_heads=[4, 8, 16, 32],
1280
+ window_size=8,
1281
+ config=audio_cfg,
1282
+ enable_fusion=enable_fusion,
1283
+ fusion_type=fusion_type,
1284
+ )
1285
+ elif audio_cfg.model_name == "large":
1286
+ model = HTSAT_Swin_Transformer(
1287
+ spec_size=256,
1288
+ patch_size=4,
1289
+ patch_stride=(4, 4),
1290
+ num_classes=audio_cfg.class_num,
1291
+ embed_dim=256,
1292
+ depths=[2, 2, 12, 2],
1293
+ num_heads=[4, 8, 16, 32],
1294
+ window_size=8,
1295
+ config=audio_cfg,
1296
+ enable_fusion=enable_fusion,
1297
+ fusion_type=fusion_type,
1298
+ )
1299
+
1300
+ return model
1301
+ except:
1302
+ raise RuntimeError(
1303
+ f"Import Model for {audio_cfg.model_name} not found, or the audio cfg parameters are not enough."
1304
+ )
audioldm2/clap/open_clip/loss.py ADDED
@@ -0,0 +1,397 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.distributed.nn
3
+ from torch import distributed as dist, nn as nn
4
+ from torch.nn import functional as F
5
+ import numpy as np
6
+ from sklearn.metrics import average_precision_score, roc_auc_score, accuracy_score
7
+
8
+ try:
9
+ import horovod.torch as hvd
10
+ except ImportError:
11
+ hvd = None
12
+
13
+
14
+ def gather_features(
15
+ audio_features,
16
+ text_features,
17
+ audio_features_mlp=None,
18
+ text_features_mlp=None,
19
+ local_loss=False,
20
+ gather_with_grad=False,
21
+ rank=0,
22
+ world_size=1,
23
+ use_horovod=False,
24
+ mlp_loss=False,
25
+ ):
26
+ if use_horovod:
27
+ assert hvd is not None, "Please install horovod"
28
+ if gather_with_grad:
29
+ all_audio_features = hvd.allgather(audio_features)
30
+ all_text_features = hvd.allgather(text_features)
31
+ if mlp_loss:
32
+ all_audio_features_mlp = hvd.allgather(audio_features_mlp)
33
+ all_text_features_mlp = hvd.allgather(text_features_mlp)
34
+ else:
35
+ with torch.no_grad():
36
+ all_audio_features = hvd.allgather(audio_features)
37
+ all_text_features = hvd.allgather(text_features)
38
+ if mlp_loss:
39
+ all_audio_features_mlp = hvd.allgather(audio_features_mlp)
40
+ all_text_features_mlp = hvd.allgather(text_features_mlp)
41
+ if not local_loss:
42
+ # ensure grads for local rank when all_* features don't have a gradient
43
+ gathered_audio_features = list(
44
+ all_audio_features.chunk(world_size, dim=0)
45
+ )
46
+ gathered_text_features = list(
47
+ all_text_features.chunk(world_size, dim=0)
48
+ )
49
+ gathered_audio_features[rank] = audio_features
50
+ gathered_text_features[rank] = text_features
51
+ all_audio_features = torch.cat(gathered_audio_features, dim=0)
52
+ all_text_features = torch.cat(gathered_text_features, dim=0)
53
+ if mlp_loss:
54
+ gathered_audio_features_mlp = list(
55
+ all_audio_features_mlp.chunk(world_size, dim=0)
56
+ )
57
+ gathered_text_features_mlp = list(
58
+ all_text_features_mlp.chunk(world_size, dim=0)
59
+ )
60
+ gathered_audio_features_mlp[rank] = audio_features_mlp
61
+ gathered_text_features_mlp[rank] = text_features_mlp
62
+ all_audio_features_mlp = torch.cat(
63
+ gathered_audio_features_mlp, dim=0
64
+ )
65
+ all_text_features_mlp = torch.cat(gathered_text_features_mlp, dim=0)
66
+ else:
67
+ # We gather tensors from all gpus
68
+ if gather_with_grad:
69
+ all_audio_features = torch.cat(
70
+ torch.distributed.nn.all_gather(audio_features), dim=0
71
+ )
72
+ all_text_features = torch.cat(
73
+ torch.distributed.nn.all_gather(text_features), dim=0
74
+ )
75
+ if mlp_loss:
76
+ all_audio_features_mlp = torch.cat(
77
+ torch.distributed.nn.all_gather(audio_features_mlp), dim=0
78
+ )
79
+ all_text_features_mlp = torch.cat(
80
+ torch.distributed.nn.all_gather(text_features_mlp), dim=0
81
+ )
82
+ else:
83
+ gathered_audio_features = [
84
+ torch.zeros_like(audio_features) for _ in range(world_size)
85
+ ]
86
+ gathered_text_features = [
87
+ torch.zeros_like(text_features) for _ in range(world_size)
88
+ ]
89
+ dist.all_gather(gathered_audio_features, audio_features)
90
+ dist.all_gather(gathered_text_features, text_features)
91
+ if mlp_loss:
92
+ gathered_audio_features_mlp = [
93
+ torch.zeros_like(audio_features_mlp) for _ in range(world_size)
94
+ ]
95
+ gathered_text_features_mlp = [
96
+ torch.zeros_like(text_features_mlp) for _ in range(world_size)
97
+ ]
98
+ dist.all_gather(gathered_audio_features_mlp, audio_features_mlp)
99
+ dist.all_gather(gathered_text_features_mlp, text_features_mlp)
100
+ if not local_loss:
101
+ # ensure grads for local rank when all_* features don't have a gradient
102
+ gathered_audio_features[rank] = audio_features
103
+ gathered_text_features[rank] = text_features
104
+ if mlp_loss:
105
+ gathered_audio_features_mlp[rank] = audio_features_mlp
106
+ gathered_text_features_mlp[rank] = text_features_mlp
107
+
108
+ all_audio_features = torch.cat(gathered_audio_features, dim=0)
109
+ all_text_features = torch.cat(gathered_text_features, dim=0)
110
+ if mlp_loss:
111
+ all_audio_features_mlp = torch.cat(gathered_audio_features_mlp, dim=0)
112
+ all_text_features_mlp = torch.cat(gathered_text_features_mlp, dim=0)
113
+ if mlp_loss:
114
+ return (
115
+ all_audio_features,
116
+ all_text_features,
117
+ all_audio_features_mlp,
118
+ all_text_features_mlp,
119
+ )
120
+ else:
121
+ return all_audio_features, all_text_features
122
+
123
+
124
+ class ClipLoss(nn.Module):
125
+ def __init__(
126
+ self,
127
+ local_loss=False,
128
+ gather_with_grad=False,
129
+ cache_labels=False,
130
+ rank=0,
131
+ world_size=1,
132
+ use_horovod=False,
133
+ mlp_loss=False,
134
+ weight_loss_kappa=0,
135
+ ):
136
+ super().__init__()
137
+ self.local_loss = local_loss
138
+ self.gather_with_grad = gather_with_grad
139
+ self.cache_labels = cache_labels
140
+ self.rank = rank
141
+ self.world_size = world_size
142
+ self.use_horovod = use_horovod
143
+ self.mlp_loss = mlp_loss
144
+ self.weighted_loss = bool(weight_loss_kappa != 0)
145
+ self.weight_loss_kappa = weight_loss_kappa
146
+ # cache state
147
+ self.prev_num_logits = 0
148
+ self.labels = {}
149
+
150
+ def forward(
151
+ self,
152
+ audio_features,
153
+ text_features,
154
+ logit_scale_a,
155
+ logit_scale_t=None,
156
+ audio_features_mlp=None,
157
+ text_features_mlp=None,
158
+ ):
159
+ device = audio_features.device
160
+ if self.mlp_loss:
161
+ if self.world_size > 1:
162
+ (
163
+ all_audio_features,
164
+ all_text_features,
165
+ all_audio_features_mlp,
166
+ all_text_features_mlp,
167
+ ) = gather_features(
168
+ audio_features=audio_features,
169
+ text_features=text_features,
170
+ audio_features_mlp=audio_features_mlp,
171
+ text_features_mlp=text_features_mlp,
172
+ local_loss=self.local_loss,
173
+ gather_with_grad=self.gather_with_grad,
174
+ rank=self.rank,
175
+ world_size=self.world_size,
176
+ use_horovod=self.use_horovod,
177
+ mlp_loss=self.mlp_loss,
178
+ )
179
+ if self.local_loss:
180
+ a_logits_per_audio = (
181
+ logit_scale_a * audio_features @ all_text_features_mlp.T
182
+ )
183
+ a_logits_per_text = (
184
+ logit_scale_a * text_features_mlp @ all_audio_features.T
185
+ )
186
+ t_logits_per_audio = (
187
+ logit_scale_t * audio_features_mlp @ all_text_features.T
188
+ )
189
+ t_logits_per_text = (
190
+ logit_scale_t * text_features @ all_audio_features_mlp.T
191
+ )
192
+ else:
193
+ a_logits_per_audio = (
194
+ logit_scale_a * all_audio_features @ all_text_features_mlp.T
195
+ )
196
+ a_logits_per_text = a_logits_per_audio.T
197
+ t_logits_per_audio = (
198
+ logit_scale_t * all_audio_features_mlp @ all_text_features.T
199
+ )
200
+ t_logits_per_text = t_logits_per_audio.T
201
+ else:
202
+ a_logits_per_audio = (
203
+ logit_scale_a * audio_features @ text_features_mlp.T
204
+ )
205
+ a_logits_per_text = logit_scale_a * text_features_mlp @ audio_features.T
206
+ t_logits_per_audio = (
207
+ logit_scale_t * audio_features_mlp @ text_features.T
208
+ )
209
+ t_logits_per_text = logit_scale_t * text_features @ audio_features_mlp.T
210
+
211
+ # calculated ground-truth and cache if enabled
212
+ num_logits = a_logits_per_audio.shape[0]
213
+ if self.prev_num_logits != num_logits or device not in self.labels:
214
+ labels = torch.arange(num_logits, device=device, dtype=torch.long)
215
+ if self.world_size > 1 and self.local_loss:
216
+ labels = labels + num_logits * self.rank
217
+ if self.cache_labels:
218
+ self.labels[device] = labels
219
+ self.prev_num_logits = num_logits
220
+ else:
221
+ labels = self.labels[device]
222
+
223
+ if not self.weighted_loss:
224
+ total_loss = (
225
+ F.cross_entropy(a_logits_per_audio, labels)
226
+ + F.cross_entropy(a_logits_per_text, labels)
227
+ + F.cross_entropy(t_logits_per_audio, labels)
228
+ + F.cross_entropy(t_logits_per_text, labels)
229
+ ) / 4
230
+ else:
231
+ audio_weight = (audio_features @ audio_features.T).detach()
232
+ audio_weight = (
233
+ torch.exp(
234
+ torch.sum(audio_weight, axis=1)
235
+ / (self.weight_loss_kappa * len(audio_weight))
236
+ )
237
+ ).detach()
238
+ text_weight = (text_features @ text_features.T).detach()
239
+ text_weight = (
240
+ torch.exp(
241
+ torch.sum(text_weight, axis=1)
242
+ / (self.weight_loss_kappa * len(text_features))
243
+ )
244
+ ).detach()
245
+ total_loss = (
246
+ F.cross_entropy(a_logits_per_audio, labels, weight=audio_weight)
247
+ + F.cross_entropy(a_logits_per_text, labels, weight=audio_weight)
248
+ + F.cross_entropy(t_logits_per_audio, labels, weight=text_weight)
249
+ + F.cross_entropy(t_logits_per_text, labels, weight=text_weight)
250
+ ) / 4
251
+ else:
252
+ if self.world_size > 1:
253
+ all_audio_features, all_text_features = gather_features(
254
+ audio_features=audio_features,
255
+ text_features=text_features,
256
+ local_loss=self.local_loss,
257
+ gather_with_grad=self.gather_with_grad,
258
+ rank=self.rank,
259
+ world_size=self.world_size,
260
+ use_horovod=self.use_horovod,
261
+ mlp_loss=self.mlp_loss,
262
+ )
263
+
264
+ if self.local_loss:
265
+ logits_per_audio = (
266
+ logit_scale_a * audio_features @ all_text_features.T
267
+ )
268
+ logits_per_text = (
269
+ logit_scale_a * text_features @ all_audio_features.T
270
+ )
271
+ else:
272
+ logits_per_audio = (
273
+ logit_scale_a * all_audio_features @ all_text_features.T
274
+ )
275
+ logits_per_text = logits_per_audio.T
276
+ else:
277
+ logits_per_audio = logit_scale_a * audio_features @ text_features.T
278
+ logits_per_text = logit_scale_a * text_features @ audio_features.T
279
+
280
+ # calculated ground-truth and cache if enabled
281
+ num_logits = logits_per_audio.shape[0]
282
+ if self.prev_num_logits != num_logits or device not in self.labels:
283
+ labels = torch.arange(num_logits, device=device, dtype=torch.long)
284
+ if self.world_size > 1 and self.local_loss:
285
+ labels = labels + num_logits * self.rank
286
+ if self.cache_labels:
287
+ self.labels[device] = labels
288
+ self.prev_num_logits = num_logits
289
+ else:
290
+ labels = self.labels[device]
291
+ if not self.weighted_loss:
292
+ total_loss = (
293
+ F.cross_entropy(logits_per_audio, labels)
294
+ + F.cross_entropy(logits_per_text, labels)
295
+ ) / 2
296
+ else:
297
+ audio_weight = (all_audio_features @ all_audio_features.T).detach()
298
+ audio_weight = (
299
+ torch.exp(
300
+ torch.sum(audio_weight, axis=1)
301
+ / (self.weight_loss_kappa * len(all_audio_features))
302
+ )
303
+ ).detach()
304
+ text_weight = (all_text_features @ all_text_features.T).detach()
305
+ text_weight = (
306
+ torch.exp(
307
+ torch.sum(text_weight, axis=1)
308
+ / (self.weight_loss_kappa * len(all_text_features))
309
+ )
310
+ ).detach()
311
+ total_loss = (
312
+ F.cross_entropy(logits_per_audio, labels, weight=text_weight)
313
+ + F.cross_entropy(logits_per_text, labels, weight=audio_weight)
314
+ ) / 2
315
+ return total_loss
316
+
317
+
318
+ def lp_gather_features(pred, target, world_size=1, use_horovod=False):
319
+ if use_horovod:
320
+ assert hvd is not None, "Please install horovod"
321
+ with torch.no_grad():
322
+ all_preds = hvd.allgather(pred)
323
+ all_targets = hvd.allgath(target)
324
+ else:
325
+ gathered_preds = [torch.zeros_like(pred) for _ in range(world_size)]
326
+ gathered_targets = [torch.zeros_like(target) for _ in range(world_size)]
327
+
328
+ dist.all_gather(gathered_preds, pred)
329
+ dist.all_gather(gathered_targets, target)
330
+ all_preds = torch.cat(gathered_preds, dim=0)
331
+ all_targets = torch.cat(gathered_targets, dim=0)
332
+
333
+ return all_preds, all_targets
334
+
335
+
336
+ def get_map(pred, target):
337
+ pred = torch.sigmoid(pred).numpy()
338
+ target = target.numpy()
339
+ return np.mean(average_precision_score(target, pred, average=None))
340
+
341
+
342
+ def get_acc(pred, target):
343
+ pred = torch.argmax(pred, 1).numpy()
344
+ target = torch.argmax(target, 1).numpy()
345
+ return accuracy_score(target, pred)
346
+
347
+
348
+ def get_mauc(pred, target):
349
+ pred = torch.sigmoid(pred).numpy()
350
+ target = target.numpy()
351
+ return np.mean(roc_auc_score(target, pred, average=None))
352
+
353
+
354
+ class LPMetrics(object):
355
+ def __init__(self, metric_names=["map", "acc", "mauc"]):
356
+ self.metrics = []
357
+ for name in metric_names:
358
+ self.metrics.append(self.get_metric(name))
359
+ self.metric_names = metric_names
360
+
361
+ def get_metric(self, name):
362
+ if name == "map":
363
+ return get_map
364
+ elif name == "acc":
365
+ return get_acc
366
+ elif name == "mauc":
367
+ return get_mauc
368
+ else:
369
+ raise ValueError(f"the metric should be at least one of [map, acc, mauc]")
370
+
371
+ def evaluate_mertics(self, pred, target):
372
+ metric_dict = {}
373
+ for i in range(len(self.metric_names)):
374
+ metric_dict[self.metric_names[i]] = self.metrics[i](pred, target)
375
+ return metric_dict
376
+
377
+
378
+ def calc_celoss(pred, target):
379
+ target = torch.argmax(target, 1).long()
380
+ return nn.CrossEntropyLoss()(pred, target)
381
+
382
+
383
+ class LPLoss(nn.Module):
384
+ def __init__(self, loss_name):
385
+ super().__init__()
386
+ if loss_name == "bce":
387
+ self.loss_func = nn.BCEWithLogitsLoss()
388
+ elif loss_name == "ce":
389
+ self.loss_func = calc_celoss
390
+ elif loss_name == "mse":
391
+ self.loss_func = nn.MSELoss()
392
+ else:
393
+ raise ValueError(f"the loss func should be at least one of [bce, ce, mse]")
394
+
395
+ def forward(self, pred, target):
396
+ loss = self.loss_func(pred, target)
397
+ return loss
audioldm2/clap/open_clip/model.py ADDED
@@ -0,0 +1,931 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ CLAP Model
2
+
3
+ Adapted from CLIP: https://github.com/openai/CLIP. Originally MIT License, Copyright (c) 2021 OpenAI.
4
+ Adapted to the Audio Task.
5
+ """
6
+
7
+ from collections import OrderedDict
8
+ from dataclasses import dataclass
9
+ from typing import Tuple, Union, Callable, Optional
10
+
11
+ import numpy as np
12
+ import torch
13
+ import torch.nn.functional as F
14
+ from torch import nn
15
+
16
+ import logging
17
+ from .utils import freeze_batch_norm_2d
18
+
19
+ from .pann_model import create_pann_model
20
+ from .htsat import create_htsat_model
21
+ from transformers import BertModel, RobertaModel, BartModel, RobertaConfig
22
+
23
+
24
+ class MLPLayers(nn.Module):
25
+ def __init__(self, units=[512, 512, 512], nonlin=nn.ReLU(), dropout=0.1):
26
+ super(MLPLayers, self).__init__()
27
+ self.nonlin = nonlin
28
+ self.dropout = dropout
29
+
30
+ sequence = []
31
+ for u0, u1 in zip(units[:-1], units[1:]):
32
+ sequence.append(nn.Linear(u0, u1))
33
+ sequence.append(self.nonlin)
34
+ sequence.append(nn.Dropout(self.dropout))
35
+ sequence = sequence[:-2]
36
+
37
+ self.sequential = nn.Sequential(*sequence)
38
+
39
+ def forward(self, X):
40
+ X = self.sequential(X)
41
+ return X
42
+
43
+
44
+ class Bottleneck(nn.Module):
45
+ expansion = 4
46
+
47
+ def __init__(self, inplanes, planes, stride=1):
48
+ super().__init__()
49
+
50
+ # all conv layers have stride 1. an avgpool is performed after the second convolution when stride > 1
51
+ self.conv1 = nn.Conv2d(inplanes, planes, 1, bias=False)
52
+ self.bn1 = nn.BatchNorm2d(planes)
53
+
54
+ self.conv2 = nn.Conv2d(planes, planes, 3, padding=1, bias=False)
55
+ self.bn2 = nn.BatchNorm2d(planes)
56
+
57
+ self.avgpool = nn.AvgPool2d(stride) if stride > 1 else nn.Identity()
58
+
59
+ self.conv3 = nn.Conv2d(planes, planes * self.expansion, 1, bias=False)
60
+ self.bn3 = nn.BatchNorm2d(planes * self.expansion)
61
+
62
+ self.relu = nn.ReLU(inplace=True)
63
+ self.downsample = None
64
+ self.stride = stride
65
+
66
+ if stride > 1 or inplanes != planes * Bottleneck.expansion:
67
+ # downsampling layer is prepended with an avgpool, and the subsequent convolution has stride 1
68
+ self.downsample = nn.Sequential(
69
+ OrderedDict(
70
+ [
71
+ ("-1", nn.AvgPool2d(stride)),
72
+ (
73
+ "0",
74
+ nn.Conv2d(
75
+ inplanes,
76
+ planes * self.expansion,
77
+ 1,
78
+ stride=1,
79
+ bias=False,
80
+ ),
81
+ ),
82
+ ("1", nn.BatchNorm2d(planes * self.expansion)),
83
+ ]
84
+ )
85
+ )
86
+
87
+ def forward(self, x: torch.Tensor):
88
+ identity = x
89
+
90
+ out = self.relu(self.bn1(self.conv1(x)))
91
+ out = self.relu(self.bn2(self.conv2(out)))
92
+ out = self.avgpool(out)
93
+ out = self.bn3(self.conv3(out))
94
+
95
+ if self.downsample is not None:
96
+ identity = self.downsample(x)
97
+
98
+ out += identity
99
+ out = self.relu(out)
100
+ return out
101
+
102
+
103
+ class AttentionPool2d(nn.Module):
104
+ def __init__(
105
+ self, spacial_dim: int, embed_dim: int, num_heads: int, output_dim: int = None
106
+ ):
107
+ super().__init__()
108
+ self.positional_embedding = nn.Parameter(
109
+ torch.randn(spacial_dim**2 + 1, embed_dim) / embed_dim**0.5
110
+ )
111
+ self.k_proj = nn.Linear(embed_dim, embed_dim)
112
+ self.q_proj = nn.Linear(embed_dim, embed_dim)
113
+ self.v_proj = nn.Linear(embed_dim, embed_dim)
114
+ self.c_proj = nn.Linear(embed_dim, output_dim or embed_dim)
115
+ self.num_heads = num_heads
116
+
117
+ def forward(self, x):
118
+ x = x.reshape(x.shape[0], x.shape[1], x.shape[2] * x.shape[3]).permute(
119
+ 2, 0, 1
120
+ ) # NCHW -> (HW)NC
121
+ x = torch.cat([x.mean(dim=0, keepdim=True), x], dim=0) # (HW+1)NC
122
+ x = x + self.positional_embedding[:, None, :].to(x.dtype) # (HW+1)NC
123
+ x, _ = F.multi_head_attention_forward(
124
+ query=x,
125
+ key=x,
126
+ value=x,
127
+ embed_dim_to_check=x.shape[-1],
128
+ num_heads=self.num_heads,
129
+ q_proj_weight=self.q_proj.weight,
130
+ k_proj_weight=self.k_proj.weight,
131
+ v_proj_weight=self.v_proj.weight,
132
+ in_proj_weight=None,
133
+ in_proj_bias=torch.cat(
134
+ [self.q_proj.bias, self.k_proj.bias, self.v_proj.bias]
135
+ ),
136
+ bias_k=None,
137
+ bias_v=None,
138
+ add_zero_attn=False,
139
+ dropout_p=0,
140
+ out_proj_weight=self.c_proj.weight,
141
+ out_proj_bias=self.c_proj.bias,
142
+ use_separate_proj_weight=True,
143
+ training=self.training,
144
+ need_weights=False,
145
+ )
146
+
147
+ return x[0]
148
+
149
+
150
+ class ModifiedResNet(nn.Module):
151
+ """
152
+ A ResNet class that is similar to torchvision's but contains the following changes:
153
+ - There are now 3 "stem" convolutions as opposed to 1, with an average pool instead of a max pool.
154
+ - Performs anti-aliasing strided convolutions, where an avgpool is prepended to convolutions with stride > 1
155
+ - The final pooling layer is a QKV attention instead of an average pool
156
+ """
157
+
158
+ def __init__(self, layers, output_dim, heads, image_size=224, width=64):
159
+ super().__init__()
160
+ self.output_dim = output_dim
161
+ self.image_size = image_size
162
+
163
+ # the 3-layer stem
164
+ self.conv1 = nn.Conv2d(
165
+ 3, width // 2, kernel_size=3, stride=2, padding=1, bias=False
166
+ )
167
+ self.bn1 = nn.BatchNorm2d(width // 2)
168
+ self.conv2 = nn.Conv2d(
169
+ width // 2, width // 2, kernel_size=3, padding=1, bias=False
170
+ )
171
+ self.bn2 = nn.BatchNorm2d(width // 2)
172
+ self.conv3 = nn.Conv2d(width // 2, width, kernel_size=3, padding=1, bias=False)
173
+ self.bn3 = nn.BatchNorm2d(width)
174
+ self.avgpool = nn.AvgPool2d(2)
175
+ self.relu = nn.ReLU(inplace=True)
176
+
177
+ # residual layers
178
+ self._inplanes = width # this is a *mutable* variable used during construction
179
+ self.layer1 = self._make_layer(width, layers[0])
180
+ self.layer2 = self._make_layer(width * 2, layers[1], stride=2)
181
+ self.layer3 = self._make_layer(width * 4, layers[2], stride=2)
182
+ self.layer4 = self._make_layer(width * 8, layers[3], stride=2)
183
+
184
+ embed_dim = width * 32 # the ResNet feature dimension
185
+ self.attnpool = AttentionPool2d(image_size // 32, embed_dim, heads, output_dim)
186
+
187
+ self.init_parameters()
188
+
189
+ def _make_layer(self, planes, blocks, stride=1):
190
+ layers = [Bottleneck(self._inplanes, planes, stride)]
191
+
192
+ self._inplanes = planes * Bottleneck.expansion
193
+ for _ in range(1, blocks):
194
+ layers.append(Bottleneck(self._inplanes, planes))
195
+
196
+ return nn.Sequential(*layers)
197
+
198
+ def init_parameters(self):
199
+ if self.attnpool is not None:
200
+ std = self.attnpool.c_proj.in_features**-0.5
201
+ nn.init.normal_(self.attnpool.q_proj.weight, std=std)
202
+ nn.init.normal_(self.attnpool.k_proj.weight, std=std)
203
+ nn.init.normal_(self.attnpool.v_proj.weight, std=std)
204
+ nn.init.normal_(self.attnpool.c_proj.weight, std=std)
205
+
206
+ for resnet_block in [self.layer1, self.layer2, self.layer3, self.layer4]:
207
+ for name, param in resnet_block.named_parameters():
208
+ if name.endswith("bn3.weight"):
209
+ nn.init.zeros_(param)
210
+
211
+ def lock(self, unlocked_groups=0, freeze_bn_stats=False):
212
+ assert (
213
+ unlocked_groups == 0
214
+ ), "partial locking not currently supported for this model"
215
+ for param in self.parameters():
216
+ param.requires_grad = False
217
+ if freeze_bn_stats:
218
+ freeze_batch_norm_2d(self)
219
+
220
+ def stem(self, x):
221
+ for conv, bn in [
222
+ (self.conv1, self.bn1),
223
+ (self.conv2, self.bn2),
224
+ (self.conv3, self.bn3),
225
+ ]:
226
+ x = self.relu(bn(conv(x)))
227
+ x = self.avgpool(x)
228
+ return x
229
+
230
+ def forward(self, x):
231
+ x = self.stem(x)
232
+ x = self.layer1(x)
233
+ x = self.layer2(x)
234
+ x = self.layer3(x)
235
+ x = self.layer4(x)
236
+ x = self.attnpool(x)
237
+
238
+ return x
239
+
240
+
241
+ class LayerNorm(nn.LayerNorm):
242
+ """Subclass torch's LayerNorm to handle fp16."""
243
+
244
+ def forward(self, x: torch.Tensor):
245
+ orig_type = x.dtype
246
+ x = F.layer_norm(x, self.normalized_shape, self.weight, self.bias, self.eps)
247
+ return x.to(orig_type)
248
+
249
+
250
+ class QuickGELU(nn.Module):
251
+ # NOTE This is slower than nn.GELU or nn.SiLU and uses more GPU memory
252
+ def forward(self, x: torch.Tensor):
253
+ return x * torch.sigmoid(1.702 * x)
254
+
255
+
256
+ class ResidualAttentionBlock(nn.Module):
257
+ def __init__(self, d_model: int, n_head: int, act_layer: Callable = nn.GELU):
258
+ super().__init__()
259
+
260
+ self.attn = nn.MultiheadAttention(d_model, n_head)
261
+ self.ln_1 = LayerNorm(d_model)
262
+ self.mlp = nn.Sequential(
263
+ OrderedDict(
264
+ [
265
+ ("c_fc", nn.Linear(d_model, d_model * 4)),
266
+ ("gelu", act_layer()),
267
+ ("c_proj", nn.Linear(d_model * 4, d_model)),
268
+ ]
269
+ )
270
+ )
271
+ self.ln_2 = LayerNorm(d_model)
272
+
273
+ def attention(self, x: torch.Tensor, attn_mask: Optional[torch.Tensor] = None):
274
+ return self.attn(x, x, x, need_weights=False, attn_mask=attn_mask)[0]
275
+
276
+ def forward(self, x: torch.Tensor, attn_mask: Optional[torch.Tensor] = None):
277
+ x = x + self.attention(self.ln_1(x), attn_mask=attn_mask)
278
+ x = x + self.mlp(self.ln_2(x))
279
+ return x
280
+
281
+
282
+ class Transformer(nn.Module):
283
+ def __init__(
284
+ self, width: int, layers: int, heads: int, act_layer: Callable = nn.GELU
285
+ ):
286
+ super().__init__()
287
+ self.width = width
288
+ self.layers = layers
289
+ self.resblocks = nn.ModuleList(
290
+ [
291
+ ResidualAttentionBlock(width, heads, act_layer=act_layer)
292
+ for _ in range(layers)
293
+ ]
294
+ )
295
+
296
+ def forward(self, x: torch.Tensor, attn_mask: Optional[torch.Tensor] = None):
297
+ for r in self.resblocks:
298
+ x = r(x, attn_mask=attn_mask)
299
+ return x
300
+
301
+
302
+ class VisualTransformer(nn.Module):
303
+ def __init__(
304
+ self,
305
+ image_size: int,
306
+ patch_size: int,
307
+ width: int,
308
+ layers: int,
309
+ heads: int,
310
+ output_dim: int,
311
+ act_layer: Callable = nn.GELU,
312
+ ):
313
+ super().__init__()
314
+ self.image_size = image_size
315
+ self.output_dim = output_dim
316
+ self.conv1 = nn.Conv2d(
317
+ in_channels=3,
318
+ out_channels=width,
319
+ kernel_size=patch_size,
320
+ stride=patch_size,
321
+ bias=False,
322
+ )
323
+
324
+ scale = width**-0.5
325
+ self.class_embedding = nn.Parameter(scale * torch.randn(width))
326
+ self.positional_embedding = nn.Parameter(
327
+ scale * torch.randn((image_size // patch_size) ** 2 + 1, width)
328
+ )
329
+ self.ln_pre = LayerNorm(width)
330
+
331
+ self.text_branch = Transformer(width, layers, heads, act_layer=act_layer)
332
+
333
+ self.ln_post = LayerNorm(width)
334
+ self.proj = nn.Parameter(scale * torch.randn(width, output_dim))
335
+
336
+ def lock(self, unlocked_groups=0, freeze_bn_stats=False):
337
+ assert (
338
+ unlocked_groups == 0
339
+ ), "partial locking not currently supported for this model"
340
+ for param in self.parameters():
341
+ param.requires_grad = False
342
+
343
+ def forward(self, x: torch.Tensor):
344
+ x = self.conv1(x) # shape = [*, width, grid, grid]
345
+ x = x.reshape(x.shape[0], x.shape[1], -1) # shape = [*, width, grid ** 2]
346
+ x = x.permute(0, 2, 1) # shape = [*, grid ** 2, width]
347
+ x = torch.cat(
348
+ [
349
+ self.class_embedding.to(x.dtype)
350
+ + torch.zeros(
351
+ x.shape[0], 1, x.shape[-1], dtype=x.dtype, device=x.device
352
+ ),
353
+ x,
354
+ ],
355
+ dim=1,
356
+ ) # shape = [*, grid ** 2 + 1, width]
357
+ x = x + self.positional_embedding.to(x.dtype)
358
+ x = self.ln_pre(x)
359
+
360
+ x = x.permute(1, 0, 2) # NLD -> LND
361
+ x = self.text_branch(x)
362
+ x = x.permute(1, 0, 2) # LND -> NLD
363
+
364
+ x = self.ln_post(x[:, 0, :])
365
+
366
+ if self.proj is not None:
367
+ x = x @ self.proj
368
+
369
+ return x
370
+
371
+
372
+ @dataclass
373
+ class CLAPVisionCfg:
374
+ layers: Union[Tuple[int, int, int, int], int] = 12
375
+ width: int = 768
376
+ patch_size: int = 16
377
+ image_size: Union[Tuple[int, int], int] = 224
378
+ timm_model_name: str = (
379
+ None # a valid model name overrides layers, width, patch_size
380
+ )
381
+ timm_model_pretrained: bool = (
382
+ False # use (imagenet) pretrained weights for named model
383
+ )
384
+ timm_pool: str = (
385
+ "avg" # feature pooling for timm model ('abs_attn', 'rot_attn', 'avg', '')
386
+ )
387
+ timm_proj: str = (
388
+ "linear" # linear projection for timm model output ('linear', 'mlp', '')
389
+ )
390
+
391
+
392
+ # Audio Config Class
393
+ @dataclass
394
+ class CLAPAudioCfp:
395
+ model_type: str = "PANN"
396
+ model_name: str = "Cnn14"
397
+ sample_rate: int = 48000
398
+ # Param
399
+ audio_length: int = 1024
400
+ window_size: int = 1024
401
+ hop_size: int = 1024
402
+ fmin: int = 50
403
+ fmax: int = 14000
404
+ class_num: int = 527
405
+ mel_bins: int = 64
406
+ clip_samples: int = 480000
407
+
408
+
409
+ @dataclass
410
+ class CLAPTextCfg:
411
+ context_length: int
412
+ vocab_size: int
413
+ width: int
414
+ heads: int
415
+ layers: int
416
+ model_type: str
417
+
418
+
419
+ class CLAP(nn.Module):
420
+ def __init__(
421
+ self,
422
+ embed_dim: int,
423
+ audio_cfg: CLAPAudioCfp,
424
+ text_cfg: CLAPTextCfg,
425
+ quick_gelu: bool = False,
426
+ enable_fusion: bool = False,
427
+ fusion_type: str = "None",
428
+ joint_embed_shape: int = 512,
429
+ mlp_act: str = "relu",
430
+ ):
431
+ super().__init__()
432
+ if isinstance(audio_cfg, dict):
433
+ audio_cfg = CLAPAudioCfp(**audio_cfg)
434
+ if isinstance(text_cfg, dict):
435
+ text_cfg = CLAPTextCfg(**text_cfg)
436
+
437
+ self.audio_cfg = audio_cfg
438
+ self.text_cfg = text_cfg
439
+ self.enable_fusion = enable_fusion
440
+ self.fusion_type = fusion_type
441
+ self.joint_embed_shape = joint_embed_shape
442
+ self.mlp_act = mlp_act
443
+
444
+ self.context_length = text_cfg.context_length
445
+
446
+ # OpenAI models are pretrained w/ QuickGELU but native nn.GELU is both faster and more
447
+ # memory efficient in recent PyTorch releases (>= 1.10).
448
+ # NOTE: timm models always use native GELU regardless of quick_gelu flag.
449
+ act_layer = QuickGELU if quick_gelu else nn.GELU
450
+
451
+ if mlp_act == "relu":
452
+ mlp_act_layer = nn.ReLU()
453
+ elif mlp_act == "gelu":
454
+ mlp_act_layer = nn.GELU()
455
+ else:
456
+ raise NotImplementedError
457
+
458
+ # audio branch
459
+ # audio branch parameters
460
+ if audio_cfg.model_type == "PANN":
461
+ self.audio_branch = create_pann_model(audio_cfg, enable_fusion, fusion_type)
462
+ elif audio_cfg.model_type == "HTSAT":
463
+ self.audio_branch = create_htsat_model(
464
+ audio_cfg, enable_fusion, fusion_type
465
+ )
466
+ else:
467
+ logging.error(f"Model config for {audio_cfg.model_type} not found")
468
+ raise RuntimeError(f"Model config for {audio_cfg.model_type} not found.")
469
+
470
+ # text branch
471
+ # text branch parameters
472
+ if text_cfg.model_type == "transformer":
473
+ self.text_branch = Transformer(
474
+ width=text_cfg.width,
475
+ layers=text_cfg.layers,
476
+ heads=text_cfg.heads,
477
+ act_layer=act_layer,
478
+ )
479
+ self.vocab_size = text_cfg.vocab_size
480
+ self.token_embedding = nn.Embedding(text_cfg.vocab_size, text_cfg.width)
481
+ self.positional_embedding = nn.Parameter(
482
+ torch.empty(self.context_length, text_cfg.width)
483
+ )
484
+ self.ln_final = LayerNorm(text_cfg.width)
485
+ self.text_transform = MLPLayers(
486
+ units=[
487
+ self.joint_embed_shape,
488
+ self.joint_embed_shape,
489
+ self.joint_embed_shape,
490
+ ],
491
+ dropout=0.1,
492
+ )
493
+ self.text_projection = nn.Sequential(
494
+ nn.Linear(text_cfg.width, self.joint_embed_shape),
495
+ mlp_act_layer,
496
+ nn.Linear(self.joint_embed_shape, self.joint_embed_shape),
497
+ )
498
+ elif text_cfg.model_type == "bert":
499
+ self.text_branch = BertModel.from_pretrained("bert-base-uncased")
500
+ self.text_transform = MLPLayers(
501
+ units=[
502
+ self.joint_embed_shape,
503
+ self.joint_embed_shape,
504
+ self.joint_embed_shape,
505
+ ],
506
+ dropout=0.1,
507
+ )
508
+ self.text_projection = nn.Sequential(
509
+ nn.Linear(768, self.joint_embed_shape),
510
+ mlp_act_layer,
511
+ nn.Linear(self.joint_embed_shape, self.joint_embed_shape),
512
+ )
513
+ elif text_cfg.model_type == "roberta":
514
+ self.text_branch = RobertaModel(
515
+ RobertaConfig.from_pretrained("roberta-base")
516
+ )
517
+ self.text_transform = MLPLayers(
518
+ units=[
519
+ self.joint_embed_shape,
520
+ self.joint_embed_shape,
521
+ self.joint_embed_shape,
522
+ ],
523
+ dropout=0.1,
524
+ )
525
+ self.text_projection = nn.Sequential(
526
+ nn.Linear(768, self.joint_embed_shape),
527
+ mlp_act_layer,
528
+ nn.Linear(self.joint_embed_shape, self.joint_embed_shape),
529
+ )
530
+ elif text_cfg.model_type == "bart":
531
+ self.text_branch = BartModel.from_pretrained("facebook/bart-base")
532
+ self.text_transform = MLPLayers(
533
+ units=[
534
+ self.joint_embed_shape,
535
+ self.joint_embed_shape,
536
+ self.joint_embed_shape,
537
+ ],
538
+ dropout=0.1,
539
+ )
540
+ self.text_projection = nn.Sequential(
541
+ nn.Linear(768, self.joint_embed_shape),
542
+ mlp_act_layer,
543
+ nn.Linear(self.joint_embed_shape, self.joint_embed_shape),
544
+ )
545
+ else:
546
+ logging.error(f"Model config for {text_cfg.model_type} not found")
547
+ raise RuntimeError(f"Model config for {text_cfg.model_type} not found.")
548
+ self.text_branch_type = text_cfg.model_type
549
+ # text branch parameters
550
+
551
+ # audio branch parameters
552
+ self.audio_transform = MLPLayers(
553
+ units=[
554
+ self.joint_embed_shape,
555
+ self.joint_embed_shape,
556
+ self.joint_embed_shape,
557
+ ],
558
+ dropout=0.1,
559
+ )
560
+
561
+ # below here is text branch parameters
562
+
563
+ # ============================================================================================================
564
+ self.audio_projection = nn.Sequential(
565
+ nn.Linear(embed_dim, self.joint_embed_shape),
566
+ mlp_act_layer,
567
+ nn.Linear(self.joint_embed_shape, self.joint_embed_shape),
568
+ )
569
+
570
+ self.logit_scale_a = nn.Parameter(torch.ones([]) * np.log(1 / 0.07))
571
+ self.logit_scale_t = nn.Parameter(torch.ones([]) * np.log(1 / 0.07))
572
+ self.register_buffer("attn_mask", self.build_attention_mask(), persistent=False)
573
+
574
+ self.init_text_branch_parameters()
575
+
576
+ def init_text_branch_parameters(self):
577
+ if self.text_branch_type == "transformer":
578
+ nn.init.normal_(self.token_embedding.weight, std=0.02)
579
+ nn.init.normal_(self.positional_embedding, std=0.01)
580
+ proj_std = (self.text_branch.width**-0.5) * (
581
+ (2 * self.text_branch.layers) ** -0.5
582
+ )
583
+ attn_std = self.text_branch.width**-0.5
584
+ fc_std = (2 * self.text_branch.width) ** -0.5
585
+ for block in self.text_branch.resblocks:
586
+ nn.init.normal_(block.attn.in_proj_weight, std=attn_std)
587
+ nn.init.normal_(block.attn.out_proj.weight, std=proj_std)
588
+ nn.init.normal_(block.mlp.c_fc.weight, std=fc_std)
589
+ nn.init.normal_(block.mlp.c_proj.weight, std=proj_std)
590
+ if self.text_branch_type == "bert" or self.text_branch_type == "roberta":
591
+ self.text_branch.embeddings.word_embeddings.weight.shape[-1]
592
+ elif self.text_branch_type == "bart":
593
+ self.text_branch.shared.weight.shape[-1]
594
+ else:
595
+ self.text_branch.width
596
+ nn.init.constant_(self.logit_scale_a, np.log(1 / 0.07))
597
+ nn.init.constant_(self.logit_scale_t, np.log(1 / 0.07))
598
+
599
+ # deprecated
600
+ # if hasattr(self.visual, 'init_parameters'):
601
+ # self.visual.init_parameters()
602
+
603
+ # if self.text_projection is not None:
604
+ # nn.init.normal_(self.text_projection, std=width**-0.5)
605
+
606
+ def build_attention_mask(self):
607
+ # lazily create causal attention mask, with full attention between the vision tokens
608
+ # pytorch uses additive attention mask; fill with -inf
609
+ mask = torch.empty(self.context_length, self.context_length)
610
+ mask.fill_(float("-inf"))
611
+ mask.triu_(1) # zero out the lower diagonal
612
+ return mask
613
+
614
+ def encode_audio(self, audio, device):
615
+ return self.audio_branch(
616
+ audio, mixup_lambda=None, device=device
617
+ ) # mix lambda needs to add
618
+
619
+ # def list_of_dict_of_tensor2dict_of_tensor(self, x, device):
620
+ # tmp = {}
621
+ # for k in x[0].keys():
622
+ # tmp[k] = []
623
+ # for i in range(len(x)):
624
+ # tmp[k].append(x[i][k][:77])
625
+ # for k in x[0].keys():
626
+ # tmp[k] = torch.tensor(tmp[k]).to(device=device, non_blocking=True)
627
+ # return tmp
628
+
629
+ def encode_text(self, text, device):
630
+ if self.text_branch_type == "transformer":
631
+ text = text.to(device=device, non_blocking=True)
632
+ x = self.token_embedding(text) # [batch_size, n_ctx, d_model]
633
+
634
+ x = x + self.positional_embedding
635
+ x = x.permute(1, 0, 2) # NLD -> LND
636
+ x = self.text_branch(x, attn_mask=self.attn_mask)
637
+ x = x.permute(1, 0, 2) # LND -> NLD
638
+ x = self.ln_final(x)
639
+
640
+ # x.shape = [batch_size, n_ctx, transformer.width]
641
+ # take features from the eot embedding (eot_token is the highest number in each sequence)
642
+ x = self.text_projection(x[torch.arange(x.shape[0]), text.argmax(dim=-1)])
643
+ elif self.text_branch_type == "bert":
644
+ # text = self.list_of_dict_of_tensor2dict_of_tensor(text, device)
645
+ # text = BatchEncoding(text)
646
+ x = self.text_branch(
647
+ input_ids=text["input_ids"].to(device=device, non_blocking=True),
648
+ attention_mask=text["attention_mask"].to(
649
+ device=device, non_blocking=True
650
+ ),
651
+ token_type_ids=text["token_type_ids"].to(
652
+ device=device, non_blocking=True
653
+ ),
654
+ )["pooler_output"]
655
+ x = self.text_projection(x)
656
+ elif self.text_branch_type == "roberta":
657
+ x = self.text_branch(
658
+ input_ids=text["input_ids"].to(device=device, non_blocking=True),
659
+ attention_mask=text["attention_mask"].to(
660
+ device=device, non_blocking=True
661
+ ),
662
+ )["pooler_output"]
663
+ x = self.text_projection(x)
664
+ elif self.text_branch_type == "bart":
665
+ x = torch.mean(
666
+ self.text_branch(
667
+ input_ids=text["input_ids"].to(device=device, non_blocking=True),
668
+ attention_mask=text["attention_mask"].to(
669
+ device=device, non_blocking=True
670
+ ),
671
+ )["encoder_last_hidden_state"],
672
+ axis=1,
673
+ )
674
+ x = self.text_projection(x)
675
+ else:
676
+ logging.error(f"Model type {self.text_branch_type} not found")
677
+ raise RuntimeError(f"Model type {self.text_branch_type} not found.")
678
+ return x
679
+
680
+ def forward(self, audio, text, device=None):
681
+ """Forward audio and text into the CLAP
682
+
683
+ Parameters
684
+ ----------
685
+ audio: torch.Tensor (batch_size, audio_length)
686
+ the time-domain audio input / the batch of mel_spec and longer list.
687
+ text: torch.Tensor () // need to add
688
+ the text token input
689
+ """
690
+ if device is None:
691
+ if audio is not None:
692
+ device = audio.device
693
+ elif text is not None:
694
+ device = text.device
695
+ if audio is None and text is None:
696
+ # a hack to get the logit scale
697
+ return self.logit_scale_a.exp(), self.logit_scale_t.exp()
698
+ elif audio is None:
699
+ return self.encode_text(text, device=device)
700
+ elif text is None:
701
+ return self.audio_projection(
702
+ self.encode_audio(audio, device=device)["embedding"]
703
+ )
704
+ audio_features = self.audio_projection(
705
+ self.encode_audio(audio, device=device)["embedding"]
706
+ )
707
+ audio_features = F.normalize(audio_features, dim=-1)
708
+
709
+ text_features = self.encode_text(text, device=device)
710
+ # print("text_features", text_features)
711
+ # print("text_features.shape", text_features.shape)
712
+ # print("text_features.type", type(text_features))
713
+ text_features = F.normalize(text_features, dim=-1)
714
+
715
+ audio_features_mlp = self.audio_transform(audio_features)
716
+ text_features_mlp = self.text_transform(text_features)
717
+ # Four outputs: audio features (basic & MLP), text features (basic & MLP)
718
+ return (
719
+ audio_features,
720
+ text_features,
721
+ audio_features_mlp,
722
+ text_features_mlp,
723
+ self.logit_scale_a.exp(),
724
+ self.logit_scale_t.exp(),
725
+ )
726
+
727
+ def get_logit_scale(self):
728
+ return self.logit_scale_a.exp(), self.logit_scale_t.exp()
729
+
730
+ def get_text_embedding(self, data):
731
+ """Get the text embedding from the model
732
+
733
+ Parameters
734
+ ----------
735
+ data: torch.Tensor
736
+ a tensor of text embedding
737
+
738
+ Returns
739
+ ----------
740
+ text_embed: torch.Tensor
741
+ a tensor of text_embeds (N, D)
742
+
743
+ """
744
+ device = next(self.parameters()).device
745
+ for k in data:
746
+ data[k] = data[k].to(device)
747
+ text_embeds = self.encode_text(data, device=device)
748
+ text_embeds = F.normalize(text_embeds, dim=-1)
749
+
750
+ return text_embeds
751
+
752
+ def get_audio_embedding(self, data):
753
+ """Get the audio embedding from the model
754
+
755
+ Parameters
756
+ ----------
757
+ data: a list of dict
758
+ the audio input dict list from 'get_audio_feature' method
759
+
760
+ Returns
761
+ ----------
762
+ audio_embed: torch.Tensor
763
+ a tensor of audio_embeds (N, D)
764
+
765
+ """
766
+ device = next(self.parameters()).device
767
+ # input_dict = {}
768
+ # keys = data[0].keys()
769
+ # for k in keys:
770
+ # input_dict[k] = torch.cat([d[k].unsqueeze(0) for d in data], dim=0).to(
771
+ # device
772
+ # )
773
+ audio_embeds = self.audio_projection(
774
+ self.encode_audio(data, device=device)["embedding"]
775
+ )
776
+ audio_embeds = F.normalize(audio_embeds, dim=-1)
777
+
778
+ return audio_embeds
779
+
780
+ def audio_infer(self, audio, hopsize=None, device=None):
781
+ """Forward one audio and produce the audio embedding
782
+
783
+ Parameters
784
+ ----------
785
+ audio: (audio_length)
786
+ the time-domain audio input, notice that it must be only one input
787
+ hopsize: int
788
+ the overlap hopsize as the sliding window
789
+
790
+ Returns
791
+ ----------
792
+ output_dict: {
793
+ key: [n, (embedding_shape)] if "HTS-AT"
794
+ or
795
+ key: [(embedding_shape)] if "PANN"
796
+ }
797
+ the list of key values of the audio branch
798
+
799
+ """
800
+
801
+ assert not self.training, "the inference mode must be run at eval stage"
802
+ output_dict = {}
803
+ # PANN
804
+ if self.audio_cfg.model_type == "PANN":
805
+ audio_input = audio.unsqueeze(dim=0)
806
+ output_dict[key] = self.encode_audio(audio_input, device=device)[
807
+ key
808
+ ].squeeze(dim=0)
809
+ elif self.audio_cfg.model_type == "HTSAT":
810
+ # repeat
811
+ audio_len = len(audio)
812
+ k = self.audio_cfg.clip_samples // audio_len
813
+ if k > 1:
814
+ audio = audio.repeat(k)
815
+ audio_len = len(audio)
816
+
817
+ if hopsize is None:
818
+ hopsize = min(hopsize, audio_len)
819
+
820
+ if audio_len > self.audio_cfg.clip_samples:
821
+ audio_input = [
822
+ audio[pos : pos + self.audio_cfg.clip_samples].clone()
823
+ for pos in range(
824
+ 0, audio_len - self.audio_cfg.clip_samples, hopsize
825
+ )
826
+ ]
827
+ audio_input.append(audio[-self.audio_cfg.clip_samples :].clone())
828
+ audio_input = torch.stack(audio_input)
829
+ output_dict[key] = self.encode_audio(audio_input, device=device)[key]
830
+ else:
831
+ audio_input = audio.unsqueeze(dim=0)
832
+ output_dict[key] = self.encode_audio(audio_input, device=device)[
833
+ key
834
+ ].squeeze(dim=0)
835
+
836
+ return output_dict
837
+
838
+
839
+ def convert_weights_to_fp16(model: nn.Module):
840
+ """Convert applicable model parameters to fp16"""
841
+
842
+ def _convert_weights_to_fp16(l):
843
+ if isinstance(l, (nn.Conv1d, nn.Conv2d, nn.Linear)):
844
+ l.weight.data = l.weight.data.half()
845
+ if l.bias is not None:
846
+ l.bias.data = l.bias.data.half()
847
+
848
+ if isinstance(l, nn.MultiheadAttention):
849
+ for attr in [
850
+ *[f"{s}_proj_weight" for s in ["in", "q", "k", "v"]],
851
+ "in_proj_bias",
852
+ "bias_k",
853
+ "bias_v",
854
+ ]:
855
+ tensor = getattr(l, attr)
856
+ if tensor is not None:
857
+ tensor.data = tensor.data.half()
858
+
859
+ for name in ["text_projection", "proj"]:
860
+ if hasattr(l, name):
861
+ attr = getattr(l, name)
862
+ if attr is not None:
863
+ attr.data = attr.data.half()
864
+
865
+ model.apply(_convert_weights_to_fp16)
866
+
867
+
868
+ # Ignore the state dict of the vision part
869
+ def build_model_from_openai_state_dict(
870
+ state_dict: dict, model_cfg, enable_fusion: bool = False, fusion_type: str = "None"
871
+ ):
872
+ embed_dim = model_cfg["embed_dim"]
873
+ audio_cfg = model_cfg["audio_cfg"]
874
+ text_cfg = model_cfg["text_cfg"]
875
+ state_dict["positional_embedding"].shape[0]
876
+ state_dict["token_embedding.weight"].shape[0]
877
+ transformer_width = state_dict["ln_final.weight"].shape[0]
878
+ transformer_width // 64
879
+ transformer_layers = len(
880
+ set(
881
+ k.split(".")[2]
882
+ for k in state_dict
883
+ if k.startswith(f"transformer.resblocks")
884
+ )
885
+ )
886
+
887
+ audio_cfg = CLAPAudioCfp(**audio_cfg)
888
+ text_cfg = CLAPTextCfg(**text_cfg)
889
+
890
+ model = CLAP(
891
+ embed_dim,
892
+ audio_cfg=audio_cfg,
893
+ text_cfg=text_cfg,
894
+ quick_gelu=True, # OpenAI models were trained with QuickGELU
895
+ enable_fusion=enable_fusion,
896
+ fusion_type=fusion_type,
897
+ )
898
+ state_dict["logit_scale_a"] = state_dict["logit_scale"]
899
+ state_dict["logit_scale_t"] = state_dict["logit_scale"]
900
+ pop_keys = list(state_dict.keys())[::]
901
+ # pop the visual branch saved weights
902
+ for key in pop_keys:
903
+ if key.startswith("visual."):
904
+ state_dict.pop(key, None)
905
+
906
+ for key in ["logit_scale", "input_resolution", "context_length", "vocab_size"]:
907
+ state_dict.pop(key, None)
908
+
909
+ # not use fp16
910
+ # convert_weights_to_fp16(model)
911
+ model.load_state_dict(state_dict, strict=False)
912
+ return model.eval()
913
+
914
+
915
+ def trace_model(model, batch_size=256, device=torch.device("cpu")):
916
+ model.eval()
917
+ audio_length = model.audio_cfg.audio_length
918
+ example_audio = torch.ones((batch_size, audio_length), device=device)
919
+ example_text = torch.zeros(
920
+ (batch_size, model.context_length), dtype=torch.int, device=device
921
+ )
922
+ model = torch.jit.trace_module(
923
+ model,
924
+ inputs=dict(
925
+ forward=(example_audio, example_text),
926
+ encode_text=(example_text,),
927
+ encode_image=(example_audio,),
928
+ ),
929
+ )
930
+ model.audio_cfg.audio_length = audio_length # Question: what does this do?
931
+ return model
audioldm2/clap/open_clip/model_configs/HTSAT-base.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "embed_dim": 1024,
3
+ "audio_cfg": {
4
+ "audio_length": 1024,
5
+ "clip_samples": 480000,
6
+ "mel_bins": 64,
7
+ "sample_rate": 48000,
8
+ "window_size": 1024,
9
+ "hop_size": 480,
10
+ "fmin": 50,
11
+ "fmax": 14000,
12
+ "class_num": 527,
13
+ "model_type": "HTSAT",
14
+ "model_name": "base"
15
+ },
16
+ "text_cfg": {
17
+ "context_length": 77,
18
+ "vocab_size": 49408,
19
+ "width": 512,
20
+ "heads": 8,
21
+ "layers": 12
22
+ }
23
+ }
audioldm2/clap/open_clip/model_configs/HTSAT-large.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "embed_dim": 2048,
3
+ "audio_cfg": {
4
+ "audio_length": 1024,
5
+ "clip_samples": 480000,
6
+ "mel_bins": 64,
7
+ "sample_rate": 48000,
8
+ "window_size": 1024,
9
+ "hop_size": 480,
10
+ "fmin": 50,
11
+ "fmax": 14000,
12
+ "class_num": 527,
13
+ "model_type": "HTSAT",
14
+ "model_name": "large"
15
+ },
16
+ "text_cfg": {
17
+ "context_length": 77,
18
+ "vocab_size": 49408,
19
+ "width": 512,
20
+ "heads": 8,
21
+ "layers": 12
22
+ }
23
+ }
audioldm2/clap/open_clip/model_configs/HTSAT-tiny-win-1536.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "embed_dim": 768,
3
+ "audio_cfg": {
4
+ "audio_length": 1024,
5
+ "clip_samples": 480000,
6
+ "mel_bins": 64,
7
+ "sample_rate": 48000,
8
+ "window_size": 1536,
9
+ "hop_size": 480,
10
+ "fmin": 50,
11
+ "fmax": 14000,
12
+ "class_num": 527,
13
+ "model_type": "HTSAT",
14
+ "model_name": "tiny"
15
+ },
16
+ "text_cfg": {
17
+ "context_length": 77,
18
+ "vocab_size": 49408,
19
+ "width": 512,
20
+ "heads": 8,
21
+ "layers": 12
22
+ }
23
+ }
audioldm2/clap/open_clip/model_configs/HTSAT-tiny.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "embed_dim": 768,
3
+ "audio_cfg": {
4
+ "audio_length": 1024,
5
+ "clip_samples": 480000,
6
+ "mel_bins": 64,
7
+ "sample_rate": 48000,
8
+ "window_size": 1024,
9
+ "hop_size": 480,
10
+ "fmin": 50,
11
+ "fmax": 14000,
12
+ "class_num": 527,
13
+ "model_type": "HTSAT",
14
+ "model_name": "tiny"
15
+ },
16
+ "text_cfg": {
17
+ "context_length": 77,
18
+ "vocab_size": 49408,
19
+ "width": 512,
20
+ "heads": 8,
21
+ "layers": 12
22
+ }
23
+ }
audioldm2/clap/open_clip/model_configs/PANN-10.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "embed_dim": 1024,
3
+ "audio_cfg": {
4
+ "audio_length": 1024,
5
+ "clip_samples": 480000,
6
+ "mel_bins": 64,
7
+ "sample_rate": 48000,
8
+ "window_size": 1024,
9
+ "hop_size": 480,
10
+ "fmin": 50,
11
+ "fmax": 14000,
12
+ "class_num": 527,
13
+ "model_type": "PANN",
14
+ "model_name": "Cnn10"
15
+ },
16
+ "text_cfg": {
17
+ "context_length": 77,
18
+ "vocab_size": 49408,
19
+ "width": 512,
20
+ "heads": 8,
21
+ "layers": 12
22
+ }
23
+ }
audioldm2/clap/open_clip/model_configs/PANN-14-fmax-18k.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "embed_dim": 2048,
3
+ "audio_cfg": {
4
+ "audio_length": 1024,
5
+ "clip_samples": 480000,
6
+ "mel_bins": 64,
7
+ "sample_rate": 48000,
8
+ "window_size": 1024,
9
+ "hop_size": 480,
10
+ "fmin": 50,
11
+ "fmax": 18000,
12
+ "class_num": 527,
13
+ "model_type": "PANN",
14
+ "model_name": "Cnn14"
15
+ },
16
+ "text_cfg": {
17
+ "context_length": 77,
18
+ "vocab_size": 49408,
19
+ "width": 512,
20
+ "heads": 8,
21
+ "layers": 12
22
+ }
23
+ }
audioldm2/clap/open_clip/model_configs/PANN-14-fmax-8k-20s.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "embed_dim": 2048,
3
+ "audio_cfg": {
4
+ "audio_length": 1024,
5
+ "clip_samples": 960000,
6
+ "mel_bins": 64,
7
+ "sample_rate": 48000,
8
+ "window_size": 1024,
9
+ "hop_size": 360,
10
+ "fmin": 50,
11
+ "fmax": 8000,
12
+ "class_num": 527,
13
+ "model_type": "PANN",
14
+ "model_name": "Cnn14"
15
+ },
16
+ "text_cfg": {
17
+ "context_length": 77,
18
+ "vocab_size": 49408,
19
+ "width": 512,
20
+ "heads": 8,
21
+ "layers": 12
22
+ }
23
+ }
audioldm2/clap/open_clip/model_configs/PANN-14-tiny-transformer.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "embed_dim": 2048,
3
+ "audio_cfg": {
4
+ "audio_length": 1024,
5
+ "clip_samples": 480000,
6
+ "mel_bins": 64,
7
+ "sample_rate": 48000,
8
+ "window_size": 1024,
9
+ "hop_size": 480,
10
+ "fmin": 50,
11
+ "fmax": 14000,
12
+ "class_num": 527,
13
+ "model_type": "PANN",
14
+ "model_name": "Cnn14"
15
+ },
16
+ "text_cfg": {
17
+ "context_length": 77,
18
+ "vocab_size": 49408,
19
+ "width": 512,
20
+ "heads": 8,
21
+ "layers": 4
22
+ }
23
+ }
audioldm2/clap/open_clip/model_configs/PANN-14-win-1536.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "embed_dim": 2048,
3
+ "audio_cfg": {
4
+ "audio_length": 1024,
5
+ "clip_samples": 480000,
6
+ "mel_bins": 64,
7
+ "sample_rate": 48000,
8
+ "window_size": 1536,
9
+ "hop_size": 480,
10
+ "fmin": 50,
11
+ "fmax": 14000,
12
+ "class_num": 527,
13
+ "model_type": "PANN",
14
+ "model_name": "Cnn14"
15
+ },
16
+ "text_cfg": {
17
+ "context_length": 77,
18
+ "vocab_size": 49408,
19
+ "width": 512,
20
+ "heads": 8,
21
+ "layers": 12
22
+ }
23
+ }
audioldm2/clap/open_clip/model_configs/PANN-14.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "embed_dim": 2048,
3
+ "audio_cfg": {
4
+ "audio_length": 1024,
5
+ "clip_samples": 480000,
6
+ "mel_bins": 64,
7
+ "sample_rate": 48000,
8
+ "window_size": 1024,
9
+ "hop_size": 480,
10
+ "fmin": 50,
11
+ "fmax": 14000,
12
+ "class_num": 527,
13
+ "model_type": "PANN",
14
+ "model_name": "Cnn14"
15
+ },
16
+ "text_cfg": {
17
+ "context_length": 77,
18
+ "vocab_size": 49408,
19
+ "width": 512,
20
+ "heads": 8,
21
+ "layers": 12
22
+ }
23
+ }
audioldm2/clap/open_clip/model_configs/PANN-6.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "embed_dim": 512,
3
+ "audio_cfg": {
4
+ "audio_length": 1024,
5
+ "clip_samples": 480000,
6
+ "mel_bins": 64,
7
+ "sample_rate": 48000,
8
+ "window_size": 1024,
9
+ "hop_size": 480,
10
+ "fmin": 50,
11
+ "fmax": 14000,
12
+ "class_num": 527,
13
+ "model_type": "PANN",
14
+ "model_name": "Cnn6"
15
+ },
16
+ "text_cfg": {
17
+ "context_length": 77,
18
+ "vocab_size": 49408,
19
+ "width": 512,
20
+ "heads": 8,
21
+ "layers": 12
22
+ }
23
+ }
audioldm2/clap/open_clip/model_configs/RN101-quickgelu.json ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "embed_dim": 512,
3
+ "quick_gelu": true,
4
+ "vision_cfg": {
5
+ "image_size": 224,
6
+ "layers": [
7
+ 3,
8
+ 4,
9
+ 23,
10
+ 3
11
+ ],
12
+ "width": 64,
13
+ "patch_size": null
14
+ },
15
+ "text_cfg": {
16
+ "context_length": 77,
17
+ "vocab_size": 49408,
18
+ "width": 512,
19
+ "heads": 8,
20
+ "layers": 12
21
+ }
22
+ }