在尝试对一些文本内容进行分类时,我经常会得到类似这样的结果:
{"category":"SOME_CATEGORY","confidence":NaN}
除了它不是有效的 JSON(Nan
未经授权)之外,我不明白发生了什么。
如有必要,我可以通过在计算期间附加调试器来提供中间值。
在尝试对一些文本内容进行分类时,我经常会得到类似这样的结果:
{"category":"SOME_CATEGORY","confidence":NaN}
除了它不是有效的 JSON(Nan
未经授权)之外,我不明白发生了什么。
如有必要,我可以通过在计算期间附加调试器来提供中间值。
嗯,所以我的想法是问题出在NBAlgorithm.predict
方法上,它的发生原因如下。如果您查看PreparedData
使用 Spark MLLib 的HashingTF
类创建的频率向量。该向量的默认大小为 1,048,576,并且每个标记都映射到与其哈希值对应的索引,该哈希值以特征向量的大小为模。鉴于所提供的信息,我最好的猜测是,在朴素贝叶斯训练中,一些结果向量索引在所有类中产生了 0 概率估计(这将解释获取日志时的不确定值)。
鉴于此,我只是在 2.3 版本中添加了一个参数numFeatures
来PreparatorParams
控制特征向量的大小(将默认值设置为 15000,尽管您可以在engine.json
文件中随意修改),并测试了一些查询。让我知道这是否为您解决了问题,否则,请提供有关您的数据以及产生这些值的查询的任何额外信息。
- - 编辑 - -
好的,所以这是我提出的一个避免这些NaN
值的小技巧。
特别是,您可以从文档中看到后验类概率的向量(给定文档中观察到的单词)由向量表示:
这意味着在给定从文档中获得的字数的情况下,观察属于 k 类的后验概率可以写成:
现在,我们有明显的相等性:
这尤其意味着我们可以将后一个概率写为:
那么为什么这一切都很重要呢?好吧,我们担心概率计算中的 c_k 值是具有大绝对值的负数的情况。后者将其中最大的一个约束为 1,其余的一些值小于 1。也就是说,如果不失一般性,我们假设类 1 与绝对值最小的 c_1 相关联,那么我们有平等:
我认为这些方程的威力最好用一个代码示例来说明:
import scala.math._
val probs = Seq(-13452, -13255, -13345)
// Results in a sequence of 0.0 values.
probs
.map(k => exp(k))
// Same transformation using the latter equalities.
// Note that this yields non-zero values.
probs
.map(k => (abs(probs.max) - abs(probs(k)))*log10(E))
.map(x => pow(10, x))
将尽快实施此捕获,谢谢您的提醒。