forked from kscience/kmath
analytic tests and examples
This commit is contained in:
parent
b59e48410f
commit
d0281871fa
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.tensors
|
||||
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra
|
||||
import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra
|
||||
|
||||
// Dataset normalization
|
||||
|
||||
fun main() {
|
||||
|
||||
// work in context with analytic methods
|
||||
DoubleAnalyticTensorAlgebra {
|
||||
// take dataset of 5-element vectors from normal distribution
|
||||
val dataset = randomNormal(intArrayOf(100, 5)) * 1.5 // all elements from N(0, 1.5)
|
||||
BroadcastDoubleTensorAlgebra {
|
||||
dataset += fromArray(
|
||||
intArrayOf(5),
|
||||
doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // rows means
|
||||
)
|
||||
}
|
||||
|
||||
// find out mean and standard deviation of each column
|
||||
val mean = dataset.mean(0, false)
|
||||
val std = dataset.std(0, false)
|
||||
|
||||
println("Mean:\n$mean")
|
||||
println("Standard deviation:\n$std")
|
||||
|
||||
// also we can calculate other statistic as minimum and maximum of rows
|
||||
println("Minimum:\n${dataset.min(0, false)}")
|
||||
println("Maximum:\n${dataset.max(0, false)}")
|
||||
|
||||
// now we can scale dataset with mean normalization
|
||||
val datasetScaled = BroadcastDoubleTensorAlgebra { (dataset - mean) / std }
|
||||
|
||||
// find out mean and std of scaled dataset
|
||||
|
||||
println("Mean of scaled:\n${datasetScaled.mean(0, false)}")
|
||||
println("Mean of scaled:\n${datasetScaled.std(0, false)}")
|
||||
}
|
||||
}
|
@ -51,7 +51,6 @@ public interface AnalyticTensorAlgebra<T> :
|
||||
*/
|
||||
public fun Tensor<T>.max(dim: Int, keepDim: Boolean): Tensor<T>
|
||||
|
||||
|
||||
/**
|
||||
* @return the mean of all elements in the input tensor.
|
||||
*/
|
||||
@ -110,7 +109,7 @@ public interface AnalyticTensorAlgebra<T> :
|
||||
public fun Tensor<T>.exp(): Tensor<T>
|
||||
|
||||
//For information: https://pytorch.org/docs/stable/generated/torch.log.html
|
||||
public fun Tensor<T>.log(): Tensor<T>
|
||||
public fun Tensor<T>.ln(): Tensor<T>
|
||||
|
||||
//For information: https://pytorch.org/docs/stable/generated/torch.sqrt.html
|
||||
public fun Tensor<T>.sqrt(): Tensor<T>
|
||||
|
@ -25,7 +25,6 @@ public object DoubleAnalyticTensorAlgebra :
|
||||
override fun Tensor<Double>.max(dim: Int, keepDim: Boolean): DoubleTensor =
|
||||
foldDim({ x -> x.maxOrNull()!! }, dim, keepDim)
|
||||
|
||||
|
||||
override fun Tensor<Double>.mean(): Double = this.fold { it.sum() / tensor.numElements }
|
||||
|
||||
override fun Tensor<Double>.mean(dim: Int, keepDim: Boolean): DoubleTensor =
|
||||
@ -70,7 +69,7 @@ public object DoubleAnalyticTensorAlgebra :
|
||||
|
||||
override fun Tensor<Double>.exp(): DoubleTensor = tensor.map(::exp)
|
||||
|
||||
override fun Tensor<Double>.log(): DoubleTensor = tensor.map(::ln)
|
||||
override fun Tensor<Double>.ln(): DoubleTensor = tensor.map(::ln)
|
||||
|
||||
override fun Tensor<Double>.sqrt(): DoubleTensor = tensor.map(::sqrt)
|
||||
|
||||
|
@ -2,35 +2,159 @@ package space.kscience.kmath.tensors.core
|
||||
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.exp
|
||||
import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra.tan
|
||||
import kotlin.math.*
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
internal class TestDoubleAnalyticTensorAlgebra {
|
||||
|
||||
val shape = intArrayOf(2, 1, 3, 2)
|
||||
val buffer = doubleArrayOf(27.1, 20.0, 19.84, 23.123, 0.0, 1.0, 3.23, 133.7, 25.3, 100.3, 11.0, 12.012)
|
||||
val buffer = doubleArrayOf(
|
||||
27.1, 20.0, 19.84,
|
||||
23.123, 3.0, 2.0,
|
||||
|
||||
3.23, 133.7, 25.3,
|
||||
100.3, 11.0, 12.012
|
||||
)
|
||||
val tensor = DoubleTensor(shape, buffer)
|
||||
|
||||
fun DoubleArray.fmap(transform: (Double) -> Double): DoubleArray {
|
||||
return this.map(transform).toDoubleArray()
|
||||
}
|
||||
|
||||
fun DoubleArray.epsEqual(other: DoubleArray, eps: Double = 1e-5): Boolean {
|
||||
for ((elem1, elem2) in this.asSequence().zip(other.asSequence())) {
|
||||
if (abs(elem1 - elem2) > eps) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
fun expectedTensor(transform: (Double) -> Double): DoubleTensor {
|
||||
return DoubleTensor(shape, buffer.fmap(transform))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testExp() = DoubleAnalyticTensorAlgebra {
|
||||
tensor.exp().let {
|
||||
assertTrue { shape contentEquals it.shape }
|
||||
assertTrue { buffer.fmap(::exp).epsEqual(it.mutableBuffer.array())}
|
||||
}
|
||||
assertTrue { tensor.exp() eq expectedTensor(::exp) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLog() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor.ln() eq expectedTensor(::ln) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSqrt() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor.sqrt() eq expectedTensor(::sqrt) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCos() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor.cos() eq expectedTensor(::cos) }
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun testCosh() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor.cosh() eq expectedTensor(::cosh) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAcosh() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor.acosh() eq expectedTensor(::acosh) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSin() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor.sin() eq expectedTensor(::sin) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSinh() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor.sinh() eq expectedTensor(::sinh) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAsinh() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor.asinh() eq expectedTensor(::asinh) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testTan() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor.tan() eq expectedTensor(::tan) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAtan() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor.atan() eq expectedTensor(::atan) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testTanh() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor.tanh() eq expectedTensor(::tanh) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCeil() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor.ceil() eq expectedTensor(::ceil) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFloor() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor.floor() eq expectedTensor(::floor) }
|
||||
}
|
||||
|
||||
val shape2 = intArrayOf(2, 2)
|
||||
val buffer2 = doubleArrayOf(
|
||||
1.0, 2.0,
|
||||
-3.0, 4.0
|
||||
)
|
||||
val tensor2 = DoubleTensor(shape2, buffer2)
|
||||
|
||||
@Test
|
||||
fun testMin() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor2.min() == -3.0 }
|
||||
assertTrue { tensor2.min(0, true) eq fromArray(
|
||||
intArrayOf(1, 2),
|
||||
doubleArrayOf(-3.0, 2.0)
|
||||
)}
|
||||
assertTrue { tensor2.min(1, false) eq fromArray(
|
||||
intArrayOf(2),
|
||||
doubleArrayOf(1.0, -3.0)
|
||||
)}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMax() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor2.max() == 4.0 }
|
||||
assertTrue { tensor2.max(0, true) eq fromArray(
|
||||
intArrayOf(1, 2),
|
||||
doubleArrayOf(1.0, 4.0)
|
||||
)}
|
||||
assertTrue { tensor2.max(1, false) eq fromArray(
|
||||
intArrayOf(2),
|
||||
doubleArrayOf(2.0, 4.0)
|
||||
)}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSum() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor2.sum() == 4.0 }
|
||||
assertTrue { tensor2.sum(0, true) eq fromArray(
|
||||
intArrayOf(1, 2),
|
||||
doubleArrayOf(-2.0, 6.0)
|
||||
)}
|
||||
assertTrue { tensor2.sum(1, false) eq fromArray(
|
||||
intArrayOf(2),
|
||||
doubleArrayOf(3.0, 1.0)
|
||||
)}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMean() = DoubleAnalyticTensorAlgebra {
|
||||
assertTrue { tensor2.mean() == 1.0 }
|
||||
assertTrue { tensor2.mean(0, true) eq fromArray(
|
||||
intArrayOf(1, 2),
|
||||
doubleArrayOf(-1.0, 3.0)
|
||||
)}
|
||||
assertTrue { tensor2.mean(1, false) eq fromArray(
|
||||
intArrayOf(2),
|
||||
doubleArrayOf(1.5, 0.5)
|
||||
)}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user