Skip to content

Instantly share code, notes, and snippets.

@thomasnield
Last active September 20, 2018 23:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thomasnield/fbe2e2205233388577e6abe6f5bbe897 to your computer and use it in GitHub Desktop.
Save thomasnield/fbe2e2205233388577e6abe6f5bbe897 to your computer and use it in GitHub Desktop.
Kotlin Linear Regression with Gradient Descent
import java.net.URL
fun main(args: Array<String>) {
// Fit points to a line conforming to y = mx + b
class Point(val x: Double, val y: Double)
val points = URL("https://tinyurl.com/yaxgfjzt")
.readText().split(Regex("\\r?\\n"))
.asSequence()
.filter { it.isNotEmpty() }
.map { it.split(",") }
.map { Point(it[0].toDouble(), it[1].toDouble()) }
.toList()
// Points that exactly fit y = 2x + 100
// You'll want epochs = 1000000 and learningRate = .00001
// val points = (1..100).map { Point(it, (it * 2) + 100) }
val n = points.count().toDouble()
// partial derivative with respect to M
fun dM(expectedYs: List<Double>) =
(-2.0 / n) * points.mapIndexed { i, p -> p.x * (p.y - expectedYs[i]) }.sum()
// partial derivative with respect to B
fun dB(expectedYs: List<Double>) =
(-2.0 / n) * points.mapIndexed { i, p -> p.y - expectedYs[i] }.sum()
val learningRate = .000001
var m = 0.0
var b = 0.0
val epochs = 1000 // epochs is a fancy name for # of iterations
(0..epochs).forEach { _ ->
val yPredictions = points.map { (m * it.x) + b }
val dM = dM(yPredictions)
val dB = dB(yPredictions)
m -= learningRate * dM
b -= learningRate * dB
}
println("f(x) = ${m}x + $b")
// RESULT:
// f(x) = 1.6633912038847907x + 0.003908633274244349
// View Graph on Desmos
// https://www.desmos.com/calculator/ntomwigo6k
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment