Skip to content

Commit da56aa3

Browse files
committed
Merge remote-tracking branch 'refs/remotes/origin/vecxt_io' into vecxt_io
2 parents fe18dfc + 19d02d5 commit da56aa3

9 files changed

Lines changed: 107 additions & 85 deletions

File tree

experiments/src/mnist.scala

Lines changed: 63 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
import scala.util.chaining.*
32

43
import io.github.quafadas.plots.SetupVegaBrowser.{*, given}
@@ -35,12 +34,14 @@ import scala.annotation.targetName
3534
val imageHeight = 28
3635

3736
val labels: Array[Int] = traindata.col(0) // y data, the labels are in the first column
38-
val pixelData : Matrix[Float] = traindata(::,1 until traindata.cols).deepCopy / 255.0f
37+
val pixelData: Matrix[Float] = traindata(::, 1 until traindata.cols).deepCopy / 255.0f
3938

4039
if samplePlot then
41-
VegaPlot.fromResource("hist.vg.json").plot(
42-
_.data._0.values := labels.map(label => (u = label)).asJson
43-
)
40+
VegaPlot
41+
.fromResource("hist.vg.json")
42+
.plot(
43+
_.data._0.values := labels.map(label => (u = label)).asJson
44+
)
4445
end if
4546

4647
val one_hot_Y = oneHotEncode[Float](labels)
@@ -52,15 +53,20 @@ import scala.annotation.targetName
5253
val data = pixelData.row(idx)
5354
val pixelSize = 10
5455
val d = dataToCoords(data, pixelSize)
55-
VegaPlot.fromResource("pixelPlot.vg.json").plot(
56-
_.data.values := d.asJson,
57-
_.mark.width := pixelSize,
58-
_.mark.height := pixelSize,
59-
_.width := imageWidth * pixelSize,
60-
_.height := imageHeight * pixelSize,
61-
_.title := s"Sample: $idx - Label ${labels(idx)}"
62-
)
63-
one_hot_Y.row(idx).mkString(", ").tap(str => println(s"One hot encoding for sample $idx:, label ${labels(idx)}: $str"))
56+
VegaPlot
57+
.fromResource("pixelPlot.vg.json")
58+
.plot(
59+
_.data.values := d.asJson,
60+
_.mark.width := pixelSize,
61+
_.mark.height := pixelSize,
62+
_.width := imageWidth * pixelSize,
63+
_.height := imageHeight * pixelSize,
64+
_.title := s"Sample: $idx - Label ${labels(idx)}"
65+
)
66+
one_hot_Y
67+
.row(idx)
68+
.mkString(", ")
69+
.tap(str => println(s"One hot encoding for sample $idx:, label ${labels(idx)}: $str"))
6470
}
6571

6672
end if
@@ -77,7 +83,9 @@ import scala.annotation.targetName
7783
val bias2 = Array.fill(l3Size)(startBias)
7884

7985
if shapeDiagnostic then
80-
println(s"pixelData shape: ${pixelData.shape}, pixelData rows: ${pixelData.rows}, pixelData cols: ${pixelData.cols}, pixelData rowStride: ${pixelData.rowStride}, pixelData colStride: ${pixelData.colStride} pixelData offset: ${pixelData.offset}")
86+
println(
87+
s"pixelData shape: ${pixelData.shape}, pixelData rows: ${pixelData.rows}, pixelData cols: ${pixelData.cols}, pixelData rowStride: ${pixelData.rowStride}, pixelData colStride: ${pixelData.colStride} pixelData offset: ${pixelData.offset}"
88+
)
8189

8290
println(s"x layout ${pixelData.layout}")
8391

@@ -114,7 +122,6 @@ import scala.annotation.targetName
114122
b2 = bias2
115123
)
116124

117-
118125
end mnist
119126

120127
// Helper methods.
@@ -178,46 +185,44 @@ end foward_prop
178185

179186
// Float version
180187
def foward_prop(w1: Matrix[Float], b1: Array[Float], w2: Matrix[Float], b2: Array[Float], x: Matrix[Float]) =
181-
val z1 = (x @@ w1)
182-
z1.mapRowsInPlace(r => r.tap(_ += b1))
183-
val a1 = reluM(z1) // get rid of negative values
184-
val z2 = (a1 @@ w2)
185-
z2.mapRowsInPlace(r => r.tap(_ += b2)) // results [(rows, 10) @ (10, 10)] = (rows, 10)
186-
val a2 = softmaxRows(z2)
187-
(z1 = z1, a1 = a1, z2 = z2, a2 = a2)
188+
val z1 = (x @@ w1)
189+
z1.mapRowsInPlace(r => r.tap(_ += b1))
190+
val a1 = reluM(z1) // get rid of negative values
191+
val z2 = (a1 @@ w2)
192+
z2.mapRowsInPlace(r => r.tap(_ += b2)) // results [(rows, 10) @ (10, 10)] = (rows, 10)
193+
val a2 = softmaxRows(z2)
194+
(z1 = z1, a1 = a1, z2 = z2, a2 = a2)
188195
end foward_prop
189196

190-
191197
def back_prop(
192-
w1: Matrix[Float],
193-
b1: Array[Float],
194-
w2: Matrix[Float],
195-
b2: Array[Float],
196-
z1: Matrix[Float],
197-
a1: Matrix[Float],
198-
z2: Matrix[Float],
199-
a2: Matrix[Float],
200-
X: Matrix[Float],
201-
Y: Matrix[Float]
198+
w1: Matrix[Float],
199+
b1: Array[Float],
200+
w2: Matrix[Float],
201+
b2: Array[Float],
202+
z1: Matrix[Float],
203+
a1: Matrix[Float],
204+
z2: Matrix[Float],
205+
a2: Matrix[Float],
206+
X: Matrix[Float],
207+
Y: Matrix[Float]
202208
) =
203-
val m = Y.rows
204-
val m_inv = 1.0f / m
205-
val dz2 = a2 - Y
206-
val dw2 = m_inv * (a1.transpose @@ dz2)
209+
val m = Y.rows
210+
val m_inv = 1.0f / m
211+
val dz2 = a2 - Y
212+
val dw2 = m_inv * (a1.transpose @@ dz2)
207213

208-
val db2 = dz2.mapColsToScalar(_.sum).raw
209-
val dz1Check = (z1 > 0)
210-
val dz1 = (dz2 @@ w2.transpose)
211-
dz1 *:*= dz1Check
214+
val db2 = dz2.mapColsToScalar(_.sum).raw
215+
val dz1Check = (z1 > 0)
216+
val dz1 = (dz2 @@ w2.transpose)
217+
dz1 *:*= dz1Check
212218

213-
val dw1 = m_inv * (X.transpose @@ dz1)
219+
val dw1 = m_inv * (X.transpose @@ dz1)
214220

215-
val db1 = dz1.mapColsToScalar(r => r.sumSIMD * m_inv).raw
216-
// println("back propagation (Float) done ----")
217-
(dw1 = dw1, db1 = db1, dw2 = dw2, db2 = db2)
221+
val db1 = dz1.mapColsToScalar(r => r.sumSIMD * m_inv).raw
222+
// println("back propagation (Float) done ----")
223+
(dw1 = dw1, db1 = db1, dw2 = dw2, db2 = db2)
218224
end back_prop
219225

220-
221226
def back_prop(
222227
w1: Matrix[Double],
223228
b1: Array[Double],
@@ -295,17 +300,17 @@ def loss(predicted: Array[Int], actual: Array[Int]) =
295300
(predicted =:= actual).trues.toDouble / predicted.length
296301

297302
def gradient_descentf(
298-
x: Matrix[Float],
299-
y: Matrix[Float],
300-
labels: Array[Int],
301-
iterations: Int,
302-
batchSize: Int,
303-
alpha: Float,
304-
decayRate: Float,
305-
w1: Matrix[Float],
306-
b1: Array[Float],
307-
w2: Matrix[Float],
308-
b2: Array[Float]
303+
x: Matrix[Float],
304+
y: Matrix[Float],
305+
labels: Array[Int],
306+
iterations: Int,
307+
batchSize: Int,
308+
alpha: Float,
309+
decayRate: Float,
310+
w1: Matrix[Float],
311+
b1: Array[Float],
312+
w2: Matrix[Float],
313+
b2: Array[Float]
309314
) =
310315
import BoundsCheck.DoBoundsCheck.yes
311316
println("Starting gradient descent...")
@@ -356,7 +361,6 @@ def gradient_descentf(
356361
end if
357362
end for
358363

359-
360364
val (_, _, _, a2) = foward_prop(w1_, b1_, w2_, b2_, x)
361365
println(s"iterations: $iterations, alpha: $alpha_, samples: ${x.rows}, classes: ${w2_.cols}")
362366
// println(s"w1_ shape: ${w1_.shape}, w1_ rows: ${w1_.rows}, w1_ cols: ${w1_.cols}, ${w1.raw.take(10).printArr}")

vecxt/src-jvm/floatmatrix.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,6 @@ object JvmFloatMatrix:
173173
else ???
174174
end *
175175

176-
177176
inline def >=(d: Float): Matrix[Boolean] =
178177
if m.hasSimpleContiguousMemoryLayout then
179178
Matrix[Boolean](vecxt.floatarrays.>=(m.raw)(d), m.shape)(using BoundsCheck.DoBoundsCheck.no)
@@ -348,15 +347,16 @@ object JvmFloatMatrix:
348347
end +=
349348

350349
@targetName("floatmatrixSubVector")
351-
inline def - (mat1: Matrix[Float])(using inline boundsCheck: BoundsCheck): Matrix[Float] =
350+
inline def -(mat1: Matrix[Float])(using inline boundsCheck: BoundsCheck): Matrix[Float] =
352351
sameDimMatCheck(m, mat1)
353352
if sameDenseElementWiseMemoryLayoutCheck(m, mat1) then
354353
val newArr = vecxt.floatarrays.-(m.raw)(mat1.raw)
355354
Matrix[Float](newArr, m.rows, m.cols, m.rowStride, m.colStride, m.offset)(using BoundsCheck.DoBoundsCheck.no)
356355
else
357356
val newArr = Array.ofDim[Float](m.numel)
358357
m.raw.copyToArray(newArr)
359-
val newMat = Matrix[Float](newArr, m.rows, m.cols, m.rowStride, m.colStride, m.offset)(using BoundsCheck.DoBoundsCheck.no)
358+
val newMat =
359+
Matrix[Float](newArr, m.rows, m.cols, m.rowStride, m.colStride, m.offset)(using BoundsCheck.DoBoundsCheck.no)
360360
var i = 0
361361
while i < m.rows do
362362
var j = 0
@@ -586,8 +586,7 @@ object JvmFloatMatrix:
586586
end -=
587587

588588
inline def *=(d: Float): Unit =
589-
if m.hasSimpleContiguousMemoryLayout then
590-
floatarrays.*=(m.raw)(d)
589+
if m.hasSimpleContiguousMemoryLayout then floatarrays.*=(m.raw)(d)
591590
else ???
592591
end *=
593592

vecxt/src-jvm/intarrays.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,8 @@ object intarrays:
399399
lane += 1
400400
end while
401401

402-
FloatVector.fromArray(spf, tmp, 0)
402+
FloatVector
403+
.fromArray(spf, tmp, 0)
403404
.div(scalarFloatVec)
404405
.intoArray(result, i)
405406
i += spfl
@@ -427,7 +428,8 @@ object intarrays:
427428
lane += 1
428429
end while
429430

430-
FloatVector.fromArray(spf, tmp, 0)
431+
FloatVector
432+
.fromArray(spf, tmp, 0)
431433
.mul(scalarFloatVec)
432434
.intoArray(result, i)
433435
i += spfl

vecxt/test/src-jvm/TODO.test.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,4 @@ class TODO extends FunSuite:
7070
mat *= 2.0f
7171
}
7272

73-
end TODO
73+
end TODO

vecxt/test/src-jvm/floatmatrix.test.scala

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ class FloatMatrixJvmSuite extends FunSuite:
1818
end while
1919
end assertFloatVecEquals
2020

21-
private def assertFloatMatrixEquals(actual: Matrix[Float], expected: Matrix[Float])(implicit loc: munit.Location): Unit =
21+
private def assertFloatMatrixEquals(actual: Matrix[Float], expected: Matrix[Float])(implicit
22+
loc: munit.Location
23+
): Unit =
2224
assertEquals(actual.shape, expected.shape, "matrix shape mismatch")
2325
var row = 0
2426
while row < actual.rows do
@@ -31,7 +33,9 @@ class FloatMatrixJvmSuite extends FunSuite:
3133
end while
3234
end assertFloatMatrixEquals
3335

34-
private def assertDoubleMatrixEquals(actual: Matrix[Double], expected: Matrix[Double])(implicit loc: munit.Location): Unit =
36+
private def assertDoubleMatrixEquals(actual: Matrix[Double], expected: Matrix[Double])(implicit
37+
loc: munit.Location
38+
): Unit =
3539
assertEquals(actual.shape, expected.shape, "matrix shape mismatch")
3640
var row = 0
3741
while row < actual.rows do
@@ -44,7 +48,9 @@ class FloatMatrixJvmSuite extends FunSuite:
4448
end while
4549
end assertDoubleMatrixEquals
4650

47-
private def assertBooleanMatrixEquals(actual: Matrix[Boolean], expected: Matrix[Boolean])(implicit loc: munit.Location): Unit =
51+
private def assertBooleanMatrixEquals(actual: Matrix[Boolean], expected: Matrix[Boolean])(implicit
52+
loc: munit.Location
53+
): Unit =
4854
assertEquals(actual.shape, expected.shape, "matrix shape mismatch")
4955
var row = 0
5056
while row < actual.rows do
@@ -590,4 +596,4 @@ class FloatMatrixJvmSuite extends FunSuite:
590596
)
591597
)
592598

593-
end FloatMatrixJvmSuite
599+
end FloatMatrixJvmSuite

vecxt/test/src-jvm/intarraysJvm.test.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ class IntArraysJvmSuite extends munit.FunSuite:
1919
end while
2020
}
2121

22-
end IntArraysJvmSuite
22+
end IntArraysJvmSuite

vecxt_io/src-jvm-native/ArrayIO.scala

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@ object ArrayIO:
1212
line.split(java.util.regex.Pattern.quote(seperator.toString), -1).map(_.trim)
1313

1414
private inline def parseValue[A: Numeric](value: String): A =
15-
summon[Numeric[A]].parseString(value).getOrElse(
16-
throw new IllegalArgumentException(s"Could not parse array value '$value'")
17-
)
15+
summon[Numeric[A]]
16+
.parseString(value)
17+
.getOrElse(
18+
throw new IllegalArgumentException(s"Could not parse array value '$value'")
19+
)
1820

1921
extension [A](arr: Array[A])
2022
def write(path: os.Path, seperator: Char = ','): Unit =
2123
os.write.over(path, arr.mkString(seperator.toString))
24+
end extension
2225

2326
def loadArray[A: Numeric: ClassTag](
2427
path: os.Path | os.ResourcePath,
@@ -43,13 +46,16 @@ object ArrayIO:
4346
throw new IllegalArgumentException(
4447
s"Array file contains an empty value at line ${lineIndex + 1}, column ${valueIndex + 1}"
4548
)
49+
end if
4650

4751
builder += parseValue[A](value)
4852
valueIndex += 1
4953
end while
5054
lineIndex += 1
5155
end while
5256
builder.result()
57+
end if
58+
end loadArray
5359

5460
def fromResource[A: Numeric: ClassTag](
5561
resourceName: String,
@@ -58,4 +64,4 @@ object ArrayIO:
5864
): Array[A] =
5965
loadArray(os.resource / resourceName, seperator, dropRows)
6066

61-
end ArrayIO
67+
end ArrayIO

0 commit comments

Comments
 (0)