Как развернуть определение слова триггера с помощью тензорного потока - PullRequest
1 голос
/ 01 апреля 2020

Я работаю над моделью «обнаружения слова триггера» и решил развернуть модель на своем телефоне.

Форма ввода модели - (None, 5511, 101). Выходная форма равна (None, 1375, 1).

Но в реальном развернутом приложении модель не может получить 5511 временных шагов одновременно, вместо этого аудио кадр, производимый датчиком телефона, один за другим.

Как я могу подать эти фрагменты данных в модель один за другим и получать выходные данные на каждом временном шаге?

Модель является периодической. Но «model.predict ()» принимает первый параметр (None, 5511,101), и я собираюсь сделать это

output = []
for i in range(5511): 
    a = model.func(i, (None,1,101))
    output.append(a)

структура модели:

structure of the model

enter image description here

Ответы [ 3 ]

2 голосов
/ 06 апреля 2020

Эту проблему можно решить, сделав оси временных шагов динамическими c. Другими словами, когда вы определяете модель, количество временных шагов должно быть установлено на None. Вот пример, иллюстрирующий, как это будет работать для упрощенной версии вашей модели:

from keras.layers import GRU, Input, Conv1D
from keras.models import Model
import numpy as np

x = Input(shape=(None, 101))
h = Conv1D(196, 15, strides=4)(x)
h = GRU(1, return_sequences=True)(h)
model = Model(x, h)


# The model works for the original number of timesteps (5511)
batch_size = 2
out = model.predict(np.random.rand(batch_size, 5511, 101))
print(out.shape)


# ... but also for fewer timesteps (say 32)
out = model.predict(np.random.rand(batch_size, 32, 101))
print(out.shape)


# However, it will not work if timesteps < Conv1D filter_size (15)!
out = model.predict(np.random.rand(batch_size, 14, 101))
print(out.shape)

Обратите внимание, однако, что вы не сможете подавать менее 15 временных шагов (размерность фильтров Conv1D), если только Вы дополняете входные последовательности до 15.

1 голос
/ 06 апреля 2020

Для поэтапной передачи входных данных вам нужны повторяющиеся слои с stateful=True.

Сверточный слой наверняка помешает вам достичь того, что вы хотите. Либо вы удаляете его, либо вы передаете входные данные группами по 15 шагов (где 15 - размер вашего ядра для свертки).

Вам нужно будет согласовать эти 15 шагов с шагом 4 и, возможно, потребуется заполнение. Если я могу предложить, чтобы избежать математических трудностей, вы можете использовать kernel_size=16, stride=4 и input_steps = 5512, это кратное 4, которое является вашим значением шага. (Это позволит избежать заполнения и упростит вычисления), и ваши выходные шаги будут 1375 идеально круглыми.

Тогда ваша модель будет выглядеть так:

inputs = Input(batch_shape=(batch_size,None, 101)) #where you will always use input shapes of (batch_size, 16, 101)
out = Conv1D(196, 16, strides=4)(inputs)
...
...
out = GRU(..., stateful=True)(out)
...
out = GRU(..., stateful=True)(out)
...
...

model = Model(inputs, out)

Необходимо иметь фиксированный размер партии с моделью stateful=True. Это может быть 1, но для оптимизации скорости обработки, если у вас есть несколько последовательностей для параллельной обработки (и независимо друг от друга), используйте больший размер пакета.

Для пошаговой обработки, Прежде всего, вам нужно сбросить состояния (всякий раз, когда вы используете модель stateful=True, вам необходимо сохранять сброс состояний каждый раз, когда вы собираетесь передавать новую последовательность или новую серию параллельных последовательностей).

Итак:

#will start a new batch containing a number of sequences equal to batch_size:
model.reset_states()

#received 16 steps from batch_size sequences:
steps = an_array_shaped((batch_size, 16, 101))

#for training 
model.train_on_batch(steps, something_for_y_shaped((batch_size, 1, 1)), ...)
    #I don't recommend to train like this because of the batch normalizations    
    #If you can train the entire length at once, do it.    
    #never forget: for full length training, you would need model.reset_states() every batch. 

#for predicting:
predictions = model.predict_on_batch(steps, ...)

#received 4 new steps from X sequences:
steps = np.concatenate([steps[:,4:], new_steps], axis=1)

#these new steps belong to the "same" batch_size sequences! Don't call reset states!
#repeat one of the above for training or predicting
new_predictions = model.predict_on_batch(steps, ...)
predictions = np.concatenate([predictions, new_predictions], axis=1)

#keep repeating this loop until you reach the last step

Finally, when you reached the last step, for safety, call `model.reset_states()` again, everything that you input will be "new" sequences, not new "steps" or the previous sequences. 

------------

# Training hint

If you are able to train with the full sequences (not step by step), use a `stateful=False` model, train normally with `model.fit(...)`, later you recreate the model exactly, but using `stateful=True`, copy the weights with `new_model.set_weights(old_model.get_weights())`, and use the new model for predicting like above. 
1 голос
/ 05 апреля 2020

Вы должны либо изменить свою модель на периодическую, где вы можете подавать фрагменты данных по одному, либо вам следует подумать об изменении модели и использовании чего-то, что работает (перекрывается) windows во времени, где вы применяете моделируйте каждые несколько фрагментов данных и получайте частичный вывод.

Тем не менее, в зависимости от модели вы можете получить желаемый результат только в конце. Вы должны разработать его соответствующим образом.

Вот пример: https://hacks.mozilla.org/2018/09/speech-recognition-deepspeech/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...