我正在使用Golang实现朴素贝叶斯分类器,用于处理一个具有超过30000个可能标签的数据集。我已经构建了模型并处于分类阶段。我正在努力对1000条记录进行分类,但这需要长达5分钟的时间。我已经使用pprof功能对代码进行了分析;以下是前10个结果:
Total: 28896 samples
16408 56.8% 56.8% 24129 83.5% runtime.mapaccess1_faststr
4977 17.2% 74.0% 4977 17.2% runtime.aeshashbody
2552 8.8% 82.8% 2552 8.8% runtime.memeqbody
1468 5.1% 87.9% 28112 97.3% main.(*Classifier).calcProbs
861 3.0% 90.9% 861 3.0% math.Log
435 1.5% 92.4% 435 1.5% runtime.markspan
267 0.9% 93.3% 302 1.0% MHeap_AllocLocked
187 0.6% 94.0% 187 0.6% runtime.aeshashstr
183 0.6% 94.6% 1137 3.9% runtime.mallocgc
127 0.4% 95.0% 988 3.4% math.log10
令人惊讶的是,地图访问似乎成为了瓶颈。有没有人有过这样的经验?还有哪些键值数据结构可以用来避免这种瓶颈?以下代码片段中完成了所有地图访问:
func (nb *Classifier) calcProbs(data string) *BoundedPriorityQueue{
probs := &BoundedPriorityQueue{}
heap.Init(probs)
terms := strings.Split(data, " ")
for class, prob := range nb.classProb{
condProb := prob
clsProbs := nb.model[class]
for _, term := range terms{
termProb := clsProbs[term]
if termProb != 0{
condProb += math.Log10(termProb)
}else{
condProb += -6 //math.Log10(0.000001)
}
}
entry := &Item{
value: class,
priority: condProb,
}
heap.Push(probs,entry)
}
return probs
}
这些图是nb.classProb,其中包含map[string]float64
类型,而nb.model是一个嵌套的map,其类型为
map[string]map[string]float64
for _, term := range terms
循环是主要代码(内循环),那么显然 map 查找将是最耗时的。 - Volker