analytic tests and examples #314
@ -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>
|
public fun Tensor<T>.max(dim: Int, keepDim: Boolean): Tensor<T>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the mean of all elements in the input tensor.
|
* @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>
|
public fun Tensor<T>.exp(): Tensor<T>
|
||||||
|
|
||||||
//For information: https://pytorch.org/docs/stable/generated/torch.log.html
|
//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
|
//For information: https://pytorch.org/docs/stable/generated/torch.sqrt.html
|
||||||
public fun Tensor<T>.sqrt(): Tensor<T>
|
public fun Tensor<T>.sqrt(): Tensor<T>
|
||||||
|
@ -25,7 +25,6 @@ public object DoubleAnalyticTensorAlgebra :
|
|||||||
override fun Tensor<Double>.max(dim: Int, keepDim: Boolean): DoubleTensor =
|
override fun Tensor<Double>.max(dim: Int, keepDim: Boolean): DoubleTensor =
|
||||||
foldDim({ x -> x.maxOrNull()!! }, dim, keepDim)
|
foldDim({ x -> x.maxOrNull()!! }, dim, keepDim)
|
||||||
|
|
||||||
|
|
||||||
override fun Tensor<Double>.mean(): Double = this.fold { it.sum() / tensor.numElements }
|
override fun Tensor<Double>.mean(): Double = this.fold { it.sum() / tensor.numElements }
|
||||||
|
|
||||||
override fun Tensor<Double>.mean(dim: Int, keepDim: Boolean): DoubleTensor =
|
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>.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)
|
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.operations.invoke
|
||||||
import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra
|
import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra
|
||||||
import kotlin.math.abs
|
import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra.tan
|
||||||
import kotlin.math.exp
|
import kotlin.math.*
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
internal class TestDoubleAnalyticTensorAlgebra {
|
internal class TestDoubleAnalyticTensorAlgebra {
|
||||||
|
|
||||||
val shape = intArrayOf(2, 1, 3, 2)
|
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)
|
val tensor = DoubleTensor(shape, buffer)
|
||||||
|
|
||||||
fun DoubleArray.fmap(transform: (Double) -> Double): DoubleArray {
|
fun DoubleArray.fmap(transform: (Double) -> Double): DoubleArray {
|
||||||
return this.map(transform).toDoubleArray()
|
return this.map(transform).toDoubleArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun DoubleArray.epsEqual(other: DoubleArray, eps: Double = 1e-5): Boolean {
|
fun expectedTensor(transform: (Double) -> Double): DoubleTensor {
|
||||||
for ((elem1, elem2) in this.asSequence().zip(other.asSequence())) {
|
return DoubleTensor(shape, buffer.fmap(transform))
|
||||||
if (abs(elem1 - elem2) > eps) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testExp() = DoubleAnalyticTensorAlgebra {
|
fun testExp() = DoubleAnalyticTensorAlgebra {
|
||||||
tensor.exp().let {
|
assertTrue { tensor.exp() eq expectedTensor(::exp) }
|
||||||
assertTrue { shape contentEquals it.shape }
|
|
||||||
assertTrue { buffer.fmap(::exp).epsEqual(it.mutableBuffer.array())}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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