Github user srowen commented on a diff in the pull request:

    https://github.com/apache/spark/pull/6761#discussion_r32520095
  
    --- Diff: 
mllib/src/main/scala/org/apache/spark/mllib/classification/NaiveBayes.scala ---
    @@ -113,6 +106,55 @@ class NaiveBayesModel private[mllib] (
         }
       }
     
    +  def predictProbabilities(testData: RDD[Vector]): RDD[Map[Double, 
Double]] = {
    +    val bcModel = testData.context.broadcast(this)
    +    testData.mapPartitions { iter =>
    +      val model = bcModel.value
    +      iter.map(model.predictProbabilities)
    +    }
    +  }
    +
    +  def predictProbabilities(testData: Vector): Map[Double, Double] = {
    +    modelType match {
    +      case Multinomial =>
    +        val prob = multinomialCalculation(testData)
    +        posteriorProbabilities(prob)
    +      case Bernoulli =>
    +        val prob = bernoulliCalculation(testData)
    +        posteriorProbabilities(prob)
    +      case _ =>
    +        // This should never happen.
    +        throw new UnknownError(s"Invalid modelType: $modelType.")
    +    }
    +  }
    +
    +  protected[classification] def multinomialCalculation(testData: Vector): 
DenseVector = {
    +    val prob = thetaMatrix.multiply(testData)
    +    BLAS.axpy(1.0, piVector, prob)
    +    prob
    +  }
    +
    +  protected[classification] def bernoulliCalculation(testData: Vector): 
DenseVector = {
    +    testData.foreachActive { (index, value) =>
    +      if (value != 0.0 && value != 1.0) {
    +        throw new SparkException(
    +          s"Bernoulli naive Bayes requires 0 or 1 feature values but found 
$testData.")
    +      }
    +    }
    +    val prob = thetaMinusNegTheta.get.multiply(testData)
    +    BLAS.axpy(1.0, piVector, prob)
    +    BLAS.axpy(1.0, negThetaSum.get, prob)
    +    prob
    +  }
    +
    +  protected[classification] def posteriorProbabilities(prob: DenseVector): 
Map[Double, Double] = {
    +    val maxLogs = max(prob.toBreeze)
    +    val minLogs = min(prob.toBreeze)
    +    val normalized = prob.toArray.map(e => (e - minLogs) / (maxLogs - 
minLogs))
    --- End diff --
    
    "Dividing / multiplying the log probabilities is the only way to maintain 
the probabilities scale because they will be scaled by the same multiplicative 
factor.":
    
    Not being funny but do you understand logarithms? you are trying to scale 
probabilities to sum to 1, by multiplying them by a normalizing factor. But 
"multiply" becomes "add" in log space.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at [email protected] or file a JIRA ticket
with INFRA.
---

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to