2017-05-06 17 views
11

Próbuję wytrenować RNN do przetwarzania sygnału cyfrowego (audio) za pomocą deeplearning4j. Chodzi o to, aby mieć 2 pliki .wav: jeden to nagranie dźwiękowe, drugi to to samo nagranie audio, ale przetworzone (na przykład z filtrem dolnoprzepustowym). Wejście RNN jest pierwszym (nieprzetworzonym) nagraniem audio, wyjście jest drugim (przetworzonym) nagraniem dźwiękowym.deeplearning4j - używanie RNN/LSTM do przetwarzania sygnałów audio

Użyłem przykładowego przykładu GravesLSTMCharModelling z przykładów dl4j, a przede wszystkim dostosowałem klasę CharacterIterator do akceptowania danych dźwiękowych zamiast tekstu.

Mój pierwszy projekt do pracy z dźwiękiem w ogóle z dl4j polega w zasadzie na zrobieniu tego samego, co GravesLSTMCharModellingExample, ale generowaniu dźwięku zamiast tekstu, pracując z 8-bitowym mono audio 11025Hz, który działa (dla niektórych dość zabawnych wyników). Więc podstawy pracujące z dźwiękiem w tym kontekście wydają się działać.

Więc krok 2 było przystosować to do przetwarzania dźwięku zamiast dźwięku generacji.

Niestety, nie mam dużego sukcesu. Najlepsze, co wydaje się być w stanie wykonać, to wypuszczenie bardzo hałaśliwej wersji wejścia.

Jako "test poczytalności" przetestowałem używając tego samego pliku audio zarówno dla wejścia, jak i wyjścia, które spodziewałem się szybko połączyć z modelem, po prostu kopiując dane wejściowe. Ale tak nie jest. Ponownie, po długim okresie szkolenia, wszystko, co wydawało się być w stanie zrobić, to wytworzyć głośniejszą wersję danych wejściowych.

Najbardziej istotne kawałek kodu Chyba jest() metoda DataSetIterator.next (zaadaptowany z przykładu w klasie CharacterIterator), który teraz wyglądać następująco:

public DataSet next(int num) { 
    if (exampleStartOffsets.size() == 0) 
     throw new NoSuchElementException(); 

    int currMinibatchSize = Math.min(num, exampleStartOffsets.size()); 
    // Allocate space: 
    // Note the order here: 
    // dimension 0 = number of examples in minibatch 
    // dimension 1 = size of each vector (i.e., number of characters) 
    // dimension 2 = length of each time series/example 
    // Why 'f' order here? See http://deeplearning4j.org/usingrnns.html#data 
    // section "Alternative: Implementing a custom DataSetIterator" 
    INDArray input = Nd4j.create(new int[] { currMinibatchSize, columns, exampleLength }, 'f'); 
    INDArray labels = Nd4j.create(new int[] { currMinibatchSize, columns, exampleLength }, 'f'); 

    for (int i = 0; i < currMinibatchSize; i++) { 
     int startIdx = exampleStartOffsets.removeFirst(); 
     int endIdx = startIdx + exampleLength; 

     for (int j = startIdx, c = 0; j < endIdx; j++, c++) { 
      // inputIndices/idealIndices are audio samples converted to indices. 
      // With 8-bit audio, this translates to values between 0-255. 
      input.putScalar(new int[] { i, inputIndices[j], c }, 1.0); 
      labels.putScalar(new int[] { i, idealIndices[j], c }, 1.0); 
     } 
    } 

    return new DataSet(input, labels); 
} 

Więc może mam podstawową niezrozumienie tego, co mają robić LSTM. Czy w opublikowanym kodzie jest coś nie tak, czego mi brakuje? Czy istnieje oczywisty powód, dla którego szkolenie na tym samym pliku niekoniecznie musi zbiegać się szybko z modelem, który kopiuje dane wejściowe? (nie wspominając już o próbie szkolenia go na przetwarzaniu sygnału, który faktycznie coś robi?)

Widziałem Using RNN to recover sine wave from noisy signal, który wydaje się być o podobnym problemie (ale przy użyciu innej struktury ML), ale to nie dostało odpowiedź.

Wszelkie uwagi są mile widziane!

+2

potrafisz odpowiedzieć następujący temat swojego projektu? Dlaczego warto korzystać z architektury sieci LSTM? Istotne znaczenie będzie również dostarczenie wskazówek dotyczących sposobu grupowania danych wejściowych. Czy wykonujesz na nim jakieś normalizacje? – Nathan

+0

Moje myślenie o używaniu LSTM polega na tym, że uczę się na danych, w których sekwencja tych danych ma znaczenie i mam nadzieję, że NN nauczy się czegoś od tego, jakie dane zostały przetworzone wcześniej (w przeciwieństwie do czegoś takiego jak "normalny" FF NN). – erikd71

+0

Do grupowania używam mini-partii o wielkości 32, przykładowej wielkości 10000 i długości TBPTT równej 1000 (chociaż eksperymentuję z tymi wartościami). – erikd71

Odpowiedz

1

cześć myślę logiki dla zestawu danych spróbuje użyć długiego typu zamiast liczby całkowitej

public DataSet next(int num) 

zastępować

public DataSet next(long num) 
+0

To naruszyłoby interfejs DataSetIterator i nie jestem pewien, czy i tak jest to związane z problemem. – erikd71

Powiązane problemy