generated from freudenreichan/info2Praktikum-NeuronalesNetz
Merge branch 'main' of https://git.efi.th-nuernberg.de/gitea/kohlerma104069/NeuronalesNetz_TMN
This commit is contained in:
commit
24d13aa781
2 files changed
+152
-13
No files matched your search
@@ -8,15 +8,93 @@
|
|||||||
|
|
||||||
// TODO Implementieren Sie geeignete Hilfsfunktionen für das Lesen der Bildserie aus einer Datei
|
// TODO Implementieren Sie geeignete Hilfsfunktionen für das Lesen der Bildserie aus einer Datei
|
||||||
|
|
||||||
|
static GrayScaleImage *readIndividualImage(unsigned int width, unsigned int height, FILE *file){
|
||||||
|
|
||||||
|
char *buf = calloc(width * height, sizeof(char));
|
||||||
|
if(!buf){
|
||||||
|
fprintf(stderr, "calloc failed!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(fread(buf, sizeof(char), width * height,file) != (width* height)){
|
||||||
|
fprintf(stderr, "imageline not in the rigth format!\n");
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GrayScaleImage *gimage = calloc(sizeof(GrayScaleImage, 1));
|
||||||
|
if(gimage == NULL){
|
||||||
|
fprintf(stderr, "calloc failed!\n");
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gimage->buffer = buf;
|
||||||
|
gimage->width = width;
|
||||||
|
gimage->height = height;
|
||||||
|
|
||||||
|
return gimage;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO Vervollständigen Sie die Funktion readImages unter Benutzung Ihrer Hilfsfunktionen
|
// TODO Vervollständigen Sie die Funktion readImages unter Benutzung Ihrer Hilfsfunktionen
|
||||||
GrayScaleImageSeries *readImages(const char *path)
|
GrayScaleImageSeries *readImages(const char *path)
|
||||||
{
|
{
|
||||||
GrayScaleImageSeries *series = NULL;
|
GrayScaleImageSeries *series = NULL;
|
||||||
|
|
||||||
|
series = calloc(1, sizeof(GrayScaleImageSeries));
|
||||||
|
if(series == NULL){
|
||||||
|
fprintf(stderr, "Couldn't allocate enough space!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *file = fopen(path, "rb");
|
||||||
|
if(file == NULL){
|
||||||
|
fprintf(stderr, "%s could not be opened!\n", path);
|
||||||
|
clearSeries(series);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Schaue ob die erste Zeile der richtige Header ist.
|
||||||
|
char buffer[32];
|
||||||
|
size_t bytes = fread(buffer, sizeof(char), strlen(FILE_HEADER_STRING), file);
|
||||||
|
if(!strncmp(buffer, FILE_HEADER_STRING, strlen(FILE_HEADER_STRING))){
|
||||||
|
fprintf(stderr, "__info2_image_file_format__ not found!\n");
|
||||||
|
clearSeries(series);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bytes = fread(buffer, sizeof(short), 3, file) != (3*szieof(short))){
|
||||||
|
fprintf(stderr, "Couldn't read number of images/sizes of Images!\n");
|
||||||
|
clearSeries(series);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
series->count = (short)buffer[0];
|
||||||
|
unsigned int width = (short)buffer[1];
|
||||||
|
unsigned int height = (short)buffer[2];
|
||||||
|
|
||||||
|
series->labels = calloc(count, sizeof(char));
|
||||||
|
if(series->labels == NULL){
|
||||||
|
fprintf(stderr, "calloc failed!\n");
|
||||||
|
clearSeries(series);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++){
|
||||||
|
if(series->images[i] = readIndividualImage(width, heigth, file) == NULL){
|
||||||
|
clearSeries(series);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fread(series->labels[i], sizeof(char), 1, file);
|
||||||
|
}
|
||||||
|
|
||||||
return series;
|
return series;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Vervollständigen Sie die Funktion clearSeries, welche eine Bildserie vollständig aus dem Speicher freigibt
|
// TODO Vervollständigen Sie die Funktion clearSeries, welche eine Bildserie vollständig aus dem Speicher freigibt
|
||||||
void clearSeries(GrayScaleImageSeries *series)
|
void clearSeries(GrayScaleImageSeries *series)
|
||||||
{
|
{
|
||||||
|
for(int i = 0; i < series->count; i++){
|
||||||
|
free(series->GrayScaleImage[i]);
|
||||||
|
}
|
||||||
|
free(series);
|
||||||
}
|
}
|
||||||
@@ -4,13 +4,55 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "neuralNetwork.h"
|
#include "neuralNetwork.h"
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
static void prepareNeuralNetworkFile(const char *path, const NeuralNetwork nn)
|
*/
|
||||||
|
// TODO Nico
|
||||||
|
static void prepareNeuralNetworkFile(const char *path, const NeuralNetwork nn) //Exklusive Funktion ohne Rückgabewert mit Übergabewerten "path" für den Dateinamen und "nn" für das neuronale Netz dessen Daten abgespeichert werden soll
|
||||||
{
|
{
|
||||||
// TODO
|
/*---Datei zum Schreiben im Binärmodus öffnen---*/
|
||||||
}
|
FILE *file = fopen(path, "wb"); //Öffnet die Datei "path" als write Binary
|
||||||
|
if(file == NULL) //Wenn Datei nicht geöffnet werden kann, bringe einen Fehler und breche das Programm ab
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---Indifikationstag an den Anfang schreiben---*/
|
||||||
|
const char *fileTag = "info2_neural_network_file_format"; //Der Text der laut Angabe am Anfang der Datei stehen muss
|
||||||
|
fwrite(fileTag, sizeof(char), strlen(fileTag), file); //Schreibbefehl mit Parametern (Vorgegebener Text soll geschrieben werden (Adresse), Größe eines Buchstaben, Länge des Textes, Zielort "file")
|
||||||
|
|
||||||
|
/*---Anzahl der Layer speichern---*/
|
||||||
|
fwrite(&nn.numberOfLayers, sizeof(int), 1, file); //Schreibbefehl mit Parametern (Die Adresse von "nn.numberOfLayers" soll geschrieben werden, eine ganze Zahl als "int" wird abgespeichert, es wird genau eine solche Zahl geschrieben, Zielort "file")
|
||||||
|
|
||||||
|
/*---Schleife für jeden Layer um Gewichte und Bias zu speichern---*/
|
||||||
|
for(int i = 0; i < nn.numberOfLayers; i++) //Schleife von 0 bis Anzahl der Layer
|
||||||
|
{
|
||||||
|
Layer layer = nn.layers[i]; //Benutzt aktuellen Layer mit Nummer "i" und benutzt Hilfsvariable "layer"
|
||||||
|
|
||||||
|
/*---Weights speichern---*/
|
||||||
|
fwrite(&layer.weights.rows, sizeof(int), 1, file); //Schreibbefehl mit Parametern mit (Anzahl Zeilen Weights (Adresse), eine ganze Zahl als "int" abspeichern, es wird genau eine solche Zahl gespeichert, Zielort "file") --> Speichert ab, wie viele Zeilen Gewichts-Tabelle hat
|
||||||
|
fwrite(&layer.weights.cols, sizeof(int), 1, file); //Schreibbefehl mit Parametern mit (Anzahl Spalten Weights (Adresse), eine ganze Zahl als "int" abspeichern, es wird genau eine solche Zahl gespeichert, Zielort "file") --> Speichert ab, wie viele Spalten Gewichts-Tabelle hat
|
||||||
|
|
||||||
|
int weightCount = layer.weights.rows * layer.weights.cols; //Berechnet die Gesamtzahl der Zahlen in der Weight Tabelle
|
||||||
|
|
||||||
|
fwrite(layer.weights.buffer, sizeof(MatrixType), weightCount, file); //Schreibbefehl mit Parametern mit (Weight Buffer (Adresse), eine ganze Zahl in "MatrixType" abspeichern, es wird der zuvor berechnete Wert gespeichert, Zielort "file") --> Speichert alle eigentlichen Zahlenwerte der Weights auf einmal in die Datei. Buffer ist bereits intern ein Zeiger, deswegen kein "&"
|
||||||
|
|
||||||
|
|
||||||
|
/*---Bias speichern---*/
|
||||||
|
fwrite(&layer.biases.rows, sizeof(int), 1, file); //Schreibbefehl mit Parametern mit (Anzahl Zeilen Bias (Adresse), eine ganze Zahl als "int" abspeichern, es wird genau eine solche Zahl gespeichert, Zielort "file") --> Speichert ab, wie viele Zeilen Bias-Tabelle hat
|
||||||
|
fwrite(&layer.biases.cols, sizeof(int), 1, file); //Schreibbefehl mit Parametern mit (Anzahl Spalten Bias (Adresse), eine ganze Zahl als "int" abspeichern, es wird genau eine solche Zahl gespeichert, Zielort "file") --> Speichert ab, wie viele Spalten Bias-Tabelle hat
|
||||||
|
|
||||||
|
int biasCount = layer.biases.rows * layer.biases.cols; //Berechnet die Gesamtzahl der Zahlen in der Bias Tabelle
|
||||||
|
|
||||||
|
fwrite(layer.biases.buffer, sizeof(MatrixType), biasCount, file); //Schreibbefehl mit Parametern mit (Bias Buffer (Adresse), eine ganze Zahl in "MatrixType" abspeichern, es wird der zuvor berechnete Wert gespeichert, Zielort "file") --> Speichert alle eigentlichen Zahlenwerte der Weights auf einmal in die Datei. Buffer ist bereits intern ein Zeiger, deswegen kein "&"
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---Datei wieder schließen---*/
|
||||||
|
fclose(file); //Schließe die Datei wieder, wenn alle Daten sauber geschrieben wurden
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
void test_loadModelReturnsCorrectNumberOfLayers(void)
|
void test_loadModelReturnsCorrectNumberOfLayers(void)
|
||||||
{
|
{
|
||||||
const char *path = "some__nn_test_file.info2";
|
const char *path = "some__nn_test_file.info2";
|
||||||
@@ -35,7 +77,9 @@ void test_loadModelReturnsCorrectNumberOfLayers(void)
|
|||||||
TEST_ASSERT_EQUAL_INT(expectedNet.numberOfLayers, netUnderTest.numberOfLayers);
|
TEST_ASSERT_EQUAL_INT(expectedNet.numberOfLayers, netUnderTest.numberOfLayers);
|
||||||
clearModel(&netUnderTest);
|
clearModel(&netUnderTest);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
void test_loadModelReturnsCorrectWeightDimensions(void)
|
void test_loadModelReturnsCorrectWeightDimensions(void)
|
||||||
{
|
{
|
||||||
const char *path = "some__nn_test_file.info2";
|
const char *path = "some__nn_test_file.info2";
|
||||||
@@ -59,6 +103,9 @@ void test_loadModelReturnsCorrectWeightDimensions(void)
|
|||||||
clearModel(&netUnderTest);
|
clearModel(&netUnderTest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
void test_loadModelReturnsCorrectBiasDimensions(void)
|
void test_loadModelReturnsCorrectBiasDimensions(void)
|
||||||
{
|
{
|
||||||
const char *path = "some__nn_test_file.info2";
|
const char *path = "some__nn_test_file.info2";
|
||||||
@@ -81,7 +128,9 @@ void test_loadModelReturnsCorrectBiasDimensions(void)
|
|||||||
TEST_ASSERT_EQUAL_INT(expectedNet.layers[0].biases.cols, netUnderTest.layers[0].biases.cols);
|
TEST_ASSERT_EQUAL_INT(expectedNet.layers[0].biases.cols, netUnderTest.layers[0].biases.cols);
|
||||||
clearModel(&netUnderTest);
|
clearModel(&netUnderTest);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
void test_loadModelReturnsCorrectWeights(void)
|
void test_loadModelReturnsCorrectWeights(void)
|
||||||
{
|
{
|
||||||
const char *path = "some__nn_test_file.info2";
|
const char *path = "some__nn_test_file.info2";
|
||||||
@@ -106,7 +155,9 @@ void test_loadModelReturnsCorrectWeights(void)
|
|||||||
TEST_ASSERT_EQUAL_INT_ARRAY(expectedNet.layers[0].weights.buffer, netUnderTest.layers[0].weights.buffer, n);
|
TEST_ASSERT_EQUAL_INT_ARRAY(expectedNet.layers[0].weights.buffer, netUnderTest.layers[0].weights.buffer, n);
|
||||||
clearModel(&netUnderTest);
|
clearModel(&netUnderTest);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
void test_loadModelReturnsCorrectBiases(void)
|
void test_loadModelReturnsCorrectBiases(void)
|
||||||
{
|
{
|
||||||
const char *path = "some__nn_test_file.info2";
|
const char *path = "some__nn_test_file.info2";
|
||||||
@@ -131,7 +182,9 @@ void test_loadModelReturnsCorrectBiases(void)
|
|||||||
TEST_ASSERT_EQUAL_INT_ARRAY(expectedNet.layers[0].biases.buffer, netUnderTest.layers[0].biases.buffer, n);
|
TEST_ASSERT_EQUAL_INT_ARRAY(expectedNet.layers[0].biases.buffer, netUnderTest.layers[0].biases.buffer, n);
|
||||||
clearModel(&netUnderTest);
|
clearModel(&netUnderTest);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
void test_loadModelFailsOnWrongFileTag(void)
|
void test_loadModelFailsOnWrongFileTag(void)
|
||||||
{
|
{
|
||||||
const char *path = "some_nn_test_file.info2";
|
const char *path = "some_nn_test_file.info2";
|
||||||
@@ -154,7 +207,9 @@ void test_loadModelFailsOnWrongFileTag(void)
|
|||||||
TEST_ASSERT_NULL(netUnderTest.layers);
|
TEST_ASSERT_NULL(netUnderTest.layers);
|
||||||
TEST_ASSERT_EQUAL_INT(0, netUnderTest.numberOfLayers);
|
TEST_ASSERT_EQUAL_INT(0, netUnderTest.numberOfLayers);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
void test_clearModelSetsMembersToNull(void)
|
void test_clearModelSetsMembersToNull(void)
|
||||||
{
|
{
|
||||||
const char *path = "some__nn_test_file.info2";
|
const char *path = "some__nn_test_file.info2";
|
||||||
@@ -186,7 +241,9 @@ static void someActivation(Matrix *matrix)
|
|||||||
matrix->buffer[i] = fabs(matrix->buffer[i]);
|
matrix->buffer[i] = fabs(matrix->buffer[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
void test_predictReturnsCorrectLabels(void)
|
void test_predictReturnsCorrectLabels(void)
|
||||||
{
|
{
|
||||||
const unsigned char expectedLabels[] = {4, 2};
|
const unsigned char expectedLabels[] = {4, 2};
|
||||||
@@ -215,15 +272,19 @@ void test_predictReturnsCorrectLabels(void)
|
|||||||
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedLabels, predictedLabels, n);
|
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedLabels, predictedLabels, n);
|
||||||
free(predictedLabels);
|
free(predictedLabels);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
void setUp(void) {
|
void setUp(void) {
|
||||||
// Falls notwendig, kann hier Vorbereitungsarbeit gemacht werden
|
// Falls notwendig, kann hier Vorbereitungsarbeit gemacht werden
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void tearDown(void) {
|
void tearDown(void) {
|
||||||
// Hier kann Bereinigungsarbeit nach jedem Test durchgeführt werden
|
// Hier kann Bereinigungsarbeit nach jedem Test durchgeführt werden
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------------------------------------- */
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
UNITY_BEGIN();
|
UNITY_BEGIN();
|
||||||
@@ -239,4 +300,4 @@ int main()
|
|||||||
RUN_TEST(test_predictReturnsCorrectLabels);
|
RUN_TEST(test_predictReturnsCorrectLabels);
|
||||||
|
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user