Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e17eaf4542 | ||
|
|
6c26652744 | ||
|
|
5d8dbd548b | ||
|
|
225dbac29f | ||
|
|
c476386ff3 | ||
|
|
a031bb0b7a | ||
|
|
545acd0356 | ||
|
|
934ba2d06e | ||
|
|
8c2ed38abf | ||
|
|
86359bb37f | ||
|
|
807bbbd375 | ||
|
|
8ac27e20c5 | ||
|
|
e3349f7f68 | ||
|
|
9817c87e7a | ||
|
|
8c98197327 | ||
|
|
8368439db1 | ||
|
|
c1db7c612f | ||
|
|
97bf884e59 |
No files matched your search
+3
-60
@@ -1,61 +1,4 @@
|
||||
# ---> C
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Object files
|
||||
mnist
|
||||
runTests
|
||||
*.o
|
||||
*.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
|
||||
*.exe
|
||||
Binary file not shown.
@@ -1,22 +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__"
|
||||
|
||||
// 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,35 +0,0 @@
|
||||
#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)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
#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;
|
||||
|
||||
}
|
||||
@@ -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.
@@ -1,3 +1,4 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "imageInput.h"
|
||||
@@ -6,6 +7,8 @@
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
//readImages("mnist_test.info2");
|
||||
|
||||
const unsigned int windowWidth = 800;
|
||||
const unsigned int windowHeight = 600;
|
||||
|
||||
@@ -29,7 +32,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)
|
||||
@@ -65,4 +68,5 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,128 @@
|
||||
#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;
|
||||
}
|
||||
@@ -6,6 +6,13 @@
|
||||
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);
|
||||
@@ -71,32 +71,6 @@ 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};
|
||||
@@ -164,7 +138,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, sizeof(buffer)/sizeof(MatrixType));
|
||||
TEST_ASSERT_EQUAL_FLOAT_ARRAY(expectedResults, matrixToTest.buffer, matrixToTest.cols * matrixToTest.rows);
|
||||
}
|
||||
|
||||
void setUp(void) {
|
||||
@@ -185,7 +159,6 @@ 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,7 +8,58 @@
|
||||
|
||||
static void prepareNeuralNetworkFile(const char *path, const NeuralNetwork nn)
|
||||
{
|
||||
// TODO
|
||||
// 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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.
Reference in new issue
Block a user