From cc114041c4eb2c71248d8a54876d57668286cc95 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 24 Oct 2021 18:33:39 +0300 Subject: [PATCH] Initial implementation of TensorFlow connector --- .../tensorflow/DoubleTensorFlowAlgebra.kt | 40 +++++++++++++++ .../kmath/tensorflow/TensorFlowAlgebra.kt | 49 +++++++++---------- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 14 +++--- 3 files changed, 71 insertions(+), 32 deletions(-) create mode 100644 kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt diff --git a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt new file mode 100644 index 000000000..864205e17 --- /dev/null +++ b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt @@ -0,0 +1,40 @@ +package space.kscience.kmath.tensorflow + +import org.tensorflow.Graph +import org.tensorflow.Output +import org.tensorflow.ndarray.NdArray +import org.tensorflow.ndarray.Shape +import org.tensorflow.op.core.Constant +import org.tensorflow.types.TFloat64 +import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.tensors.api.Tensor + +public class DoubleTensorFlowOutput( + graph: Graph, + output: Output +) : TensorFlowOutput(graph, output) { + override fun org.tensorflow.Tensor.actualizeTensor(): NdArray = output.asTensor() +} + +public class DoubleTensorFlowAlgebra internal constructor( + graph: Graph +) : TensorFlowAlgebra(graph) { + + override fun Tensor.asTensorFlow(): TensorFlowOutput = + if (this is TensorFlowOutput && output.type() == TFloat64::class.java) { + @Suppress("UNCHECKED_CAST") + this as TensorFlowOutput + } else { + val res = TFloat64.tensorOf(Shape.of(*shape.toLongArray())) { array -> + @OptIn(PerformancePitfall::class) + elements().forEach { (index, value) -> + array.setDouble(value, *index.toLongArray()) + } + } + DoubleTensorFlowOutput(graph, ops.constant(res).asOutput()) + } + + override fun Output.wrap(): TensorFlowOutput = DoubleTensorFlowOutput(graph, this) + + override fun const(value: Double): Constant = ops.constant(value) +} \ No newline at end of file diff --git a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt index 849a2e909..12c1211db 100644 --- a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt +++ b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt @@ -14,11 +14,10 @@ import space.kscience.kmath.nd.Shape import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.api.TensorAlgebra -private fun IntArray.toLongArray() = LongArray(size) { get(it).toLong() } -private fun LongArray.toIntArray() = IntArray(size) { get(it).toInt() } +internal fun IntArray.toLongArray() = LongArray(size) { get(it).toLong() } +internal fun LongArray.toIntArray() = IntArray(size) { get(it).toInt() } -private val NdArray.scalar: T - get() = getObject() +internal val NdArray.scalar: T get() = getObject() public sealed interface TensorFlowTensor : Tensor @@ -72,14 +71,12 @@ public abstract class TensorFlowOutput( public abstract class TensorFlowAlgebra internal constructor( - private val graph: Graph + protected val graph: Graph ) : TensorAlgebra { - private val ops by lazy { Ops.create(graph) } + protected val ops: Ops by lazy { Ops.create(graph) } - protected fun Tensor.asTensorFlow(): TensorFlowOutput = if (this is TensorFlowOutput) this else { - TODO() - } + protected abstract fun Tensor.asTensorFlow(): TensorFlowOutput protected abstract fun Output.wrap(): TensorFlowOutput @@ -138,27 +135,29 @@ public abstract class TensorFlowAlgebra internal constructor( private inline fun unOp(value: Tensor, operation: (Operand) -> Operand): TensorFlowOutput = operation(value.asTensorFlow().output).asOutput().wrap() - override fun T.plus(other: Tensor) = biOp(other, ops.math::add) + override fun T.plus(other: Tensor): TensorFlowOutput = biOp(other, ops.math::add) - override fun Tensor.plus(value: T) = biOp(value, ops.math::add) + override fun Tensor.plus(value: T): TensorFlowOutput = biOp(value, ops.math::add) - override fun Tensor.plus(other: Tensor) = biOp(other, ops.math::add) + override fun Tensor.plus(other: Tensor): TensorFlowOutput = biOp(other, ops.math::add) override fun Tensor.plusAssign(value: T): Unit = inPlaceOp(value, ops.math::add) override fun Tensor.plusAssign(other: Tensor): Unit = inPlaceOp(other, ops.math::add) - override fun Tensor.minus(value: T) = biOp(value, ops.math::sub) + override fun Tensor.minus(value: T): TensorFlowOutput = biOp(value, ops.math::sub) - override fun Tensor.minus(other: Tensor) = biOp(other, ops.math::sub) + override fun Tensor.minus(other: Tensor): TensorFlowOutput = biOp(other, ops.math::sub) + + override fun T.minus(other: Tensor): Tensor = biOp(other, ops.math::sub) override fun Tensor.minusAssign(value: T): Unit = inPlaceOp(value, ops.math::sub) override fun Tensor.minusAssign(other: Tensor): Unit = inPlaceOp(other, ops.math::sub) - override fun T.times(other: Tensor) = biOp(other, ops.math::mul) + override fun T.times(other: Tensor): TensorFlowOutput = biOp(other, ops.math::mul) - override fun Tensor.times(value: T) = biOp(value, ops.math::mul) + override fun Tensor.times(value: T): TensorFlowOutput = biOp(value, ops.math::mul) override fun Tensor.times(other: Tensor): TensorFlowOutput = biOp(other, ops.math::mul) @@ -166,14 +165,14 @@ public abstract class TensorFlowAlgebra internal constructor( override fun Tensor.timesAssign(other: Tensor): Unit = inPlaceOp(other, ops.math::mul) - override fun Tensor.unaryMinus() = unOp(this, ops.math::neg) + override fun Tensor.unaryMinus(): TensorFlowOutput = unOp(this, ops.math::neg) - override fun Tensor.get(i: Int): Tensor{ - ops. + override fun Tensor.get(i: Int): Tensor { + TODO("Not yet implemented") } - override fun Tensor.transpose(i: Int, j: Int): Tensor { - TODO("Not yet implemented") + override fun Tensor.transpose(i: Int, j: Int): Tensor = unOp(this) { + ops.linalg.transpose(it, ops.constant(intArrayOf(i, j))) } override fun Tensor.view(shape: IntArray): Tensor { @@ -184,15 +183,15 @@ public abstract class TensorFlowAlgebra internal constructor( TODO("Not yet implemented") } - override fun Tensor.dot(other: Tensor) = biOp(other, ops.math.) + override fun Tensor.dot(other: Tensor): TensorFlowOutput = biOp(other) { l, r -> + ops.linalg.matMul(l, r) + } override fun diagonalEmbedding(diagonalEntries: Tensor, offset: Int, dim1: Int, dim2: Int): Tensor = ops.run { TODO("Not yet implemented") } - override fun Tensor.sum(): T { - TODO("Not yet implemented") - } + override fun Tensor.sum(): T = TODO("Not yet implemented") override fun Tensor.sum(dim: Int, keepDim: Boolean): Tensor { TODO("Not yet implemented") diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 16ed4b834..3267e4adb 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -22,7 +22,7 @@ import kotlin.math.* public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra, AnalyticTensorAlgebra, - LinearOpsTensorAlgebra{ + LinearOpsTensorAlgebra { public companion object : DoubleTensorAlgebra() @@ -361,16 +361,16 @@ public open class DoubleTensorAlgebra : dotHelper(a.as2D(), b.as2D(), res.as2D(), l, m1, n) } - if (penultimateDim) { - return resTensor.view( + return if (penultimateDim) { + resTensor.view( resTensor.shape.dropLast(2).toIntArray() + intArrayOf(resTensor.shape.last()) ) + } else if (lastDim) { + resTensor.view(resTensor.shape.dropLast(1).toIntArray()) + } else { + resTensor } - if (lastDim) { - return resTensor.view(resTensor.shape.dropLast(1).toIntArray()) - } - return resTensor } override fun diagonalEmbedding(