Keras - классификация текста - оверфиттинг, и как улучшить модель

Для любителей обсудить что круче Linux или Win32, Java или C#.

Модератор: Duncon

Ответить
glorsh66
Сообщения: 3
Зарегистрирован: 09 июл 2017, 10:15

19 ноя 2017, 12:15

Я делаю нейронную сеть для классификации текста на русском языке по этим примерам -
https://github.com/jiegzhan/multi-class ... on-cnn-rnn
https://machinelearningmastery.com/sequ ... hon-keras/

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

Следующие параметры
Максимальная длина статьи - 969 слов (в среднем значительно меньше), но мы добавляем PAD вместо пустых слов.
размер получающегося словаря - 53886
Колилчество классов - 12 ( и они к сожалению распределены очень неравномерно, например первый класс содержит 5000 записий, а второй только 1500)

Также самая главная проблема - это размер учебного набора -
Всего 9876 записей
И увеличить его к сожалению никак нельзя.


Вот мой код

x, x_test, y, y_test = train_test_split(x_, y_, test_size=0.1)
x_train, x_dev, y_train, y_dev = train_test_split(x, y, test_size=0.1)

embedding_vecor_length = 100

model = Sequential()
model.add(Embedding(top_words, embedding_vecor_length, input_length=max_review_length))
model.add(Conv1D(filters=32, kernel_size=3, padding='same', activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(keras.layers.Dropout(0.3))
model.add(Conv1D(filters=32, kernel_size=4, padding='same', activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(keras.layers.Dropout(0.3))
model.add(Conv1D(filters=32, kernel_size=5, padding='same', activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(keras.layers.Dropout(0.3))
model.add(Conv1D(filters=32, kernel_size=7, padding='same', activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(keras.layers.Dropout(0.3))
model.add(Conv1D(filters=32, kernel_size=9, padding='same', activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(keras.layers.Dropout(0.3))
model.add(Conv1D(filters=32, kernel_size=12, padding='same', activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(keras.layers.Dropout(0.3))
model.add(Conv1D(filters=32, kernel_size=15, padding='same', activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(keras.layers.Dropout(0.3))
model.add(LSTM(200,dropout=0.3, recurrent_dropout=0.3))
model.add(Dense(labels_count, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

print(model.summary())

model.fit(x_train, y_train, epochs=25, batch_size=30)
scores = model.evaluate(x_tеst, y_test)


Я пробовал разные параметры, и сеть вроде работает.
Во время обучения получается очень большая тоночть (до 98%)
Но если проводить оценку - то максимум что я смог взять это было 74 процента (это были маленькие знаничения embedding_vecor_length, и batch_size)
Ну это явно оферфитинг..


Вопросы у меня такие
1) Правильно ли я построил модель в приципе? Я просто не совсем понимаю как текстовые данные сохраняются при конволюции (все примеры в интернете про картинки)
Может мне нужно использовать одновременную конволюцию с разными размерами фильтров и потом их мержить?
Вообще расскажите как правильно делать конволюцию для текста и какие размеры фильтров выбирать?
(мне кажется что в первом слое filters=32, kernel_size=3 конволюцию происходит только по 96 слловам? Или я не прав? и он берет весь текст?)

2) Как Решить проблему с оверффитингом? У меня нет возможности увеличить дата сет..
Я уже добавил Dropout (кстати правильно ли?)

3) Может нужна совсем другая структура сети? Например - читсая RNN?

Буду рад любым советам.
Аватара пользователя
AiK
Сообщения: 2273
Зарегистрирован: 13 фев 2004, 18:14
Откуда: СПб
Контактная информация:

20 ноя 2017, 11:16

Некоторые соображения:

1. По сути классифицируются не тексты, а стили авторов. Соответственно если текст какого-то специфического автора не попал в обучающую выборку, то хорошей модели не построить по определению.

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

3. С учётом пп.1 и 2 соотношение 98% - 74% не выглядит плохим. То есть как минимум требуется обосновать, почему такая точность считается плохой.

4. С количеством текстов решить проблему элементарно - разбить тексты одного автора на предложения и рандомно сгенерировать из них любое количество текстов любой нужной длины. Если информации об авторстве нет, то разбивать тексты на предложения внутри одного класса.
Даже самый дурацкий замысел можно воплотить мастерски
glorsh66
Сообщения: 3
Зарегистрирован: 09 июл 2017, 10:15

21 ноя 2017, 19:36

Кстати да! Попробовал почистить тестовые данные. Основной проблемой оказалось, что некоторые штуки можно было отнести сразу к нескольким категориям.
Иначе говоря категория: прочее, иное
Убрал эту категорию и точность значительно увеличилась

И удалось поднять точность до 95% процентов.
Ответить