Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d12ecee4b
|
||
|
|
adf75b66d2
|
||
|
|
00ac1aa04a
|
||
|
|
04768db522
|
||
|
|
01a13090a5
|
||
|
|
84b65525a6 | ||
|
|
92ad1e1c31
|
||
|
|
6137e45bdb
|
||
|
|
0d7f380d87
|
||
|
|
645d471860
|
||
|
|
721f5cc2d1 | ||
|
|
79ad1285b5
|
No files matched your search
+6
-59
@@ -1,61 +1,8 @@
|
||||
# ---> 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
|
||||
runImageInputTests
|
||||
runNeuralNetworkTests
|
||||
.vscode
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "imageInput.h"
|
||||
|
||||
#define BUFFER_SIZE 100
|
||||
#define FILE_HEADER_STRING "__info2_image_file_format__"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IMG_SUCCESS = 0,
|
||||
IMG_ERR_INVALID_HEADER, // Header did not match
|
||||
IMG_ERR_READ, // Failed to read from file, maybe it's too short
|
||||
IMG_ERR, // General Error
|
||||
} ImageError;
|
||||
|
||||
static ImageError checkHeader(FILE *file);
|
||||
static ImageError readPictureParams(unsigned short *number, unsigned short *width, unsigned short *height, FILE *file);
|
||||
static ImageError readImage(size_t numPixels, GrayScalePixelType *pixelBuffer, unsigned char *label, FILE *file);
|
||||
static ImageError parseImageFile(FILE *file, GrayScaleImageSeries *series);
|
||||
|
||||
GrayScaleImageSeries *readImages(const char *path)
|
||||
{
|
||||
// It's very important to call calloc here because otherwise clearSeries() might try to free random memory
|
||||
GrayScaleImageSeries *series = calloc(1, sizeof(GrayScaleImageSeries));
|
||||
if (series == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FILE *file = fopen(path, "rb");
|
||||
// If fopen() failed
|
||||
if (file == NULL)
|
||||
{
|
||||
clearSeries(series);
|
||||
series = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Try to parse the whole file. If anything fails memory is freed
|
||||
if (parseImageFile(file, series))
|
||||
{
|
||||
clearSeries(series);
|
||||
series = NULL; // Return NULL after the file is properly closed
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return series;
|
||||
}
|
||||
|
||||
static ImageError parseImageFile(FILE *file, GrayScaleImageSeries *series)
|
||||
{
|
||||
if (checkHeader(file))
|
||||
{
|
||||
return IMG_ERR; // header check failed
|
||||
}
|
||||
|
||||
unsigned short imgCNT, width, height;
|
||||
if (readPictureParams(&imgCNT, &width, &height, file))
|
||||
{
|
||||
return IMG_ERR; // read failed
|
||||
}
|
||||
size_t pixels = width * height;
|
||||
|
||||
// The images contain more pointers, definitely use calloc here
|
||||
series->images = calloc(imgCNT, sizeof(GrayScaleImage));
|
||||
if (series->images == NULL)
|
||||
{
|
||||
return IMG_ERR;
|
||||
}
|
||||
|
||||
series->labels = malloc(imgCNT * sizeof(unsigned char));
|
||||
if (series->labels == NULL)
|
||||
{
|
||||
return IMG_ERR;
|
||||
}
|
||||
|
||||
series->count = imgCNT;
|
||||
// Read every image and it's label
|
||||
for (size_t imageIdx = 0; imageIdx < imgCNT; imageIdx++)
|
||||
{
|
||||
GrayScaleImage *curImage = &series->images[imageIdx];
|
||||
|
||||
curImage->buffer = malloc(sizeof(GrayScalePixelType) * pixels);
|
||||
if (curImage->buffer == NULL)
|
||||
{
|
||||
return IMG_ERR;
|
||||
}
|
||||
|
||||
curImage->width = width;
|
||||
curImage->height = height;
|
||||
|
||||
if (readImage(pixels, curImage->buffer, &series->labels[imageIdx], file))
|
||||
{
|
||||
return IMG_ERR;
|
||||
}
|
||||
}
|
||||
return IMG_SUCCESS;
|
||||
}
|
||||
|
||||
static ImageError checkHeader(FILE *file)
|
||||
{
|
||||
size_t len = strlen(FILE_HEADER_STRING);
|
||||
char headerBuf[len + 1];
|
||||
size_t charsRead = fread(headerBuf, 1, len, file);
|
||||
// Check if the file is to short
|
||||
if (charsRead < len)
|
||||
{
|
||||
return IMG_ERR_READ;
|
||||
}
|
||||
headerBuf[len] = '\0'; // Terminate string
|
||||
return strcmp(headerBuf, FILE_HEADER_STRING) == 0 ? IMG_SUCCESS : IMG_ERR_INVALID_HEADER;
|
||||
}
|
||||
|
||||
static ImageError readPictureParams(unsigned short *number, unsigned short *width, unsigned short *height, FILE *file)
|
||||
{
|
||||
// number of images
|
||||
if (1 != fread(number, sizeof(unsigned short), 1, file))
|
||||
{
|
||||
return IMG_ERR_READ;
|
||||
}
|
||||
|
||||
// image width
|
||||
if (1 != fread(width, sizeof(unsigned short), 1, file))
|
||||
{
|
||||
return IMG_ERR_READ;
|
||||
}
|
||||
|
||||
// height
|
||||
if (1 != fread(height, sizeof(unsigned short), 1, file))
|
||||
{
|
||||
return IMG_ERR_READ;
|
||||
}
|
||||
|
||||
return IMG_SUCCESS;
|
||||
}
|
||||
|
||||
// Read 1 image and it's label
|
||||
static ImageError readImage(size_t numPixels, GrayScalePixelType *pixelBuffer, unsigned char *label, FILE *file)
|
||||
{
|
||||
if (numPixels > fread(pixelBuffer, sizeof(GrayScalePixelType), numPixels, file))
|
||||
{
|
||||
return IMG_ERR_READ;
|
||||
}
|
||||
|
||||
if (1 != fread(label, sizeof(unsigned char), 1, file))
|
||||
{
|
||||
return IMG_ERR_READ;
|
||||
}
|
||||
|
||||
return IMG_SUCCESS;
|
||||
}
|
||||
|
||||
// Frees memory for each image buffer, image, label and finally series
|
||||
void clearSeries(GrayScaleImageSeries *series)
|
||||
{
|
||||
if (series)
|
||||
{
|
||||
|
||||
int seriesLen = series->count;
|
||||
for (size_t imageIdx = 0; imageIdx < seriesLen; imageIdx++)
|
||||
{
|
||||
free(series->images[imageIdx].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.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,152 @@
|
||||
#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);
|
||||
}
|
||||
|
||||
if (matrix1.cols != matrix2.cols)
|
||||
{
|
||||
if (matrix1.rows != matrix2.rows)
|
||||
{
|
||||
clearMatrix(&resMat);
|
||||
return resMat;
|
||||
}
|
||||
else 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
clearMatrix(&resMat);
|
||||
return resMat;
|
||||
}
|
||||
}
|
||||
|
||||
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, n), resMat, m, n);
|
||||
}
|
||||
}
|
||||
|
||||
return resMat;
|
||||
}
|
||||
|
||||
Matrix multiply(const Matrix A, const Matrix B)
|
||||
{
|
||||
if (A.cols != B.rows || A.buffer == NULL || B.buffer == NULL)
|
||||
{
|
||||
return createMatrix(0, 0);
|
||||
}
|
||||
|
||||
int rows = A.rows, cols = B.cols;
|
||||
Matrix C = createMatrix(rows, cols);
|
||||
|
||||
if (C.buffer == NULL)
|
||||
{
|
||||
return createMatrix(0, 0);
|
||||
}
|
||||
|
||||
// M = Rows, K = Common Dim, N = Cols
|
||||
size_t M = A.rows, K = A.cols, N = B.cols;
|
||||
|
||||
for (size_t i = 0; i < M; i++)
|
||||
{
|
||||
for (size_t k = 0; k < K; k++)
|
||||
|
||||
{
|
||||
MatrixType valA = A.buffer[i * K + k];
|
||||
for (size_t j = 0; j < N; j++)
|
||||
{
|
||||
// C[i, j] += A[i, k] * B[k, j];
|
||||
// M x N, M x K, K x N
|
||||
C.buffer[i * N + j] += valA * B.buffer[k * N + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return C;
|
||||
}
|
||||
@@ -5,8 +5,14 @@
|
||||
|
||||
typedef float MatrixType;
|
||||
|
||||
// TODO Matrixtyp definieren
|
||||
// Matrixtyp
|
||||
typedef struct Matrix
|
||||
{
|
||||
size_t rows;
|
||||
size_t cols;
|
||||
MatrixType *buffer;
|
||||
|
||||
} Matrix;
|
||||
|
||||
Matrix createMatrix(unsigned int rows, unsigned int cols);
|
||||
void clearMatrix(Matrix *matrix);
|
||||
@@ -15,5 +21,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.
@@ -6,9 +6,30 @@
|
||||
#include "neuralNetwork.h"
|
||||
|
||||
|
||||
static void erzeugeMatrix(FILE *file, const Matrix *m)
|
||||
{
|
||||
fwrite(&m->rows, sizeof(int), 1, file);
|
||||
fwrite(&m->cols, sizeof(int), 1, file);
|
||||
fwrite(m->buffer, sizeof(MatrixType), m->rows * m->cols, file);
|
||||
}
|
||||
|
||||
static void prepareNeuralNetworkFile(const char *path, const NeuralNetwork nn)
|
||||
{
|
||||
// TODO
|
||||
FILE *file = fopen(path, "wb");
|
||||
if (!file)
|
||||
return;
|
||||
|
||||
const char *header = "__info2_neural_network_file_format__";
|
||||
fwrite(header, sizeof(char), strlen(header), file);
|
||||
fwrite(&nn.numberOfLayers, sizeof(int), 1, file);
|
||||
|
||||
for (int i = 0; i < nn.numberOfLayers; i++)
|
||||
{
|
||||
erzeugeMatrix(file, &nn.layers[i].weights);
|
||||
erzeugeMatrix(file, &nn.layers[i].biases);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
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