Using context bounds to write a general linear classifier.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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