Как определить двоичный класс, предсказанный сверточной нейронной сетью на Keras? - PullRequest
0 голосов
/ 25 августа 2018

Я строю CNN для анализа настроений на Керасе.Все работает отлично, модель обучена и готова к запуску в производство.

Однако, когда я пытаюсь прогнозировать новые немеченые данные с помощью метода model.predict(), она выводит только связанную вероятность.Я пытался использовать метод np.argmax(), но он всегда выводит 0, даже когда он должен быть равен 1 (в тестовом наборе моя модель достигла 80% точности).

Вот мой код для предварительной обработки данных:

# Pre-processing data
x = df[df.Sentiment != 3].Headlines
y = df[df.Sentiment != 3].Sentiment

# Splitting training, validation, testing dataset
x_train, x_validation_and_test, y_train, y_validation_and_test = train_test_split(x, y, test_size=.3,
                                                                                      random_state=SEED)
x_validation, x_test, y_validation, y_test = train_test_split(x_validation_and_test, y_validation_and_test,
                                                                  test_size=.5, random_state=SEED)

tokenizer = Tokenizer(num_words=NUM_WORDS)
tokenizer.fit_on_texts(x_train)

sequences = tokenizer.texts_to_sequences(x_train)
x_train_seq = pad_sequences(sequences, maxlen=MAXLEN)

sequences_val = tokenizer.texts_to_sequences(x_validation)
x_val_seq = pad_sequences(sequences_val, maxlen=MAXLEN)

sequences_test = tokenizer.texts_to_sequences(x_test)
x_test_seq = pad_sequences(sequences_test, maxlen=MAXLEN)

А вот моя модель:

MAXLEN = 25
NUM_WORDS = 5000
VECTOR_DIMENSION = 100

tweet_input = Input(shape=(MAXLEN,), dtype='int32')

tweet_encoder = Embedding(NUM_WORDS, VECTOR_DIMENSION, input_length=MAXLEN)(tweet_input)

# Combinating n-gram to optimize results
bigram_branch = Conv1D(filters=100, kernel_size=2, padding='valid', activation="relu", strides=1)(tweet_encoder)
bigram_branch = GlobalMaxPooling1D()(bigram_branch)
trigram_branch = Conv1D(filters=100, kernel_size=3, padding='valid', activation="relu", strides=1)(tweet_encoder)
trigram_branch = GlobalMaxPooling1D()(trigram_branch)
fourgram_branch = Conv1D(filters=100, kernel_size=4, padding='valid', activation="relu", strides=1)(tweet_encoder)
fourgram_branch = GlobalMaxPooling1D()(fourgram_branch)
merged = concatenate([bigram_branch, trigram_branch, fourgram_branch], axis=1)

merged = Dense(256, activation="relu")(merged)
merged = Dropout(0.25)(merged)
output = Dense(1, activation="sigmoid")(merged)

optimizer = optimizers.adam(0.01)

model = Model(inputs=[tweet_input], outputs=[output])
model.compile(loss="binary_crossentropy", optimizer=optimizer, metrics=['accuracy'])
model.summary()

# Training the model
history = model.fit(x_train_seq, y_train, batch_size=32, epochs=5, validation_data=(x_val_seq, y_validation))

Я также пытался изменить количество активацийна последнем плотном слое от 1 до 2, но я получаю ошибку:

Error when checking target: expected dense_12 to have shape (2,) but got array with shape (1,)

1 Ответ

0 голосов
/ 25 августа 2018

Вы делаете бинарную классификацию.Таким образом, у вас есть плотный слой, состоящий из одного юнита с функцией активации sigmoid.Функция сигмоида выводит значение в диапазоне [0,1], которое соответствует вероятности того, что данный образец принадлежит положительному классу (т.е. первому классу).Все, что ниже 0,5, помечено нулем (т.е. отрицательный класс), а все, что выше 0,5, помечено единицей.Таким образом, чтобы найти прогнозируемый класс, вы можете сделать следующее:

preds = model.predict(data)
class_one = preds > 0.5

Истинные элементы class_one соответствуют образцам, помеченным единицей (то есть положительным классом).

Бонус: чтобы найти точность своих предсказаний, вы можете легко сравнить class_one с истинными метками:

acc = np.mean(class_one == true_labels)

Обратите внимание, что я предположил, что true_labels состоит из нулей и единиц.


Кроме того, если ваша модель была определена с использованием класса Sequential, вы можете легко использовать метод predict_classes:

pred_labels = model.predict_classes(data)

Однако, поскольку вы используете функциональный API Keras для построения вашей модели (на мой взгляд, это очень хорошая вещь, вы не можете использовать метод predict_classes, поскольку он плохо определен для таких моделей.

...