我正在对评论的情绪进行分类 -
0
或 1
- 在 gensim
中使用 Tensorflow 2.2.0
Doc2Vec 和 CNN:
model = tf.keras.Sequential([
tf.keras.layers.Embedding(vocab_size, embedding_dim,
input_length=maxlen,
embeddings_initializer=Constant(embedding), trainable=False),
tf.keras.layers.Conv1D(128, 5, activation='relu'),
tf.keras.layers.GlobalMaxPooling1D(),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile(loss='binary_crossentropy',
optimizer=tf.keras.optimizers.Adam(1e-4),
metrics=['accuracy'])
history = model.fit(X_train, y_train,
epochs=8,
validation_split=0.3,
batch_size=10)
然后我进行预测并使用
0
将我的 sigmoid 概率转换为 1
或 np.round()
:
predicted = model.predict(X_test)
predicted = np.round(predicted,1).astype(np.int32)
我得到了很好的结果(~96% 的准确度),表明
0.5
的阈值正在按预期工作...
但是,当我尝试预测一组新数据时,该模型似乎将差评与好评区分开来,但范围大约为
0.0
:
# Example sigmoid outputs for new test reviews:
good_review_1: 0.000052
good_review_2: 0.000098
bad_review_1: 0.112334
bad_review_2: 0.214934
请注意,模型在训练期间从未见过
X_test
,并且它能够很好地进行预测。只有当我引入一组新的评论文本字符串时,我才会遇到错误的预测。对于新评论,我在调用 model.predict()
之前所做的唯一预处理是通过用于模型训练的相同标记器来提供它们:
s = 'This is a sample bad review.'
tokenizer.texts_to_sequences(pd.Series(s))
s = pad_sequences(s, maxlen=maxlen, padding='pre', truncating='pre')
model.predict(s)
我一直在试图理解这个难题,但进展甚微。我遇到了post,它表明
有些 sigmoid 函数会将其设置为 0,而有些函数会将其设置为不同的“阈值”。
但这仍然不能解释为什么我的模型能够预测
np.round()
的0.5
数据集的X_test
阈值(模型从未学习过),然后无法同时预测新数据集 0.5
阈值...
可能的答案很少,具体取决于 OP 可能不会提供的额外详细信息,因为问题是在 3 年前发布的,但无论如何,有人可能会发现这很有用。
我得到了很好的结果(~96% 的准确度),表明阈值 0.5 > 按预期工作...
通过训练期间的验证,您的准确率达到 96% 吗?或者通过预测、四舍五入并与目标进行比较?你可以尝试使用model.evaluate()。 确保您不会以一种方式进行验证,并以另一种方式进行推理(预测)。
如果这方面一切都很好,并且您使用相同的方法进行验证和预测(可以进行测试,只需使用您的训练数据、测试数据查看输出,您提到的这个“新数据”是有问题的),也许“新数据” “只是差别很大,你可以看一下。
此外,此舍入代码可能存在问题,尤其是如果您在拟合过程中通过验证获得 96% 的准确度,并且“新的令人困惑的结果”来自舍入后的预测(不同的方法)。
predicted = np.round(predicted,1).astype(np.int32)
不确定你从哪里得到像“0.000052,0.000098..”这样的预测,如果“验证和预测的不同方法”假设是错误的,也许它真的与数据有关,看起来也不像是四舍五入后的,无论如何,这个包含示例,强调了这种舍入方法可能导致问题的方式。