From 4bf52f722feed243c0ae22f6e614d6dc95608272 Mon Sep 17 00:00:00 2001 From: michalharakal Date: Thu, 22 Oct 2026 23:02:25 +0200 Subject: [PATCH] fix(mnistdemo): declare the CNN input shape so the output layer gets its 1568 features createMNISTCNN() opened with conv2d straight away, so the DSL had no per-sample shape to carry through the conv and pool layers and flatten() handed dense(10, "out") zero input features. The layer was built as [10 x 0], loading mnist_cnn.gguf threw ArrayIndexOutOfBoundsException, and the two CNN accuracy tests failed on every engine version since the sample was written (noted in #39 and #47). input(intArrayOf(1, 28, 28)) at the top lets the DSL infer 32*7*7 = 1568 for the output layer; the GGUF loads and the CNN scores 99.2 % on 500 MNIST test images (100 % on the 100-image sample). --- .../commonMain/kotlin/sk/ainet/lang/model/MnistModels.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MNISTDemo/shared/src/commonMain/kotlin/sk/ainet/lang/model/MnistModels.kt b/MNISTDemo/shared/src/commonMain/kotlin/sk/ainet/lang/model/MnistModels.kt index 5b3b7bf..5b6055d 100644 --- a/MNISTDemo/shared/src/commonMain/kotlin/sk/ainet/lang/model/MnistModels.kt +++ b/MNISTDemo/shared/src/commonMain/kotlin/sk/ainet/lang/model/MnistModels.kt @@ -44,6 +44,12 @@ fun createMNISTMLP(): Module = sequential(evalCtx) { * - Output: 1568→10 (dense layer) */ fun createMNISTCNN(): Module = sequential(evalCtx) { + // The per-sample input shape (channels, height, width). The DSL propagates it through the + // conv and pool layers, so flatten() knows it hands 32*7*7 = 1568 features to the dense + // layer; without it the output layer was built with zero input features and the GGUF + // weights could not be loaded. + input(intArrayOf(1, 28, 28)) + // Conv block 1: 1→16 channels (grayscale input has 1 channel) conv2d("stage1.conv1") { inChannels = 1