Compare commits

..

7 Commits
Pia ... main

Author SHA1 Message Date
silvana884
164071c3ad Fehler korrigieren 2025-11-26 11:18:47 +01:00
silvana884
3e9041e437 Matrix.c kommentiert 2025-11-26 10:52:42 +01:00
silvana884
4c984c59da Matrix.h zusammengefuehrt 2025-11-26 10:33:55 +01:00
silvana884
3d352d7c06 neuralNetwork.c eingefuegt 2025-11-26 10:33:18 +01:00
silvana884
cd5e29d44d neuralNetwork.h eingefuegt 2025-11-26 10:32:37 +01:00
silvana884
cc54d4e1dc NeuralNetwork.tests.c eingefuegt 2025-11-26 10:31:46 +01:00
74e7a21999 Merge pull request 'Pia' (#2) from Pia into main
Reviewed-on: #2
2025-11-26 09:27:00 +00:00
5 changed files with 65 additions and 6 deletions

View File

@ -2,8 +2,9 @@
#include <string.h> #include <string.h>
#include "matrix.h" #include "matrix.h"
// TODO Matrix-Funktionen implementieren //Erstellt eine mit Nullen gefuellte Matrix, wenn genug Speicherplatz vorhanden ist und ein out-of-bounds-error durch unpassende Spalten oder Zeilen verhindert werden kann.
//Gibt die erstellte Matrix als Matrix-Objekt zurueck, also als eine Kopie der erstellten Matrix.
//@Param: rows gibt die Anzahl der Zeilen der neuen Matrix an, cols gibt die Anzahl der Spalten an
Matrix createMatrix(unsigned int rows, unsigned int cols) Matrix createMatrix(unsigned int rows, unsigned int cols)
{ {
if(rows && cols){ if(rows && cols){
@ -32,7 +33,8 @@ Matrix createMatrix(unsigned int rows, unsigned int cols)
return matrix; return matrix;
} }
//Loescht die uebergebene Matrix vollstaendig aus dem Speicher.
//@Param: *matrix Gibt den Zeiger auf die zu loeschende Matrix wieder. Dadurch wird nicht nur eine Kopie geloescht, sondern tatsaechlich die Matrix.
void clearMatrix(Matrix *matrix) void clearMatrix(Matrix *matrix)
{ {
free(matrix->buffer); free(matrix->buffer);
@ -41,11 +43,19 @@ void clearMatrix(Matrix *matrix)
matrix->cols = 0; matrix->cols = 0;
} }
//Setzt den Wert einer Matrix an einer bestimmten Stelle im Array.
//@Param: value gibt den einzufuegenden Wert an, matrix die Matrix, deren Wert geandert oder gesetzt werden soll,
// rowIdx die Anzahl der Zeilen, die im Speicher uebersprungen werden soll, um in die gewunschte Zeile zu kommen,
// collIdx die Nummer der Spalte, die geandert werden soll
void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx) void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{ {
matrix.buffer[rowIdx * matrix.cols + colIdx] = value; matrix.buffer[rowIdx * matrix.cols + colIdx] = value;
} }
//Gibt den Wert einer Matrix an einer bestimmten Stelle im Array zurueck.
//@Param: value gibt den einzufuegenden Wert an, matrix die Matrix, deren Wert geandert oder gesetzt werden soll,
//rowIdx die Anzahl der Zeilen, die im Speicher uebersprungen werden soll, um in die gewunschte Zeile zu kommen,
// collIdx die Nummer der Spalte, die gelesen werden soll
MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx) MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{ {
if(rowIdx >= matrix.rows || colIdx >= matrix.cols){ if(rowIdx >= matrix.rows || colIdx >= matrix.cols){
@ -54,6 +64,11 @@ MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int co
return matrix.buffer[rowIdx * matrix.cols + colIdx]; return matrix.buffer[rowIdx * matrix.cols + colIdx];
} }
//Addiert zwei Matrizen miteinander oder broadcastet die eine Matrix mit einem Vektor.
//Ueberpueft, ob broadcasting moeglich ist. Wenn nicht, werden die Matrizen addiert. Prueft zusaetzlich, ob Matrizenaddition moeglich ist.
//Ist Broadcasting moeglich, wird die broadcasting-Methode aufgerufen.
//Gibt addierte Matrix zurueck, nachdem diese in der Funktion erstellt wurde.
//@param: matrix1 und matrix2 sind die Matrizen, deren Spalten und Zeilen ueberprueft werden und von denen moeglicherweise einer ein Vektor ist fuer das Broadcasting.
Matrix add(const Matrix matrix1, const Matrix matrix2) Matrix add(const Matrix matrix1, const Matrix matrix2)
{ {
int rows1 = rows(matrix1); int rows1 = rows(matrix1);
@ -91,6 +106,9 @@ Matrix add(const Matrix matrix1, const Matrix matrix2)
} }
} }
//Gibt die Matrix zurueck, die nach dem Broadcasting entstanden ist.
//Addiert einen Vektor zu einer Matrix, sodass jede Zelle der Matrix mit der Koordinate des Vektors addiert wird.
//@param: vektor ist die einspaltige Matrix, deren Koordinaten auf die Matrix addiert werden, matrix ist die Matrix, zu der der Vektor addiert wird.
Matrix broadcasting(const Matrix vektor, const Matrix matrix) Matrix broadcasting(const Matrix vektor, const Matrix matrix)
{ {
int rowsM = rows(matrix); int rowsM = rows(matrix);
@ -109,6 +127,8 @@ Matrix broadcasting(const Matrix vektor, const Matrix matrix)
return result; return result;
} }
//Prueft, ob Multiplikation zweier Matrizen moeglich ist und gibt fuer den Fall, dass es moeglich ist, eine neue Matrix mit den Ergebnissen zurueck.
//@param: matrix1 und matrix2 geben die Matrizen an, die miteinander multipliziert werden sollen
Matrix multiply(const Matrix matrix1, const Matrix matrix2) Matrix multiply(const Matrix matrix1, const Matrix matrix2)
{ {
int rows1 = rows(matrix1); int rows1 = rows(matrix1);
@ -142,11 +162,15 @@ Matrix multiply(const Matrix matrix1, const Matrix matrix2)
return createMatrix(0,0); return createMatrix(0,0);
} }
//Gibt die Strukturvariable rows einer Matrix zurueck
//@param: matrix gibt an, von welcher Matrix die Strukturvariable uebergeben werden soll
int rows(const Matrix matrix) int rows(const Matrix matrix)
{ {
return matrix.rows; return matrix.rows;
} }
//Gibt die Strukturvariable cols einer Matrix zurueck
//@param: matrix gibt an, von welcher Matrix die Strukturvariable uebergeben werden soll
int cols(const Matrix matrix) int cols(const Matrix matrix)
{ {
return matrix.cols; return matrix.cols;

View File

@ -10,7 +10,7 @@ typedef struct{
unsigned int rows; unsigned int rows;
unsigned int cols; unsigned int cols;
MatrixType *buffer; //Data wird in einem eindimensionalen Array gespeichert (Spalten und Reihen liegen ja im Speicher hintereinannder) MatrixType *buffer; //Data wird in einem eindimensionalen Array gespeichert (Spalten und Reihen liegen ja im Speicher hintereinannder)
} Matrix; } Matrix;
Matrix createMatrix(unsigned int rows, unsigned int cols); Matrix createMatrix(unsigned int rows, unsigned int cols);

View File

@ -170,7 +170,7 @@ NeuralNetwork loadModel(const char *path)
static Matrix imageBatchToMatrixOfImageVectors(const GrayScaleImage images[], unsigned int count) static Matrix imageBatchToMatrixOfImageVectors(const GrayScaleImage images[], unsigned int count)
{ {
Matrix matrix = {NULL, 0, 0}; Matrix matrix = {0,0, NULL};
if(count > 0 && images != NULL) if(count > 0 && images != NULL)
{ {

View File

@ -1,6 +1,8 @@
#ifndef NEURALNETWORK_H #ifndef NEURALNETWORK_H
#define NEURALNETWORK_H #define NEURALNETWORK_H
#define FILE_HEADER_STRING "__info2_neural_network_file_format__"
#include "imageInput.h" #include "imageInput.h"
#include "matrix.h" #include "matrix.h"

View File

@ -6,11 +6,44 @@
#include "neuralNetwork.h" #include "neuralNetwork.h"
//Testdatei schreiben
static void prepareNeuralNetworkFile(const char *path, const NeuralNetwork nn) static void prepareNeuralNetworkFile(const char *path, const NeuralNetwork nn)
{ {
// TODO // Datei öffnen
FILE *file = fopen(path, "wb");
if (file == NULL)
return;
// Header schreiben
const char *fileTag = "__info2_neural_network_file_format__";
fwrite(fileTag, 1, strlen(fileTag), file);
// input Dimension schreiben
int inputDim = nn.layers[0].weights.cols;
fwrite(&inputDim, sizeof(int), 1, file);
// für weiter Layer nur output Dimension schreiben
for (unsigned int i = 0; i < nn.numberOfLayers; i++)
{
int outputDim = nn.layers[i].weights.rows;
fwrite(&outputDim, sizeof(int), 1, file);
int weightCount = nn.layers[i].weights.rows * nn.layers[i].weights.cols;
fwrite(nn.layers[i].weights.buffer, sizeof(MatrixType), weightCount, file);
int biasesCount = nn.layers[i].biases.rows * nn.layers[i].biases.cols;
fwrite(nn.layers[i].biases.buffer, sizeof(MatrixType), biasesCount, file);
} }
// Ende: loadModel liest 0 ein
int fileEnd = 0;
fwrite(&fileEnd, sizeof(int), 1, file);
// Datei schließen
fclose(file);
}
void test_loadModelReturnsCorrectNumberOfLayers(void) void test_loadModelReturnsCorrectNumberOfLayers(void)
{ {
const char *path = "some__nn_test_file.info2"; const char *path = "some__nn_test_file.info2";