3 Commits
Author SHA1 Message Date
kachelto100370 786aa2e6d8 working on imageinput 2025-11-25 10:53:28 +01:00
kachelto100370 58df4199b5 smal gitignore 2025-11-23 16:33:44 +01:00
kachelto100370 fb18b75b60 working on imputimage 0 test passing 2025-11-23 16:33:22 +01:00
8 changed files with 294 additions and 466 deletions
+4 -1
View File
@@ -2,6 +2,9 @@ mnist
runTests runTests
*.o *.o
*.exe *.exe
.vscode/c_cpp_properties.json .vscode/settings.json
.vscode/launch.json .vscode/launch.json
.vscode/settings.json .vscode/settings.json
.vscode/settings.json
runImageInputTests
testFile.info2
-18
View File
@@ -1,18 +0,0 @@
{
"configurations": [
{
"name": "windows-gcc-x64",
"includePath": [
"${workspaceFolder}/**"
],
"compilerPath": "C:/ProgramData/mingw64/mingw64/bin/gcc.exe",
"cStandard": "${default}",
"cppStandard": "${default}",
"intelliSenseMode": "windows-gcc-x64",
"compilerArgs": [
""
]
}
],
"version": 4
}
-24
View File
@@ -1,24 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "C/C++ Runner: Debug Session",
"type": "cppdbg",
"request": "launch",
"args": [],
"stopAtEntry": false,
"externalConsole": true,
"cwd": "c:/Users/Max-R/I2Pr/repoKachelto/I2-Pr_neuronalesNetz/info2Praktikum-NeuronalesNetz",
"program": "c:/Users/Max-R/I2Pr/repoKachelto/I2-Pr_neuronalesNetz/info2Praktikum-NeuronalesNetz/build/Debug/outDebug",
"MIMode": "gdb",
"miDebuggerPath": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
+1 -57
View File
@@ -1,59 +1,3 @@
{ {
"C_Cpp_Runner.cCompilerPath": "gcc", "makefile.configureOnOpen": false
"C_Cpp_Runner.cppCompilerPath": "g++",
"C_Cpp_Runner.debuggerPath": "gdb",
"C_Cpp_Runner.cStandard": "",
"C_Cpp_Runner.cppStandard": "",
"C_Cpp_Runner.msvcBatchPath": "C:/Program Files/Microsoft Visual Studio/VR_NR/Community/VC/Auxiliary/Build/vcvarsall.bat",
"C_Cpp_Runner.useMsvc": false,
"C_Cpp_Runner.warnings": [
"-Wall",
"-Wextra",
"-Wpedantic",
"-Wshadow",
"-Wformat=2",
"-Wcast-align",
"-Wconversion",
"-Wsign-conversion",
"-Wnull-dereference"
],
"C_Cpp_Runner.msvcWarnings": [
"/W4",
"/permissive-",
"/w14242",
"/w14287",
"/w14296",
"/w14311",
"/w14826",
"/w44062",
"/w44242",
"/w14905",
"/w14906",
"/w14263",
"/w44265",
"/w14928"
],
"C_Cpp_Runner.enableWarnings": true,
"C_Cpp_Runner.warningsAsError": false,
"C_Cpp_Runner.compilerArgs": [],
"C_Cpp_Runner.linkerArgs": [],
"C_Cpp_Runner.includePaths": [],
"C_Cpp_Runner.includeSearch": [
"*",
"**/*"
],
"C_Cpp_Runner.excludeSearch": [
"**/build",
"**/build/**",
"**/.*",
"**/.*/**",
"**/.vscode",
"**/.vscode/**"
],
"C_Cpp_Runner.useAddressSanitizer": false,
"C_Cpp_Runner.useUndefinedSanitizer": false,
"C_Cpp_Runner.useLeakSanitizer": false,
"C_Cpp_Runner.showCompilationTime": false,
"C_Cpp_Runner.useLinkTimeOptimization": false,
"C_Cpp_Runner.msvcSecureNoWarnings": false
} }
+29 -3
View File
@@ -15,10 +15,36 @@ GrayScaleImage readImage()
// TODO Vervollständigen Sie die Funktion readImages unter Benutzung Ihrer Hilfsfunktionen // TODO Vervollständigen Sie die Funktion readImages unter Benutzung Ihrer Hilfsfunktionen
GrayScaleImageSeries *readImages(const char *path) GrayScaleImageSeries *readImages(const char *path)
{ {
unsigned short * numImages;
unsigned short * breiteBilder;
unsigned short * laengeBilder;
GrayScaleImageSeries *series = NULL; GrayScaleImageSeries *series = NULL;
FILE *file = fopen("mnist_test.info2","rb"); FILE *file = fopen(*path,"rb");
char headOfFile; char * headOfFile;
series = malloc();
fread(headOfFile, sizeof(FILE_HEADER_STRING),1, file); //liest den header ein und überprüft ob korrekte datei
if(strcmp(headOfFile, FILE_HEADER_STRING) != 0)
return NULL;
// liest numIMages, breite und länge der Bilder ein
fseek(file, sizeof(FILE_HEADER_STRING), SEEK_SET);
fread(numImages, sizeof(short), 1, file);
fseek(file, sizeof(short), SEEK_CUR);
fread(breiteBilder, sizeof(short), 1, file);
fseek(file, sizeof(short), SEEK_CUR);
fread(laengeBilder, sizeof(short), 1, file);
series = malloc(*numImages * *breiteBilder * *laengeBilder * sizeof(short));
for(int i = 0; i < numImages; i++)
{
}
return series; return series;
} }
+3 -1
View File
@@ -63,4 +63,6 @@ ifeq ($(OS),Windows_NT)
else else
rm -f *.o mnist runMatrixTests runNeuralNetworkTests runImageInputTests rm -f *.o mnist runMatrixTests runNeuralNetworkTests runImageInputTests
endif endif
clean für windows
clean:
rm -f *.o *.exe
+14 -152
View File
@@ -8,10 +8,6 @@
MatrixType *buffer; //Zeiger auf Speicherbereich Reihen*Spalten MatrixType *buffer; //Zeiger auf Speicherbereich Reihen*Spalten
} Matrix;*/ } Matrix;*/
Matrix createMatrix(unsigned int rows, unsigned int cols) { Matrix createMatrix(unsigned int rows, unsigned int cols) {
if (cols == 0 || rows == 0){
Matrix errorMatrix = {0, 0, NULL};
return errorMatrix;
}
MatrixType *buffer = MatrixType *buffer =
malloc(rows * cols * sizeof(MatrixType)); // Speicher reservieren, malloc malloc(rows * cols * sizeof(MatrixType)); // Speicher reservieren, malloc
// liefert Zeiger auf Speicher // liefert Zeiger auf Speicher
@@ -28,12 +24,8 @@ void setMatrixAt(const MatrixType value, Matrix matrix,
const unsigned int rowIdx, // Kopie der Matrix wird übergeben const unsigned int rowIdx, // Kopie der Matrix wird übergeben
const unsigned int colIdx) { const unsigned int colIdx) {
if (rowIdx >= matrix.rows || colIdx >= matrix.cols) { matrix.buffer[rowIdx * matrix.cols + colIdx] =
// Speichergröße nicht überschreiten value; // rowIdx * matrix.cols -> Beginn der Zeile colIdx ->Spalte
return;
}
matrix.buffer[rowIdx * matrix.cols + colIdx] = value;
// rowIdx * matrix.cols -> Beginn der Zeile colIdx ->Spalte
// innerhalb der Zeile // innerhalb der Zeile
} }
MatrixType getMatrixAt(const Matrix matrix, MatrixType getMatrixAt(const Matrix matrix,
@@ -48,159 +40,29 @@ MatrixType getMatrixAt(const Matrix matrix,
return value; return value;
} }
Matrix broadcastingCols(const Matrix matrix, const unsigned int cols){
Matrix copy1 = createMatrix(matrix.rows, cols);
for (int r= 0; r < matrix.rows; r++){
MatrixType valueMatrix1 = getMatrixAt(matrix, r, 0);
for (int c=0; c < cols; c++){
setMatrixAt(valueMatrix1, copy1,r,c);
}
}
return copy1;
}
Matrix broadcastingRows(const Matrix matrix, const unsigned int rows){
Matrix copy1 = createMatrix(rows, matrix.cols);
for (int c= 0; c < matrix.cols; c++){
MatrixType valueMatrix1 = getMatrixAt(matrix, 0, c);
for (int r=0; r < rows; r++){
setMatrixAt(valueMatrix1, copy1,r,c);
}
}
return copy1;
}
Matrix add(const Matrix matrix1, const Matrix matrix2) { Matrix add(const Matrix matrix1, const Matrix matrix2) {
// Ergebnismatrix
Matrix result; Matrix result;
const int cols1 = matrix1.cols; const int cols1 = matrix1.cols;
const int rows1 = matrix1.rows; const int rows1 = matrix1.rows;
const int cols2 = matrix2.cols; const int cols2 = matrix2.cols;
const int rows2 = matrix2.rows; const int rows2 = matrix2.rows;
const int colsEqu = (matrix1.cols == matrix2.cols) ? 1 : 0;
const int rowsEqu = (matrix1.rows == matrix2.rows) ? 1 : 0;
const int rowsEqual = (matrix1.rows==matrix2.rows) ? 1: 0; if(colsEqu && rowsEqu)
const int colsEqual = (matrix1.cols==matrix2.cols) ? 1: 0; {
// Broadcasting nur bei Vektor und Matrix, Fehlermeldung bei zwei unpassender
// Matrix
if (rowsEqual == 1 && colsEqual == 1){
Matrix result = createMatrix(matrix1.rows, matrix1.cols); Matrix result = createMatrix(matrix1.rows, matrix1.cols);
if (result.buffer == NULL){ for(int i = 0; i < rows1; i++)
return (Matrix){0,0,NULL}; {
} for (int j = 0; j < cols1; j++)
for (int i = 0; i< rows1; i++) { {
for (int j= 0; j< cols1; j++){ int valueM1 = getMatrixAt(matrix1, i, j);
int valueM1= getMatrixAt(matrix1, i, j); int valueM2 =getMatrixAt(matrix2, i, j);
int valueM2= getMatrixAt(matrix2, i, j);
int sum = valueM1 + valueM2; int sum = valueM1 + valueM2;
setMatrixAt(sum, result, i, j); setMatrixAt(sum, result,i,j);
}
}
return result;
}
else if (rowsEqual ==1 && (cols1 ==1 || cols2 ==1)){
if (cols1==1){ //broadcasting von vektor 1 zu matrix 1, add
Matrix newMatrix = broadcastingCols(matrix1, cols2);
//add
Matrix result = createMatrix(newMatrix.rows, newMatrix.cols);
if (result.buffer == NULL){
return (Matrix){0,0,NULL};
}
for (int i = 0; i< rows1; i++) {
for (int j= 0; j< cols2; j++){
int valueM1= getMatrixAt(newMatrix, i, j);
int valueM2= getMatrixAt(matrix2, i, j);
int sum = valueM1 + valueM2;
setMatrixAt(sum, result, i, j);
}
}
return result;
}
else{
Matrix newMatrix2 = broadcastingCols(matrix2, cols1);
//add
Matrix result = createMatrix(newMatrix2.rows, newMatrix2.cols);
if (result.buffer == NULL){
return (Matrix){0,0,NULL};
}
for (int i = 0; i< rows1; i++) {
for (int j= 0; j< cols1; j++){
int valueM1= getMatrixAt(matrix1, i, j);
int valueM2= getMatrixAt(newMatrix2, i, j);
int sum = valueM1 + valueM2;
setMatrixAt(sum, result, i, j);
}
}
return result;
} }
} }
else if ((rows1 ==1 || rows2 ==1) && colsEqual == 1){
if (rows1==1){
Matrix newMatrix = broadcastingRows(matrix1, rows2);
//add
Matrix result = createMatrix(newMatrix.rows, newMatrix.cols);
if (result.buffer == NULL){
return (Matrix){0,0,NULL};
}
for (int i = 0; i< rows2; i++) {
for (int j= 0; j< cols1; j++){
int valueM1= getMatrixAt(newMatrix, i, j);
int valueM2= getMatrixAt(matrix2, i, j);
int sum = valueM1 + valueM2;
setMatrixAt(sum, result, i, j);
}
}
return result; return result;
} }
else{
Matrix newMatrix2 = broadcastingRows(matrix2, rows1);
//add
Matrix result = createMatrix(newMatrix2.rows, newMatrix2.cols);
if (result.buffer == NULL){
return (Matrix){0,0,NULL};
}
for (int i = 0; i< rows1; i++) {
for (int j= 0; j< cols1; j++){
int valueM1= getMatrixAt(matrix1, i, j);
int valueM2= getMatrixAt(newMatrix2, i, j);
int sum = valueM1 + valueM2;
setMatrixAt(sum, result, i, j);
}
}
return result;
}
}
else {
// kein add möglich
Matrix errorMatrix = {0, 0, NULL};
return errorMatrix;
}
return result;
}
Matrix multiply(const Matrix matrix1, const Matrix matrix2) {
//Spalten1 müssen gleich zeilen2 sein! dann multiplizieren
if (matrix1.cols == matrix2.rows){
Matrix multMatrix = createMatrix(matrix1.rows,matrix2.cols);
//durch neue matrix iterieren
for (int r=0; r< matrix1.rows; r++){
for (int c=0; c< matrix2.cols; c++){
MatrixType sum = 0.0;
//skalarprodukte berechnen, k damit die ganze zeile mal die ganze spalte genommen wird quasi
for (int k=0; k< matrix1.cols; k++){
//sum+= matrix1.buffer[r*matrix1.cols+k]*matrix2.buffer[k*matrix2.cols+c];
sum += getMatrixAt(matrix1, r, k)*getMatrixAt(matrix2, k, c);
}
//Ergebnisse in neue matrix speichern
setMatrixAt(sum, multMatrix, r, c);
}
}
return multMatrix;
}
//sonst fehler, kein multiply möglich
else{
Matrix errorMatrix = {0, 0, NULL};
return errorMatrix;
}
} }
Matrix multiply(const Matrix matrix1, const Matrix matrix2) { return matrix1; }
+101 -68
View File
@@ -1,29 +1,35 @@
#include "neuralNetwork.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h> #include <string.h>
#include "neuralNetwork.h"
#define BUFFER_SIZE 100 #define BUFFER_SIZE 100
#define FILE_HEADER_STRING "__info2_neural_network_file_format__" #define FILE_HEADER_STRING "__info2_neural_network_file_format__"
static void softmax(Matrix *matrix) { static void softmax(Matrix *matrix)
if (matrix->cols > 0) { {
if(matrix->cols > 0)
{
double *colSums = (double *)calloc(matrix->cols, sizeof(double)); double *colSums = (double *)calloc(matrix->cols, sizeof(double));
if (colSums != NULL) { if(colSums != NULL)
for (int colIdx = 0; colIdx < matrix->cols; colIdx++) { {
for (int rowIdx = 0; rowIdx < matrix->rows; rowIdx++) { for(int colIdx = 0; colIdx < matrix->cols; colIdx++)
{
for(int rowIdx = 0; rowIdx < matrix->rows; rowIdx++)
{
MatrixType expValue = exp(getMatrixAt(*matrix, rowIdx, colIdx)); MatrixType expValue = exp(getMatrixAt(*matrix, rowIdx, colIdx));
setMatrixAt(expValue, *matrix, rowIdx, colIdx); setMatrixAt(expValue, *matrix, rowIdx, colIdx);
colSums[colIdx] += expValue; colSums[colIdx] += expValue;
} }
} }
for (int colIdx = 0; colIdx < matrix->cols; colIdx++) { for(int colIdx = 0; colIdx < matrix->cols; colIdx++)
for (int rowIdx = 0; rowIdx < matrix->rows; rowIdx++) { {
MatrixType normalizedValue = for(int rowIdx = 0; rowIdx < matrix->rows; rowIdx++)
getMatrixAt(*matrix, rowIdx, colIdx) / colSums[colIdx]; {
MatrixType normalizedValue = getMatrixAt(*matrix, rowIdx, colIdx) / colSums[colIdx];
setMatrixAt(normalizedValue, *matrix, rowIdx, colIdx); setMatrixAt(normalizedValue, *matrix, rowIdx, colIdx);
} }
} }
@@ -32,49 +38,54 @@ static void softmax(Matrix *matrix) {
} }
} }
static void relu(Matrix *matrix) { static void relu(Matrix *matrix)
for (int i = 0; i < matrix->rows * matrix->cols; i++) { {
for(int i = 0; i < matrix->rows * matrix->cols; i++)
{
matrix->buffer[i] = matrix->buffer[i] >= 0 ? matrix->buffer[i] : 0; matrix->buffer[i] = matrix->buffer[i] >= 0 ? matrix->buffer[i] : 0;
} }
} }
static int checkFileHeader(FILE *file) { static int checkFileHeader(FILE *file)
{
int isValid = 0; int isValid = 0;
int fileHeaderLen = strlen(FILE_HEADER_STRING); int fileHeaderLen = strlen(FILE_HEADER_STRING);
char buffer[BUFFER_SIZE] = {0}; char buffer[BUFFER_SIZE] = {0};
if (BUFFER_SIZE - 1 < fileHeaderLen) if(BUFFER_SIZE-1 < fileHeaderLen)
fileHeaderLen = BUFFER_SIZE - 1; fileHeaderLen = BUFFER_SIZE-1;
if (fread(buffer, sizeof(char), fileHeaderLen, file) == fileHeaderLen) if(fread(buffer, sizeof(char), fileHeaderLen, file) == fileHeaderLen)
isValid = strcmp(buffer, FILE_HEADER_STRING) == 0; isValid = strcmp(buffer, FILE_HEADER_STRING) == 0;
return isValid; return isValid;
} }
static unsigned int readDimension(FILE *file) { static unsigned int readDimension(FILE *file)
{
int dimension = 0; int dimension = 0;
if (fread(&dimension, sizeof(int), 1, file) != 1) if(fread(&dimension, sizeof(int), 1, file) != 1)
dimension = 0; dimension = 0;
return dimension; return dimension;
} }
static Matrix readMatrix(FILE *file, unsigned int rows, unsigned int cols) { static Matrix readMatrix(FILE *file, unsigned int rows, unsigned int cols)
{
Matrix matrix = createMatrix(rows, cols); Matrix matrix = createMatrix(rows, cols);
if (matrix.buffer != NULL) { if(matrix.buffer != NULL)
if (fread(matrix.buffer, sizeof(MatrixType), rows * cols, file) != {
rows * cols) if(fread(matrix.buffer, sizeof(MatrixType), rows*cols, file) != rows*cols)
clearMatrix(&matrix); clearMatrix(&matrix);
} }
return matrix; return matrix;
} }
static Layer readLayer(FILE *file, unsigned int inputDimension, static Layer readLayer(FILE *file, unsigned int inputDimension, unsigned int outputDimension)
unsigned int outputDimension) { {
Layer layer; Layer layer;
layer.weights = readMatrix(file, outputDimension, inputDimension); layer.weights = readMatrix(file, outputDimension, inputDimension);
layer.biases = readMatrix(file, outputDimension, 1); layer.biases = readMatrix(file, outputDimension, 1);
@@ -82,54 +93,62 @@ static Layer readLayer(FILE *file, unsigned int inputDimension,
return layer; return layer;
} }
static int isEmptyLayer(const Layer layer) { static int isEmptyLayer(const Layer layer)
return layer.biases.cols == 0 || layer.biases.rows == 0 || {
layer.biases.buffer == NULL || layer.weights.rows == 0 || return layer.biases.cols == 0 || layer.biases.rows == 0 || layer.biases.buffer == NULL || layer.weights.rows == 0 || layer.weights.cols == 0 || layer.weights.buffer == NULL;
layer.weights.cols == 0 || layer.weights.buffer == NULL;
} }
static void clearLayer(Layer *layer) { static void clearLayer(Layer *layer)
if (layer != NULL) { {
if(layer != NULL)
{
clearMatrix(&layer->weights); clearMatrix(&layer->weights);
clearMatrix(&layer->biases); clearMatrix(&layer->biases);
layer->activation = NULL; layer->activation = NULL;
} }
} }
static void assignActivations(NeuralNetwork model) { static void assignActivations(NeuralNetwork model)
for (int i = 0; i < (int)model.numberOfLayers - 1; i++) { {
for(int i = 0; i < (int)model.numberOfLayers-1; i++)
{
model.layers[i].activation = relu; model.layers[i].activation = relu;
} }
if (model.numberOfLayers > 0) if(model.numberOfLayers > 0)
model.layers[model.numberOfLayers - 1].activation = softmax; model.layers[model.numberOfLayers-1].activation = softmax;
} }
NeuralNetwork loadModel(const char *path) { NeuralNetwork loadModel(const char *path)
{
NeuralNetwork model = {NULL, 0}; NeuralNetwork model = {NULL, 0};
FILE *file = fopen(path, "rb"); FILE *file = fopen(path, "rb");
if (file != NULL) { if(file != NULL)
if (checkFileHeader(file)) { {
if(checkFileHeader(file))
{
unsigned int inputDimension = readDimension(file); unsigned int inputDimension = readDimension(file);
unsigned int outputDimension = readDimension(file); unsigned int outputDimension = readDimension(file);
while (inputDimension > 0 && outputDimension > 0) { while(inputDimension > 0 && outputDimension > 0)
{
Layer layer = readLayer(file, inputDimension, outputDimension); Layer layer = readLayer(file, inputDimension, outputDimension);
Layer *layerBuffer = NULL; Layer *layerBuffer = NULL;
if (isEmptyLayer(layer)) { if(isEmptyLayer(layer))
{
clearLayer(&layer); clearLayer(&layer);
clearModel(&model); clearModel(&model);
break; break;
} }
layerBuffer = (Layer *)realloc( layerBuffer = (Layer *)realloc(model.layers, (model.numberOfLayers + 1) * sizeof(Layer));
model.layers, (model.numberOfLayers + 1) * sizeof(Layer));
if (layerBuffer != NULL) if(layerBuffer != NULL)
model.layers = layerBuffer; model.layers = layerBuffer;
else { else
{
clearModel(&model); clearModel(&model);
break; break;
} }
@@ -149,16 +168,20 @@ NeuralNetwork loadModel(const char *path) {
return model; return model;
} }
static Matrix imageBatchToMatrixOfImageVectors(const GrayScaleImage images[], static Matrix imageBatchToMatrixOfImageVectors(const GrayScaleImage images[], unsigned int count)
unsigned int count) { {
Matrix matrix = {0, 0, NULL}; Matrix matrix = {NULL, 0, 0};
if (count > 0 && images != NULL) { if(count > 0 && images != NULL)
{
matrix = createMatrix(images[0].height * images[0].width, count); matrix = createMatrix(images[0].height * images[0].width, count);
if (matrix.buffer != NULL) { if(matrix.buffer != NULL)
for (int i = 0; i < count; i++) { {
for (int j = 0; j < images[i].width * images[i].height; j++) { for(int i = 0; i < count; i++)
{
for(int j = 0; j < images[i].width * images[i].height; j++)
{
setMatrixAt((MatrixType)images[i].buffer[j], matrix, j, i); setMatrixAt((MatrixType)images[i].buffer[j], matrix, j, i);
} }
} }
@@ -168,11 +191,14 @@ static Matrix imageBatchToMatrixOfImageVectors(const GrayScaleImage images[],
return matrix; return matrix;
} }
static Matrix forward(const NeuralNetwork model, Matrix inputBatch) { static Matrix forward(const NeuralNetwork model, Matrix inputBatch)
{
Matrix result = inputBatch; Matrix result = inputBatch;
if (result.buffer != NULL) { if(result.buffer != NULL)
for (int i = 0; i < model.numberOfLayers; i++) { {
for(int i = 0; i < model.numberOfLayers; i++)
{
Matrix biasResult; Matrix biasResult;
Matrix weightResult; Matrix weightResult;
@@ -181,7 +207,7 @@ static Matrix forward(const NeuralNetwork model, Matrix inputBatch) {
biasResult = add(model.layers[i].biases, weightResult); biasResult = add(model.layers[i].biases, weightResult);
clearMatrix(&weightResult); clearMatrix(&weightResult);
if (model.layers[i].activation != NULL) if(model.layers[i].activation != NULL)
model.layers[i].activation(&biasResult); model.layers[i].activation(&biasResult);
result = biasResult; result = biasResult;
} }
@@ -190,19 +216,23 @@ static Matrix forward(const NeuralNetwork model, Matrix inputBatch) {
return result; return result;
} }
unsigned char *argmax(const Matrix matrix) { unsigned char *argmax(const Matrix matrix)
{
unsigned char *maxIdx = NULL; unsigned char *maxIdx = NULL;
if (matrix.rows > 0 && matrix.cols > 0) { if(matrix.rows > 0 && matrix.cols > 0)
{
maxIdx = (unsigned char *)malloc(sizeof(unsigned char) * matrix.cols); maxIdx = (unsigned char *)malloc(sizeof(unsigned char) * matrix.cols);
if (maxIdx != NULL) { if(maxIdx != NULL)
for (int colIdx = 0; colIdx < matrix.cols; colIdx++) { {
for(int colIdx = 0; colIdx < matrix.cols; colIdx++)
{
maxIdx[colIdx] = 0; maxIdx[colIdx] = 0;
for (int rowIdx = 1; rowIdx < matrix.rows; rowIdx++) { for(int rowIdx = 1; rowIdx < matrix.rows; rowIdx++)
if (getMatrixAt(matrix, rowIdx, colIdx) > {
getMatrixAt(matrix, maxIdx[colIdx], colIdx)) if(getMatrixAt(matrix, rowIdx, colIdx) > getMatrixAt(matrix, maxIdx[colIdx], colIdx))
maxIdx[colIdx] = rowIdx; maxIdx[colIdx] = rowIdx;
} }
} }
@@ -212,8 +242,8 @@ unsigned char *argmax(const Matrix matrix) {
return maxIdx; return maxIdx;
} }
unsigned char *predict(const NeuralNetwork model, const GrayScaleImage images[], unsigned char *predict(const NeuralNetwork model, const GrayScaleImage images[], unsigned int numberOfImages)
unsigned int numberOfImages) { {
Matrix inputBatch = imageBatchToMatrixOfImageVectors(images, numberOfImages); Matrix inputBatch = imageBatchToMatrixOfImageVectors(images, numberOfImages);
Matrix outputBatch = forward(model, inputBatch); Matrix outputBatch = forward(model, inputBatch);
@@ -224,9 +254,12 @@ unsigned char *predict(const NeuralNetwork model, const GrayScaleImage images[],
return result; return result;
} }
void clearModel(NeuralNetwork *model) { void clearModel(NeuralNetwork *model)
if (model != NULL) { {
for (int i = 0; i < model->numberOfLayers; i++) { if(model != NULL)
{
for(int i = 0; i < model->numberOfLayers; i++)
{
clearLayer(&model->layers[i]); clearLayer(&model->layers[i]);
} }
model->layers = NULL; model->layers = NULL;