Compare commits

..
7 Commits
39 changed files with 152 additions and 300 deletions

No files matched your search

+60 -3
View File
@@ -1,4 +1,61 @@
mnist
runTests
# ---> C
# Prerequisites
*.d
# Object files
*.o
*.exe
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
Startcode/mnist
Startcode/runTests
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# IDE folders
.vscode/
.idea/
# macOS
.DS_Store
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "imageInput.h"
#define BUFFER_SIZE 100
#define FILE_HEADER_STRING "__info2_image_file_format__"
// TODO Implementieren Sie geeignete Hilfsfunktionen für das Lesen der Bildserie aus einer Datei
// TODO Vervollständigen Sie die Funktion readImages unter Benutzung Ihrer Hilfsfunktionen
GrayScaleImageSeries *readImages(const char *path)
{
GrayScaleImageSeries *series = NULL;
return series;
}
// TODO Vervollständigen Sie die Funktion clearSeries, welche eine Bildserie vollständig aus dem Speicher freigibt
void clearSeries(GrayScaleImageSeries *series)
{
}
+1 -1
View File
@@ -19,5 +19,5 @@ typedef struct
GrayScaleImageSeries *readImages(const char *path);
void clearSeries(GrayScaleImageSeries *series);
FILE *checkFile(const char *path);
#endif
@@ -70,7 +70,7 @@ void test_readImagesReturnsCorrectImageHeight(void)
GrayScaleImageSeries *series = NULL;
const unsigned short expectedHeight = 10;
const char *path = "testFile.info2";
prepareImageFile(path,8, expectedHeight, 2, 1);
prepareImageFile(path, 8, expectedHeight, 2, 1);
series = readImages(path);
TEST_ASSERT_NOT_NULL(series);
TEST_ASSERT_NOT_NULL(series->images);
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2 -6
View File
@@ -1,4 +1,3 @@
#include <stdio.h>
#include <stdlib.h>
#include "imageInput.h"
@@ -7,8 +6,6 @@
int main(int argc, char *argv[])
{
//readImages("mnist_test.info2");
const unsigned int windowWidth = 800;
const unsigned int windowHeight = 600;
@@ -32,7 +29,7 @@ int main(int argc, char *argv[])
unsigned char *predictions = NULL;
printf("Processing %u images ...\n", series->count);
predictions = predict(model, series->images, series->count);
if(predictions != NULL)
@@ -68,5 +65,4 @@ int main(int argc, char *argv[])
}
return exitCode;
}
}
View File
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+35
View File
@@ -0,0 +1,35 @@
#include <stdlib.h>
#include <string.h>
#include "matrix.h"
// TODO Matrix-Funktionen implementieren
Matrix createMatrix(unsigned int rows, unsigned int cols)
{
}
void clearMatrix(Matrix *matrix)
{
}
void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
}
MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
}
Matrix add(const Matrix matrix1, const Matrix matrix2)
{
}
Matrix multiply(const Matrix matrix1, const Matrix matrix2)
{
}
-7
View File
@@ -6,13 +6,6 @@
typedef float MatrixType;
// TODO Matrixtyp definieren
typedef struct
{
MatrixType *buffer;
unsigned int rows;
unsigned int cols;
} Matrix;
Matrix createMatrix(unsigned int rows, unsigned int cols);
+28 -1
View File
@@ -71,6 +71,32 @@ void test_addFailsOnDifferentInputDimensions(void)
TEST_ASSERT_EQUAL_UINT32(0, result.cols);
}
void test_addSupportsBroadcasting(void)
{
MatrixType buffer1[] = {1, 2, 3, 4, 5, 6};
MatrixType buffer2[] = {7, 8};
Matrix matrix1 = {.rows=2, .cols=3, .buffer=buffer1};
Matrix matrix2 = {.rows=2, .cols=1, .buffer=buffer2};
Matrix result1 = add(matrix1, matrix2);
Matrix result2 = add(matrix2, matrix1);
float expectedResults[] = {8, 9, 10, 12, 13, 14};
TEST_ASSERT_EQUAL_UINT32(matrix1.rows, result1.rows);
TEST_ASSERT_EQUAL_UINT32(matrix1.cols, result1.cols);
TEST_ASSERT_EQUAL_UINT32(matrix1.rows, result2.rows);
TEST_ASSERT_EQUAL_UINT32(matrix1.cols, result2.cols);
TEST_ASSERT_EQUAL_INT(sizeof(expectedResults)/sizeof(expectedResults[0]), result1.rows * result1.cols);
TEST_ASSERT_EQUAL_FLOAT_ARRAY(expectedResults, result1.buffer, result1.cols * result1.rows);
TEST_ASSERT_EQUAL_INT(sizeof(expectedResults)/sizeof(expectedResults[0]), result2.rows * result2.cols);
TEST_ASSERT_EQUAL_FLOAT_ARRAY(expectedResults, result2.buffer, result2.cols * result2.rows);
free(result1.buffer);
free(result2.buffer);
}
void test_multiplyReturnsCorrectResults(void)
{
MatrixType buffer1[] = {1, 2, 3, 4, 5, 6};
@@ -138,7 +164,7 @@ void test_setMatrixAtFailsOnIndicesOutOfRange(void)
Matrix matrixToTest = {.rows=2, .cols=3, .buffer=buffer};
setMatrixAt(-1, matrixToTest, 2, 3);
TEST_ASSERT_EQUAL_FLOAT_ARRAY(expectedResults, matrixToTest.buffer, matrixToTest.cols * matrixToTest.rows);
TEST_ASSERT_EQUAL_FLOAT_ARRAY(expectedResults, matrixToTest.buffer, sizeof(buffer)/sizeof(MatrixType));
}
void setUp(void) {
@@ -159,6 +185,7 @@ int main()
RUN_TEST(test_clearMatrixSetsMembersToNull);
RUN_TEST(test_addReturnsCorrectResult);
RUN_TEST(test_addFailsOnDifferentInputDimensions);
RUN_TEST(test_addSupportsBroadcasting);
RUN_TEST(test_multiplyReturnsCorrectResults);
RUN_TEST(test_multiplyFailsOnWrongInputDimensions);
RUN_TEST(test_getMatrixAtReturnsCorrectResult);
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -197,7 +197,7 @@ static Matrix forward(const NeuralNetwork model, Matrix inputBatch)
if(result.buffer != NULL)
{
for(int i = 0; i < model.numberOfLayers; i++)
for(int i = 0; i < model.numberOfLayers; i++)
{
Matrix biasResult;
Matrix weightResult;
@@ -246,7 +246,7 @@ unsigned char *predict(const NeuralNetwork model, const GrayScaleImage images[],
{
Matrix inputBatch = imageBatchToMatrixOfImageVectors(images, numberOfImages);
Matrix outputBatch = forward(model, inputBatch);
unsigned char *result = argmax(outputBatch);
clearMatrix(&outputBatch);
File renamed without changes.
@@ -8,58 +8,7 @@
static void prepareNeuralNetworkFile(const char *path, const NeuralNetwork nn)
{
// TODO : Fehlerbehandlung
// Öffne die Datei zum Schreiben im Binärmodus
FILE *file = fopen(path, "wb");
if (!file) return;
// Schreibe den Datei-Tag
const char *tag = "__info2_neural_network_file_format__";
fwrite(tag, 1, strlen(tag), file);
// Schreibe die Anzahl der Layer
if (nn.numberOfLayers == 0) {
fclose(file);
return;
}
// Schreibe die Eingabe- und Ausgabegrößen des Netzwerks
int input = nn.layers[0].weights.cols;
int output = nn.layers[0].weights.rows;
fwrite(&input, sizeof(int), 1, file);
fwrite(&output, sizeof(int), 1, file);
// Schreibe die Layer-Daten
for (int i = 0; i < nn.numberOfLayers; i++)
{
const Layer *layer = &nn.layers[i];
int out = layer->weights.rows;
int in = layer->weights.cols;
fwrite(layer->weights.buffer, sizeof(MatrixType), out * in, file);
fwrite(layer->biases.buffer, sizeof(MatrixType), out * 1, file);
if (i + 1 < nn.numberOfLayers)
{
int nextOut = nn.layers[i + 1].weights.rows;
fwrite(&nextOut, sizeof(int), 1, file);
}
}
fclose(file);
// Debuging-Ausgabe
printf("prepareNeuralNetworkFile: Datei '%s' erstellt mit %u Layer(n)\n", path, nn.numberOfLayers);
for (unsigned int i = 0; i < nn.numberOfLayers; i++) {
Layer layer = nn.layers[i];
printf("Layer %u: weights (%u x %u), biases (%u x %u)\n",
i, layer.weights.rows, layer.weights.cols, layer.biases.rows, layer.biases.cols);
}
// TODO
}
void test_loadModelReturnsCorrectNumberOfLayers(void)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
-99
View File
@@ -1,99 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "imageInput.h"
#define BUFFER_SIZE 100
#define FILE_HEADER_STRING "__info2_image_file_format__"
#define FILE_HEADER_SIZE (sizeof(FILE_HEADER_STRING)-1)
// TODO Implementieren Sie geeignete Hilfsfunktionen für das Lesen der Bildserie aus einer Datei
FILE *checkFile(const char *path)
{
FILE *datei = fopen(path,"rb");
if (datei == NULL)
{
perror("Datei konnte nicht geoeffnet werden");
return NULL;
}
char buffer[FILE_HEADER_SIZE+1];
if (fread(buffer,1,FILE_HEADER_SIZE,datei)!=FILE_HEADER_SIZE)
{
perror("Header konnte nicht eingelessen werden");
fclose(datei);
return NULL;
}
buffer[FILE_HEADER_SIZE] = '\0';
if (strcmp(buffer,FILE_HEADER_STRING)!=0)
{
printf("Falscher Dateikopf");
//printf("\n%s",buffer);
//printf("\n%s",FILE_HEADER_STRING);
//printf("\n%d",strcmp(buffer,FILE_HEADER_STRING));
fclose(datei);
return NULL;
}
return datei;
}
// TODO Vervollständigen Sie die Funktion readImages unter Benutzung Ihrer Hilfsfunktionen
GrayScaleImageSeries *readImages(const char *path)
{
FILE *datei = checkFile(path);
if (datei==NULL)
{
return NULL;
}
unsigned short image_count, width, height;
fread(&image_count,sizeof(unsigned short),1,datei);
fread(&width,sizeof(unsigned short),1,datei);
fread(&height,sizeof(unsigned short),1,datei);
//printf("%u Bilder und %u mal %u",image_count,width,height);
GrayScaleImageSeries *series = NULL;
series = malloc(sizeof(GrayScaleImageSeries));
series->count = image_count;
series->images = malloc(image_count*sizeof(GrayScaleImage));
series->labels = malloc(image_count*sizeof(unsigned char));
for(unsigned short i = 0;i<image_count;i++)
{
series->images[i].width = width;
series->images[i].height = height;
series->images[i].buffer = malloc(width*height);
}
for(unsigned short i = 0;i<image_count;i++)
{
for (unsigned int j=0;j<(width*height);j++)
{
fread(&series->images[i].buffer[j],1,1,datei);
}
fread(&series->labels[i],1,1,datei);
//printf("%d\n",series->labels[i]);
}
fclose(datei);
return series;
}
// TODO Vervollständigen Sie die Funktion clearSeries, welche eine Bildserie vollständig aus dem Speicher freigibt
void clearSeries(GrayScaleImageSeries *series)
{
if(series == NULL)
{
printf("Serie nicht vorhanden\n");
return;
}
unsigned short anzahl = series->count;
for(unsigned short i = 0;i<anzahl;i++)
{
free(series->images[i].buffer );
}
free(series->images);
free(series->labels);
free(series);
printf("Serie freigegeben\n");
return;
}
-128
View File
@@ -1,128 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include "matrix.h"
#include <stdio.h>
// Matrix erzeugen
Matrix createMatrix(unsigned int rows, unsigned int cols)
{
Matrix matrix;
matrix.buffer = NULL;
matrix.rows = 0;
matrix.cols = 0;
if (rows == 0 || cols == 0)
return matrix; // leere Matrix
matrix.buffer = (MatrixType *)malloc(rows * cols * sizeof(MatrixType));
if (!matrix.buffer)
return matrix; // Speicher konnte nicht reserviert werden
matrix.rows = rows;
matrix.cols = cols;
// Initialisiere alle Werte auf UNDEFINED_MATRIX_VALUE
for (unsigned int i = 0; i < rows * cols; i++)
matrix.buffer[i] = UNDEFINED_MATRIX_VALUE;
return matrix;
}
// Matrix Speicher freigeben
void clearMatrix(Matrix *matrix)
{
if (!matrix) return;
if (matrix->buffer)
free(matrix->buffer);
matrix->buffer = NULL;
matrix->rows = 0;
matrix->cols = 0;
}
// Wert setzen
void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
if (!matrix.buffer) return;
if (rowIdx >= matrix.rows || colIdx >= matrix.cols) return;
matrix.buffer[rowIdx * matrix.cols + colIdx] = value;
}
// Wert auslesen
MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
if (!matrix.buffer) return UNDEFINED_MATRIX_VALUE;
if (rowIdx >= matrix.rows || colIdx >= matrix.cols) return UNDEFINED_MATRIX_VALUE;
return matrix.buffer[rowIdx * matrix.cols + colIdx];
}
// Matrizen addieren
Matrix add(const Matrix m1, const Matrix m2)
{
if (!m1.buffer || !m2.buffer) return createMatrix(0,0);
// gleiche Dimension
if (m1.rows == m2.rows && m1.cols == m2.cols)
{
Matrix result = createMatrix(m1.rows, m1.cols);
if (!result.buffer) return result;
for (unsigned int r = 0; r < m1.rows; r++)
for (unsigned int c = 0; c < m1.cols; c++)
result.buffer[r * result.cols + c] = m1.buffer[r * m1.cols + c] + m2.buffer[r * m2.cols + c];
return result;
}
// Matrix2 ist ein Spaltenvektor
if (m1.rows == m2.rows && m2.cols == 1)
{
Matrix result = createMatrix(m1.rows, m1.cols);
if (!result.buffer) return result;
for (unsigned int r = 0; r < m1.rows; r++)
for (unsigned int c = 0; c < m1.cols; c++)
result.buffer[r * result.cols + c] = m1.buffer[r * m1.cols + c] + m2.buffer[r];
return result;
}
// Matrix1 ist ein Spaltenvektor
if (m1.rows == m2.rows && m1.cols == 1)
{
Matrix result = createMatrix(m2.rows, m2.cols);
if (!result.buffer) return result;
for (unsigned int r = 0; r < m2.rows; r++)
for (unsigned int c = 0; c < m2.cols; c++)
result.buffer[r * result.cols + c] = m1.buffer[r] + m2.buffer[r * m2.cols + c];
return result;
}
// passt nicht
return createMatrix(0,0);
}
// Matrizen multiplizieren
Matrix multiply(const Matrix m1, const Matrix m2)
{
if (!m1.buffer || !m2.buffer) return createMatrix(0,0);
if (m1.cols != m2.rows) return createMatrix(0,0);
Matrix result = createMatrix(m1.rows, m2.cols);
if (!result.buffer) return result;
for (unsigned int r = 0; r < m1.rows; r++)
for (unsigned int c = 0; c < m2.cols; c++)
{
MatrixType sum = 0;
for (unsigned int k = 0; k < m1.cols; k++)
sum += m1.buffer[r * m1.cols + k] * m2.buffer[k * m2.cols + c];
result.buffer[r * result.cols + c] = sum;
}
return result;
}