Автоэнкодер звуковых данных в Керасе

У меня есть 2-мерный массив мел-спектрограмм звуковых образцов в логарифмическом масштабе для 5 различных категорий.

Для обучения я использовал сверточную и плотную нейронную сеть в Keras. Вот код:

model = Sequential()
model.add(Conv1D(80, 8, activation='relu', padding='same',input_shape=(60,108)))
model.add(MaxPooling1D(2,padding='same',strides=None))
model.add(Flatten())
initializer=initializers.TruncatedNormal()
model.add(Dense(200, activation='relu', kernel_initializer=initializer,bias_initializer=initializer))
model.add(BatchNormalization())
model.add(Dropout(0.8))
model.add(Dense(50, activation='relu', kernel_initializer=initializer,bias_initializer=initializer))
model.add(Dropout(0.8))
model.add(Dense(5, activation='softmax', kernel_initializer=initializer,bias_initializer=initializer))
model.compile(loss='categorical_crossentropy',
          optimizer='adam',lr=0.01,
          metrics=['accuracy'])

Какой автоэнкодер я могу применить к такому типу ввода данных? Какая модель? Любое предложение или пример кода были бы полезны. :)


person Emanuela Liaci    schedule 18.10.2017    source источник
comment
Я думаю, что, вероятно, вы можете использовать сверточные слои 3D Keras, например, вы можете начать с простой сверточной сети с 16 ядрами 3x3x3 в первом слое и 16 ядрами 5x5x5 во втором + добавить простой MLP с выходом softmax. Я дам точный ответ с образцом кода для ваших данных, если вы можете поделиться им. Однако до тех пор вы можете увидеть образец CAE для изображения здесь, в моем вопросе - stackoverflow.com/questions/46921246/issue-with-simple-cae   -  person Stepan Novikov    schedule 25.10.2017
comment
Я поделился своей моделью, которая сейчас немного изменилась, поскольку входные данные представляют собой 2-мерный массив. Я с нетерпением жду ваших предложений. Спасибо   -  person Emanuela Liaci    schedule 28.10.2017
comment
Почему вы используете Conv1D для двумерных данных? Я предлагаю использовать Conv2D, поскольку у нас двухмерный характер данных. Это должно дать лучший результат. Однако я не могу это проверить, так как у меня нет данных для проверки. Тем не менее, я могу предложить вам несколько моделей для проверки с помощью Conv2D, если вы не против использования Conv2d, но я могу дать вам гораздо более точный ответ, если бы у меня были данные для тестирования, потому что хорошая модель должна учитывать природу данных.   -  person Stepan Novikov    schedule 28.10.2017
comment
Как я могу поделиться с вами набором данных? Извините за незнание, но я новичок в stackoverflow.   -  person Emanuela Liaci    schedule 28.10.2017
comment
Вы можете загрузить его на Google Диск и поделиться своим файлом со всеми, у кого есть ссылка, а затем добавить эту ссылку в свой вопрос или опубликовать в комментарии. Однако я уже подготовил, вероятно, не очень точный ответ, основанный на моих вышеупомянутых предположениях о природе данных. Так что вы можете сначала проверить это. Однако, если вы не можете успешно построить свою модель или подготовить данные для обучения, рассмотрите возможность поделиться своими данными по ссылке, и я смогу вам с этим помочь.   -  person Stepan Novikov    schedule 28.10.2017
comment
ваша помощь с моим набором данных была бы большой, также с предложением Conv2D. Вот ссылка на мои звуковые данные: особенности (drive.google.com/open?id=0B02xhizkrpq9V0VE / a>), ярлыки (drive.google.com/open?id=0B02xhizkrpq9eVVXMmmRepq9eVVXMm )   -  person Emanuela Liaci    schedule 28.10.2017
comment
Нормально будет сделать. Однако я не знаю, как открывать / читать данные из SoundDataX.msg и SoundDataY.msg, не могли бы вы дать мне пример кода, чтобы открыть его?   -  person Stepan Novikov    schedule 28.10.2017
comment
Давайте продолжим это обсуждение в чате.   -  person Emanuela Liaci    schedule 28.10.2017


Ответы (1)


Поскольку у меня нет ответов на свой вопрос о природе данных, я предполагаю, что у нас есть набор двухмерных данных с формой вроде (NSamples, 68, 108). Кроме того, я предполагаю, что ответ на мое предложение использовать Convolutional2D вместо Convolutional1D - да

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

from keras.layers.core import Dense, Dropout, Flatten, Reshape
from keras.layers import Conv1D, Conv2D, Deconv2D, MaxPooling1D, MaxPooling2D, UpSampling2D, Conv2DTranspose, Flatten, BatchNormalization, Dropout
from keras.callbacks import ModelCheckpoint
import keras.models as models
import keras.initializers as initializers
from sklearn.model_selection import train_test_split

ae = models.Sequential()
#model.add(Conv1D(80, 8, activation='relu', padding='same',input_shape=(60,108)))
#encoder
c = Conv2D(80, 3, activation='relu', padding='same',input_shape=(60, 108, 1))
ae.add(c)
ae.add(MaxPooling2D(pool_size=(2, 2), padding='same', strides=None))
ae.add(Flatten())
initializer=initializers.TruncatedNormal()
d1 = Dense(200, activation='relu', kernel_initializer=initializer,bias_initializer=initializer)
ae.add(d1)
ae.add(BatchNormalization())
ae.add(Dropout(0.8))
d2 = Dense(50, activation='relu', kernel_initializer=initializer,bias_initializer=initializer)
ae.add(d2)
ae.add(Dropout(0.8))
#decodser
ae.add(Dense(d2.input_shape[1], activation='sigmoid'))
ae.add(Dense(d1.input_shape[1], activation='sigmoid'))
ae.add(Reshape((30, 54, 80)))
ae.add(UpSampling2D((2,2)))
ae.add(Deconv2D(filters= c.filters, kernel_size= c.kernel_size, strides=c.strides, activation=c.activation, padding=c.padding, ))
ae.add(Deconv2D(filters= 1, kernel_size= c.kernel_size, strides=c.strides, activation=c.activation, padding=c.padding, ))
ae.compile(loss='binary_crossentropy',
optimizer='adam',lr=0.001,
metrics=['accuracy'])
ae.summary()
#now train your convolutional autoencoder to reconstruct your input data
#reshape your data to (NSamples, 60, 108, 1)
#Then train your autoencoder. it can be something like that:
#X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=43)
#pre_mcp = ModelCheckpoint("CAE.hdf5", monitor='val_accuracy', verbose=2, save_best_only=True, mode='max')
#pre_history = ae.fit(X_train, X_train, epochs=100, validation_data=(X_val, X_val), batch_size=22, verbose=2, callbacks=[pre_mcp])

#model
model = models.Sequential()
#model.add(Conv1D(80, 8, activation='relu', padding='same',input_shape=(60,108)))
model.add(Conv2D(80, 3, activation='relu', padding='same',input_shape=(60, 108, 1)))
model.add(MaxPooling2D(pool_size=(2, 2), padding='same',strides=None))
model.add(Flatten())
initializer=initializers.TruncatedNormal()
model.add(Dense(200, activation='relu', kernel_initializer=initializer,bias_initializer=initializer))
model.add(BatchNormalization())
model.add(Dropout(0.8))
model.add(Dense(50, activation='relu', kernel_initializer=initializer,bias_initializer=initializer))
model.add(Dropout(0.8))
model.add(Dense(5, activation='softmax', kernel_initializer=initializer,bias_initializer=initializer))
model.compile(loss='categorical_crossentropy',
optimizer='adam',lr=0.001,
metrics=['accuracy'])
#Set weights              
model.layers[0].set_weights(ae.layers[0].get_weights())       
model.layers[3].set_weights(ae.layers[3].get_weights())  
model.layers[4].set_weights(ae.layers[4].get_weights())  
model.layers[6].set_weights(ae.layers[6].get_weights())  
model.summary()
#Now you can train your model with pre-trained weights from autoencoder

Такая модель была полезна для меня с набором данных MNIST и улучшенной точностью модели с начальными весами из автокодировщика по сравнению с моделью, инициализированной со случайными весами.

Однако я бы рекомендовал использовать несколько сверточных / деконволюционных слоев, вероятно, 3 или более, поскольку по моему опыту сверточные автокодеры с 3 и более сверточными слоями более эффективны, чем с 1 сверточным слоем. Фактически, с одним сверточным слоем я иногда даже не вижу никаких улучшений точности

Обновление:

Я проверил автоматический кодировщик с данными, предоставленными Emanuela, также я проверил его с различными архитектурами автокодировщиков без какого-либо успеха

Моя гипотеза заключается в том, что данные не содержат каких-либо значимых функций, которые можно определить с помощью автокодировщика или даже CAE.

Однако похоже, что мое предположение о двумерном характере данных было подтверждено достижением точности проверки почти 99,99%:  введите описание изображения здесь

Тем не менее, в то же время точность обучающих данных 97,31% может указывать на потенциальные проблемы с набором данных, поэтому кажется хорошей идеей пересмотреть его.

Кроме того, я бы предложил использовать ансамбли сетей. Вы можете обучить, например, 10 сетей с разными данными проверки и назначить категории для элементов по категориям, получившим наибольшее количество голосов.

Вот мой код:

from keras.layers.core import Dense, Dropout, Flatten
from keras.layers import Conv2D, BatchNormalization
from keras.callbacks import ModelCheckpoint
from keras.optimizers import Adam
from sklearn.model_selection import train_test_split
import keras.models as models
import keras.initializers as initializers
import msgpack
import numpy as np

with open('SoundDataX.msg', "rb") as fx,open('SoundDataY.msg', "rb") as fy: 
    dataX=msgpack.load(fx) 
    dataY=msgpack.load(fy)

num_samples = len(dataX)
x = np.empty((num_samples, 60, 108, 1), dtype = np.float32)
y = np.empty((num_samples, 4), dtype = np.float32)

for i in range(0, num_samples):
    x[i] = np.asanyarray(dataX[i]).reshape(60, 108, 1)
    y[i] = np.asanyarray(dataY[i])

X_train, X_val, y_train, y_val = train_test_split(x, y, test_size=0.2, random_state=43)

#model
model = models.Sequential()
model.add(Conv2D(128, 3, activation='relu', padding='same',input_shape=(60, 108, 1)))
model.add(Conv2D(128, 5, activation='relu', padding='same',input_shape=(60, 108, 1)))
model.add(Conv2D(128, 7, activation='relu', padding='same',input_shape=(60, 108, 1)))
model.add(Flatten())
initializer=initializers.TruncatedNormal()
model.add(Dense(200, activation='relu', kernel_initializer=initializer,bias_initializer=initializer))
model.add(BatchNormalization())
model.add(Dropout(0.8))
model.add(Dense(50, activation='relu', kernel_initializer=initializer,bias_initializer=initializer))
model.add(Dropout(0.8))
model.add(Dense(4, activation='softmax', kernel_initializer=initializer,bias_initializer=initializer))
model.compile(loss='categorical_crossentropy',
optimizer=Adam(lr=0.0001),
metrics=['accuracy'])
model.summary()
filepath="weights-{epoch:02d}-{val_acc:.7f}-{acc:.7f}.hdf5"
mcp = ModelCheckpoint(filepath, monitor='val_acc', verbose=2, save_best_only=True, mode='max')
history = model.fit(X_train, y_train, epochs=100, validation_data=(X_val, y_val), batch_size=64, verbose=2, callbacks=[mcp])
person Stepan Novikov    schedule 28.10.2017