Skip to content

Commit

Permalink
Merge pull request #32 from dlwh/master
Browse files Browse the repository at this point in the history
update to Breeze 0.6.1
  • Loading branch information
jasonbaldridge committed Feb 27, 2014
2 parents 815673d + b31d23c commit b843993
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 62 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ resolvers ++= Seq(


libraryDependencies ++= Seq(
"org.scalanlp" % "breeze_2.10" % "0.5.2",
"org.scalanlp" % "breeze_2.10" % "0.6.1",
"org.rogach" %% "scallop" % "0.9.4",
"com.typesafe" %% "scalalogging-log4j" % "1.0.1",
"org.apache.logging.log4j" % "log4j-core" % "2.0-beta8",
Expand Down
86 changes: 40 additions & 46 deletions src/main/scala/nak/classify/LFMatrix.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package nak.classify

import breeze.util.{Encoder, Index}
import breeze.linalg.{Counter, DenseVector, NumericOps}
import breeze.linalg.{norm, Counter, DenseVector, NumericOps}
import breeze.linalg.operators._
import breeze.linalg.support.{CanCreateZerosLike, CanCopy, CanZipMapValues, CanNorm}
import breeze.generic.{URFunc, UReduceable, CanMapValues}
import breeze.linalg.support._
import breeze.generic._
import nak.serialization.DataSerialization
import nak.serialization.DataSerialization.ReadWritable
import breeze.math.{MutableCoordinateSpace, TensorSpace}
import breeze.math.{Field, MutableCoordinateSpace, TensorSpace}
import scala.reflect.ClassTag

/**
Expand Down Expand Up @@ -60,9 +60,9 @@ class LFMatrix[L,TF:ClassTag](val data: Array[TF],

object LFMatrix {
implicit def lfMatrixTimesTF[L,TF]
(implicit inner: BinaryOp[TF,TF,OpMulInner,Double], numeric: TF=>NumericOps[TF])
: BinaryOp[LFMatrix[L,TF],TF,OpMulMatrix,DenseVector[Double]] = {
new BinaryOp[LFMatrix[L,TF],TF,OpMulMatrix,DenseVector[Double]] {
(implicit inner: OpMulInner.Impl2[TF,TF,Double], numeric: TF=>NumericOps[TF])
: OpMulMatrix.Impl2[LFMatrix[L,TF],TF,DenseVector[Double]] = {
new OpMulMatrix.Impl2[LFMatrix[L,TF],TF,DenseVector[Double]] {

def apply(v1: LFMatrix[L, TF], v2: TF) = {
val r = DenseVector.zeros[Double](v1.numLabels)
Expand All @@ -75,9 +75,9 @@ object LFMatrix {
}

implicit def lfBinaryOp[L,TF,Op<:OpType]
(implicit op: BinaryOp[TF,Double,Op,TF], numeric: TF=>NumericOps[TF])
: BinaryOp[LFMatrix[L,TF],Double,Op,LFMatrix[L,TF]] = {
new BinaryOp[LFMatrix[L,TF],Double,Op,LFMatrix[L,TF]] {
(implicit op: UFunc.UImpl2[Op, TF,Double,TF], numeric: TF=>NumericOps[TF])
: UFunc.UImpl2[Op, LFMatrix[L,TF],Double,LFMatrix[L,TF]] = {
new UFunc.UImpl2[Op, LFMatrix[L,TF],Double,LFMatrix[L,TF]] {

def apply(v1: LFMatrix[L, TF], v2: Double) = {
val r = v1.empty
Expand All @@ -89,10 +89,10 @@ object LFMatrix {
}
}

implicit def lfBinaryOpBackwards[L,TF,Op<:OpType]
(implicit op: BinaryOp[Double,TF,Op,TF], numeric: TF=>NumericOps[TF])
: BinaryOp[Double,LFMatrix[L,TF],Op,LFMatrix[L,TF]] = {
new BinaryOp[Double,LFMatrix[L,TF],Op,LFMatrix[L,TF]] {
implicit def lfbinaryOpBackwards[L,TF,Op<:OpType]
(implicit op: UFunc.UImpl2[Op, Double,TF,TF], numeric: TF=>NumericOps[TF])
: UFunc.UImpl2[Op, Double,LFMatrix[L,TF],LFMatrix[L,TF]] = {
new UFunc.UImpl2[Op, Double,LFMatrix[L,TF],LFMatrix[L,TF]] {

def apply(v2: Double, v1: LFMatrix[L, TF]) = {
val r = v1.empty
Expand All @@ -105,9 +105,9 @@ object LFMatrix {
}

implicit def lfBinaryTFOp[L,TF,Op<:OpType]
(implicit op: BinaryOp[TF,TF,Op,TF], numeric: TF=>NumericOps[TF])
: BinaryOp[LFMatrix[L,TF],LFMatrix[L,TF],Op,LFMatrix[L,TF]] = {
new BinaryOp[LFMatrix[L,TF],LFMatrix[L,TF],Op,LFMatrix[L,TF]] {
(implicit op: UFunc.UImpl2[Op, TF,TF,TF], numeric: TF=>NumericOps[TF])
: UFunc.UImpl2[Op, LFMatrix[L,TF],LFMatrix[L,TF],LFMatrix[L,TF]] = {
new UFunc.UImpl2[Op, LFMatrix[L,TF],LFMatrix[L,TF],LFMatrix[L,TF]] {

def apply(v2: LFMatrix[L,TF], v1: LFMatrix[L, TF]) = {
val r = v1.empty
Expand All @@ -122,9 +122,9 @@ object LFMatrix {
}

implicit def lfInnerOp[L,TF]
(implicit op: BinaryOp[TF,TF,OpMulInner,Double], numeric: TF=>NumericOps[TF])
: BinaryOp[LFMatrix[L,TF],LFMatrix[L,TF],OpMulInner,Double] = {
new BinaryOp[LFMatrix[L,TF],LFMatrix[L,TF],OpMulInner,Double] {
(implicit op: OpMulInner.Impl2[TF,TF,Double], numeric: TF=>NumericOps[TF])
: OpMulInner.Impl2[LFMatrix[L,TF],LFMatrix[L,TF],Double] = {
new OpMulInner.Impl2[LFMatrix[L,TF],LFMatrix[L,TF],Double] {
def apply(v2: LFMatrix[L,TF], v1: LFMatrix[L, TF]) = {
var r = 0.0
for( (tf, l) <- v1.data.zipWithIndex) {
Expand All @@ -137,27 +137,26 @@ object LFMatrix {
}

implicit def lfBinaryOp2[L,TF,Op]
(implicit op: BinaryOp[TF,Double,OpMulScalar,TF], numeric: TF=>NumericOps[TF])
: BinaryOp[LFMatrix[L,TF],Double,OpMulScalar,LFMatrix[L,TF]] = {
new BinaryOp[LFMatrix[L,TF],Double, OpMulScalar, LFMatrix[L,TF]] {
(implicit op: UFunc.UImpl2[OpMulScalar.type, TF, Double,TF], numeric: TF=>NumericOps[TF])
: UFunc.UImpl2[OpMulScalar.type, LFMatrix[L,TF], Double,LFMatrix[L,TF]] = {
new UFunc.UImpl2[OpMulScalar.type, LFMatrix[L,TF],Double, LFMatrix[L,TF]] {

def apply(v1: LFMatrix[L, TF], v2: Double) = {
val r = v1.empty
for( (tf, l) <- v1.data.zipWithIndex) {
r(l) = tf :* v2
r(l) = tf.:*(v2)(op)
}
r
}
}
}

implicit def lfUpdateOp[L,TF,Op<:OpType]
(implicit op: BinaryUpdateOp[TF,Double,Op], numeric: TF=>NumericOps[TF])
: BinaryUpdateOp[LFMatrix[L,TF],Double,Op] = {
new BinaryUpdateOp[LFMatrix[L,TF],Double,Op] {
(implicit op: UFunc.InPlaceImpl2[Op, TF,Double], numeric: TF=>NumericOps[TF])
: UFunc.InPlaceImpl2[Op, LFMatrix[L,TF],Double] = {
new UFunc.InPlaceImpl2[Op, LFMatrix[L,TF], Double] {

def apply(v1: LFMatrix[L, TF], v2: Double) {
val r = v1.empty
for( tf <- v1.data) {
op(tf,v2)
}
Expand All @@ -166,9 +165,9 @@ object LFMatrix {
}

implicit def lfBinaryTFUpdateOp[L,TF,Op<:OpType]
(implicit op: BinaryUpdateOp[TF,TF,Op], numeric: TF=>NumericOps[TF])
: BinaryUpdateOp[LFMatrix[L,TF],LFMatrix[L,TF],Op] = {
new BinaryUpdateOp[LFMatrix[L,TF],LFMatrix[L,TF],Op] {
(implicit op: UFunc.InPlaceImpl2[Op, TF,TF], numeric: TF=>NumericOps[TF])
: UFunc.InPlaceImpl2[Op, LFMatrix[L,TF],LFMatrix[L,TF]] = {
new UFunc.InPlaceImpl2[Op, LFMatrix[L,TF],LFMatrix[L,TF]] {
def apply(v2: LFMatrix[L,TF], v1: LFMatrix[L, TF]) {
require(v2.labelIndex == v1.labelIndex)
for( (tf, l) <- v1.data.zipWithIndex) {
Expand All @@ -194,9 +193,9 @@ object LFMatrix {
}

implicit def lfUnaryOp[L,TF,Op<:OpType]
(implicit op: UnaryOp[TF,Op,TF], numeric: TF=>NumericOps[TF])
: UnaryOp[LFMatrix[L,TF], Op, LFMatrix[L, TF]] = {
new UnaryOp[LFMatrix[L,TF],Op, LFMatrix[L, TF]] {
(implicit op: UFunc.UImpl[Op, TF, TF], numeric: TF=>NumericOps[TF])
: UFunc.UImpl[Op, LFMatrix[L,TF], LFMatrix[L, TF]] = {
new UFunc.UImpl[Op, LFMatrix[L,TF], LFMatrix[L, TF]] {
def apply(v1: LFMatrix[L, TF]) = {
val r = v1.empty
for( (tf, l) <- v1.data.zipWithIndex) {
Expand All @@ -207,8 +206,8 @@ object LFMatrix {
}
}

implicit def lfNorm[L,TF](implicit op: CanNorm[TF]) : CanNorm[LFMatrix[L,TF]] = {
new CanNorm[LFMatrix[L,TF]] {
implicit def lfNorm[L,TF](implicit op: norm.Impl2[TF, Double, Double]) : norm.Impl2[LFMatrix[L,TF], Double, Double] = {
new norm.Impl2[LFMatrix[L,TF], Double, Double] {
def apply(v1: LFMatrix[L, TF], v2: Double) = {
math.pow(v1.data.iterator.map(op.apply(_,v2)).map(math.pow(_,v2)).sum, 1/v2)
}
Expand Down Expand Up @@ -283,14 +282,9 @@ object LFMatrix {
}
}

implicit def ureduceable[L, TF, I, V](implicit space: TensorSpace[TF, I, V]) = new UReduceable[LFMatrix[L, TF], V] {
import space._
def apply[Final](c: LFMatrix[L, TF], f: URFunc[V, Final]): Final = f(c.data.iterator.flatMap(_.valuesIterator))
}

implicit def coordSpace[L, V, I](implicit space: MutableCoordinateSpace[V, Double]) = {
import space._
MutableCoordinateSpace.make[LFMatrix[L, V], Double]
MutableCoordinateSpace.make[LFMatrix[L,V], Double]
}


Expand All @@ -308,10 +302,10 @@ class UnindexedLFMatrix[L,TF](val indexed: LFMatrix[L, TF]) extends NumericOps[
}

object UnindexedLFMatrix {
implicit def lfMatrixTimesTF[L,TF]
(implicit inner: BinaryOp[TF,TF,OpMulInner,Double], numeric: TF=>NumericOps[TF])
: BinaryOp[UnindexedLFMatrix[L,TF],TF,OpMulMatrix,Counter[L, Double]] = {
new BinaryOp[UnindexedLFMatrix[L,TF],TF,OpMulMatrix,Counter[L, Double]] {
implicit def ulfMatrixTimesTF[L,TF]
(implicit inner: OpMulMatrix.Impl2[ LFMatrix[L, TF], TF, DenseVector[Double]], numeric: TF=>NumericOps[TF])
: OpMulMatrix.Impl2[UnindexedLFMatrix[L,TF],TF,Counter[L, Double]] = {
new OpMulMatrix.Impl2[UnindexedLFMatrix[L,TF],TF,Counter[L, Double]] {

def apply(v1: UnindexedLFMatrix[L, TF], v2: TF) = {
val dv = v1.indexed * v2
Expand Down
12 changes: 4 additions & 8 deletions src/main/scala/nak/classify/LinearClassifier.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,10 @@ package nak.classify


import nak.serialization.DataSerialization.ReadWritable
import nak.serialization.{SerializationFormat, DataSerialization}
import nak.serialization.DataSerialization
import breeze.linalg._
import breeze.linalg.operators._
import breeze.math.{MutableCoordinateSpace, TensorSpace, VectorSpace}
import breeze.linalg.support.{CanCopy, CanZipMapValues, CanNorm, CanCreateZerosLike}
import breeze.generic.{URFunc, UReduceable, CanMapValues}
import breeze.util.{Index, MutableIndex}
import collection.mutable.ArrayBuffer
import breeze.math.VectorSpace

/**
* A LinearClassifier is a multi-class classifier with decision
Expand All @@ -41,7 +37,7 @@ import collection.mutable.ArrayBuffer
class LinearClassifier[L,T2, TL, TF]
(val featureWeights: T2, val intercepts: TL)
(implicit viewT2 : T2<:<NumericOps[T2], vspace: VectorSpace[TL, Double],
mulTensors : BinaryOp[T2,TF,OpMulMatrix,TL],
mulTensors : OpMulMatrix.Impl2[T2, TF, TL],
view: TL <:< QuasiTensor[L, Double]) extends Classifier[L,TF] with Serializable {
import vspace._
def scores(o: TF) = {
Expand All @@ -56,7 +52,7 @@ class LinearClassifier[L,T2, TL, TF]

object LinearClassifier {
implicit def linearClassifierReadWritable[L, T2, TL, TF](implicit viewT2 : T2<:<NumericOps[T2], vspace: VectorSpace[TL, Double],
mulTensors : BinaryOp[T2,TF,OpMulMatrix,TL],
mulTensors : OpMulMatrix.Impl2[T2, TF, TL],
view: TL <:< Tensor[L, Double],
tfW: DataSerialization.ReadWritable[T2],
tlW: DataSerialization.ReadWritable[TL]) = {
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/nak/classify/LogisticClassifier.scala
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,8 @@ object LogisticClassifierFromCsv {
// Output full predictions
if (params.fullOutput) {
predictions.foreach { prediction => {
val pcounter = prediction
val distribution = exp(logNormalize(pcounter))
val pcounter = logNormalize(prediction:Counter[String, Double])
val distribution = exp(pcounter)
val sortedDistributionString =
distribution
.argsort
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/nak/cluster/Kmeans.scala
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ object Kmeans {
* Compute cosine distance: 1-cosine(a,b)
*/
val cosineDistance = (a: Vector[Double], b: Vector[Double]) => {
1 - (a dot b)/(norm(a)*norm(b))
1 - (a dot b)/(norm(a, 2)*norm(b, 2))
}

/**
Expand All @@ -167,7 +167,7 @@ object Kmeans {
* Compute euclidean distance (l2 norm).
*/
val euclideanDistance = (a: Vector[Double], b: Vector[Double]) => {
norm(a-b)
norm(a-b, 2)
}

}
4 changes: 2 additions & 2 deletions src/main/scala/nak/inference/bp/Factor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package nak.inference.bp

import breeze.numerics._
import breeze.util.Index
import breeze.linalg.DenseVector
import breeze.linalg.{softmax, DenseVector}

/**
* A Factor knows about a set of variables and can
Expand Down Expand Up @@ -35,7 +35,7 @@ trait Factor extends nak.inference.Factor[Factor] {
off += 1
}

logSum(scores, off)
softmax.array(scores, off)
}

def isConvergedTo(f: Factor, diff: Double):Boolean = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ object TableRowWritable extends LowPriorityTableRowWritableImplicits {
* @author dramage
*/
trait TableRowCompanion[This,Format] { self =>
import breeze.util.CanPack
import nak.util.CanPack
import com.thoughtworks.paranamer.BytecodeReadingParanamer

private val method = try {
Expand Down
90 changes: 90 additions & 0 deletions src/main/scala/nak/util/CanPack.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package nak.util

/**
* Capability trait for packing and unpacking tuples (or other things) to a
* List of Any. This class is used by reflection based companion object
* mix-ins, such as TableRowCompanion.
*
* @author dramage
*/
trait CanPack[T] {
def unpack(value : T) : List[Any];
def pack(values : List[Any]) : T;
}


/**
* Low priority implicit for packing a single value as itself.
*
* @author
*/
trait LowPriorityCanPackImplicits {
implicit def canPackValue[T] = new CanPack[T] {
def unpack(value : T) = List[Any](value);
def pack(values : List[Any]) = {
require(values.length == 1, "Wrong size");
values.head.asInstanceOf[T];
}
}
}

/**
* Implicit packers for tuples.
*
* @author dramage
*/
object CanPack extends LowPriorityCanPackImplicits {
implicit def canPackTuple2[A,B] : CanPack[(A,B)] = new CanPack[(A,B)] {
def unpack(value : (A,B)) = List[Any](value._1, value._2);
def pack(values : List[Any]) = {
require(values.length == 2, "Wrong size");
val iter = values.iterator;
(iter.next, iter.next).asInstanceOf[(A,B)];
}
}

implicit def canPackTuple3[A,B,C] : CanPack[(A,B,C)] = new CanPack[(A,B,C)] {
def unpack(value : (A,B,C)) = List[Any](value._1, value._2, value._3);
def pack(values : List[Any]) = {
require(values.length == 3, "Wrong size");
val iter = values.iterator;
(iter.next, iter.next, iter.next).asInstanceOf[(A,B,C)];
}
}

implicit def canPackTuple4[A,B,C,D] : CanPack[(A,B,C,D)] = new CanPack[(A,B,C,D)] {
def unpack(value : (A,B,C,D)) = List[Any](value._1, value._2, value._3, value._4);
def pack(values : List[Any]) = {
require(values.length == 4, "Wrong size");
val iter = values.iterator;
(iter.next, iter.next, iter.next, iter.next).asInstanceOf[(A,B,C,D)];
}
}

implicit def canPackTuple5[A,B,C,D,E] : CanPack[(A,B,C,D,E)] = new CanPack[(A,B,C,D,E)] {
def unpack(value : (A,B,C,D,E)) = List[Any](value._1, value._2, value._3, value._4, value._5);
def pack(values : List[Any]) = {
require(values.length == 5, "Wrong size");
val iter = values.iterator;
(iter.next, iter.next, iter.next, iter.next, iter.next).asInstanceOf[(A,B,C,D,E)];
}
}

implicit def canPackTuple6[A,B,C,D,E,F] : CanPack[(A,B,C,D,E,F)] = new CanPack[(A,B,C,D,E,F)] {
def unpack(value : (A,B,C,D,E,F)) = List[Any](value._1, value._2, value._3, value._4, value._5, value._6);
def pack(values : List[Any]) = {
require(values.length == 6, "Wrong size");
val iter = values.iterator;
(iter.next, iter.next, iter.next, iter.next, iter.next, iter.next).asInstanceOf[(A,B,C,D,E,F)];
}
}

implicit def canPackTuple7[A,B,C,D,E,F,G] : CanPack[(A,B,C,D,E,F,G)] = new CanPack[(A,B,C,D,E,F,G)] {
def unpack(value : (A,B,C,D,E,F,G)) = List[Any](value._1, value._2, value._3, value._4, value._5, value._6, value._7);
def pack(values : List[Any]) = {
require(values.length == 7, "Wrong size");
val iter = values.iterator;
(iter.next, iter.next, iter.next, iter.next, iter.next, iter.next, iter.next).asInstanceOf[(A,B,C,D,E,F,G)];
}
}
}

0 comments on commit b843993

Please sign in to comment.