Я пытаюсь обучить RNN для обработки цифрового (аудио) сигнала, используя deeplayning4j. Идея состоит в том, чтобы иметь 2.wav файла: один - аудиозапись, вторая - одна и та же запись звука, но обрабатываемая (например, с фильтром нижних частот). Вход RNN является первой (необработанной) аудиозаписью, выход - 2-й (обработанной) аудиозаписью.
Я использовал GravesLSTMCharModellingExample из примеров dl4j и в основном адаптировал класс CharacterIterator для приема аудиоданных вместо текста.
Мой первый проект для работы с аудио вообще с dl4j состоит в том, чтобы в основном сделать то же самое, что и GravesLSTMCharModellingExample, но генерировать аудио вместо текста, работая с 8-битным монофоническим звуком 11025Hz, который работает (с некоторыми довольно забавными результатами). Таким образом, основы работы с аудио в этом контексте, похоже, сработают.
Итак, шаг 2 заключался в том, чтобы адаптировать это для обработки звука вместо генерации звука.
К сожалению, у меня нет большого успеха. Лучшее, что может показаться возможным, это вывод очень шумной версии ввода.
Как "проверка работоспособности", я тестировал один и тот же аудиофайл для ввода и вывода, который, как я ожидал, быстро сходится к модели, просто копируя входные данные. Но это не так. Опять же, после долгого времени обучения все, что казалось возможным, это сделать более шумную версию ввода.
Наиболее подходящим фрагментом кода я считаю метод DataSetIterator.next() (адаптированный из примера класса CharacterIterator), который теперь выглядит следующим образом:
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);
}
Так что, возможно, у меня есть фундаментальное непонимание того, что LSTM должны делать. Есть ли что-то явно неправильное в опубликованном коде, который мне не хватает? Есть ли очевидная причина, почему обучение в одном файле не обязательно быстро сходится к модели, которая просто копирует вход? (не говоря уже о том, чтобы попытаться обучить его обработке сигналов, которая на самом деле что-то делает?)
Я видел Использование RNN для восстановления синусоидальной волны из шумного сигнала, которая, похоже, связана с аналогичной проблемой (но с использованием другой среды ML), но это не было не получишь ответа.
Любая обратная связь приветствуется!