forked from lgallet/XOR-NeuralNetwork-C
feat: ✨ Create Neural network for XOR
This commit is contained in:
commit
82b65ae2a1
297
.gitignore
vendored
Normal file
297
.gitignore
vendored
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
*.csv
|
||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/c,cmake,jetbrains,clion,macos
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=c,cmake,jetbrains,clion,macos
|
||||||
|
|
||||||
|
### C ###
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
*.o
|
||||||
|
*.ko
|
||||||
|
*.obj
|
||||||
|
*.elf
|
||||||
|
|
||||||
|
# Linker output
|
||||||
|
*.ilk
|
||||||
|
*.map
|
||||||
|
*.exp
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Libraries
|
||||||
|
*.lib
|
||||||
|
*.a
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
|
|
||||||
|
# Shared objects (inc. Windows DLLs)
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
*.i*86
|
||||||
|
*.x86_64
|
||||||
|
*.hex
|
||||||
|
|
||||||
|
# Debug files
|
||||||
|
*.dSYM/
|
||||||
|
*.su
|
||||||
|
*.idb
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Kernel Module Compile Results
|
||||||
|
*.mod*
|
||||||
|
*.cmd
|
||||||
|
.tmp_versions/
|
||||||
|
modules.order
|
||||||
|
Module.symvers
|
||||||
|
Mkfile.old
|
||||||
|
dkms.conf
|
||||||
|
|
||||||
|
### CLion ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
.idea/sonarlint/
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
### CLion Patch ###
|
||||||
|
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||||
|
|
||||||
|
# *.iml
|
||||||
|
# modules.xml
|
||||||
|
# .idea/misc.xml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# Sonarlint plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/7973-sonarlint
|
||||||
|
.idea/**/sonarlint/
|
||||||
|
|
||||||
|
# SonarQube Plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
|
||||||
|
.idea/**/sonarIssues.xml
|
||||||
|
|
||||||
|
# Markdown Navigator plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
|
||||||
|
.idea/**/markdown-navigator.xml
|
||||||
|
.idea/**/markdown-navigator-enh.xml
|
||||||
|
.idea/**/markdown-navigator/
|
||||||
|
|
||||||
|
# Cache file creation bug
|
||||||
|
# See https://youtrack.jetbrains.com/issue/JBR-2257
|
||||||
|
.idea/$CACHE_FILE$
|
||||||
|
|
||||||
|
# CodeStream plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/12206-codestream
|
||||||
|
.idea/codestream.xml
|
||||||
|
|
||||||
|
# Azure Toolkit for IntelliJ plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
|
||||||
|
.idea/**/azureSettings.xml
|
||||||
|
|
||||||
|
### CMake ###
|
||||||
|
CMakeLists.txt.user
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles
|
||||||
|
CMakeScripts
|
||||||
|
Testing
|
||||||
|
Makefile
|
||||||
|
cmake_install.cmake
|
||||||
|
install_manifest.txt
|
||||||
|
compile_commands.json
|
||||||
|
CTestTestfile.cmake
|
||||||
|
_deps
|
||||||
|
|
||||||
|
### CMake Patch ###
|
||||||
|
# External projects
|
||||||
|
*-prefix/
|
||||||
|
|
||||||
|
### JetBrains ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
|
||||||
|
### JetBrains Patch ###
|
||||||
|
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||||
|
|
||||||
|
# *.iml
|
||||||
|
# modules.xml
|
||||||
|
# .idea/misc.xml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# Sonarlint plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/7973-sonarlint
|
||||||
|
|
||||||
|
# SonarQube Plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
|
||||||
|
|
||||||
|
# Markdown Navigator plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
|
||||||
|
|
||||||
|
# Cache file creation bug
|
||||||
|
# See https://youtrack.jetbrains.com/issue/JBR-2257
|
||||||
|
|
||||||
|
# CodeStream plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/12206-codestream
|
||||||
|
|
||||||
|
# Azure Toolkit for IntelliJ plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
|
||||||
|
|
||||||
|
### macOS ###
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
### macOS Patch ###
|
||||||
|
# iCloud generated files
|
||||||
|
*.icloud
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/c,cmake,jetbrains,clion,macos
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Louis Gallet
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
237
main.c
Normal file
237
main.c
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
//
|
||||||
|
// Created by Louis Gallet on 24/09/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
double sigmoid(double x)
|
||||||
|
{
|
||||||
|
if(x > 20) return 1.0;
|
||||||
|
if(x < -20) return 0.0;
|
||||||
|
|
||||||
|
double z = exp(-x);
|
||||||
|
return 1.0 / (1.0 + z);
|
||||||
|
}
|
||||||
|
|
||||||
|
double sigmoid_derivative(double x)
|
||||||
|
{
|
||||||
|
return x * (1.0 - x);
|
||||||
|
}
|
||||||
|
double init_weights()
|
||||||
|
{
|
||||||
|
double placeholder = ((double) rand()) / ((double) RAND_MAX);
|
||||||
|
return placeholder;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shuffle(int *array, size_t n){
|
||||||
|
if(n > 1) {
|
||||||
|
size_t i;
|
||||||
|
for(i = 0; i < n - 1; i++) {
|
||||||
|
size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
|
||||||
|
int t = array[j];
|
||||||
|
array[j] = array[i];
|
||||||
|
array[i] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void backup_weights(char filename[], double hiddenWeights[NUM_INPUTS][NUM_HIDDEN], double hiddenLayerBias[NUM_HIDDEN],
|
||||||
|
double outputWeights[NUM_HIDDEN][NUM_OUTPUTS], double outputLayerBias[NUM_OUTPUTS])
|
||||||
|
{
|
||||||
|
FILE *fpt;
|
||||||
|
fpt = fopen(filename, "w+");
|
||||||
|
for(int j = 0; j < NUM_HIDDEN; j++){
|
||||||
|
for(int k = 0; k < NUM_INPUTS; k++){
|
||||||
|
fprintf(fpt, "%f,", hiddenWeights[k][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Final Hidden Biases: \n");
|
||||||
|
for(int j = 0; j < NUM_HIDDEN; j++){
|
||||||
|
fprintf(fpt, "%f,", hiddenLayerBias[j]);
|
||||||
|
}
|
||||||
|
printf("Final Output Weights: \n");
|
||||||
|
for(int j = 0; j < NUM_OUTPUTS; j++){
|
||||||
|
for(int k = 0; k < NUM_HIDDEN; k++){
|
||||||
|
fprintf(fpt, "%f,", outputWeights[k][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Final Output Biases: \n");
|
||||||
|
for(int j = 0; j < NUM_OUTPUTS; j++){
|
||||||
|
fprintf(fpt, "%f,", outputLayerBias[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
//learning rate
|
||||||
|
const double lr = 0.1f;
|
||||||
|
|
||||||
|
double hiddenLayer[NUM_HIDDEN];
|
||||||
|
double outputLayer[NUM_OUTPUTS];
|
||||||
|
|
||||||
|
double hiddenLayerBias[NUM_HIDDEN];
|
||||||
|
double outputLayerBias[NUM_OUTPUTS];
|
||||||
|
|
||||||
|
double hiddenWeights[NUM_INPUTS][NUM_HIDDEN];
|
||||||
|
double outputWeights[NUM_HIDDEN][NUM_OUTPUTS];
|
||||||
|
|
||||||
|
double trainingInputs[NUM_TRAINING_SETS][NUM_INPUTS] = {{0.0f, 0.0f}, {1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f}, {1.0f, 1.0f}};
|
||||||
|
|
||||||
|
double trainingOutputs[NUM_TRAINING_SETS][NUM_OUTPUTS] = {{0.0f}, {1.0f}, {1.0f}, {0.0f}};
|
||||||
|
|
||||||
|
for(int i = 0; i < NUM_INPUTS; i++){
|
||||||
|
for(int j = 0; j < NUM_HIDDEN; j++){
|
||||||
|
hiddenWeights[i][j] = init_weights();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < NUM_HIDDEN; i++){
|
||||||
|
for(int j = 0; j < NUM_OUTPUTS; j++){
|
||||||
|
outputWeights[i][j] = init_weights();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < NUM_OUTPUTS; i++){
|
||||||
|
outputLayerBias[i] = init_weights();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < NUM_HIDDEN; i++){
|
||||||
|
hiddenLayerBias[i] = init_weights();
|
||||||
|
}
|
||||||
|
|
||||||
|
int trainingSetOrder[] = {0,1,2,3};
|
||||||
|
|
||||||
|
int numEpochs = 100000;
|
||||||
|
|
||||||
|
//training loop
|
||||||
|
for(int epoch = 0; epoch < numEpochs; epoch++){
|
||||||
|
shuffle(trainingSetOrder, NUM_TRAINING_SETS);
|
||||||
|
|
||||||
|
for(int x = 0; x < NUM_TRAINING_SETS; x++){
|
||||||
|
int i = trainingSetOrder[x];
|
||||||
|
|
||||||
|
//forward pass
|
||||||
|
//compute hidden layer activation
|
||||||
|
for(int j = 0; j < NUM_HIDDEN; j++){
|
||||||
|
double activation = hiddenLayerBias[j];
|
||||||
|
|
||||||
|
for(int k = 0; k < NUM_INPUTS; k++){
|
||||||
|
activation += trainingInputs[i][k] * hiddenWeights[k][j];
|
||||||
|
}
|
||||||
|
//printf("Hidden layer activation[%d] = %f\n", j, activation);
|
||||||
|
hiddenLayer[j] = sigmoid(activation);
|
||||||
|
|
||||||
|
if(isnan(hiddenLayer[j])){
|
||||||
|
//printf("NaN in hidden layer at index %d\n", j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//compute output layer activation
|
||||||
|
for(int j = 0; j < NUM_OUTPUTS; j++){
|
||||||
|
double activation = outputLayerBias[j];
|
||||||
|
for(int k = 0; k < NUM_HIDDEN; k++){
|
||||||
|
activation += hiddenLayer[k] * outputWeights[k][j];
|
||||||
|
}
|
||||||
|
//printf("Output layer activation[%d] = %f\n", j, activation);
|
||||||
|
outputLayer[j] = sigmoid(activation);
|
||||||
|
if(isnan(outputLayer[j])){
|
||||||
|
//printf("NaN in output layer at index %d\n", j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Input: %g %g Output: %g Predicted Output: %g\n", trainingInputs[i][0], trainingInputs[i][1], outputLayer[0], trainingOutputs[i][0]);
|
||||||
|
|
||||||
|
//Back prop
|
||||||
|
//compute change in output weights
|
||||||
|
|
||||||
|
double deltaOutput[NUM_OUTPUTS];
|
||||||
|
|
||||||
|
for(int j = 0; j < NUM_OUTPUTS; j++){
|
||||||
|
double error = (trainingOutputs[i][j] - outputLayer[j]);
|
||||||
|
deltaOutput[j] = error * sigmoid_derivative(outputLayer[j]);
|
||||||
|
if(isnan(deltaOutput[j])){
|
||||||
|
//printf("NaN in deltaOutput at index %d\n", j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//compute change in hidden weights
|
||||||
|
|
||||||
|
double deltaHidden[NUM_HIDDEN];
|
||||||
|
|
||||||
|
for(int j = 0; j < NUM_HIDDEN; j++){
|
||||||
|
double error = 0.0f;
|
||||||
|
for(int k = 0; k < NUM_OUTPUTS; k++){
|
||||||
|
error += deltaOutput[k] * outputWeights[j][k];
|
||||||
|
}
|
||||||
|
deltaHidden[j] = error * sigmoid_derivative(hiddenLayer[j]);
|
||||||
|
if(isnan(deltaHidden[j])){
|
||||||
|
//printf("NaN in deltaHidden at index %d\n", j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//apply change in output weights
|
||||||
|
for(int j = 0; j < NUM_OUTPUTS; j++){
|
||||||
|
outputLayerBias[j] += deltaOutput[j] * lr;
|
||||||
|
|
||||||
|
for(int k = 0; k < NUM_HIDDEN; k++){
|
||||||
|
outputWeights[k][j] += hiddenLayer[k] * deltaOutput[j] * lr;
|
||||||
|
if(isnan(outputWeights[k][j])){
|
||||||
|
//printf("NaN in outputWeights at [%d][%d]\n", k, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int j = 0; j < NUM_HIDDEN; j++){
|
||||||
|
hiddenLayerBias[j] += deltaHidden[j] * lr;
|
||||||
|
for(int k = 0; k < NUM_INPUTS; k++){
|
||||||
|
hiddenWeights[k][j] += trainingInputs[i][k] * deltaHidden[j] * lr;
|
||||||
|
if(isnan(hiddenWeights[k][j])){
|
||||||
|
//printf("NaN in hiddenWeights at [%d][%d]\n", k, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//print final weights after training
|
||||||
|
printf("\nFinal Hidden Weights: \n");
|
||||||
|
for(int j = 0; j < NUM_HIDDEN; j++){
|
||||||
|
for(int k = 0; k < NUM_INPUTS; k++){
|
||||||
|
printf("%f ", hiddenWeights[k][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Final Hidden Biases: \n");
|
||||||
|
for(int j = 0; j < NUM_HIDDEN; j++){
|
||||||
|
printf("%f ", hiddenLayerBias[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n\n\n");
|
||||||
|
|
||||||
|
printf("Final Output Weights: \n");
|
||||||
|
for(int j = 0; j < NUM_OUTPUTS; j++){
|
||||||
|
for(int k = 0; k < NUM_HIDDEN; k++){
|
||||||
|
printf("%f ", outputWeights[k][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
|
||||||
|
printf("Final Output Biases: \n");
|
||||||
|
for(int j = 0; j < NUM_OUTPUTS; j++){
|
||||||
|
printf("%f ", outputLayerBias[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
backup_weights("weights.csv", hiddenWeights, hiddenLayerBias, outputWeights, outputLayerBias);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
26
main.h
Normal file
26
main.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Created by Louis Gallet on 24/09/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MAIN_H
|
||||||
|
#define MAIN_H
|
||||||
|
#include <sys/_types/_size_t.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define NUM_INPUTS 2
|
||||||
|
#define NUM_HIDDEN 2
|
||||||
|
#define NUM_OUTPUTS 1
|
||||||
|
#define NUM_TRAINING_SETS 4
|
||||||
|
|
||||||
|
double sigmoid(double x);
|
||||||
|
double sigmoid_derivative(double x);
|
||||||
|
double init_weights();
|
||||||
|
void shuffle(int *array, size_t n);
|
||||||
|
void backup_weights(char filename[], double hiddenWeights[NUM_INPUTS][NUM_HIDDEN], double hiddenLayerBias[NUM_HIDDEN],
|
||||||
|
double outputWeights[NUM_HIDDEN][NUM_OUTPUTS], double outputLayerBias[NUM_OUTPUTS]);
|
||||||
|
|
||||||
|
|
||||||
|
int main();
|
||||||
|
|
||||||
|
#endif //MAIN_H
|
98
use.c
Normal file
98
use.c
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <err.h>
|
||||||
|
|
||||||
|
// Function prototypes
|
||||||
|
void getvalues(char filename[], double **HiddenWeights, double *HiddenBiases, double **FinalOutputWeights, double *FinalOutputBiases);
|
||||||
|
double sigmoid(double x);
|
||||||
|
double sigmoid_derivative(double x);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// Allocate memory for weights and biases
|
||||||
|
double **HiddenWeights = (double **)malloc(2 * sizeof(double *));
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
HiddenWeights[i] = (double *)malloc(2 * sizeof(double));
|
||||||
|
}
|
||||||
|
double *HiddenBiases = (double *)malloc(2 * sizeof(double));
|
||||||
|
double **FinalOutputWeights = (double **)malloc(2 * sizeof(double *));
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
FinalOutputWeights[i] = (double *)malloc(1 * sizeof(double));
|
||||||
|
}
|
||||||
|
double *FinalOutputBiases = (double *)malloc(1 * sizeof(double));
|
||||||
|
|
||||||
|
// Load weights and biases from CSV file
|
||||||
|
getvalues("weights.csv", HiddenWeights, HiddenBiases, FinalOutputWeights, FinalOutputBiases);
|
||||||
|
|
||||||
|
// Prompt user for input values
|
||||||
|
double input1, input2;
|
||||||
|
printf("Enter two values to compute XOR: ");
|
||||||
|
scanf("%lf %lf", &input1, &input2);
|
||||||
|
|
||||||
|
// Perform forward pass
|
||||||
|
double hiddenLayer[2];
|
||||||
|
double outputLayer[1];
|
||||||
|
|
||||||
|
// Compute hidden layer activation
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
double activation = HiddenBiases[j];
|
||||||
|
activation += input1 * HiddenWeights[0][j];
|
||||||
|
activation += input2 * HiddenWeights[1][j];
|
||||||
|
hiddenLayer[j] = sigmoid(activation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute output layer activation
|
||||||
|
for (int j = 0; j < 1; j++) {
|
||||||
|
double activation = FinalOutputBiases[j];
|
||||||
|
activation += hiddenLayer[0] * FinalOutputWeights[0][j];
|
||||||
|
activation += hiddenLayer[1] * FinalOutputWeights[1][j];
|
||||||
|
outputLayer[j] = sigmoid(activation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the result
|
||||||
|
printf("Input: %g %g Predicted Output: %g Output round: %g\n", input1, input2, outputLayer[0], round(outputLayer[0]));
|
||||||
|
|
||||||
|
// Free allocated memory
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
free(HiddenWeights[i]);
|
||||||
|
free(FinalOutputWeights[i]);
|
||||||
|
}
|
||||||
|
free(HiddenWeights);
|
||||||
|
free(HiddenBiases);
|
||||||
|
free(FinalOutputWeights);
|
||||||
|
free(FinalOutputBiases);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void getvalues(char filename[], double **HiddenWeights, double *HiddenBiases, double **FinalOutputWeights, double *FinalOutputBiases) {
|
||||||
|
FILE *fp = fopen(filename, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
errx(EXIT_FAILURE, "Could not open file %s", filename);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
fscanf(fp, "%lf,", &HiddenWeights[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
fscanf(fp, "%lf,", &HiddenBiases[i]);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
for (int j = 0; j < 1; j++) {
|
||||||
|
fscanf(fp, "%lf,", &FinalOutputWeights[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 1; i++) {
|
||||||
|
fscanf(fp, "%lf,", &FinalOutputBiases[i]);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
double sigmoid(double x) {
|
||||||
|
return 1.0 / (1.0 + exp(-x));
|
||||||
|
}
|
||||||
|
|
||||||
|
double sigmoid_derivative(double x) {
|
||||||
|
return x * (1.0 - x);
|
||||||
|
}
|
18
use.h
Normal file
18
use.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// Created by Louis Gallet on 27/09/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef USE_H
|
||||||
|
#define USE_H
|
||||||
|
|
||||||
|
#define NUM_INPUTS 2
|
||||||
|
#define NUM_HIDDEN 2
|
||||||
|
#define NUM_OUTPUTS 1
|
||||||
|
#define NUM_TRAINING_SETS 4
|
||||||
|
|
||||||
|
|
||||||
|
void getvalues(char filename[], double **HiddenWeights, double *HiddenBiases, double **FinalOutputWeights, double *FinalOutputBiases);
|
||||||
|
int main();
|
||||||
|
|
||||||
|
|
||||||
|
#endif //USE_H
|
Reference in New Issue
Block a user