Прогноз идентичен для всех входных данных в Multi-Label Classification (NLP) - PullRequest
0 голосов
/ 27 октября 2019

Я пытаюсь построить модель глубокого обучения, чтобы предсказать 5 лучших жанров фильма, используя синопсис фильмов в качестве входных данных. К жанрам фильмов, которые я включаю в данные, относятся 19, но, независимо от входных данных теста, модель всегда предсказывает одни и те же 5 жанров фильма. Ниже мой код построения модели. Однако точность при подгонке составляет 90%. Можете ли вы указать мне правильное направление относительно того, что я делаю неправильно?

from keras.preprocessing.text import one_hot
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
from keras.layers.core import Activation, Dropout, Dense
from keras.layers import Flatten, LSTM
from keras.layers import GlobalMaxPooling1D
from keras.models import Model
from keras.layers.embeddings import Embedding
from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.model_selection import train_test_split
from keras.preprocessing.text import Tokenizer
from keras.layers import Input
from keras.layers.merge import Concatenate

import pandas as pd
import numpy as np
import re

data = pd.read_csv('train.csv', encoding = 'utf-8')
#Create column with comma separated genres
data['genres_comma'] = data['genres'].str.split()
mlb = MultiLabelBinarizer()
#Create new dataframe with one hot encoded labels
train = pd.concat([
    data.drop(['genres', 'genres_comma'], 1),
    pd.DataFrame(mlb.fit_transform(data['genres_comma']), columns=mlb.classes_),
], 1)

genre_names = list(mlb.classes_)
genres = train.drop(['movie_id', 'synopsis'], 1)

def preprocess_text(sen):
    # Remove punctuations and numbers
    sentence = re.sub('[^a-zA-Z]', ' ', sen)

    # Single character removal
    sentence = re.sub(r"\s+[a-zA-Z]\s+", ' ', sentence)

    # Removing multiple spaces
    sentence = re.sub(r'\s+', ' ', sentence)

    return sentence

X = []
sentences = list(train['synopsis'])
for sen in sentences:
    X.append(preprocess_text(sen))

y = genres.values

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42)

#Convert text inputs into embedded vectors.
tokenizer = Tokenizer(num_words=5000)
tokenizer.fit_on_texts(X_train)

X_train = tokenizer.texts_to_sequences(X_train)
X_test = tokenizer.texts_to_sequences(X_test)

vocab_size = len(tokenizer.word_index) + 1

maxlen = 200

X_train = pad_sequences(X_train, padding='post', maxlen=maxlen)
X_test = pad_sequences(X_test, padding='post', maxlen=maxlen)

#GloVe word embeddings to convert text inputs to their numeric counterparts
from numpy import asarray
from numpy import zeros

embeddings_dictionary = dict()

glove_file = open('glove.6B.100d.txt', encoding="utf8")

for line in glove_file:
    records = line.split()
    word = records[0]
    vector_dimensions = asarray(records[1:], dtype='float32')
    embeddings_dictionary[word] = vector_dimensions
glove_file.close()

embedding_matrix = zeros((vocab_size, 100))
for word, index in tokenizer.word_index.items():
    embedding_vector = embeddings_dictionary.get(word)
    if embedding_vector is not None:
        embedding_matrix[index] = embedding_vector

#Model Creation
deep_inputs = Input(shape=(maxlen,))
embedding_layer = Embedding(vocab_size, 100, weights=[embedding_matrix], trainable=False)(deep_inputs)
LSTM_Layer_1 = LSTM(128)(embedding_layer)
dense_layer_1 = Dense(19, activation='sigmoid')(LSTM_Layer_1)
model = Model(inputs=deep_inputs, outputs=dense_layer_1)

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

print(model.summary())


history = model.fit(X_train, y_train, batch_size=128, epochs=5, verbose=1, validation_split=0.2)

score = model.evaluate(X_test, y_test, verbose=1)

Ответы [ 2 ]

0 голосов
/ 29 октября 2019

Другой подход, который иногда помогает, состоит в том, чтобы сгруппировать 14 классов меньшинства в класс «другой». Возможно, это достаточно часто для вашего классификатора, чтобы выучить его.

Если это так, то вы можете обучить другого классификатора предсказывать правильный класс, только для «других» примеров.

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

0 голосов
/ 27 октября 2019

Проверяли ли вы распределение классов в ваших данных обучения? точность не очень хорошая мера, если у вас сильно несбалансированные классы. Например, если эти 5 жанров составляют> 90% ваших обучающих данных, модель, возможно, не научилась классифицировать какой-либо другой жанр, но все же достигла точности 90% (обычным режимом сбоя является постоянный выход, который может иметьвысокая точность с несбалансированными классами). Итак, первым шагом должно быть рассмотрение количества обучающих фильмов в соответствующих категориях.

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

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