From df5045ad48d49c52f472efd02a3f77a2adf0e7c9 Mon Sep 17 00:00:00 2001 From: Kilian Muckelbauer Date: Mon, 1 Dec 2025 11:10:57 +0100 Subject: [PATCH] neuralnetwork.c und neuralnetworktests.c --- neuralNetwork.c | 42 ++++++++++++++++++++++++++++++++---------- neuralNetworkTests.c | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 11 deletions(-) diff --git a/neuralNetwork.c b/neuralNetwork.c index bd8f164..dd1fac6 100644 --- a/neuralNetwork.c +++ b/neuralNetwork.c @@ -170,7 +170,8 @@ NeuralNetwork loadModel(const char *path) static Matrix imageBatchToMatrixOfImageVectors(const GrayScaleImage images[], unsigned int count) { - Matrix matrix = {NULL, 0, 0}; + // Matrix matrix = {NULL, 0, 0}; + Matrix matrix = {.rows = 0, .cols = 0, .buffer = NULL}; if(count > 0 && images != NULL) { @@ -190,26 +191,47 @@ static Matrix imageBatchToMatrixOfImageVectors(const GrayScaleImage images[], un return matrix; } +// +static void addBiasInPlace(Matrix *matrix, const Matrix *biases) +{ + // biases: rows x 1, matrix: rows x cols + if(matrix == NULL || biases == NULL) + return; + if(matrix->buffer == NULL || biases->buffer == NULL) + return; + if(matrix->rows != biases->rows || biases->cols != 1) + return; + for(unsigned int rowIdx = 0; rowIdx < matrix->rows; rowIdx++) + { + MatrixType b = getMatrixAt(*biases, rowIdx, 0); + for(unsigned int colIdx = 0; colIdx < matrix->cols; colIdx++) + { + MatrixType v = getMatrixAt(*matrix, rowIdx, colIdx); + setMatrixAt(v + b, *matrix, rowIdx, colIdx); + } + } +} +// static Matrix forward(const NeuralNetwork model, Matrix inputBatch) { Matrix result = inputBatch; if(result.buffer != NULL) { - for(int i = 0; i < model.numberOfLayers; i++) + for(int i = 0; i < (int)model.numberOfLayers; i++) { - Matrix biasResult; - Matrix weightResult; - - weightResult = multiply(model.layers[i].weights, result); + // 1) weights * aktuelles Ergebnis + Matrix weightResult = multiply(model.layers[i].weights, result); clearMatrix(&result); - biasResult = add(model.layers[i].biases, weightResult); - clearMatrix(&weightResult); + result = weightResult; + // 2) Bias auf alle Spalten addieren (Broadcast) + addBiasInPlace(&result, &model.layers[i].biases); + + // 3) Aktivierungsfunktion anwenden if(model.layers[i].activation != NULL) - model.layers[i].activation(&biasResult); - result = biasResult; + model.layers[i].activation(&result); } } diff --git a/neuralNetworkTests.c b/neuralNetworkTests.c index 21ab370..04a278e 100644 --- a/neuralNetworkTests.c +++ b/neuralNetworkTests.c @@ -8,7 +8,46 @@ static void prepareNeuralNetworkFile(const char *path, const NeuralNetwork nn) { - // TODO + FILE *file = fopen(path, "wb"); //Datei öffnen im write binary modus + if (!file) //wenn fopen 0 zurück gibt + { + fprintf(stderr, "Fehler: Datei konnte nicht geöffnet werden.\n"); + return; + } + + // Header schreiben + const char *header = "__info2_neural_network_file_format__"; + fwrite(header, sizeof(char), strlen(header), file); // Zeiger auf Daten, größe des ElementsChar (1 byte), + //länge des Stings ohen \0, Zieldatei + + // Erste Dimension: Input-Dimension der ersten Schicht (Anzahl der Eingangsneuronen)Anzahl Spalten + unsigned int inputDim = nn.layers[0].weights.cols; + // Speichert die Input-Dimension in die Datei + fwrite(&inputDim, sizeof(unsigned int), 1, file); + + // Für jede Schicht im Netzwerk + for (int i = 0; i < nn.numberOfLayers; i++) + { + Layer layer = nn.layers[i]; // Zugriff auf die aktuelle Schicht + + // Output-Dimension: Anzahl der Neuronen in dieser Schicht (Anzahl Zeilen der Gewichtsmatrix) + unsigned int outputDim = layer.weights.rows; + // Speichert die Output-Dimension in die Datei + fwrite(&outputDim, sizeof(unsigned int), 1, file); + + // Speichert die Gewichtsmatrix der Schicht in die Datei + // Anzahl der Elemente = rows * cols, Typ = MatrixType + fwrite(layer.weights.buffer, sizeof(MatrixType), + layer.weights.rows * layer.weights.cols, file); + + // Speichert die Bias-Werte der Schicht in die Datei + // Anzahl der Elemente = rows * cols (meist rows x 1), Typ = MatrixType + fwrite(layer.biases.buffer, sizeof(MatrixType), + layer.biases.rows * layer.biases.cols, file); + } + +// Schließt die Datei nach dem Schreiben +fclose(file); } void test_loadModelReturnsCorrectNumberOfLayers(void)