forked from echen/link-prediction
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Scorer.scala
77 lines (67 loc) · 2.5 KB
/
Scorer.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import scala.collection.mutable.Map
import scala.io._
/**
* Given a file of predictions on a test set, score these predictions
* according to the mean average precision.
*
* @author Edwin Chen
*/
object Scorer {
def main(args: Array[String]) = {
// Read in our predictions.
val myPredictionsFile = args(0) // Example row: "23,15 25 9 50" means that we predict user 23 is following users 15, 25, 9, and 50.
val myPredictions: List[(Int, Array[Int])] =
Source.fromFile(myPredictionsFile).getLines().map { line: String =>
val Array(src, predictedDests) = line.split(",")
(src.toInt, predictedDests.split(" ").map { _.toInt }.distinct)
}.toList
// Read in the set of followings that we want to predict.
val followings = Map[Int, Set[Int]]()
Source.fromFile("my_data/my_test_with_responses.csv").getLines().foreach { line: String =>
val Array(src, actualDests) = line.split(",")
followings(src.toInt) = actualDests.split(" ").map { _.toInt }.toSet
}
// Calculate the average precisions for each user.
val averagePrecisions =
myPredictions.map { case (src, predictedDests) =>
calculateAveragePrecision(predictedDests, getFollowings(src.toInt, followings))
}
// Calculate the mean of these average precisions.
val map = if (averagePrecisions.size == 0) {
0.0
} else {
averagePrecisions.sum / averagePrecisions.size
}
println(map)
}
/**
* Calculate the average precision of a sequence of predicted followings, given the
* true set.
* See http://www.kaggle.com/c/FacebookRecruiting/details/Evaluation for more details
* on the average precision metric.
*
* Examples:
*
* calculateAveragePrecision( [A, B, C], [A, C, X] )
* => (1/1 + 2/3) / 3 ~ 0.56
*
* calculateAveragePrecision( [A, B], [A, B, C] )
* => (1/1 + 2/2) /3 ~ 0.67
*/
def calculateAveragePrecision(predictions: Seq[Int], actuals: Set[Int]) : Float = {
var numCorrect = 0
val precisions =
predictions.zipWithIndex.map { case (prediction, index) =>
if (actuals.contains(prediction)) {
numCorrect += 1
numCorrect.toFloat / (index + 1)
} else {
0
}
}
if (actuals.size == 0) 0 else (precisions.sum / actuals.size)
}
def getFollowings(source : Int, followings : Map[Int, Set[Int]]) : Set[Int] = {
followings.getOrElse(source, Set[Int]())
}
}