seorim0 / DNN-based-Speech-Enhancement-in-the-frequency-domain

DNN-based SE in the frequency domain using Pytorch. You can test some state-of-the-art networks using T-F masking or spectral mapping method.
MIT License
50 stars 14 forks source link

error when running SE_tutorials.ipynb (maybe dataloading problem...) #7

Closed suzy1616 closed 2 years ago

suzy1616 commented 2 years ago

안녕하세요 :) 한국사람이신것 같아서 한국어로 질문 남깁니다! 딥러닝 처음으로 돌려보는 학부생이라서,, 너무 무식한 질문이라고 생각하실수도 있지만,, 답변해주시면 정말 감사하겠습니다 :)

올려주신 SE_tutorials.ipynb그대로를 colab으로 돌려봤는데 마지막 셀인 Train_interface의 Train의 Validation부분에 다음과 같은 오류가 떴습니다

`2022-6-28 9:13:53

total params : 1703436 (1.70 M, 6.81 MBytes)

Load the data... Load the data... Starting new training run... 300/300: [================================================>.] - ETA 4.9s 10/50: [>.................................................] - ETA 0.0s --------------------------------------------------------------------------- NoUtterancesError Traceback (most recent call last) [](https://localhost:8080/#) in () 114 115 # Validation --> 116 vali_loss, vali_pesq, vali_stoi = model_validate(model, validation_loader, dir_to_save, epoch, DEVICE) 117 model_validate(model, validation_loader, dir_to_save, epoch, DEVICE) 118 5 frames /usr/local/lib/python3.7/dist-packages/pesq/cypesq.pyx in cypesq.cypesq() NoUtterancesError: b'No utterances detected'` 아마 data set의 load가 되지않아서 data가 인식이 안되지않았나 싶습니다. 코드를 다 살펴봤는데 data의 경로를 지정해준 부분이 없는 것 같아 보이더라구요..! 그래서 Dataloader 셀에서 data path부분에 있던 주석처리를 해제하고 경로 설정을 해주고, 경로설정을 하면서 glob를 사용해 Requirement 셀에 import glob, os를 추가해주었습니다. 그래도 data load 때문에 또 마지막 셀인 Train_interface에서 오류가 생기는데 무슨 문제인지 확인해주실수 있을까요?? 고친 코드는 https://colab.research.google.com/drive/1-Hw6kxeGe_hPkxpgBZ8r8Z-ZWTqz52RL?usp=sharing 여기에 있습니다! 질문 읽어주셔서 감사합니다! 좋은 하루 보내세요! :)
seorim0 commented 2 years ago

네, 안녕하세요 :)

일단, NoUtterancesError: b'No utterances detected'는 말그대로 pesq를 측정할 수 있는 utterance가 없다는 것입니다. 제가 올려둔 SE_tutorials.ipynb는 전체 코드가 어떻게 돌아가는지 느낌을 확인할 수 있게 짜둔 것으로, 데이터 입력을 self.input = np.ones((50, 2, 16000))와 같이 0값으로 채워두었습니다. 때문에 pesq를 측정하려면 실제 값을 넣어주셔야 합니다.

올려주신 링크 확인해보았는데 현재 repo의 dataloader는 (total_data_num, 2(clean,noisy), wav_length)의 형태를 가진 .npy 파일을 로드해서 사용하도록 코딩해두었습니다. 전체 wav를 가져다 사용할 예정이라면 def __get_item__ 부분을 수정해주셔야 합니다. 그리고 target을 위한 clean wav도 함께 불러와서 사용해주셔야합니다.

.npy 파일을 만들지 않고 clean과 noisy wav를 직접 가져오실 예정이라면 아래의 코드를 참고해주세요 :)

class Wave_Dataset(Dataset):
    def __init__(self, mode):
        # load data
        self.mode = mode

        if mode == 'train':
            print('<Training dataset>')
            print('Load the data...')
            # load the wav addr
            self.noisy_dirs = scan_directory(cfg.noisy_dirs_for_train)
            self.clean_dirs = find_pair(self.noisy_dirs)

        elif mode == 'valid':
            print('<Validation dataset>')
            print('Load the data...')
            # load the wav addr
            self.noisy_dirs = scan_directory(cfg.noisy_dirs_for_valid)
            self.clean_dirs = find_pair(self.noisy_dirs)

    def __len__(self):
        return len(self.noisy_dirs)

    def __getitem__(self, idx):
        # read the wav
        inputs = addr2wav(self.noisy_dirs[idx])
        targets = addr2wav(self.clean_dirs[idx])

        # transform to torch from numpy
        inputs = torch.from_numpy(inputs)
        targets = torch.from_numpy(targets)

        # (-1, 1)
        inputs = torch.clamp_(inputs, -1, 1)
        targets = torch.clamp_(targets, -1, 1)

        return inputs, targets
suzy1616 commented 2 years ago

답변 정말 정말 감사합니다! :)

수정해주신 class Wave_Dataset 으로 바꾸고 def init의 # load the wav addr라고 주석 처리된곳 밑이 data path를 지정해준곳인것같아 경로를 넣었더니 syntax에러가 뜨네요,, 사실 생성자부분이라 거기에 경로를 설정해주는게 맞는건지도 확신이 없어서 다시 질문드립니다ㅠㅠ 경로를 넣은 코드는 https://colab.research.google.com/drive/1-Hw6kxeGe_hPkxpgBZ8r8Z-ZWTqz52RL?usp=sharing 여기에 있습니다!

또 궁금한 점이 말씀하신대로 train시킬 noisy파일들이 들어간 폴더와 clean파일이 들어간 폴더의 경로를 넣어주려하는데

# load the wav addr
            self.noisy_dirs = scan_directory(cfg.noisy_dirs_for_train)
            self.clean_dirs = find_pair(self.noisy_dirs)

clean파일의 경로가 들어갈듯한 부분에 self.noisy_dirs가 들어가서 어디에 clean파일이 들어간 폴더의 경로를 넣어줘야할지를 모르겠습니다

참고로 제가 갖고 있는 train data set의 구성은 다음과 같습니다..!

dataset
L noisy
   L p226_001
   L p226_002
   L .....
L clean
   L p226_001
   L p226_002
   L .....

요즘 날씨가 많이 오락가락한데 우산 잘 챙기시고 오늘 하루도 힘내세요! 감사합니다!! :)

seorim0 commented 2 years ago

scan_directory와 find_pair, addr2wav는 제가 짠 함수라서 같이 추가해주셔야 할 거 같습니다. 각각 scan_directory는 directory 내의 전체 파일 경로를 불러오는 함수, find_pair는 불러온 잡음 데이터 경로를 통해 깨끗한 데이터 경로를 불러오는 함수, addr2wav는 간단하게 경로로부터 wav 파일을 읽는 함수입니다.

아래 repo 에서 확인 가능합니다. https://github.com/seorim0/NUNet-TLS/blob/main/tools.py

이때, find_pair 함수는 TIMIT 음성 데이터셋에 맞춰서 코딩한 거라서 위에 보여주신 것처럼 잡음 데이터와 깨끗한 데이터의 파일 명이 같다면 아래처럼 수정하여 쓰시면 됩니다.

def find_pair(noisy_dirs):
    clean_dirs = []
    for i in range(len(noisy_dirs)):
        addrs = noisy_dirs[i]
        if addrs.endswith(".wav"):
            addr_noisy = str(addrs)
            addr_clean = str(addrs).replace('noisy', 'clean')
            clean_dirs.append(addr_clean)
    return clean_dirs

그리고 이 경우 만약 잡음 데이터 경로가 ./dataset/noisy/라면 아래와 같이 경로를 주시면 됩니다.

self.noisy_dirs = scan_directory('./dataset/noisy/')
self.clean_dirs = find_pair(self.noisy_dirs)

네, 감사합니다. 오늘 하루 힘내세요 :)