Skip to content

Instantly share code, notes, and snippets.

@davidandrzej
Created June 22, 2012 23:27
Embed
What would you like to do?
Using context bounds to write a general linear classifier.
object ContextBoundExample extends App {
// This trait allows us to compute a fixed-length
// feature vector from a given instance of T
trait FeatureVector[T] {
def features(x: T): Array[Double]
}
// This context bound allows us to T "has-a" corresponding
// FeatureVector implementation in the caller's implicit scope
class LinearClassifier[T : FeatureVector](weights: Array[Double]) {
val featureMapping = implicitly[FeatureVector[T]]
def innerProduct(x: Array[Double], y: Array[Double]): Double = {
(0 until x.size).map{i => x(i) * y(i)}.sum
}
def classify(x: T): Boolean = {
innerProduct(featureMapping.features(x), weights) > 0
}
}
// This implicit supplies a means to
// compute feature vectors from Strings
implicit object StringFeatures extends FeatureVector[String] {
def features(x: String): Array[Double] = {
// Just count the occurrences of a, b, and c
val result = Array.ofDim[Double](3)
result(0) = x.filter{_ equals 'a'}.size.toDouble
result(1) = x.filter{_ equals 'b'}.size.toDouble
result(2) = x.filter{_ equals 'c'}.size.toDouble
result
}
}
// Build a very simple classifier
val testWeights = Array[Double](-1.0, 0.0, 1.0)
//
// Classify some Strings
//
val stringClassifier = new LinearClassifier[String](testWeights)
// negative-weight 'a', should be classified as false
val ex1 = "aaa"
val predict1 = stringClassifier.classify(ex1)
println("%s is classified as %b".format(ex1, predict1))
// positive-weight 'c' and zero-weight 'b' (classify as true)
val ex2 = "bbbcc"
val predict2 = stringClassifier.classify(ex2)
println("%s is classified as %b".format(ex2, predict2))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment