mod_layer.f90 Source File


This file depends on

sourcefile~~mod_layer.f90~~EfferentGraph sourcefile~mod_layer.f90 mod_layer.f90 sourcefile~mod_kinds.f90 mod_kinds.f90 sourcefile~mod_layer.f90->sourcefile~mod_kinds.f90 sourcefile~mod_random.f90 mod_random.f90 sourcefile~mod_layer.f90->sourcefile~mod_random.f90 sourcefile~mod_activation.f90 mod_activation.f90 sourcefile~mod_layer.f90->sourcefile~mod_activation.f90 sourcefile~mod_random.f90->sourcefile~mod_kinds.f90 sourcefile~mod_activation.f90->sourcefile~mod_kinds.f90

Files dependent on this one

sourcefile~~mod_layer.f90~~AfferentGraph sourcefile~mod_layer.f90 mod_layer.f90 sourcefile~mod_network.f90 mod_network.f90 sourcefile~mod_network.f90->sourcefile~mod_layer.f90

Contents

Source Code


Source Code

module mod_layer

  !! Defines the layer type and its methods.

  use mod_activation
  use mod_kinds, only: ik, rk
  use mod_random, only: randn

  implicit none

  private
  public :: array1d, array2d, db_init, db_co_sum, dw_init, dw_co_sum, layer_type

  type :: layer_type
    real(rk), allocatable :: a(:) !! activations
    real(rk), allocatable :: b(:) !! biases
    real(rk), allocatable :: w(:,:) !! weights
    real(rk), allocatable :: z(:) !! arg. to activation function
    procedure(activation_function), pointer, nopass :: activation => null()
    procedure(activation_function), pointer, nopass :: activation_prime => null()
    character(len=:), allocatable :: activation_str !! activation character string
  contains
    procedure, public, pass(self) :: set_activation
  end type layer_type

  type :: array1d
    real(rk), allocatable :: array(:)
  end type array1d

  type :: array2d
    real(rk), allocatable :: array(:,:)
  end type array2d

  interface layer_type
    module procedure :: constructor
  end interface layer_type

  interface array1d
    module procedure :: array1d_constructor
  end interface array1d

  interface array2d
    module procedure :: array2d_constructor
  end interface array2d

contains

  type(layer_type) function constructor(this_size, next_size) result(layer)
    !! Layer class constructor. this_size is the number of neurons in the layer.
    !! next_size is the number of neurons in the next layer, used to allocate
    !! the weights.
    integer(ik), intent(in) :: this_size, next_size
    allocate(layer % a(this_size))
    allocate(layer % z(this_size))
    layer % a = 0
    layer % z = 0
    layer % w = randn(this_size, next_size) / this_size
    layer % b = randn(this_size)
  end function constructor

  pure type(array1d) function array1d_constructor(length) result(a)
    !! Overloads the default type constructor.
    integer(ik), intent(in) :: length
    allocate(a % array(length))
    a % array = 0
  end function array1d_constructor

  pure type(array2d) function array2d_constructor(dims) result(a)
    !! Overloads the default type constructor.
    integer(ik), intent(in) :: dims(2)
    allocate(a % array(dims(1), dims(2)))
    a % array = 0
  end function array2d_constructor

  pure subroutine db_init(db, dims)
    !! Initialises biases structure.
    type(array1d), allocatable, intent(in out) :: db(:)
    integer(ik), intent(in) :: dims(:)
    integer(ik) :: n, nm
    nm = size(dims)
    allocate(db(nm))
    do n = 1, nm - 1
      db(n) = array1d(dims(n))
    end do
    db(n) = array1d(dims(n))
  end subroutine db_init

  pure subroutine dw_init(dw, dims)
    !! Initialises weights structure.
    type(array2d), allocatable, intent(in out) :: dw(:)
    integer(ik), intent(in) :: dims(:)
    integer(ik) :: n, nm
    nm = size(dims)
    allocate(dw(nm))
    do n = 1, nm - 1
      dw(n) = array2d(dims(n:n+1))
    end do
    dw(n) = array2d([dims(n), 1])
  end subroutine dw_init

  subroutine db_co_sum(db)
    !! Performs a collective sum of bias tendencies.
    type(array1d), allocatable, intent(in out) :: db(:)
    integer(ik) :: n
    do n = 2, size(db)
#ifdef CAF
      call co_sum(db(n) % array)
#endif
    end do
  end subroutine db_co_sum

  subroutine dw_co_sum(dw)
    !! Performs a collective sum of weights tendencies.
    type(array2d), allocatable, intent(in out) :: dw(:)
    integer(ik) :: n
    do n = 1, size(dw) - 1
#ifdef CAF
      call co_sum(dw(n) % array)
#endif
    end do
  end subroutine dw_co_sum

  pure elemental subroutine set_activation(self, activation)
    !! Sets the activation function. Input string must match one of
    !! provided activation functions, otherwise it defaults to sigmoid.
    !! If activation not present, defaults to sigmoid.
    class(layer_type), intent(in out) :: self
    character(len=*), intent(in) :: activation
    select case(trim(activation))
      case('gaussian')
        self % activation => gaussian
        self % activation_prime => gaussian_prime
        self % activation_str = 'gaussian'
      case('relu')
        self % activation => relu
        self % activation_prime => relu_prime
        self % activation_str = 'relu'
      case('sigmoid')
        self % activation => sigmoid
        self % activation_prime => sigmoid_prime
        self % activation_str = 'sigmoid'
      case('step')
        self % activation => step
        self % activation_prime => step_prime
        self % activation_str = 'step'
      case('tanh')
        self % activation => tanhf
        self % activation_prime => tanh_prime
        self % activation_str = 'tanh'
      case default
        self % activation => sigmoid
        self % activation_prime => sigmoid_prime
        self % activation_str = 'sigmoid'
    end select
  end subroutine set_activation

end module mod_layer