neural network with backpropagation (OOP)
Posted: Fri Jun 19, 2009 11:55 am
well.. guess there are already some examples around but maybe
someone likes this implementation more :P
CDoublyLinkedList.pbi
http://www.purebasic.fr/english/viewtopic.php?t=36278
CNeuralNetwork.pbi
Edit: some bugs fixed and load/save from file command added
Edit: added number parameter for addHiddenLayer and addNeuron
Edit: added error function to teach() to get a better idea how good the network is trained
Edit: added methods to manipulate the learning rate
someone likes this implementation more :P
CDoublyLinkedList.pbi
http://www.purebasic.fr/english/viewtopic.php?t=36278
CNeuralNetwork.pbi
Code: Select all
XIncludeFile "CDoublyLinkedList.pbi"
Interface INeuralNetwork
;- public
;network construction
addHiddenLayer(number.i = 1)
addNeuron(layer.i, number.i = 1)
removeNeuron(layer.i)
removeHiddenLayer(layer.i)
clearLayer(layer.i)
buildSynapses()
;for rebuilding, must be called prior
;to network manipulation if the synapses were already built
clearSynapses()
;data manipulation
getNeuronInput.f(layer.i, neuron.i)
getNeuronOutput.f(layer.i, neuron.i)
getNeuronBias.f(layer.i, neuron.i)
setNeuronInput(layer.i, neuron.i, value.f)
setNeuronOutput(layer.i, neuron.i, value.f)
setNeuronBias(layer.i, neuron.i, value.f)
getNeuronSynapseWeight.f(srcLayer.i, srcNeuron.i, destNeuron.i)
setNeuronSynapseWeight(srcLayer.i, srcNeuron.i, destNeuron.i, value.f)
getLearningRate.f()
setLearningRate(value.f)
;information
getLayerCount()
getNeuronCount(layer.i)
;feed-forward
update()
;propagation of error
teach.f()
;file operations
load(FileID.i)
save(FileID.i)
;network destruction
clear()
;free object
delete()
;- private
;getter
getNeuron(layer.i, neuron.i)
EndInterface
;layer index:
; input: -2
; output: -1
; hidden layer: 0 <= i < hidden layers
#INN_InputLayer = -2
#INN_OutputLayer = -1
Structure ENeuralNetworkNeuronList
*layer.IDoublyLinkedList
EndStructure
Structure ENeuralNetworkNeuron
synapses.IDoublyLinkedList
bias.f
delta.f
input.f
output.f
EndStructure
Structure ENeuralNetworkSynapse
*srcNeuron.ENeuralNetworkNeuron
weight.f
EndStructure
Structure ONeuralNetwork
;Address to the methods array
methodAddress.i
;Class Attributes
input.ENeuralNetworkNeuronList
layers.IDoublyLinkedList
learningRate.f
networkBuilt.i
EndStructure
Declare.i newNeuralNetwork(learningRate.f = 0.5)
Declare.i NeuralNetwork_addHiddenLayer(*this.INeuralNetwork, number.i = 1)
Declare.i NeuralNetwork_addNeuron(*this.INeuralNetwork, layer.i, number.i = 1)
Declare.i NeuralNetwork_removeNeuron(*this.INeuralNetwork, layer.i)
Declare.i NeuralNetwork_removeHiddenLayer(*this.INeuralNetwork, layer.i)
Declare.i NeuralNetwork_clearLayer(*this.INeuralNetwork, layer.i)
Declare.i NeuralNetwork_buildSynapses(*this.INeuralNetwork)
Declare.i NeuralNetwork_clearSynapses(*this.INeuralNetwork)
Declare.f NeuralNetwork_getNeuronInput(*this.INeuralNetwork, layer.i, neuron.i)
Declare.f NeuralNetwork_getNeuronOutput(*this.INeuralNetwork, layer.i, neuron.i)
Declare.f NeuralNetwork_getNeuronBias(*this.INeuralNetwork, layer.i, neuron.i)
Declare.i NeuralNetwork_setNeuronInput(*this.INeuralNetwork, layer.i, neuron.i, value.f)
Declare.i NeuralNetwork_setNeuronOutput(*this.INeuralNetwork, layer.i, neuron.i, value.f)
Declare.i NeuralNetwork_setNeuronBias(*this.INeuralNetwork, layer.i, neuron.i, value.f)
Declare.f NeuralNetwork_getNeuronSynapseWeight(*this.INeuralNetwork, srcLayer.i, srcNeuron.i, destNeuron.i)
Declare.i NeuralNetwork_setNeuronSynapseWeight(*this.INeuralNetwork, srcLayer.i, srcNeuron.i, destNeuron.i, value.f)
Declare.f NeuralNetwork_getLearningRate(*this.INeuralNetwork)
Declare.i NeuralNetwork_setLearningRate(*this.INeuralNetwork, value.f)
Declare.i NeuralNetwork_getLayerCount(*this.INeuralNetwork)
Declare.i NeuralNetwork_getNeuronCount(*this.INeuralNetwork, layer.i)
Declare.i NeuralNetwork_update(*this.INeuralNetwork)
Declare.f NeuralNetwork_teach(*this.INeuralNetwork)
Declare.i NeuralNetwork_load(*this.INeuralNetwork, FileID.i)
Declare.i NeuralNetwork_save(*this.INeuralNetwork, FileID.i)
Declare.i NeuralNetwork_clear(*this.INeuralNetwork)
Declare NeuralNetwork_delete(*this.INeuralNetwork)
Declare.i NeuralNetwork_getNeuron(*this.INeuralNetwork, layer.i, neuron.i)
DataSection
ONeuralNetwork_methods:
Data.i @NeuralNetwork_addHiddenLayer()
Data.i @NeuralNetwork_addNeuron()
Data.i @NeuralNetwork_removeNeuron()
Data.i @NeuralNetwork_removeHiddenLayer()
Data.i @NeuralNetwork_clearLayer()
Data.i @NeuralNetwork_buildSynapses()
Data.i @NeuralNetwork_clearSynapses()
Data.i @NeuralNetwork_getNeuronInput()
Data.i @NeuralNetwork_getNeuronOutput()
Data.i @NeuralNetwork_getNeuronBias()
Data.i @NeuralNetwork_setNeuronInput()
Data.i @NeuralNetwork_setNeuronOutput()
Data.i @NeuralNetwork_setNeuronBias()
Data.i @NeuralNetwork_getNeuronSynapseWeight()
Data.i @NeuralNetwork_setNeuronSynapseWeight()
Data.i @NeuralNetwork_getLearningRate()
Data.i @NeuralNetwork_setLearningRate()
Data.i @NeuralNetwork_getLayerCount()
Data.i @NeuralNetwork_getNeuronCount()
Data.i @NeuralNetwork_update()
Data.i @NeuralNetwork_teach()
Data.i @NeuralNetwork_load()
Data.i @NeuralNetwork_save()
Data.i @NeuralNetwork_clear()
Data.i @NeuralNetwork_delete()
Data.i @NeuralNetwork_getNeuron()
EndDataSection
Procedure.i newNeuralNetwork(learningRate.f = 0.5)
Protected *object.ONeuralNetwork, *aLayer.ENeuralNetworkNeuronList
*object = AllocateMemory(SizeOf(ONeuralNetwork))
If *object = #Null
ProcedureReturn #Null
EndIf
*object\methodAddress = ?ONeuralNetwork_methods
*object\input\layer = newDoublyLinkedList(SizeOf(ENeuralNetworkNeuron))
If *object\input = #Null
FreeMemory(*object)
ProcedureReturn #Null
EndIf
*object\layers = newDoublyLinkedList(SizeOf(INTEGER))
If *object\layers = #Null
*object\input\layer\delete()
FreeMemory(*object)
ProcedureReturn #Null
EndIf
;add output layer
*aLayer = *object\layers\addE()
If *aLayer = #Null
*object\layers\delete()
*object\input\layer\delete()
FreeMemory(*object)
ProcedureReturn #Null
EndIf
*aLayer\layer = newDoublyLinkedList(SizeOf(ENeuralNetworkNeuron))
If *aLayer\layer = #Null
*object\layers\delete()
*object\input\layer\delete()
FreeMemory(*object)
ProcedureReturn #Null
EndIf
*object\learningRate = learningRate
*object\networkBuilt = #False
ProcedureReturn *object
EndProcedure
Procedure.i NeuralNetwork_addHiddenLayer(*this.INeuralNetwork, number.i = 1)
Protected *object.ONeuralNetwork, *aLayer.ENeuralNetworkNeuronList
If *this = #Null Or number < 1
ProcedureReturn #False
EndIf
*object = *this
For i = 1 To number
*object\layers\firstE()
*aLayer = *object\layers\insertE()
If *aLayer = #Null
ProcedureReturn #False
EndIf
*aLayer\layer = newDoublyLinkedList(SizeOf(ENeuralNetworkNeuron))
If *aLayer\layer = #Null
*object\layers\deleteE()
ProcedureReturn #False
EndIf
Next i
ProcedureReturn #True
EndProcedure
Procedure.i NeuralNetwork_addNeuron(*this.INeuralNetwork, layer.i, number.i = 1)
Protected *object.ONeuralNetwork, *neuron.ENeuralNetworkNeuron, *aLayer.ENeuralNetworkNeuronList
If *this = #Null Or number < 1
ProcedureReturn #False
EndIf
*object = *this
If *object\networkBuilt
ProcedureReturn #False
EndIf
If layer = #INN_InputLayer
*aLayer = *object\input
ElseIf layer = #INN_OutputLayer
*aLayer = *object\layers\lastE()
Else
If layer >= *object\layers\size()
ProcedureReturn #False
EndIf
*aLayer = *object\layers\selectE(layer)
EndIf
If *aLayer = #Null Or *aLayer\layer = #Null
ProcedureReturn #False
EndIf
For i = 1 To number
*aLayer\layer\firstE()
*neuron = *aLayer\layer\addE()
If *neuron = #Null
ProcedureReturn #False
EndIf
*neuron\synapses = newDoublyLinkedList(SizeOf(ENeuralNetworkSynapse))
If *neuron\synapses = #Null
*aLayer\layer\deleteE()
ProcedureReturn #False
EndIf
Next i
ProcedureReturn #True
EndProcedure
Procedure.i NeuralNetwork_removeNeuron(*this.INeuralNetwork, layer.i)
Protected *object.ONeuralNetwork, *neuron.ENeuralNetworkNeuron, *aLayer.ENeuralNetworkNeuronList
If *this = #Null
ProcedureReturn #False
EndIf
*object = *this
If *object\networkBuilt
ProcedureReturn #False
EndIf
If layer = #INN_InputLayer
*aLayer = *object\input
ElseIf layer = #INN_OutputLayer
*aLayer = *object\layers\lastE()
Else
If layer >= *object\layers\size()
ProcedureReturn #False
EndIf
*aLayer = *object\layers\selectE(layer)
EndIf
If *aLayer = #Null Or *aLayer\layer = #Null
ProcedureReturn #False
EndIf
*neuron = *aLayer\layer\lastE()
If *neuron = #Null
ProcedureReturn #False
EndIf
*neuron\synapses\delete()
If *aLayer\layer\deleteE() = #Null
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
Procedure.i NeuralNetwork_removeHiddenLayer(*this.INeuralNetwork, layer.i)
Protected *object.ONeuralNetwork, *neuron.ENeuralNetworkNeuron, *aLayer.ENeuralNetworkNeuronList
If *this = #Null
ProcedureReturn #False
EndIf
*object = *this
If *object\networkBuilt
ProcedureReturn #False
EndIf
If layer >= *object\layers\size()
ProcedureReturn #False
EndIf
*aLayer = *object\layers\selectE(layer)
If *aLayer = #Null Or *aLayer\layer = #Null
ProcedureReturn #False
EndIf
*aLayer\layer\reset()
While *aLayer\layer\nextE()
*neuron = *aLayer\layer\currentE()
If *neuron\synapses
*neuron\synapses\delete()
EndIf
Wend
If *aLayer\layer\deleteE() = #Null
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
Procedure.i NeuralNetwork_clearLayer(*this.INeuralNetwork, layer.i)
Protected *object.ONeuralNetwork, *neuron.ENeuralNetworkNeuron, *aLayer.ENeuralNetworkNeuronList
If *this = #Null
ProcedureReturn #False
EndIf
*object = *this
If *object\networkBuilt
ProcedureReturn #False
EndIf
If layer = #INN_InputLayer
*aLayer = *object\input
ElseIf layer = #INN_OutputLayer
*aLayer = *object\layers\lastE()
Else
If layer >= *object\layers\size()
ProcedureReturn #False
EndIf
*aLayer = *object\layers\selectE(layer)
EndIf
If *aLayer = #Null Or *aLayer\layer = #Null
ProcedureReturn #False
EndIf
*aLayer\layer\reset()
While *aLayer\layer\nextE()
*neuron = *aLayer\layer\currentE()
If *neuron\synapses
*neuron\synapses\clear()
EndIf
Wend
*aLayer\layer\clear()
ProcedureReturn #True
EndProcedure
Procedure.i NeuralNetwork_buildSynapses(*this.INeuralNetwork)
Protected *object.ONeuralNetwork, *synapse.ENeuralNetworkSynapse
Protected *srcNeuron.ENeuralNetworkNeuron, *destNeuron.ENeuralNetworkNeuron
Protected *srcLayer.ENeuralNetworkNeuronList, *destLayer.ENeuralNetworkNeuronList
If *this = #Null
ProcedureReturn #False
EndIf
*object = *this
If *object\layers\size() < 1
ProcedureReturn #False
EndIf
If *object\networkBuilt
ProcedureReturn #True
EndIf
*destLayer = *object\input
*object\layers\reset()
While *object\layers\nextE()
*srcLayer = *destLayer
*destLayer = *object\layers\currentE()
*destLayer\layer\reset()
While *destLayer\layer\nextE()
*destNeuron = *destLayer\layer\currentE()
If *destNeuron\synapses
*destNeuron\synapses\clear()
Else
ProcedureReturn #False
EndIf
*destNeuron\bias = Random($FFFFFF) / $FFFFFF
*srcLayer\layer\reset()
While *srcLayer\layer\nextE()
*srcNeuron = *srcLayer\layer\currentE()
*destNeuron\synapses\lastE()
*synapse = *destNeuron\synapses\addE()
If *synapse = #Null
ProcedureReturn #False
EndIf
*synapse\srcNeuron = *srcNeuron
*synapse\weight = Random($FFFFFF) / $FFFFFF
Wend
Wend
Wend
*object\networkBuilt = #True
ProcedureReturn #True
EndProcedure
Procedure.i NeuralNetwork_clearSynapses(*this.INeuralNetwork)
Protected *object.ONeuralNetwork, *neuron.ENeuralNetworkNeuron, *aLayer.ENeuralNetworkNeuronList
If *this = #Null
ProcedureReturn #False
EndIf
*object = *this
If *object\networkBuilt = #False
ProcedureReturn #False
EndIf
*aLayer = *object\input
*aLayer\layer\reset()
While *aLayer\layer\nextE()
*neuron = *aLayer\layer\currentE()
If *neuron\synapses
*neuron\synapses\clear()
EndIf
Wend
*object\layers\reset()
While *object\layers\nextE()
*aLayer = *object\layers\currentE()
If *aLayer\layer
*aLayer\layer\reset()
While *aLayer\layer\nextE()
*neuron = *aLayer\layer\currentE()
If *neuron\synapses
*neuron\synapses\clear()
EndIf
Wend
EndIf
Wend
*object\networkBuilt = #False
ProcedureReturn #True
EndProcedure
Procedure.f NeuralNetwork_getNeuronInput(*this.INeuralNetwork, layer.i, neuron.i)
Protected *object.ONeuralNetwork, *neuron.ENeuralNetworkNeuron
If *this = #Null
ProcedureReturn 0
EndIf
*object = *this
If *object\networkBuilt = #False
ProcedureReturn 0
EndIf
*neuron = *this\getNeuron(layer, neuron)
If *neuron = #Null
ProcedureReturn 0
EndIf
ProcedureReturn *neuron\input
EndProcedure
Procedure.f NeuralNetwork_getNeuronOutput(*this.INeuralNetwork, layer.i, neuron.i)
Protected *object.ONeuralNetwork, *neuron.ENeuralNetworkNeuron
If *this = #Null
ProcedureReturn 0
EndIf
*object = *this
If *object\networkBuilt = #False
ProcedureReturn 0
EndIf
*neuron = *this\getNeuron(layer, neuron)
If *neuron = #Null
ProcedureReturn 0
EndIf
ProcedureReturn *neuron\output
EndProcedure
Procedure.f NeuralNetwork_getNeuronBias(*this.INeuralNetwork, layer.i, neuron.i)
Protected *object.ONeuralNetwork, *neuron.ENeuralNetworkNeuron
If *this = #Null
ProcedureReturn 0
EndIf
*object = *this
If *object\networkBuilt = #False
ProcedureReturn 0
EndIf
*neuron = *this\getNeuron(layer, neuron)
If *neuron = #Null
ProcedureReturn 0
EndIf
ProcedureReturn *neuron\bias
EndProcedure
Procedure.i NeuralNetwork_setNeuronInput(*this.INeuralNetwork, layer.i, neuron.i, value.f)
Protected *object.ONeuralNetwork, *neuron.ENeuralNetworkNeuron
If *this = #Null
ProcedureReturn #False
EndIf
*object = *this
If *object\networkBuilt = #False
ProcedureReturn #False
EndIf
*neuron = *this\getNeuron(layer, neuron)
If *neuron = #Null
ProcedureReturn #False
EndIf
*neuron\input = value
If layer = #INN_InputLayer
*neuron\output = value
EndIf
ProcedureReturn #True
EndProcedure
Procedure.i NeuralNetwork_setNeuronOutput(*this.INeuralNetwork, layer.i, neuron.i, value.f)
Protected *object.ONeuralNetwork, *neuron.ENeuralNetworkNeuron
If *this = #Null Or layer = #INN_InputLayer
ProcedureReturn #False
EndIf
*object = *this
If *object\networkBuilt = #False
ProcedureReturn #False
EndIf
*neuron = *this\getNeuron(layer, neuron)
If *neuron = #Null
ProcedureReturn #False
EndIf
*neuron\output = value
ProcedureReturn #True
EndProcedure
Procedure.i NeuralNetwork_setNeuronBias(*this.INeuralNetwork, layer.i, neuron.i, value.f)
Protected *object.ONeuralNetwork, *neuron.ENeuralNetworkNeuron
If *this = #Null Or layer = #INN_InputLayer
ProcedureReturn #False
EndIf
*object = *this
If *object\networkBuilt = #False
ProcedureReturn #False
EndIf
*neuron = *this\getNeuron(layer, neuron)
If *neuron = #Null
ProcedureReturn #False
EndIf
*neuron\bias = value
ProcedureReturn #True
EndProcedure
Procedure.f NeuralNetwork_getNeuronSynapseWeight(*this.INeuralNetwork, srcLayer.i, srcNeuron.i, destNeuron.i)
Protected *object.ONeuralNetwork, *neuron.ENeuralNetworkNeuron, *synapse.ENeuralNetworkSynapse, destLayer.i
If *this = #Null
ProcedureReturn 0
EndIf
*object = *this
If *object\networkBuilt = #False
ProcedureReturn 0
EndIf
Select srcLayer
Case #INN_InputLayer
destLayer = 0
Case #INN_OutputLayer
ProcedureReturn 0
Default
destLayer = srcLayer + 1
EndSelect
*neuron = *this\getNeuron(destLayer, destNeuron)
If *neuron = #Null
ProcedureReturn 0
EndIf
If *neuron\synapses = #Null
ProcedureReturn 0
EndIf
*synapse = *neuron\synapses\selectE(srcNeuron)
If *synapse = #Null
ProcedureReturn 0
EndIf
ProcedureReturn *synapse\weight
EndProcedure
Procedure.i NeuralNetwork_setNeuronSynapseWeight(*this.INeuralNetwork, srcLayer.i, srcNeuron.i, destNeuron.i, value.f)
Protected *object.ONeuralNetwork, *neuron.ENeuralNetworkNeuron, *synapse.ENeuralNetworkSynapse, destLayer.i
If *this = #Null
ProcedureReturn #False
EndIf
*object = *this
If *object\networkBuilt = #False
ProcedureReturn #False
EndIf
Select srcLayer
Case #INN_InputLayer
destLayer = 0
Case #INN_OutputLayer
ProcedureReturn 0
Default
destLayer = srcLayer + 1
EndSelect
*neuron = *this\getNeuron(destLayer, destNeuron)
If *neuron = #Null
ProcedureReturn #False
EndIf
If *neuron\synapses = #Null
ProcedureReturn #False
EndIf
*synapse = *neuron\synapses\selectE(srcNeuron)
If *synapse = #Null
ProcedureReturn #False
EndIf
*synapse\weight = value
ProcedureReturn #True
EndProcedure
Procedure.f NeuralNetwork_getLearningRate(*this.INeuralNetwork)
Protected *object.ONeuralNetwork
If *this = #Null
ProcedureReturn 0
EndIf
*object = *this
ProcedureReturn *object\learningRate
EndProcedure
Procedure.i NeuralNetwork_setLearningRate(*this.INeuralNetwork, value.f)
Protected *object.ONeuralNetwork
If *this = #Null
ProcedureReturn #False
EndIf
*object = *this
*object\learningRate = value
ProcedureReturn #True
EndProcedure
Procedure.i NeuralNetwork_getLayerCount(*this.INeuralNetwork)
Protected *object.ONeuralNetwork
If *this = #Null
ProcedureReturn 0
EndIf
*object = *this
ProcedureReturn *object\layers\size() + 1
EndProcedure
Procedure.i NeuralNetwork_getNeuronCount(*this.INeuralNetwork, layer.i)
Protected *object.ONeuralNetwork, *aLayer.ENeuralNetworkNeuronList
If *this = #Null
ProcedureReturn 0
EndIf
*object = *this
If layer = #INN_InputLayer
*aLayer = *object\input
ElseIf layer = #INN_OutputLayer
*aLayer = *object\layers\lastE()
Else
If layer >= *object\layers\size()
ProcedureReturn 0
EndIf
*aLayer = *object\layers\selectE(layer)
EndIf
If *aLayer = #Null Or *aLayer\layer = #Null
ProcedureReturn 0
EndIf
ProcedureReturn *aLayer\layer\size()
EndProcedure
Procedure.i NeuralNetwork_update(*this.INeuralNetwork)
Protected *object.ONeuralNetwork, *aLayer.ENeuralNetworkNeuronList, *neuron.ENeuralNetworkNeuron
Protected *synapse.ENeuralNetworkSynapse
If *this = #Null
ProcedureReturn #False
EndIf
*object = *this
If *object\networkBuilt = #False
ProcedureReturn #False
EndIf
*object\layers\reset()
While *object\layers\nextE()
*aLayer = *object\layers\currentE()
*aLayer\layer\reset()
While *aLayer\layer\nextE()
*neuron = *aLayer\layer\currentE()
If *neuron\synapses
*neuron\synapses\reset()
*neuron\input = *neuron\bias
While *neuron\synapses\nextE()
*synapse = *neuron\synapses\currentE()
*neuron\input + (*synapse\srcNeuron\output * *synapse\weight)
Wend
EndIf
*neuron\output = 1 / (1 + Pow(2.718281828459045235, - *neuron\input))
*neuron\delta = *neuron\output
Wend
Wend
ProcedureReturn #True
EndProcedure
Procedure.f NeuralNetwork_teach(*this.INeuralNetwork)
Protected *object.ONeuralNetwork, *aLayer.ENeuralNetworkNeuronList, *lastLayer.ENeuralNetworkNeuronList
Protected layerIndex.i, *neuron.ENeuralNetworkNeuron, error.f
Protected *synapse.ENeuralNetworkSynapse, *srcNeuron.ENeuralNetworkNeuron
If *this = #Null
ProcedureReturn -1
EndIf
*object = *this
If *object\networkBuilt = #False
ProcedureReturn -1
EndIf
*aLayer = *object\layers\lastE()
If *aLayer = #Null Or *aLayer\layer = #Null
ProcedureReturn -1
EndIf
error = 0
*aLayer\layer\reset()
While *aLayer\layer\nextE()
*neuron = *aLayer\layer\currentE()
error + Abs(*neuron\output - *neuron\delta)
*neuron\delta = *neuron\output - *neuron\delta ;old output was saved in delta
Wend
*lastLayer = *aLayer
While *aLayer And *aLayer\layer
*aLayer = *object\layers\currentE()
*aLayer\layer\reset()
While *aLayer\layer\nextE()
*neuron = *aLayer\layer\currentE()
If *aLayer <> *lastLayer
*neuron\delta = *neuron\output * (1 - *neuron\output) * *neuron\delta
EndIf
*neuron\bias + (*object\learningRate * *neuron\delta)
If *neuron\synapses
*neuron\synapses\reset()
layerIndex = *aLayer\layer\index()
While *neuron\synapses\nextE()
*synapse = *neuron\synapses\currentE()
*srcNeuron = *synapse\srcNeuron
If layerIndex = 0
*srcNeuron\delta = (*synapse\weight * *neuron\delta)
Else
*srcNeuron\delta + (*synapse\weight * *neuron\delta)
EndIf
*synapse\weight + (*object\learningRate * *srcNeuron\output * *neuron\delta)
Wend
EndIf
Wend
*aLayer = *object\layers\priorE()
Wend
ProcedureReturn error
EndProcedure
Procedure.i NeuralNetwork_load(*this.INeuralNetwork, FileID.i)
Protected *object.ONeuralNetwork, result.i, layerCount.i, neurons.i, priorLayer.i
If *this = #Null Or IsFile(FileID) = #Null
ProcedureReturn #False
EndIf
*object = *this
result = #True
If *object\networkBuilt = #True
result & *this\clear()
EndIf
layerCount = ReadLong(FileID)
result & *this\addHiddenLayer(layerCount - 2)
neurons = ReadLong(FileID)
result & *this\addNeuron(#INN_InputLayer, neurons)
For i = 0 To layerCount - 2
neurons = ReadLong(FileID)
result & *this\addNeuron(i, neurons)
Next i
result & *this\buildSynapses()
If result = #False
ProcedureReturn #False
EndIf
For i = 0 To layerCount - 2
priorLayer = i - 1
If priorLayer < 0 : priorLayer = #INN_InputLayer : EndIf
For j = 0 To *this\getNeuronCount(i) - 1
result & *this\setNeuronBias(i, j, ReadFloat(FileID))
For k = 0 To *this\getNeuronCount(priorLayer) - 1
result & *this\setNeuronSynapseWeight(priorLayer, k, j, ReadFloat(FileID))
Next k
Next j
Next i
ProcedureReturn result
EndProcedure
Procedure.i NeuralNetwork_save(*this.INeuralNetwork, FileID.i)
Protected *object.ONeuralNetwork, layerCount.i, priorLayer.i
If *this = #Null Or IsFile(FileID) = #Null
ProcedureReturn #False
EndIf
*object = *this
If *object\networkBuilt = #False
ProcedureReturn #False
EndIf
layerCount = *this\getLayerCount()
WriteLong(FileID, layerCount)
WriteLong(FileID, *this\getNeuronCount(#INN_InputLayer))
For i = 0 To layerCount - 2
WriteLong(FileID, *this\getNeuronCount(i))
Next i
For i = 0 To layerCount - 2
priorLayer = i - 1
If priorLayer < 0 : priorLayer = #INN_InputLayer : EndIf
For j = 0 To *this\getNeuronCount(i) - 1
WriteFloat(FileID, *this\getNeuronBias(i, j))
For k = 0 To *this\getNeuronCount(priorLayer) - 1
WriteFloat(FileID, *this\getNeuronSynapseWeight(priorLayer, k, j))
Next k
Next j
Next i
ProcedureReturn #True
EndProcedure
Procedure.i NeuralNetwork_clear(*this.INeuralNetwork)
Protected *object.ONeuralNetwork, *aLayer.ENeuralNetworkNeuronList, index.i
If *this = #Null
ProcedureReturn #False
EndIf
*object = *this
*this\clearSynapses()
index = #INN_InputLayer
While *this\clearLayer(index)
index + 1
Wend
While *object\layers\size() > 1
*aLayer = *object\layers\firstE()
If *aLayer\layer
*aLayer\layer\delete()
EndIf
*object\layers\deleteE()
Wend
ProcedureReturn #True
EndProcedure
Procedure NeuralNetwork_delete(*this.INeuralNetwork)
Protected *object.ONeuralNetwork, *aLayer.ENeuralNetworkNeuronList
If *this = #Null
ProcedureReturn
EndIf
*object = *this
*this\clear()
*object\input\layer\delete()
*object\layers\reset()
If *object\layers\firstE()
*aLayer = *object\layers\currentE()
If *aLayer\layer
*aLayer\layer\delete()
EndIf
EndIf
*object\layers\delete()
FreeMemory(*object)
EndProcedure
Procedure.i NeuralNetwork_getNeuron(*this.INeuralNetwork, layer.i, neuron.i)
Protected *object.ONeuralNetwork, *neuron.ENeuralNetworkNeuron, *aLayer.ENeuralNetworkNeuronList
If *this = #Null
ProcedureReturn #Null
EndIf
*object = *this
If layer = #INN_InputLayer
*aLayer = *object\input
ElseIf layer = #INN_OutputLayer
*aLayer = *object\layers\lastE()
Else
If layer >= *object\layers\size()
ProcedureReturn #Null
EndIf
*aLayer = *object\layers\selectE(layer)
EndIf
If *aLayer = #Null Or *aLayer\layer = #Null
ProcedureReturn #Null
EndIf
*neuron = *aLayer\layer\selectE(neuron)
ProcedureReturn *neuron
EndProcedure
;##################################################################################################
Debug "##########"
Macro dbgBool(value)
If value = #True
Debug "#True"
Else
Debug "#False"
EndIf
EndMacro
o.INeuralNetwork = newNeuralNetwork()
dbgBool(o\addHiddenLayer())
Debug "--"
Debug o\getLayerCount()
dbgBool(o\addNeuron(#INN_InputLayer, 2))
dbgBool(o\addNeuron(0, 3))
dbgBool(o\addNeuron(#INN_OutputLayer, 1))
Debug "--"
Debug "neurons per layer"
Debug o\getNeuronCount(#INN_InputLayer)
Debug o\getNeuronCount(0)
Debug o\getNeuronCount(#INN_OutputLayer)
Debug "--"
dbgBool(o\buildSynapses())
Debug "--"
Debug "debug current network outputs"
dbgBool(o\setNeuronInput(#INN_InputLayer, 0, 0))
dbgBool(o\setNeuronInput(#INN_InputLayer, 1, 0))
dbgBool(o\update())
Debug o\getNeuronOutput(#INN_OutputLayer, 0)
dbgBool(o\setNeuronInput(#INN_InputLayer, 0, 0))
dbgBool(o\setNeuronInput(#INN_InputLayer, 1, 1))
dbgBool(o\update())
Debug o\getNeuronOutput(#INN_OutputLayer, 0)
dbgBool(o\setNeuronInput(#INN_InputLayer, 0, 1))
dbgBool(o\setNeuronInput(#INN_InputLayer, 1, 0))
dbgBool(o\update())
Debug o\getNeuronOutput(#INN_OutputLayer, 0)
dbgBool(o\setNeuronInput(#INN_InputLayer, 0, 1))
dbgBool(o\setNeuronInput(#INN_InputLayer, 1, 1))
dbgBool(o\update())
Debug o\getNeuronOutput(#INN_OutputLayer, 0)
Debug "--"
Debug "teaching XOR operator..."
For i = 1 To 1000
;init input
o\setNeuronInput(#INN_InputLayer, 0, 0)
o\setNeuronInput(#INN_InputLayer, 1, 0)
;calculate output
o\update()
;set wanted output
o\setNeuronOutput(#INN_OutputLayer, 0, 0)
;teach wanted output to the network
o\teach()
;init input
o\setNeuronInput(#INN_InputLayer, 0, 0)
o\setNeuronInput(#INN_InputLayer, 1, 1)
;calculate output
o\update()
;set wanted output
o\setNeuronOutput(#INN_OutputLayer, 0, 1)
;teach wanted output to the network
o\teach()
;init input
o\setNeuronInput(#INN_InputLayer, 0, 1)
o\setNeuronInput(#INN_InputLayer, 1, 0)
;calculate output
o\update()
;set wanted output
o\setNeuronOutput(#INN_OutputLayer, 0, 1)
;teach wanted output to the network
o\teach()
;init input
o\setNeuronInput(#INN_InputLayer, 0, 1)
o\setNeuronInput(#INN_InputLayer, 1, 1)
;calculate output
o\update()
;set wanted output
o\setNeuronOutput(#INN_OutputLayer, 0, 0)
;teach wanted output to the network
o\teach()
Next
Debug "--"
Debug "debug current network outputs"
o\setNeuronInput(#INN_InputLayer, 0, 0)
o\setNeuronInput(#INN_InputLayer, 1, 0)
o\update()
Debug o\getNeuronOutput(#INN_OutputLayer, 0)
o\setNeuronInput(#INN_InputLayer, 0, 0)
o\setNeuronInput(#INN_InputLayer, 1, 1)
o\update()
Debug o\getNeuronOutput(#INN_OutputLayer, 0)
o\setNeuronInput(#INN_InputLayer, 0, 1)
o\setNeuronInput(#INN_InputLayer, 1, 0)
o\update()
Debug o\getNeuronOutput(#INN_OutputLayer, 0)
o\setNeuronInput(#INN_InputLayer, 0, 1)
o\setNeuronInput(#INN_InputLayer, 1, 1)
o\update()
Debug o\getNeuronOutput(#INN_OutputLayer, 0)
o\delete()
Edit: added number parameter for addHiddenLayer and addNeuron
Edit: added error function to teach() to get a better idea how good the network is trained
Edit: added methods to manipulate the learning rate