audiolm-pytorch

repository·main·Indexed 25 days ago

https://github.com/lucidrains/audiolm-pytorch

A PyTorch implementation of AudioLM (Language Modeling Approach to Audio Generation). It features hierarchical transformer training via SemanticTransformer, CoarseTransformer, and FineTransformer, and supports text-to-audio and TTS capabilities through T5 conditioning. The library includes tools for neural codecs like SoundStream and EncodecWrapper, as well as integrated support for Hugging Face accelerate for multi-GPU training and Weights & Biases tracking.

Tokens
3.7K
Snippets
12
Records
13
Agent score
33%

What's inside audiolm-pytorch

  1. Enable Weights & Biases tracking for SoundStreamTrainer

    main

    To use Weights & Biases, set use_wandb_tracking = True in the SoundStreamTrainer and wrap the .train() call with the wandb_tracker context manager.

    trainer = SoundStreamTrainer(
        soundstream,
        ...,
        use_wandb_tracking = True
    )
    
    with trainer.wandb_tracker(project = 'soundstream', run = 'baseline'):
        trainer.train()
  2. Train Hierarchical Transformers for AudioLM

    main

    AudioLM requires training three separate transformers in a hierarchy: SemanticTransformer, CoarseTransformer, and FineTransformer.

    1. SemanticTransformer: Uses HubertWithKmeans to model semantic tokens.
    2. CoarseTransformer: Models coarse acoustic tokens using the SoundStream codec.
    3. FineTransformer: Models fine acoustic tokens using the SoundStream codec.

    Each transformer has a corresponding trainer: SemanticTransformerTrainer, CoarseTransformerTrainer, and FineTransformerTrainer.

  3. Perform Multi-GPU training with Accelerate

    main

    The trainer classes in audiolm-pytorch use Hugging Face accelerate. To run training on multiple GPUs, use the accelerate CLI.

    First, configure your environment:

    $ accelerate config

    Then, launch your training script (e.g., train.py):

    $ accelerate launch train.py
    $ accelerate config
    $ accelerate launch train.py
  4. Implement Text Conditioned Audio Synthesis with SemanticTransformer

    main

    To perform text-conditioned audio synthesis (similar to VALL-E), use the SemanticTransformer and SemanticTransformerTrainer.

    1. Initialize HubertWithKmeans: Load a pre-trained Hubert model and its corresponding K-means quantization file.
    2. Configure SemanticTransformer: Set has_condition = True. You can use cond_as_self_attn_prefix = True to condition via self-attention prefix instead of cross-attention.
    3. Prepare Dataset: Extend torch.utils.data.Dataset to return a tuple containing a string (the text caption) and an audio tensor. The framework automatically routes these to the transformer.
    4. Train: Use SemanticTransformerTrainer to manage the training loop.
    5. Generate: Use trainer.generate(text=[...]) to synthesize audio from text prompts.
    import torch
    from audiolm_pytorch import HubertWithKmeans, SemanticTransformer, SemanticTransformerTrainer
    from torch.utils.data import Dataset
    
    # 1. Setup Wav2Vec/Hubert
    wav2vec = HubertWithKmeans(
        checkpoint_path = './hubert/hubert_base_ls960.pt',
        kmeans_path = './hubert/hubert_base_ls960_L9_km500.bin'
    )
    
    # 2. Setup Semantic Transformer
    semantic_transformer = SemanticTransformer(
        num_semantic_tokens = 500,
        dim = 1024,
        depth = 6,
        has_condition = True,
        cond_as_self_attn_prefix = True
    ).cuda()
    
    # 3. Define Dataset (must return caption and audio)
    class MockTextAudioDataset(Dataset):
        def __init__(self, length = 100, audio_length = 320 * 32):
            super().__init__()
            self.audio_length = audio_length
            self.len = length
    
        def __len__(self):
            return self.len
    
        def __getitem__(self, idx):
            mock_audio = torch.randn(self.audio_length)
            mock_caption = 'audio caption'
            return mock_caption, mock_audio
    
    dataset = MockTextAudioDataset()
    
    # 4. Train
    trainer = SemanticTransformerTrainer(
        transformer = semantic_transformer,
        wav2vec = wav2vec,
        dataset = dataset,
        batch_size = 4,
        grad_accum_every = 8,
        data_max_length = 320 * 32,
        num_train_steps = 1_000_000
    )
    
    trainer.train()
    
    # 5. Generate
    sample = trainer.generate(text = ['sound of rain drops on the rooftops'], batch_size = 1, max_length = 2)
  5. Train and use SoundStream

    main

    You can train a SoundStream model using SoundStreamTrainer. Once trained, you can use it for audio autoencoding, tokenization, and decoding.

    Key features:

    • SoundStream.init_and_load_from(path): Loads a model from a checkpoint without needing to manually re-specify configurations.
    • soundstream.tokenize(audio): Converts audio to codebook indices.
    • soundstream.decode_from_codebook_indices(codes): Reconstructs audio from indices.
    • soundstream(audio, return_recons_only = True): Returns only the reconstructed audio.
    from audiolm_pytorch import SoundStream, SoundStreamTrainer
    
    soundstream = SoundStream(
        codebook_size = 4096,
        rq_num_quantizers = 8,
        rq_groups = 2,
        use_lookup_free_quantizer = True,
        use_finite_scalar_quantizer = False,
        attn_window_size = 128,
        attn_depth = 2
    )
    
    trainer = SoundStreamTrainer(
        soundstream,
        folder = '/path/to/audio/files',
        batch_size = 4,
        grad_accum_every = 8,
        data_max_length_seconds = 2,
        num_train_steps = 1_000_000
    ).cuda()
    
    trainer.train()
    
    # Testing autoencoding
    soundstream.eval()
    audio = torch.randn(10080).cuda()
    recons = soundstream(audio, return_recons_only = True)
    
    # Tokenization and decoding
    codes = soundstream.tokenize(audio)
    recon_audio_from_codes = soundstream.decode_from_codebook_indices(codes)
  6. Use the AudioLM model for generation

    main

    Once the hierarchical transformers are trained, combine them into an AudioLM object. You can generate audio via simple sampling, priming with an existing waveform, or conditioning on text.

    from audiolm_pytorch import AudioLM
    
    # Assuming wav2vec, soundstream, semantic_transformer, 
    # coarse_transformer, and fine_transformer are already defined/trained
    
    audiolm = AudioLM(
        wav2vec = wav2vec,
        codec = soundstream,
        semantic_transformer = semantic_transformer,
        coarse_transformer = coarse_transformer,
        fine_transformer = fine_transformer
    )
    
    # 1. Simple generation
    generated_wav = audiolm(batch_size = 1)
    
    # 2. Generation with priming
    generated_wav_with_prime = audiolm(prime_wave = torch.randn(1, 320 * 8))
    
    # 3. Generation with text conditioning
    generated_wav_with_text_condition = audiolm(text = ['chirping of birds and the distant echos of bells'])
  7. Perform Inference with AudioLM

    main

    Combine all trained components (wav2vec, codec, semantic_transformer, coarse_transformer, and fine_transformer) into an AudioLM instance to generate audio from scratch.

    # Everything together
    audiolm = AudioLM(
        wav2vec = wav2vec,
        codec = soundstream,
        semantic_transformer = semantic_transformer,
        coarse_transformer = coarse_transformer,
        fine_transformer = fine_transformer
    )
    
    generated_wav = audiolm(batch_size = 1)
    
    output_path = "out.wav"
    sample_rate = 44100
    torchaudio.save(output_path, generated_wav.cpu(), sample_rate)
  8. Train FineTransformer

    main

    Train the FineTransformer using FineTransformerTrainer. This component handles the final acoustic token generation, requiring a trained SoundStream codec.

    soundstream = SoundStream(
        codebook_size = 1024,
        rq_num_quantizers = 8,
    )
    soundstream.load(f"./{soundstream_ckpt}")
    
    fine_transformer = FineTransformer(
        num_coarse_quantizers = 3,
        num_fine_quantizers = 5,
        codebook_size = 1024,
        dim = 512,
        depth = 6
    )
    
    trainer = FineTransformerTrainer(
        transformer = fine_transformer,
        codec = soundstream,
        folder = dataset_folder,
        batch_size = 1,
        data_max_length = 320 * 32,
        num_train_steps = 9
    )
    
    trainer.train()
  9. Train CoarseTransformer

    main

    Train the CoarseTransformer using CoarseTransformerTrainer. This component bridges semantic tokens and acoustic tokens, requiring both a HubertWithKmeans instance and a trained SoundStream codec.

    wav2vec = HubertWithKmeans(
        checkpoint_path = f'./{hubert_ckpt}',
        kmeans_path = f'./{hubert_quantizer}'
    )
    
    soundstream = SoundStream(
        codebook_size = 1024,
        rq_num_quantizers = 8,
    )
    soundstream.load(f"./{soundstream_ckpt}")
    
    coarse_transformer = CoarseTransformer(
        num_semantic_tokens = wav2vec.codebook_size,
        codebook_size = 1024,
        num_coarse_quantizers = 3,
        dim = 512,
        depth = 6
    )
    
    trainer = CoarseTransformerTrainer(
        transformer = coarse_transformer,
        codec = soundstream,
        wav2vec = wav2vec,
        folder = dataset_folder,
        batch_size = 1,
        data_max_length = 320 * 32,
        save_results_every = 2,
        save_model_every = 4,
        num_train_steps = 9
    )
    
    trainer.train()
  10. Train SemanticTransformer

    main

    Train the SemanticTransformer using SemanticTransformerTrainer. This requires a HubertWithKmeans instance (wav2vec) to provide semantic tokens.

    wav2vec = HubertWithKmeans(
        checkpoint_path = f'./{hubert_ckpt}',
        kmeans_path = f'./{hubert_quantizer}'
    )
    
    semantic_transformer = SemanticTransformer(
        num_semantic_tokens = wav2vec.codebook_size,
        dim = 1024,
        depth = 6
    ).cuda()
    
    trainer = SemanticTransformerTrainer(
        transformer = semantic_transformer,
        wav2vec = wav2vec,
        folder = dataset_folder,
        batch_size = 1,
        data_max_length = 320 * 32,
        num_train_steps = 1
    )
    
    trainer.train()