2022-12-20 12:08:24 +01:00
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import layer
import util / matrix
import util / activations
import util / losses
export layer , matrix , losses , activations
import std / sequtils
import std / strformat
type
NeuralNetwork * = ref object
2022-12-22 21:35:16 +01:00
## A generic feed-forward
## neural network
layers : seq [ Layer ]
2022-12-20 12:08:24 +01:00
proc newNeuralNetwork * ( layers : seq [ int ] , activationFunc : Activation , lossFunc : Loss , learnRate : float ,
weightRange : tuple [ start , stop : float ] ) : NeuralNetwork =
## Initializes a new neural network
## with the given layer layout
new ( result )
result . layers = newSeqOfCap [ Layer ] ( len ( layers ) )
for i in 0 .. < layers . high ( ) :
result . layers . add ( newLayer ( layers [ i ] , layers [ i + 1 ] , activationFunc , lossFunc , learnRate , weightRange ) )
proc predict * ( self : NeuralNetwork , data : Matrix [ float ] ) : Matrix [ float ] =
## Performs a prediction and returns a 1D array
## with the output
when not defined ( release ) :
if data . shape . rows > 1 :
raise newException ( ValueError , " input data must be one-dimensional " )
if data . shape . cols ! = self . layers [ 0 ] . inputSize :
raise newException ( ValueError , & " input is of the wrong shape (expecting (1, {self.layers[0].inputSize}), got ({data.shape.rows}, {data.shape.cols}) instead) " )
result = data
for layer in self . layers :
result = layer . compute ( result )
proc classify * ( self : NeuralNetwork , data : Matrix [ float ] ) : int =
## Performs a prediction and returns the label
## with the highest likelyhood
result = maxIndex ( self . predict ( data ) . raw [ ] )
2022-12-22 21:35:16 +01:00
proc cost * ( self : NeuralNetwork , x , y : Matrix [ float ] ) : float =
## Returns the total average cost of the network
for layer in self . layers :
result + = layer . cost ( x , y )
result / = float ( self . layers . len ( ) )