blob: 831dea25fe66cb6ab08a8428c4640a7f1830308d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.predictionio.examples.similarproduct
import org.apache.predictionio.controller.LServing
import breeze.stats.meanAndVariance
import breeze.stats.MeanAndVariance
class Serving
extends LServing[Query, PredictedResult] {
override
def serve(query: Query,
predictedResults: Seq[PredictedResult]): PredictedResult = {
// MODFIED
val standard: Seq[Array[ItemScore]] = if (query.num == 1) {
// if query 1 item, don't standardize
predictedResults.map(_.itemScores)
} else {
// Standardize the score before combine
val mvList: Seq[MeanAndVariance] = predictedResults.map { pr =>
meanAndVariance(pr.itemScores.map(_.score))
}
predictedResults.zipWithIndex
.map { case (pr, i) =>
pr.itemScores.map { is =>
// standardize score (z-score)
// if standard deviation is 0 (when all items have the same score,
// meaning all items are ranked equally), return 0.
val score = if (mvList(i).stdDev == 0) {
0
} else {
(is.score - mvList(i).mean) / mvList(i).stdDev
}
ItemScore(is.item, score)
}
}
}
// sum the standardized score if same item
val combined = standard.flatten // Array of ItemScore
.groupBy(_.item) // groupBy item id
.mapValues(itemScores => itemScores.map(_.score).reduce(_ + _))
.toArray // array of (item id, score)
.sortBy(_._2)(Ordering.Double.reverse)
.take(query.num)
.map { case (k,v) => ItemScore(k, v) }
PredictedResult(combined)
}
}