15 Commits
39 changed files with 314 additions and 120 deletions

No files matched your search

+3 -59
View File
@@ -1,61 +1,5 @@
# ---> 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
runMatrixTests
-22
View File
@@ -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)
{
}
-35
View File
@@ -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)
{
}
+112
View File
@@ -0,0 +1,112 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "imageInput.h"
#define BUFFER_SIZE 100
#define FILE_HEADER_STRING "__info2_image_file_format__"
//Datei öffnen, Header, Anzahl, Höhe und Breite lesen, geöffnete Datei zurückgeben
static FILE* openAndReadShort (const char *path, unsigned short *count, unsigned short *width, unsigned short *height) {
FILE *file = fopen(path, "rb");
if (!file) {
return NULL;
}
size_t headerLength = strlen(FILE_HEADER_STRING);
char *header = malloc (headerLength + 1);
if(!header) {
return NULL;
}
if (fread(header, sizeof(char), headerLength, file) != headerLength) {
free (header);
return NULL;
}
header[headerLength] = '\0';
if (strcmp (header, FILE_HEADER_STRING) != 0) {
free(header);
return NULL;
}
free (header);
fread(count, sizeof(unsigned short), 1, file);
fread(width, sizeof(unsigned short), 1, file);
fread(height, sizeof(unsigned short), 1, file);
return file;
}
//Speicher anlegen und Pixel eines Bildes einlesen
static GrayScaleImage* readPixles (FILE *file, unsigned short *width, unsigned short *height) {
GrayScaleImage *image = malloc (sizeof(GrayScaleImage));
image->width = *width;
image->height = *height;
image->buffer = malloc ((*width) * (*height) * sizeof(GrayScalePixelType));
if (!image->buffer) {
free(image);
return NULL;
}
for (unsigned int i = 0; i < (*width) * (*height); i++) {
unsigned char pixel;
if (fread(&pixel, sizeof(unsigned char), 1, file) != 1) {
free(image->buffer);
free(image);
return NULL;
}
image->buffer[i] = pixel;
}
return image;
}
//Ausführen von openAndReadShort, Anlegen des Speichers für Bilderserie, readPixles wird für jedes Bild ausgeführt
//Nach jedem Bild wird das zugehörige Label gelesen, bei sämtlichen Fehlern wird NULL zurückgegeben und Speicher durch clearSeries bereinigt
GrayScaleImageSeries *readImages(const char *path)
{
unsigned short count = 0, width = 0, height = 0;
FILE *file = openAndReadShort(path, &count, &width, &height);
if (file == 0) {
return NULL;
}
GrayScaleImageSeries *series = malloc(sizeof(GrayScaleImageSeries));
if (!series) {
fclose(file);
return NULL;
}
series->count = count;
series->images = malloc(count * sizeof(GrayScaleImage));
series->labels = malloc(count* sizeof(unsigned char));
for (unsigned int i = 0; i < series->count; i++) {
GrayScaleImage *image = readPixles(file, &width, &height);
series->images[i] = *image;
free(image);
if (fread(&series->labels[i], sizeof(unsigned char), 1, file) != 1) {
clearSeries(series);
fclose(file);
return NULL;
}
}
fclose(file);
return series;
}
//Bereinigt den Speicher
void clearSeries(GrayScaleImageSeries *series)
{
for (unsigned int i = 0; i < series->count; i++) {
free(series->images[i].buffer);
}
free(series->images);
free(series->labels);
free(series);
}
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.
View File
File renamed without changes.
View File
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+154
View File
@@ -0,0 +1,154 @@
#include <stdlib.h>
#include <string.h>
#include "matrix.h"
#include <stdio.h>
Matrix createMatrix(unsigned int rows, unsigned int cols)
{
Matrix mat = {.rows = rows, .cols = cols};
// If one dimension is 0, return both dimensions as 0 and don't init the array/buffer.
if (rows == 0 || cols == 0)
{
mat.rows = 0;
mat.cols = 0;
return mat;
}
// allocate contiguous and 0 initialized memory
mat.buffer = calloc(rows * cols, sizeof(MatrixType));
// check if calloc failed
if (mat.buffer == NULL)
{
clearMatrix(&mat);
perror("could not allocate memory");
}
return mat;
}
// reduce the dimensions to (0, 0) and free the memory
void clearMatrix(Matrix *matrix)
{
free(matrix->buffer);
matrix->buffer = NULL;
matrix->cols = 0;
matrix->rows = 0;
}
void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
// do nothing if idx is not in array or matrix buffer is NULL
if (!(rowIdx < matrix.rows) || !(colIdx < matrix.cols) || matrix.buffer == NULL)
{
return;
}
matrix.buffer[rowIdx * matrix.cols + colIdx] = value;
}
MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
// return UNDEFINED_MATRIX_VALUE if idx is not in array or matrix buffer is NULL
if (!(rowIdx < matrix.rows) || !(colIdx < matrix.cols) || matrix.buffer == NULL)
{
return UNDEFINED_MATRIX_VALUE;
}
return matrix.buffer[rowIdx * matrix.cols + colIdx];
};
Matrix add(const Matrix matrix1, const Matrix matrix2)
{
Matrix resMat = (matrix1.cols > matrix2.cols) ? createMatrix(matrix1.rows, matrix1.cols) : createMatrix(matrix2.rows, matrix2.cols);
if (resMat.buffer == NULL)
{
return createMatrix(0, 0);
}
// matrices not compatible
if (matrix1.rows != matrix2.rows)
{
clearMatrix(&resMat);
return resMat;
}
// check if broadcasting is possible
if (matrix1.cols != matrix2.cols)
{
// matrix1 is a vector
if (matrix1.cols == 1)
{
// broadcast vector
for (size_t m = 0; m < matrix2.rows; m++)
{
for (size_t n = 0; n < matrix2.cols; n++)
{
setMatrixAt(getMatrixAt(matrix2, m, n) + getMatrixAt(matrix1, m, 0), resMat, m, n);
}
}
return resMat;
}
// matrix2 is a vector
else if (matrix2.cols == 1)
{
// broadcast vector
for (size_t m = 0; m < matrix1.rows; m++)
{
for (size_t n = 0; n < matrix1.cols; n++)
{
setMatrixAt(getMatrixAt(matrix1, m, n) + getMatrixAt(matrix2, m, 0), resMat, m, n);
}
}
return resMat;
}
// addition not possible
else
{
clearMatrix(&resMat);
return resMat;
}
}
for (size_t m = 0; m < matrix1.rows; m++)
{
for (size_t n = 0; n < matrix1.cols; n++)
{
// this is unnecessarily complicated because at this point we already know that the matrices are compatible
setMatrixAt(getMatrixAt(matrix1, m, n) + getMatrixAt(matrix2, m, n), resMat, m, n);
}
}
return resMat;
}
Matrix multiply(const Matrix matrix1, const Matrix matrix2)
{
if (matrix1.cols != matrix2.rows || matrix1.buffer == NULL || matrix2.buffer == NULL)
{
return createMatrix(0, 0);
}
int rows = matrix1.rows, cols = matrix2.cols;
Matrix resMat = createMatrix(rows, cols);
if (resMat.buffer == NULL)
{
return createMatrix(0, 0);
}
for (size_t rowIdx = 0; rowIdx < rows; rowIdx++)
{
for (size_t colIdx = 0; colIdx < cols; colIdx++)
{
int curCellVal = 0;
for (size_t k = 0; k < matrix1.cols; k++)
{
curCellVal += getMatrixAt(matrix1, rowIdx, k) * getMatrixAt(matrix2, k, colIdx);
}
setMatrixAt(curCellVal, resMat, rowIdx, colIdx);
}
}
return resMat;
}
+7 -3
View File
@@ -5,8 +5,13 @@
typedef float MatrixType;
// TODO Matrixtyp definieren
// Matrixtyp
typedef struct Matrix
{
MatrixType *buffer;
size_t rows;
size_t cols;
} Matrix;
Matrix createMatrix(unsigned int rows, unsigned int cols);
void clearMatrix(Matrix *matrix);
@@ -15,5 +20,4 @@ MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int co
Matrix add(const Matrix matrix1, const Matrix matrix2);
Matrix multiply(const Matrix matrix1, const Matrix matrix2);
#endif
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.
@@ -5,10 +5,46 @@
#include "unity.h"
#include "neuralNetwork.h"
static void writeLayer(FILE *file, const Matrix weights, const Matrix biases, unsigned int inputDim)
{
unsigned int outputDim = (unsigned int)weights.rows;
fwrite(&outputDim, sizeof(unsigned int), 1, file);
if (weights.buffer != NULL)
fwrite(weights.buffer, sizeof(MatrixType), outputDim * inputDim, file);
if (biases.buffer != NULL)
fwrite(biases.buffer, sizeof(MatrixType), outputDim, file);
}
static void prepareNeuralNetworkFile(const char *path, const NeuralNetwork nn)
{
// TODO
FILE *file = fopen(path, "wb");
if (!file) return;
const char tag[] = "__info2_neural_network_file_format__";
fwrite(tag, sizeof(char), strlen(tag), file);
if (nn.numberOfLayers == 0)
{
unsigned int zero = 0;
fwrite(&zero, sizeof(unsigned int), 1, file);
fclose(file);
return;
}
unsigned int inputDim = (unsigned int)nn.layers[0].weights.cols;
fwrite(&inputDim, sizeof(unsigned int), 1, file);
for (int i = 0; i < nn.numberOfLayers; i++)
{
writeLayer(file, nn.layers[i].weights, nn.layers[i].biases, inputDim);
inputDim = (unsigned int)nn.layers[i].weights.rows;
}
unsigned int zero = 0;
fwrite(&zero, sizeof(unsigned int), 1, file);
fclose(file);
}
void test_loadModelReturnsCorrectNumberOfLayers(void)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
View File
@@ -0,0 +1 @@
some_tag
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.