-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #513 from margarita0303/dev
Added Levenberg-Marquardt algorithm and svd Golub-Kahan
- Loading branch information
Showing
15 changed files
with
1,780 additions
and
17 deletions.
There are no files selected for viewing
90 changes: 90 additions & 0 deletions
90
...in/kotlin/space/kscience/kmath/tensors/LevenbergMarquardt/StaticLm/staticDifficultTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
* Copyright 2018-2023 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.LevenbergMarquardt.StaticLm | ||
|
||
import space.kscience.kmath.nd.ShapeND | ||
import space.kscience.kmath.nd.as2D | ||
import space.kscience.kmath.nd.component1 | ||
import space.kscience.kmath.tensors.LevenbergMarquardt.funcDifficultForLm | ||
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra | ||
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.div | ||
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra | ||
import space.kscience.kmath.tensors.core.LMInput | ||
import space.kscience.kmath.tensors.core.levenbergMarquardt | ||
import kotlin.math.roundToInt | ||
|
||
fun main() { | ||
val NData = 200 | ||
var t_example = DoubleTensorAlgebra.ones(ShapeND(intArrayOf(NData, 1))).as2D() | ||
for (i in 0 until NData) { | ||
t_example[i, 0] = t_example[i, 0] * (i + 1) - 104 | ||
} | ||
|
||
val Nparams = 15 | ||
var p_example = DoubleTensorAlgebra.ones(ShapeND(intArrayOf(Nparams, 1))).as2D() | ||
for (i in 0 until Nparams) { | ||
p_example[i, 0] = p_example[i, 0] + i - 25 | ||
} | ||
|
||
val exampleNumber = 1 | ||
|
||
var y_hat = funcDifficultForLm(t_example, p_example, exampleNumber) | ||
|
||
var p_init = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf(Nparams, 1))).as2D() | ||
for (i in 0 until Nparams) { | ||
p_init[i, 0] = (p_example[i, 0] + 0.9) | ||
} | ||
|
||
var t = t_example | ||
val y_dat = y_hat | ||
val weight = 1.0 / Nparams * 1.0 - 0.085 | ||
val dp = BroadcastDoubleTensorAlgebra.fromArray( | ||
ShapeND(intArrayOf(1, 1)), DoubleArray(1) { -0.01 } | ||
).as2D() | ||
var p_min = DoubleTensorAlgebra.ones(ShapeND(intArrayOf(Nparams, 1))) | ||
p_min = p_min.div(1.0 / -50.0) | ||
val p_max = DoubleTensorAlgebra.ones(ShapeND(intArrayOf(Nparams, 1))) | ||
p_min = p_min.div(1.0 / 50.0) | ||
val opts = doubleArrayOf(3.0, 10000.0, 1e-6, 1e-6, 1e-6, 1e-6, 1e-2, 11.0, 9.0, 1.0) | ||
// val opts = doubleArrayOf(3.0, 10000.0, 1e-6, 1e-6, 1e-6, 1e-6, 1e-3, 11.0, 9.0, 1.0) | ||
|
||
val inputData = LMInput(::funcDifficultForLm, | ||
p_init.as2D(), | ||
t, | ||
y_dat, | ||
weight, | ||
dp, | ||
p_min.as2D(), | ||
p_max.as2D(), | ||
opts[1].toInt(), | ||
doubleArrayOf(opts[2], opts[3], opts[4], opts[5]), | ||
doubleArrayOf(opts[6], opts[7], opts[8]), | ||
opts[9].toInt(), | ||
10, | ||
1) | ||
|
||
val result = DoubleTensorAlgebra.levenbergMarquardt(inputData) | ||
|
||
println("Parameters:") | ||
for (i in 0 until result.resultParameters.shape.component1()) { | ||
val x = (result.resultParameters[i, 0] * 10000).roundToInt() / 10000.0 | ||
print("$x ") | ||
} | ||
println() | ||
|
||
println("Y true and y received:") | ||
var y_hat_after = funcDifficultForLm(t_example, result.resultParameters, exampleNumber) | ||
for (i in 0 until y_hat.shape.component1()) { | ||
val x = (y_hat[i, 0] * 10000).roundToInt() / 10000.0 | ||
val y = (y_hat_after[i, 0] * 10000).roundToInt() / 10000.0 | ||
println("$x $y") | ||
} | ||
|
||
println("Сhi_sq:") | ||
println(result.resultChiSq) | ||
println("Number of iterations:") | ||
println(result.iterations) | ||
} |
57 changes: 57 additions & 0 deletions
57
...rc/main/kotlin/space/kscience/kmath/tensors/LevenbergMarquardt/StaticLm/staticEasyTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
* Copyright 2018-2023 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.LevenbergMarquardt.StaticLm | ||
|
||
import space.kscience.kmath.nd.ShapeND | ||
import space.kscience.kmath.nd.as2D | ||
import space.kscience.kmath.nd.component1 | ||
import space.kscience.kmath.tensors.LevenbergMarquardt.funcDifficultForLm | ||
import space.kscience.kmath.tensors.LevenbergMarquardt.funcEasyForLm | ||
import space.kscience.kmath.tensors.LevenbergMarquardt.getStartDataForFuncEasy | ||
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra | ||
import space.kscience.kmath.tensors.core.LMInput | ||
import space.kscience.kmath.tensors.core.levenbergMarquardt | ||
import kotlin.math.roundToInt | ||
|
||
fun main() { | ||
val startedData = getStartDataForFuncEasy() | ||
val inputData = LMInput(::funcEasyForLm, | ||
DoubleTensorAlgebra.ones(ShapeND(intArrayOf(4, 1))).as2D(), | ||
startedData.t, | ||
startedData.y_dat, | ||
startedData.weight, | ||
startedData.dp, | ||
startedData.p_min, | ||
startedData.p_max, | ||
startedData.opts[1].toInt(), | ||
doubleArrayOf(startedData.opts[2], startedData.opts[3], startedData.opts[4], startedData.opts[5]), | ||
doubleArrayOf(startedData.opts[6], startedData.opts[7], startedData.opts[8]), | ||
startedData.opts[9].toInt(), | ||
10, | ||
startedData.example_number) | ||
|
||
val result = DoubleTensorAlgebra.levenbergMarquardt(inputData) | ||
|
||
println("Parameters:") | ||
for (i in 0 until result.resultParameters.shape.component1()) { | ||
val x = (result.resultParameters[i, 0] * 10000).roundToInt() / 10000.0 | ||
print("$x ") | ||
} | ||
println() | ||
|
||
println("Y true and y received:") | ||
var y_hat_after = funcDifficultForLm(startedData.t, result.resultParameters, startedData.example_number) | ||
for (i in 0 until startedData.y_dat.shape.component1()) { | ||
val x = (startedData.y_dat[i, 0] * 10000).roundToInt() / 10000.0 | ||
val y = (y_hat_after[i, 0] * 10000).roundToInt() / 10000.0 | ||
println("$x $y") | ||
} | ||
|
||
println("Сhi_sq:") | ||
println(result.resultChiSq) | ||
println("Number of iterations:") | ||
println(result.iterations) | ||
} |
88 changes: 88 additions & 0 deletions
88
.../main/kotlin/space/kscience/kmath/tensors/LevenbergMarquardt/StaticLm/staticMiddleTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
* Copyright 2018-2023 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.LevenbergMarquardt.StaticLm | ||
|
||
import space.kscience.kmath.nd.ShapeND | ||
import space.kscience.kmath.nd.as2D | ||
import space.kscience.kmath.nd.component1 | ||
import space.kscience.kmath.tensors.LevenbergMarquardt.funcMiddleForLm | ||
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra | ||
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.div | ||
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra | ||
import space.kscience.kmath.tensors.core.LMInput | ||
import space.kscience.kmath.tensors.core.levenbergMarquardt | ||
import kotlin.math.roundToInt | ||
fun main() { | ||
val NData = 100 | ||
var t_example = DoubleTensorAlgebra.ones(ShapeND(intArrayOf(NData, 1))).as2D() | ||
for (i in 0 until NData) { | ||
t_example[i, 0] = t_example[i, 0] * (i + 1) | ||
} | ||
|
||
val Nparams = 20 | ||
var p_example = DoubleTensorAlgebra.ones(ShapeND(intArrayOf(Nparams, 1))).as2D() | ||
for (i in 0 until Nparams) { | ||
p_example[i, 0] = p_example[i, 0] + i - 25 | ||
} | ||
|
||
val exampleNumber = 1 | ||
|
||
var y_hat = funcMiddleForLm(t_example, p_example, exampleNumber) | ||
|
||
var p_init = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf(Nparams, 1))).as2D() | ||
for (i in 0 until Nparams) { | ||
p_init[i, 0] = (p_example[i, 0] + 0.9) | ||
} | ||
|
||
var t = t_example | ||
val y_dat = y_hat | ||
val weight = 1.0 | ||
val dp = BroadcastDoubleTensorAlgebra.fromArray( | ||
ShapeND(intArrayOf(1, 1)), DoubleArray(1) { -0.01 } | ||
).as2D() | ||
var p_min = DoubleTensorAlgebra.ones(ShapeND(intArrayOf(Nparams, 1))) | ||
p_min = p_min.div(1.0 / -50.0) | ||
val p_max = DoubleTensorAlgebra.ones(ShapeND(intArrayOf(Nparams, 1))) | ||
p_min = p_min.div(1.0 / 50.0) | ||
val opts = doubleArrayOf(3.0, 7000.0, 1e-5, 1e-5, 1e-5, 1e-5, 1e-5, 11.0, 9.0, 1.0) | ||
|
||
val inputData = LMInput(::funcMiddleForLm, | ||
p_init.as2D(), | ||
t, | ||
y_dat, | ||
weight, | ||
dp, | ||
p_min.as2D(), | ||
p_max.as2D(), | ||
opts[1].toInt(), | ||
doubleArrayOf(opts[2], opts[3], opts[4], opts[5]), | ||
doubleArrayOf(opts[6], opts[7], opts[8]), | ||
opts[9].toInt(), | ||
10, | ||
1) | ||
|
||
val result = DoubleTensorAlgebra.levenbergMarquardt(inputData) | ||
|
||
println("Parameters:") | ||
for (i in 0 until result.resultParameters.shape.component1()) { | ||
val x = (result.resultParameters[i, 0] * 10000).roundToInt() / 10000.0 | ||
print("$x ") | ||
} | ||
println() | ||
|
||
|
||
var y_hat_after = funcMiddleForLm(t_example, result.resultParameters, exampleNumber) | ||
for (i in 0 until y_hat.shape.component1()) { | ||
val x = (y_hat[i, 0] * 10000).roundToInt() / 10000.0 | ||
val y = (y_hat_after[i, 0] * 10000).roundToInt() / 10000.0 | ||
println("$x $y") | ||
} | ||
|
||
println("Сhi_sq:") | ||
println(result.resultChiSq) | ||
println("Number of iterations:") | ||
println(result.iterations) | ||
} |
68 changes: 68 additions & 0 deletions
68
...s/src/main/kotlin/space/kscience/kmath/tensors/LevenbergMarquardt/StreamingLm/streamLm.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* | ||
* Copyright 2018-2023 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.LevenbergMarquardt.StreamingLm | ||
|
||
import kotlinx.coroutines.delay | ||
import kotlinx.coroutines.flow.* | ||
import space.kscience.kmath.nd.* | ||
import space.kscience.kmath.tensors.LevenbergMarquardt.StartDataLm | ||
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.zeros | ||
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra | ||
import space.kscience.kmath.tensors.core.LMInput | ||
import space.kscience.kmath.tensors.core.levenbergMarquardt | ||
import kotlin.random.Random | ||
import kotlin.reflect.KFunction3 | ||
|
||
fun streamLm(lm_func: (MutableStructure2D<Double>, MutableStructure2D<Double>, Int) -> (MutableStructure2D<Double>), | ||
startData: StartDataLm, launchFrequencyInMs: Long, numberOfLaunches: Int): Flow<MutableStructure2D<Double>> = flow{ | ||
|
||
var example_number = startData.example_number | ||
var p_init = startData.p_init | ||
var t = startData.t | ||
var y_dat = startData.y_dat | ||
val weight = startData.weight | ||
val dp = startData.dp | ||
val p_min = startData.p_min | ||
val p_max = startData.p_max | ||
val opts = startData.opts | ||
|
||
var steps = numberOfLaunches | ||
val isEndless = (steps <= 0) | ||
|
||
val inputData = LMInput(lm_func, | ||
p_init, | ||
t, | ||
y_dat, | ||
weight, | ||
dp, | ||
p_min, | ||
p_max, | ||
opts[1].toInt(), | ||
doubleArrayOf(opts[2], opts[3], opts[4], opts[5]), | ||
doubleArrayOf(opts[6], opts[7], opts[8]), | ||
opts[9].toInt(), | ||
10, | ||
example_number) | ||
|
||
while (isEndless || steps > 0) { | ||
val result = DoubleTensorAlgebra.levenbergMarquardt(inputData) | ||
emit(result.resultParameters) | ||
delay(launchFrequencyInMs) | ||
inputData.realValues = generateNewYDat(y_dat, 0.1) | ||
inputData.startParameters = result.resultParameters | ||
if (!isEndless) steps -= 1 | ||
} | ||
} | ||
|
||
fun generateNewYDat(y_dat: MutableStructure2D<Double>, delta: Double): MutableStructure2D<Double>{ | ||
val n = y_dat.shape.component1() | ||
val y_dat_new = zeros(ShapeND(intArrayOf(n, 1))).as2D() | ||
for (i in 0 until n) { | ||
val randomEps = Random.nextDouble(delta + delta) - delta | ||
y_dat_new[i, 0] = y_dat[i, 0] + randomEps | ||
} | ||
return y_dat_new | ||
} |
32 changes: 32 additions & 0 deletions
32
...ain/kotlin/space/kscience/kmath/tensors/LevenbergMarquardt/StreamingLm/streamingLmTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
* Copyright 2018-2023 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.LevenbergMarquardt.StreamingLm | ||
|
||
import space.kscience.kmath.nd.* | ||
import space.kscience.kmath.tensors.LevenbergMarquardt.* | ||
import kotlin.math.roundToInt | ||
|
||
suspend fun main(){ | ||
val startData = getStartDataForFuncDifficult() | ||
// Создание потока: | ||
val lmFlow = streamLm(::funcDifficultForLm, startData, 0, 100) | ||
var initialTime = System.currentTimeMillis() | ||
var lastTime: Long | ||
val launches = mutableListOf<Long>() | ||
// Запуск потока | ||
lmFlow.collect { parameters -> | ||
lastTime = System.currentTimeMillis() | ||
launches.add(lastTime - initialTime) | ||
initialTime = lastTime | ||
for (i in 0 until parameters.shape.component1()) { | ||
val x = (parameters[i, 0] * 10000).roundToInt() / 10000.0 | ||
print("$x ") | ||
if (i == parameters.shape.component1() - 1) println() | ||
} | ||
} | ||
|
||
println("Average without first is: ${launches.subList(1, launches.size - 1).average()}") | ||
} |
Oops, something went wrong.