如何确定 Keras 上的卷积神经网络预测的二进制 class?
How do I determine the binary class predicted by a convolutional neural network on Keras?
我正在构建一个 CNN 来对 Keras 执行情绪分析。
一切都运行良好,模型已经过训练并准备好投入生产。
但是,当我尝试使用 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))
我还尝试将最终 Dense 层上的激活数从 1 更改为 2,但出现错误:
Error when checking target: expected dense_12 to have shape (2,) but got array with shape (1,)
您正在进行二进制class化。所以你有一个 Dense 层,由一个激活函数为 sigmoid
的单元组成。 Sigmoid 函数输出范围 [0,1] 中的值,该值对应于给定样本属于正 class 的概率(即 class 一个)。低于 0.5 的所有值都标记为零(即负 class),所有高于 0.5 的值都标记为 1。因此,要找到预测的 class,您可以执行以下操作:
preds = model.predict(data)
class_one = preds > 0.5
class_one
的真实元素对应标有 1 的样本(即正 class)。
奖励: 要找到预测的准确性,您可以轻松地将 class_one
与真实标签进行比较:
acc = np.mean(class_one == true_labels)
请注意,我假设 true_labels
由零和一组成。
此外,如果您的模型是使用顺序 class 定义的,那么您可以轻松地使用 predict_classes
方法:
pred_labels = model.predict_classes(data)
但是,由于您正在使用 Keras 函数 API 来构建模型(在我看来,这样做是一件非常好的事情),因此您不能使用 predict_classes
方法,因为对于此类模型,它的定义不明确。
我正在构建一个 CNN 来对 Keras 执行情绪分析。 一切都运行良好,模型已经过训练并准备好投入生产。
但是,当我尝试使用 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))
我还尝试将最终 Dense 层上的激活数从 1 更改为 2,但出现错误:
Error when checking target: expected dense_12 to have shape (2,) but got array with shape (1,)
您正在进行二进制class化。所以你有一个 Dense 层,由一个激活函数为 sigmoid
的单元组成。 Sigmoid 函数输出范围 [0,1] 中的值,该值对应于给定样本属于正 class 的概率(即 class 一个)。低于 0.5 的所有值都标记为零(即负 class),所有高于 0.5 的值都标记为 1。因此,要找到预测的 class,您可以执行以下操作:
preds = model.predict(data)
class_one = preds > 0.5
class_one
的真实元素对应标有 1 的样本(即正 class)。
奖励: 要找到预测的准确性,您可以轻松地将 class_one
与真实标签进行比较:
acc = np.mean(class_one == true_labels)
请注意,我假设 true_labels
由零和一组成。
此外,如果您的模型是使用顺序 class 定义的,那么您可以轻松地使用 predict_classes
方法:
pred_labels = model.predict_classes(data)
但是,由于您正在使用 Keras 函数 API 来构建模型(在我看来,这样做是一件非常好的事情),因此您不能使用 predict_classes
方法,因为对于此类模型,它的定义不明确。