CoolFace
Apppublic

jone/Music_Source_Separation

sourceHugging Faceupdated 4y agoView on Hugging Face
3likes
conditional_unet.py497 linesDownload Raw Back to models
1import math2from typing import List3 4import numpy as np5import matplotlib.pyplot as plt6import pytorch_lightning as pl7import torch8import torch.nn as nn9import torch.nn.functional as F10import torch.optim as optim11from torch.optim.lr_scheduler import LambdaLR12from torchlibrosa.stft import STFT, ISTFT, magphase13 14from bytesep.models.pytorch_modules import (15    Base,16    init_bn,17    init_embedding,18    init_layer,19    act,20    Subband,21)22 23 24class ConvBlock(nn.Module):25    def __init__(26        self,27        in_channels,28        out_channels,29        condition_size,30        kernel_size,31        activation,32        momentum,33    ):34        super(ConvBlock, self).__init__()35 36        self.activation = activation37        padding = (kernel_size[0] // 2, kernel_size[1] // 2)38 39        self.conv1 = nn.Conv2d(40            in_channels=in_channels,41            out_channels=out_channels,42            kernel_size=kernel_size,43            stride=(1, 1),44            dilation=(1, 1),45            padding=padding,46            bias=False,47        )48 49        self.bn1 = nn.BatchNorm2d(out_channels, momentum=momentum)50 51        self.conv2 = nn.Conv2d(52            in_channels=out_channels,53            out_channels=out_channels,54            kernel_size=kernel_size,55            stride=(1, 1),56            dilation=(1, 1),57            padding=padding,58            bias=False,59        )60 61        self.bn2 = nn.BatchNorm2d(out_channels, momentum=momentum)62 63        self.beta1 = nn.Linear(condition_size, out_channels, bias=True)64        self.beta2 = nn.Linear(condition_size, out_channels, bias=True)65 66        self.init_weights()67 68    def init_weights(self):69        init_layer(self.conv1)70        init_layer(self.conv2)71        init_bn(self.bn1)72        init_bn(self.bn2)73        init_embedding(self.beta1)74        init_embedding(self.beta2)75 76    def forward(self, x, condition):77 78        b1 = self.beta1(condition)[:, :, None, None]79        b2 = self.beta2(condition)[:, :, None, None]80 81        x = act(self.bn1(self.conv1(x)) + b1, self.activation)82        x = act(self.bn2(self.conv2(x)) + b2, self.activation)83        return x84 85 86class EncoderBlock(nn.Module):87    def __init__(88        self,89        in_channels,90        out_channels,91        condition_size,92        kernel_size,93        downsample,94        activation,95        momentum,96    ):97        super(EncoderBlock, self).__init__()98 99        self.conv_block = ConvBlock(100            in_channels, out_channels, condition_size, kernel_size, activation, momentum101        )102        self.downsample = downsample103 104    def forward(self, x, condition):105        encoder = self.conv_block(x, condition)106        encoder_pool = F.avg_pool2d(encoder, kernel_size=self.downsample)107        return encoder_pool, encoder108 109 110class DecoderBlock(nn.Module):111    def __init__(112        self,113        in_channels,114        out_channels,115        condition_size,116        kernel_size,117        upsample,118        activation,119        momentum,120    ):121        super(DecoderBlock, self).__init__()122        self.kernel_size = kernel_size123        self.stride = upsample124        self.activation = activation125 126        self.conv1 = torch.nn.ConvTranspose2d(127            in_channels=in_channels,128            out_channels=out_channels,129            kernel_size=self.stride,130            stride=self.stride,131            padding=(0, 0),132            bias=False,133            dilation=(1, 1),134        )135 136        self.bn1 = nn.BatchNorm2d(out_channels, momentum=momentum)137 138        self.conv_block2 = ConvBlock(139            out_channels * 2,140            out_channels,141            condition_size,142            kernel_size,143            activation,144            momentum,145        )146 147        self.beta1 = nn.Linear(condition_size, out_channels, bias=True)148 149        self.init_weights()150 151    def init_weights(self):152        init_layer(self.conv1)153        init_bn(self.bn1)154        init_embedding(self.beta1)155 156    def forward(self, input_tensor, concat_tensor, condition):157        b1 = self.beta1(condition)[:, :, None, None]158        x = act(self.bn1(self.conv1(input_tensor)) + b1, self.activation)159        x = torch.cat((x, concat_tensor), dim=1)160        x = self.conv_block2(x, condition)161        return x162 163 164class ConditionalUNet(nn.Module, Base):165    def __init__(self, input_channels, target_sources_num):166        super(ConditionalUNet, self).__init__()167 168        self.input_channels = input_channels169        condition_size = target_sources_num170        self.output_sources_num = 1171 172        window_size = 2048173        hop_size = 441174        center = True175        pad_mode = "reflect"176        window = "hann"177        activation = "relu"178        momentum = 0.01179 180        self.subbands_num = 4181        self.K = 3  # outputs: |M|, cos∠M, sin∠M182 183        self.downsample_ratio = 2 ** 6  # This number equals 2^{#encoder_blcoks}184 185        self.stft = STFT(186            n_fft=window_size,187            hop_length=hop_size,188            win_length=window_size,189            window=window,190            center=center,191            pad_mode=pad_mode,192            freeze_parameters=True,193        )194 195        self.istft = ISTFT(196            n_fft=window_size,197            hop_length=hop_size,198            win_length=window_size,199            window=window,200            center=center,201            pad_mode=pad_mode,202            freeze_parameters=True,203        )204 205        self.bn0 = nn.BatchNorm2d(window_size // 2 + 1, momentum=momentum)206 207        self.subband = Subband(subbands_num=self.subbands_num)208 209        self.encoder_block1 = EncoderBlock(210            in_channels=input_channels * self.subbands_num,211            out_channels=32,212            condition_size=condition_size,213            kernel_size=(3, 3),214            downsample=(2, 2),215            activation=activation,216            momentum=momentum,217        )218        self.encoder_block2 = EncoderBlock(219            in_channels=32,220            out_channels=64,221            condition_size=condition_size,222            kernel_size=(3, 3),223            downsample=(2, 2),224            activation=activation,225            momentum=momentum,226        )227        self.encoder_block3 = EncoderBlock(228            in_channels=64,229            out_channels=128,230            condition_size=condition_size,231            kernel_size=(3, 3),232            downsample=(2, 2),233            activation=activation,234            momentum=momentum,235        )236        self.encoder_block4 = EncoderBlock(237            in_channels=128,238            out_channels=256,239            condition_size=condition_size,240            kernel_size=(3, 3),241            downsample=(2, 2),242            activation=activation,243            momentum=momentum,244        )245        self.encoder_block5 = EncoderBlock(246            in_channels=256,247            out_channels=384,248            condition_size=condition_size,249            kernel_size=(3, 3),250            downsample=(2, 2),251            activation=activation,252            momentum=momentum,253        )254        self.encoder_block6 = EncoderBlock(255            in_channels=384,256            out_channels=384,257            condition_size=condition_size,258            kernel_size=(3, 3),259            downsample=(2, 2),260            activation=activation,261            momentum=momentum,262        )263        self.conv_block7 = ConvBlock(264            in_channels=384,265            out_channels=384,266            condition_size=condition_size,267            kernel_size=(3, 3),268            activation=activation,269            momentum=momentum,270        )271        self.decoder_block1 = DecoderBlock(272            in_channels=384,273            out_channels=384,274            condition_size=condition_size,275            kernel_size=(3, 3),276            upsample=(2, 2),277            activation=activation,278            momentum=momentum,279        )280        self.decoder_block2 = DecoderBlock(281            in_channels=384,282            out_channels=384,283            condition_size=condition_size,284            kernel_size=(3, 3),285            upsample=(2, 2),286            activation=activation,287            momentum=momentum,288        )289        self.decoder_block3 = DecoderBlock(290            in_channels=384,291            out_channels=256,292            condition_size=condition_size,293            kernel_size=(3, 3),294            upsample=(2, 2),295            activation=activation,296            momentum=momentum,297        )298        self.decoder_block4 = DecoderBlock(299            in_channels=256,300            out_channels=128,301            condition_size=condition_size,302            kernel_size=(3, 3),303            upsample=(2, 2),304            activation=activation,305            momentum=momentum,306        )307        self.decoder_block5 = DecoderBlock(308            in_channels=128,309            out_channels=64,310            condition_size=condition_size,311            kernel_size=(3, 3),312            upsample=(2, 2),313            activation=activation,314            momentum=momentum,315        )316        self.decoder_block6 = DecoderBlock(317            in_channels=64,318            out_channels=32,319            condition_size=condition_size,320            kernel_size=(3, 3),321            upsample=(2, 2),322            activation=activation,323            momentum=momentum,324        )325 326        self.after_conv_block1 = ConvBlock(327            in_channels=32,328            out_channels=32,329            condition_size=condition_size,330            kernel_size=(3, 3),331            activation=activation,332            momentum=momentum,333        )334 335        self.after_conv2 = nn.Conv2d(336            in_channels=32,337            out_channels=input_channels338            * self.subbands_num339            * self.output_sources_num340            * self.K,341            kernel_size=(1, 1),342            stride=(1, 1),343            padding=(0, 0),344            bias=True,345        )346 347        self.init_weights()348 349    def init_weights(self):350        init_bn(self.bn0)351        init_layer(self.after_conv2)352 353    def feature_maps_to_wav(self, x, sp, sin_in, cos_in, audio_length):354 355        batch_size, _, time_steps, freq_bins = x.shape356 357        x = x.reshape(358            batch_size,359            self.output_sources_num,360            self.input_channels,361            self.K,362            time_steps,363            freq_bins,364        )365        # x: (batch_size, output_sources_num, input_channles, K, time_steps, freq_bins)366 367        mask_mag = torch.sigmoid(x[:, :, :, 0, :, :])368        _mask_real = torch.tanh(x[:, :, :, 1, :, :])369        _mask_imag = torch.tanh(x[:, :, :, 2, :, :])370        _, mask_cos, mask_sin = magphase(_mask_real, _mask_imag)371        # mask_cos, mask_sin: (batch_size, output_sources_num, input_channles, time_steps, freq_bins)372 373        # Y = |Y|cos∠Y + j|Y|sin∠Y374        #   = |Y|cos(∠X + ∠M) + j|Y|sin(∠X + ∠M)375        #   = |Y|(cos∠X cos∠M - sin∠X sin∠M) + j|Y|(sin∠X cos∠M + cos∠X sin∠M)376        out_cos = (377            cos_in[:, None, :, :, :] * mask_cos - sin_in[:, None, :, :, :] * mask_sin378        )379        out_sin = (380            sin_in[:, None, :, :, :] * mask_cos + cos_in[:, None, :, :, :] * mask_sin381        )382        # out_cos, out_sin: (batch_size, output_sources_num, input_channles, time_steps, freq_bins)383 384        # Calculate |Y|.385        out_mag = F.relu_(sp[:, None, :, :, :] * mask_mag)386        # out_mag: (batch_size, output_sources_num, input_channles, time_steps, freq_bins)387 388        # Calculate Y_{real} and Y_{imag} for ISTFT.389        out_real = out_mag * out_cos390        out_imag = out_mag * out_sin391        # out_real, out_imag: (batch_size, output_sources_num, input_channles, time_steps, freq_bins)392 393        # Reformat shape to (n, 1, time_steps, freq_bins) for ISTFT.394        shape = (395            batch_size * self.output_sources_num * self.input_channels,396            1,397            time_steps,398            freq_bins,399        )400        out_real = out_real.reshape(shape)401        out_imag = out_imag.reshape(shape)402 403        # ISTFT.404        wav_out = self.istft(out_real, out_imag, audio_length)405        # (batch_size * output_sources_num * input_channels, segments_num)406 407        # Reshape.408        wav_out = wav_out.reshape(409            batch_size, self.output_sources_num * self.input_channels, audio_length410        )411        # (batch_size, output_sources_num * input_channels, segments_num)412 413        return wav_out414 415    def forward(self, input_dict):416        """417        Args:418          input: (batch_size, segment_samples, channels_num)419 420        Outputs:421          output_dict: {422            'wav': (batch_size, segment_samples, channels_num),423            'sp': (batch_size, channels_num, time_steps, freq_bins)}424        """425 426        mixture = input_dict['waveform']427        condition = input_dict['condition']428 429        sp, cos_in, sin_in = self.wav_to_spectrogram_phase(mixture)430        """(batch_size, channels_num, time_steps, freq_bins)"""431 432        # Batch normalization433        x = sp.transpose(1, 3)434        x = self.bn0(x)435        x = x.transpose(1, 3)436        """(batch_size, chanenls, time_steps, freq_bins)"""437 438        # Pad spectrogram to be evenly divided by downsample ratio.439        origin_len = x.shape[2]440        pad_len = (441            int(np.ceil(x.shape[2] / self.downsample_ratio)) * self.downsample_ratio442            - origin_len443        )444        x = F.pad(x, pad=(0, 0, 0, pad_len))445        """(batch_size, channels, padded_time_steps, freq_bins)"""446 447        # Let frequency bins be evenly divided by 2, e.g., 513 -> 512448        x = x[..., 0 : x.shape[-1] - 1]  # (bs, channels, T, F)449 450        x = self.subband.analysis(x)451 452        # UNet453        (x1_pool, x1) = self.encoder_block1(454            x, condition455        )  # x1_pool: (bs, 32, T / 2, F / 2)456        (x2_pool, x2) = self.encoder_block2(457            x1_pool, condition458        )  # x2_pool: (bs, 64, T / 4, F / 4)459        (x3_pool, x3) = self.encoder_block3(460            x2_pool, condition461        )  # x3_pool: (bs, 128, T / 8, F / 8)462        (x4_pool, x4) = self.encoder_block4(463            x3_pool, condition464        )  # x4_pool: (bs, 256, T / 16, F / 16)465        (x5_pool, x5) = self.encoder_block5(466            x4_pool, condition467        )  # x5_pool: (bs, 512, T / 32, F / 32)468        (x6_pool, x6) = self.encoder_block6(469            x5_pool, condition470        )  # x6_pool: (bs, 1024, T / 64, F / 64)471        x_center = self.conv_block7(x6_pool, condition)  # (bs, 2048, T / 64, F / 64)472        x7 = self.decoder_block1(x_center, x6, condition)  # (bs, 1024, T / 32, F / 32)473        x8 = self.decoder_block2(x7, x5, condition)  # (bs, 512, T / 16, F / 16)474        x9 = self.decoder_block3(x8, x4, condition)  # (bs, 256, T / 8, F / 8)475        x10 = self.decoder_block4(x9, x3, condition)  # (bs, 128, T / 4, F / 4)476        x11 = self.decoder_block5(x10, x2, condition)  # (bs, 64, T / 2, F / 2)477        x12 = self.decoder_block6(x11, x1, condition)  # (bs, 32, T, F)478        x = self.after_conv_block1(x12, condition)  # (bs, 32, T, F)479        x = self.after_conv2(x)480        # (batch_size, input_channles * subbands_num * targets_num * k, T, F // subbands_num)481 482        x = self.subband.synthesis(x)483        # (batch_size, input_channles * targets_num * K, T, F)484 485        # Recover shape486        x = F.pad(x, pad=(0, 1))  # Pad frequency, e.g., 1024 -> 1025.487        x = x[:, :, 0:origin_len, :]  # (bs, feature_maps, T, F)488 489        audio_length = mixture.shape[2]490 491        separated_audio = self.feature_maps_to_wav(x, sp, sin_in, cos_in, audio_length)492        # separated_audio: (batch_size, output_sources_num * input_channels, segments_num)493 494        output_dict = {'waveform': separated_audio}495 496        return output_dict497