19 Commits
Author SHA1 Message Date
Kristin 9606b5a03e kp 2025-11-25 10:48:24 +01:00
Max-R efa260ccbe 0 fehler bei add abfangen 2025-11-25 10:15:52 +01:00
Max-R 801abc1b66 Merge branch 'main' of https://git.efi.th-nuernberg.de/gitea/kachelto100370/info2Praktikum-NeuronalesNetz 2025-11-25 10:00:31 +01:00
Max-R 8e518a3bdd Merge branch 'RMax' matrix.c voll 2025-11-25 09:58:03 +01:00
Max-R 0baf646832 add files to gitignore 2025-11-25 09:57:28 +01:00
kachelto100370 98dd789680 input image things 2025-11-25 09:10:54 +01:00
Max-R 21d9b5c01d so finde ich es schöner... 2025-11-22 15:29:32 +01:00
Max-R e7930c7eb0 kommentaare update 2025-11-22 15:23:50 +01:00
Max-R 5075c34983 kommentaare update 2025-11-22 15:19:41 +01:00
Max-R b187a13b17 multiply, besteht MatrixTests 2025-11-22 15:17:12 +01:00
Max-R 4e2ee7078a alles bis uf multiply 2025-11-22 12:41:46 +01:00
Max-R 35a598a276 broadcasting 2025-11-22 11:54:32 +01:00
Max-R e1ea9f33cd create matrix mit null 2025-11-22 10:55:27 +01:00
Max-R 0886489d49 Matrix noch ohne broadcasting 2025-11-20 16:03:44 +01:00
Max-R f9c46a6784 Merge branch 'main' of https://git.efi.th-nuernberg.de/gitea/kachelto100370/info2Praktikum-NeuronalesNetz into RMax 2025-11-20 14:50:33 +01:00
Max-R 5fcc3cd042 Merge branch 'main' of https://git.efi.th-nuernberg.de/gitea/kachelto100370/info2Praktikum-NeuronalesNetz into RMax 2025-11-18 10:51:55 +01:00
Max-R 3de79e2b83 clearMatrix füllen 2025-11-11 11:05:28 +01:00
Max-R ec54bdd951 create Matrix gefüllt, test unit 2025-11-11 10:36:11 +01:00
Max-R 0e3f03a03d Matrix definiert 2025-11-11 09:20:40 +01:00
7 changed files with 473 additions and 269 deletions
+3
View File
@@ -2,3 +2,6 @@ mnist
runTests runTests
*.o *.o
*.exe *.exe
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/settings.json
+18
View File
@@ -0,0 +1,18 @@
{
"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
@@ -0,0 +1,24 @@
{
"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
}
]
}
]
}
+57 -1
View File
@@ -1,3 +1,59 @@
{ {
"makefile.configureOnOpen": false "C_Cpp_Runner.cCompilerPath": "gcc",
"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
} }
+6 -8
View File
@@ -57,12 +57,10 @@ imageInputTests: imageInput.o imageInputTests.c $(unityfolder)/unity.c
# -------------------------- # --------------------------
# Clean # Clean
# -------------------------- # --------------------------
#clean:
#ifeq ($(OS),Windows_NT)
# del /f *.o *.exe
#else
# rm -f *.o mnist runMatrixTests runNeuralNetworkTests runImageInputTests
#endif
# clean für windows
clean: clean:
rm -f *.o *.exe ifeq ($(OS),Windows_NT)
del /f *.o *.exe
else
rm -f *.o mnist runMatrixTests runNeuralNetworkTests runImageInputTests
endif
+150 -12
View File
@@ -8,6 +8,10 @@
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
@@ -24,8 +28,12 @@ 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) {
matrix.buffer[rowIdx * matrix.cols + colIdx] = if (rowIdx >= matrix.rows || colIdx >= matrix.cols) {
value; // rowIdx * matrix.cols -> Beginn der Zeile colIdx ->Spalte // Speichergröße nicht überschreiten
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,
@@ -40,29 +48,159 @@ 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;
if(colsEqu && rowsEqu) const int rowsEqual = (matrix1.rows==matrix2.rows) ? 1: 0;
{ 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);
for(int i = 0; i < rows1; i++) if (result.buffer == NULL){
{ 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; return result;
} }
} }
Matrix multiply(const Matrix matrix1, const Matrix matrix2) { return matrix1; }
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;
}
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;
}
}
+61 -94
View File
@@ -1,35 +1,29 @@
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "neuralNetwork.h" #include "neuralNetwork.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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 colIdx = 0; colIdx < matrix->cols; colIdx++) for (int rowIdx = 0; rowIdx < matrix->rows; rowIdx++) {
{
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++) {
for(int rowIdx = 0; rowIdx < matrix->rows; rowIdx++) MatrixType normalizedValue =
{ getMatrixAt(*matrix, rowIdx, colIdx) / colSums[colIdx];
MatrixType normalizedValue = getMatrixAt(*matrix, rowIdx, colIdx) / colSums[colIdx];
setMatrixAt(normalizedValue, *matrix, rowIdx, colIdx); setMatrixAt(normalizedValue, *matrix, rowIdx, colIdx);
} }
} }
@@ -38,16 +32,13 @@ 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};
@@ -61,8 +52,7 @@ static int checkFileHeader(FILE *file)
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)
@@ -71,21 +61,20 @@ static unsigned int readDimension(FILE *file)
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) !=
if(fread(matrix.buffer, sizeof(MatrixType), rows*cols, file) != rows*cols) rows * cols)
clearMatrix(&matrix); clearMatrix(&matrix);
} }
return matrix; return matrix;
} }
static Layer readLayer(FILE *file, unsigned int inputDimension, unsigned int outputDimension) static Layer readLayer(FILE *file, unsigned int inputDimension,
{ 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);
@@ -93,25 +82,22 @@ static Layer readLayer(FILE *file, unsigned int inputDimension, unsigned int out
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 ||
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.biases.buffer == NULL || layer.weights.rows == 0 ||
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;
} }
@@ -119,36 +105,31 @@ static void assignActivations(NeuralNetwork model)
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(model.layers, (model.numberOfLayers + 1) * sizeof(Layer)); layerBuffer = (Layer *)realloc(
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;
} }
@@ -168,20 +149,16 @@ NeuralNetwork loadModel(const char *path)
return model; return model;
} }
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) {
{
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 i = 0; i < count; i++) for (int j = 0; j < images[i].width * images[i].height; j++) {
{
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);
} }
} }
@@ -191,14 +168,11 @@ static Matrix imageBatchToMatrixOfImageVectors(const GrayScaleImage images[], un
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;
@@ -216,23 +190,19 @@ 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) >
if(getMatrixAt(matrix, rowIdx, colIdx) > getMatrixAt(matrix, maxIdx[colIdx], colIdx)) getMatrixAt(matrix, maxIdx[colIdx], colIdx))
maxIdx[colIdx] = rowIdx; maxIdx[colIdx] = rowIdx;
} }
} }
@@ -242,8 +212,8 @@ unsigned char *argmax(const Matrix matrix)
return maxIdx; return maxIdx;
} }
unsigned char *predict(const NeuralNetwork model, const GrayScaleImage images[], unsigned int numberOfImages) unsigned char *predict(const NeuralNetwork model, const GrayScaleImage images[],
{ unsigned int numberOfImages) {
Matrix inputBatch = imageBatchToMatrixOfImageVectors(images, numberOfImages); Matrix inputBatch = imageBatchToMatrixOfImageVectors(images, numberOfImages);
Matrix outputBatch = forward(model, inputBatch); Matrix outputBatch = forward(model, inputBatch);
@@ -254,12 +224,9 @@ unsigned char *predict(const NeuralNetwork model, const GrayScaleImage images[],
return result; return result;
} }
void clearModel(NeuralNetwork *model) void clearModel(NeuralNetwork *model) {
{ if (model != NULL) {
if(model != NULL) for (int i = 0; i < model->numberOfLayers; i++) {
{
for(int i = 0; i < model->numberOfLayers; i++)
{
clearLayer(&model->layers[i]); clearLayer(&model->layers[i]);
} }
model->layers = NULL; model->layers = NULL;