RNN и CNN-RNN не будут тренироваться правильно, всегда предсказывают один класс - PullRequest
0 голосов
/ 24 марта 2020

В настоящее время я разрабатываю модель для обнаружения эмоций по тексту с использованием алгоритмов глубокого обучения. У меня есть относительно небольшой набор данных с пометкой (~ 7500) с 7 разными эмоциями на уроках. Я разработал CNN и достиг точности ~ 63%, но когда я попытался применить RNN, используя LSTM, и CNN-RNN, также используя LSTM, они просто, кажется, не тренируются должным образом и всегда в конечном итоге предсказывают того же класса. Я считаю, что мои модели в принципе хороши, но с некоторыми ошибками в параметрах. У меня есть набор данных, разделенный на 85% для обучения, еще 20% для проверки и оставшиеся 15% для тестирования. Моя матрица встраивания разработана с использованием представлений слов из Новостей Google word2ve c, а индекс слов разработан с использованием keras Tokenizer.

Разбивка набора данных:

Эмоции

гнев 1086

отвращение 1074

страх 1086

вина 1062

радость 1089

печаль 1080

позор 1058

CNN реализация

def make_model(kernel_sizes, num_filters, dropout, hidden_units):

    submodels = []
    for kernel_size in kernel_sizes:
        submodel = Sequential()

        submodel.add(Embedding(input_dim = input_dim,
                            output_dim   = output_dim,
                            weights      = [embedding_matrix],
                            input_length = max_len,
                            trainable    = True))

        submodel.add(Conv1D(filters=num_filters, kernel_size=kernel_size, padding='same',activation='relu',strides=1))
        submodel.add(GlobalMaxPooling1D())
        submodels.append(submodel)

    submodel_outputs = [model.output for model in submodels]    
    submodel_inputs = [model.input for model in submodels]

    merged = Concatenate(axis=1)(submodel_outputs)
    x = Dropout(dropout)(merged)

    if(hidden_units > 0):
        x = Dense(hidden_units, activation='relu')(x)
        x = Dropout(dropout)(x)

    x = Dense(7,activation='softmax', kernel_initializer="uniform")(x)
    out = Activation('sigmoid')(x)

    model = Model(submodel_inputs, out)
    model.compile(loss='categorical_crossentropy',optimizer='rmsprop',metrics=['acc'])

    return model
def fit_model(model, kernel_sizes, num_epochs, batch_size, x_train, y_train):

    x_train = [x_train]*len(kernel_sizes)

    history = model.fit(x_train, y_train, batch_size=batch_size, epochs=num_epochs, validation_split=0.2)

    return history
kernel_sizes  = [2,6]
num_filters   = 100
dropout       = 0.6
num_hidden    = 270
callbacks     = callbacks_list
num_epochs    = 15
batch_size = 64
model = make_model(kernel_sizes, num_filters, dropout, num_hidden)
print(model.summary())
history = fit_model(model, kernel_sizes, num_epochs, batch_size, x_train, y_train)

Модель: "model_1"


Слой (тип) Форма выхода Параметр # Подключен к

embedding_1_input (InputLayer) (Нет, 179) 0


embedding_2_input (InputLayer) (Нет, 179) 0


embedding_1 (Embedding) (Нет, 179, 300) ) 2729400 embedding_1_input [0] [0]


embedding_2 (Embedding) (Нет, 179, 300) 2729400 embedding_2_input [0] [0]


conv1d_1 (Conv1D) (Нет, 179, 100) 60100 embedding_1 [0] [0]


conv1d_2 (Conv1D) (Нет, 179, 100) 180100 embedding_2 [0] [0]


* 10 48 * global_max_pooling1d_1 (GlobalM (нет, 100) 0 conv1d_1 [0] [0]

global_max_pooling1d_2 (GlobalM (нет, 100) 0 conv1d_2 [0] [0]


concatenate_1 (Конкатенация) (None, 200) 0 global_max_pooling1d_1 [0] [0]
global_max_pooling1d_2 [0] [0]


dropout_1 (Выпадение) (None, 200) 0 concatenate_1 [ 0] [0]


density_1 (Плотный) (нет, 270) 54270 dropout_1 [0] [0]


dropout_2 (выпадение) (None, 270) 0 плотность_1 [0] [0]


плотность_2 (плотный) (нет, 7) 1897 dropout_2 [0] [0]


активация_1 (активация) (нет, 7 ) 0 dens_2 [0] [0]

Всего параметров: 5,755,167 Обучаемые параметры: 5,755,167 Необучаемые параметры: 0


Результаты обучения и проверки для CNN

Матрица путаницы CNN


Реализация RNN

def make_model(lstm_units, dropout, hidden_units):

    model = Sequential()   

    model.add(Embedding(input_dim = input_dim,
                        output_dim   = output_dim,
                        weights      = [embedding_matrix],
                        input_length = max_len,
                        trainable    = False))

    model.add(LSTM(lstm_units))

    model.add(Dropout(dropout))

    if(hidden_units > 0):
        model.add(Dense(hidden_units, activation='elu'))
        model.add(Dropout(dropout))

    model.add(Dense(7,activation='softmax', kernel_initializer="uniform"))
    model.add(Activation('sigmoid'))

    model.compile(loss='categorical_crossentropy',optimizer='rmsprop',metrics=['acc'])

    return model
lstm_units = 120
dropout = 0.5
hidden_units = 550
callbacks = [tensorboard, early]
num_epochs = 20
batch_size = 60

model = make_model(lstm_units, dropout, hidden_units)
print(model.summary())
history = fit_model(model, num_epochs, batch_size, x_train, y_train)

Модель: "sequential_6"


Слой (тип) Выходной параметр Параметр #

embedding_6 (Embedding) (Нет, 179, 300) 2729400


lstm_8 (LSTM) (Нет, 120) 202080


dropout_5 (Выпадение) (Нет, 120) 0


density_6 (Плотный) (нет, 550) 66550


dropout_6 (Выпадение) (нет, 550) 0


density_7 (Плотный) (нет, 7) 3857


активация_3 (Активация) (Нет, 7) 0

Всего параметров: 3 001 887 Обучаемых параметров: 272 487 Необучаемых параметров: 2 729 400


Оценки обучения и проверки RNN

Матрица путаницы RNN


Реализация CNN-RNN

def make_model(kernel_sizes, num_filters, dropout, hidden_units, lstm_units):

    submodels = []
    for kernel_size in kernel_sizes:
        submodel = Sequential()

        submodel.add(Embedding(input_dim = input_dim,
                            output_dim   = output_dim,
                            weights      = [embedding_matrix],
                            input_length = max_len,
                            trainable    = True))

        submodel.add(Conv1D(filters=num_filters, kernel_size=kernel_size, padding='same',activation='relu',strides=1))
        submodel.add(MaxPooling1D(pool_size=2, strides = 2))
        submodel.add(Dropout(dropout))
        submodel.add(LSTM(lstm_units)) 
        submodels.append(submodel)

    submodel_outputs = [model.output for model in submodels]    
    submodel_inputs = [model.input for model in submodels]

    merged = Concatenate(axis=1)(submodel_outputs)
    x = Dropout(dropout)(merged)

    if(hidden_units > 0):
        x = Dense(hidden_units, activation='relu')(x)
        x = Dropout(dropout)(x)

    x = Dense(7,activation='softmax', kernel_initializer="uniform")(x)
    out = Activation('sigmoid')(x)

    model = Model(submodel_inputs, out)
    model.compile(loss='categorical_crossentropy',optimizer='rmsprop',metrics=['acc'])

    return model
kernel_sizes  = [2,3,6]
num_filters   = 100
dropout       = 0.6
num_hidden    = 270
lstm_units = 80
callbacks     = [tensorboard, early]
num_epochs    = 20
batch_size = 64

model = make_model(kernel_sizes, num_filters, dropout, num_hidden, lstm_units)
print(model.summary())
history = fit_model(model, kernel_sizes, num_epochs, batch_size, x_train, y_train)

Модель: "model_2"


Слой (тип) Выходной параметр Параметр # Подключен к

embedding_8_input (InputLayer) (Нет, 179) 0


embedding_9_input (InputLayer) (Нет, 179 ) 0


embedding_10_input (InputLayer) (Нет, 179) 0


embedding_8 (Embedding) (Нет, 179, 300) 2729400 embedding_8_input [0] [0]


embedding_9 (Embedding) (Нет, 179, 300) 2729400 embedding_9_input [0] [0]


embedding_10 (Embedding) (Нет, 179, 300) 2729400 embedding_10_input [ 0] [0]


conv1d_8 (Conv1D) (нет, 179, 100) 60100 embedding_8 [0] [0]


conv1d_9 (Conv1D) (нет, 179 10 0) 90100 embedding_9 [0] [0]


conv1d_10 (Conv1D) (Нет, 179, 100) 180100 embedding_10 [0] [0]


max_pooling1d_7 (MaxPooling1D ) (Нет, 89, 100) 0 conv1d_8 [0] [0]


max_pooling1d_8 (MaxPooling1D) (Нет, 89, 100) 0 conv1d_9 [0] [0]


max_pooling1d_9 (MaxPooling1D) (None, 89, 100) 0 conv1d_10 [0] [0]


dropout_9 (Dropout) (None, 89, 100) 0 max_pooling1d_7 [0] [0]


dropout_10 (Dropout) (None, 89, 100) 0 max_pooling1d_8 [0] [0]


dropout_11 (Dropout) (None, 89, 100) 0 max_pooling1d_9 [0] [0]


lstm_2 (LSTM) (нет, 80) 57920 dropout_9 [0] [0]


lstm_3 (LSTM) (нет, 80) 57920 dropout_10 [0] [0]


lstm_4 (LSTM) (Нет, 80) 57920 dropout_11 [0] [0]


concatenate_3 (Объединенный) (Нет, 240) 0 lstm_2 [0] [0]
lstm_3 [0] [0]
lstm_4 [0] [0]


dropout_12 (Dropout) (нет, 240) 0 concatenate_3 [0] [0]


плотность_3 (плотный) (нет, 270) 65070 dropout_12 [0] [0]


dropout_13 (выпадение) (нет, 270) 0лотной_3 [0] [0]


плотность_4 (плотный) (нет, 7) 1897 dropout_13 [0] [0]


активация_2 (активация) (нет, 7) 0 плотность_4 [0] [ 0]

Всего параметров: 8 759 227 Обучаемых параметров: 8 759 227 Необучаемых параметров: 0


Результаты обучения и проверки CNN-RNN CNN-RNN Матрица путаницы

Я понимаю, что для нейронных сетей нет формулы волхвов c, и ни один размер не подходит для всех подходов, я просто ищу руководство в тех областях, в которых я мог допустить ошибки, когда внедрение CNN-RNN и RNN.

Заранее извиняюсь за любые ошибки форматирования, так как это мой первый заданный вопрос. Если требуется какая-либо другая информация, пожалуйста, дайте мне знать.

Большое спасибо.

Ответы [ 2 ]

0 голосов
/ 25 марта 2020

Прежде всего, ваша реализация CNN чрезмерно увлечена c, вы придумали архитектуру, экспериментируя с несколькими проектами, или просто выбрали ее?

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

https://i.stack.imgur.com/v1GeS.png

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

Матрица путаницы для тестового набора? Затем, кажется, что ваш тестовый сплит слишком прост, так как модель слишком перегружена, она должна работать плохо. Поэтому попытайтесь найти лучшее разделение тестов, убедившись, что не слишком много сходных данных попадает как при обучении, так и при тестировании.

Всегда лучше настроить более простую модель, прежде чем переходить к сложным. Поскольку ваша модель LSTM не работает должным образом, нет смысла пробовать еще более сложную модель (CNN-LSTM). Ваша модель LSTM не сходится, причин может быть много (очевидные причины - неправильное использование уровня активации).

def make_model(lstm_units, dropout, hidden_units):

    model = Sequential()   

    model.add(Embedding(input_dim = input_dim,
                        output_dim   = output_dim,
                        weights      = [embedding_matrix],
                        input_length = max_len,
                        trainable    = False))

    model.add(LSTM(lstm_units, return_sequences = True, recurrent_dropout = 0.2))
    model.add(Dropout(dropout))
    model.add(LSTM(lstm_units, recurrent_dropout = 0.2))

    model.add(Dropout(dropout))


    model.add(Dense(7, activation='softmax'))

    model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['acc'])

    return model

Сделайте модель полностью на основе LSTM, избавившись от F C слои, также начинаются с меньших единиц LSTM, таких как 8, 16, 32, ...

Для большего улучшения вы можете сделать следующее.

0) Избавьтесь от встраивания перчаток и используйте свои собственные встраиваемые вложения.

1) Гиперпараметрический поиск по сети, чтобы найти наиболее оптимальную модель.

Существует множество библиотек. Но я нахожу это очень гибким. https://github.com/keras-team/keras-tuner

Просто установите с помощью пипса.

Вот демонстрационный код.

from tensorflow import keras
from tensorflow.keras import layers
from kerastuner.tuners import RandomSearch


def build_model(hp):
    model = keras.Sequential()
    model.add(layers.Embedding(input_dim=hp.Int('input_dim',
                                        min_value=5000,
                                        max_value=10000,
                                        step = 1000),
                              output_dim=hp.Int('output_dim',
                                        min_value=200,
                                        max_value=800,
                                        step = 100),
                              input_length = 400))
    model.add(layers.Convolution1D(
                filters=hp.Int('filters',
                                        min_value=32,
                                        max_value=512,
                                        step = 32),
                kernel_size=hp.Int('kernel_size',
                                        min_value=3,
                                        max_value=11,
                                        step = 2),
                padding='same',
                activation='relu')),
    model.add(layers.BatchNormalization())
    model.add(layers.MaxPooling1D())
    model.add(layers.Flatten())
    model.add(layers.Dropout(0.4))
    model.add(layers.Dense(units=hp.Int('units',
                                        min_value=64,
                                        max_value=256,
                                        step=32),
                           activation='relu'))
    model.add(layers.Dropout(0.4))
    model.add(layers.Dense(7, activation='softmax'))
    model.compile(
    optimizer=keras.optimizers.Adam(
        hp.Choice('learning_rate',
                  values=[1e-2, 1e-3, 1e-4])),
    loss='categorical_crossentropy',
    metrics=['accuracy'])
    return model


tuner = RandomSearch(
    build_model,
    objective='val_accuracy',
    max_trials=5,
    executions_per_trial=3,
    directory='my_dir',
    project_name='helloworld')
tuner.search_space_summary()

## The following lines are based on your model


tuner.search(x, y,
             epochs=5,
             validation_data=(val_x, val_y))

models = tuner.get_best_models(num_models=2)

Если вы хотите чтобы извлечь более значимые функции, я нашел многообещающий подход - это извлечение предварительно обученных функций BERT, а затем обучение с использованием CNN / LSTM.

Отличным хранилищем для начала является этот - https://github.com/UKPLab/sentence-transformers

Как только вы получите вложение предложения от BERT / X LNet, вы можете использовать эти функции для обучения другого CNN, подобного тому, который вы используете, за исключением, возможно, избавления от слоя внедрения, поскольку это дорого .

0 голосов
/ 24 марта 2020

Я не могу сказать, что это решит все ваши проблемы, но что-то определенно неправильное - это повторное использование сигмовидной активации сразу после активации softmax, в то время как ваша классификационная задача состоит из 7 классов. Сигмовидная активация может разделять только два класса.

Например:

model.add(Dense(7,activation='softmax', kernel_initializer="uniform"))
model.add(Activation('sigmoid'))

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

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