From 9a6133255120b6afa2c843e65101c7a914f64178 Mon Sep 17 00:00:00 2001 From: Bert Chang Date: Sat, 3 May 2014 22:47:41 +0800 Subject: [PATCH] Make manhattan support both col&row vectors. --- metrics/pairwise/euclidean_test.go | 5 +++-- metrics/pairwise/manhattan.go | 15 +++++++++++++-- metrics/pairwise/manhattan_test.go | 21 ++++++++++++++++++--- metrics/pairwise/poly_kernel_test.go | 5 +++-- metrics/pairwise/rbf_kernel_test.go | 5 +++-- 5 files changed, 40 insertions(+), 11 deletions(-) diff --git a/metrics/pairwise/euclidean_test.go b/metrics/pairwise/euclidean_test.go index fde2777..d022ae6 100644 --- a/metrics/pairwise/euclidean_test.go +++ b/metrics/pairwise/euclidean_test.go @@ -8,11 +8,12 @@ import ( ) func TestEuclidean(t *testing.T) { + var vectorX, vectorY *mat64.Dense euclidean := NewEuclidean() Convey("Given two vectors", t, func() { - vectorX := mat64.NewDense(3, 1, []float64{1, 2, 3}) - vectorY := mat64.NewDense(3, 1, []float64{2, 4, 5}) + vectorX = mat64.NewDense(3, 1, []float64{1, 2, 3}) + vectorY = mat64.NewDense(3, 1, []float64{2, 4, 5}) Convey("When doing inner product", func() { result := euclidean.InnerProduct(vectorX, vectorY) diff --git a/metrics/pairwise/manhattan.go b/metrics/pairwise/manhattan.go index 847f05c..c734f31 100644 --- a/metrics/pairwise/manhattan.go +++ b/metrics/pairwise/manhattan.go @@ -13,13 +13,24 @@ func NewManhattan() *Manhattan { } func (self *Manhattan) Distance(vectorX *mat64.Dense, vectorY *mat64.Dense) float64 { + var length int subVector := mat64.NewDense(0, 0, nil) subVector.Sub(vectorX, vectorY) - r, _ := subVector.Dims() + r, c := subVector.Dims() + + if r == 1 { + // Force transpose to column vector + subVector.TCopy(subVector) + length = c + } else if c == 1 { + length = r + } else { + panic(mat64.ErrShape) + } result := .0 - for i := 0; i < r; i++ { + for i := 0; i < length; i++ { result += math.Abs(subVector.At(i, 0)) } diff --git a/metrics/pairwise/manhattan_test.go b/metrics/pairwise/manhattan_test.go index 8a62a5c..e6361e4 100644 --- a/metrics/pairwise/manhattan_test.go +++ b/metrics/pairwise/manhattan_test.go @@ -8,19 +8,34 @@ import ( ) func TestManhattan(t *testing.T) { + var vectorX, vectorY *mat64.Dense manhattan := NewManhattan() Convey("Given two vectors", t, func() { - vectorX := mat64.NewDense(3, 1, []float64{2, 2, 3}) - vectorY := mat64.NewDense(3, 1, []float64{1, 4, 5}) + vectorX = mat64.NewDense(3, 1, []float64{2, 2, 3}) + vectorY = mat64.NewDense(3, 1, []float64{1, 4, 5}) - Convey("When calculating distance", func() { + Convey("When calculating distance with column vectors", func() { result := manhattan.Distance(vectorX, vectorY) Convey("The result should be 5", func() { So(result, ShouldEqual, 5) }) + }) + Convey("When calculating distance with row vectors", func() { + vectorX.TCopy(vectorX) + vectorY.TCopy(vectorY) + result := manhattan.Distance(vectorX, vectorY) + + Convey("The result should be 5", func() { + So(result, ShouldEqual, 5) + }) + }) + + Convey("When calculating distance with row and column vectors", func() { + vectorX.TCopy(vectorX) + So(func() { manhattan.Distance(vectorX, vectorY) }, ShouldPanicWith, mat64.ErrShape) }) }) diff --git a/metrics/pairwise/poly_kernel_test.go b/metrics/pairwise/poly_kernel_test.go index 67293f5..31f508f 100644 --- a/metrics/pairwise/poly_kernel_test.go +++ b/metrics/pairwise/poly_kernel_test.go @@ -8,11 +8,12 @@ import ( ) func TestPolyKernel(t *testing.T) { + var vectorX, vectorY *mat64.Dense polyKernel := NewPolyKernel(3) Convey("Given two vectors", t, func() { - vectorX := mat64.NewDense(3, 1, []float64{1, 2, 3}) - vectorY := mat64.NewDense(3, 1, []float64{2, 4, 5}) + vectorX = mat64.NewDense(3, 1, []float64{1, 2, 3}) + vectorY = mat64.NewDense(3, 1, []float64{2, 4, 5}) Convey("When doing inner product", func() { result := polyKernel.InnerProduct(vectorX, vectorY) diff --git a/metrics/pairwise/rbf_kernel_test.go b/metrics/pairwise/rbf_kernel_test.go index a8e36d7..dd43082 100644 --- a/metrics/pairwise/rbf_kernel_test.go +++ b/metrics/pairwise/rbf_kernel_test.go @@ -8,11 +8,12 @@ import ( ) func TestRBFKernel(t *testing.T) { + var vectorX, vectorY *mat64.Dense rbfKernel := NewRBFKernel(0.1) Convey("Given two vectors", t, func() { - vectorX := mat64.NewDense(3, 1, []float64{1, 2, 3}) - vectorY := mat64.NewDense(3, 1, []float64{2, 4, 5}) + vectorX = mat64.NewDense(3, 1, []float64{1, 2, 3}) + vectorY = mat64.NewDense(3, 1, []float64{2, 4, 5}) Convey("When doing inner product", func() { result := rbfKernel.InnerProduct(vectorX, vectorY)