diff --git a/example/icar-qr-network.f90 b/example/icar-qr-network.f90 index 6b3423eea..0b53b3dcf 100644 --- a/example/icar-qr-network.f90 +++ b/example/icar-qr-network.f90 @@ -4,13 +4,14 @@ program icar_qr_network !! This program demonstrates how to read a neural network from a JSON file. !! query the network for a some of its properties. use command_line_m, only : command_line_t - use inference_engine_m, only : inference_engine_t, inputs_t + use inference_engine_m, only : inference_engine_t use string_m, only : string_t use matmul_m, only : matmul_t use file_m, only : file_t + use kind_parameters_m, only : rkind implicit none - type(string_t) input_file_name + type(string_t) input_file_name, activation_name type(command_line_t) command_line type(inference_engine_t) inference_engine @@ -27,9 +28,18 @@ program icar_qr_network print *, "num_outputs = ", inference_engine%num_outputs() print *, "num_hidden_layers = ", inference_engine%num_hidden_layers() print *, "neurons_per_layer = ", inference_engine%neurons_per_layer() + activation_name = inference_engine%activation_function_name() + print *, "activation function: ", activation_name%string() + print *, "using skip connections: ", merge("true ", "false", inference_engine%skip()) - print *, inference_engine%infer([5.7010256568901241e-05, 3.6012468740409531e-07, 1.4284904636951978e-07, & - 0.0000000000000000e+00, 0.0000000000000000e+00, 1.8107765197753906e+01, 1.9922698868413136e-07, & - 4.8543064679051895e-08, 2.3069851398468018e+00, 5.4544006347656250e+02], matmul_t())*120. + block + real(rkind), parameter :: inputs(*) = [ real(rkind) :: & + 5.4041727707954124e-05_rkind, 1.8311046012797760e-09_rkind, 5.4236606525370767e-13_rkind, 0._rkind, 0._rkind, & + 2.3016514256596565e-02_rkind, 1.0734779465337851e-07_rkind, 3.9603170742807947e-10_rkind, 2.3047807216644287e+00_rkind, & + 5.3973675537109375e+02_rkind & + ] + print *, "inputs: ", inputs + print *, "outputs: ", inference_engine%infer(inputs, matmul_t()) + end block end program diff --git a/example/read.f90 b/example/read.f90 index 07a65dc49..b2099a32a 100644 --- a/example/read.f90 +++ b/example/read.f90 @@ -13,6 +13,7 @@ program read_json type(string_t) input_file_name type(command_line_t) command_line type(inference_engine_t) inference_engine + type(string_t) activation_name input_file_name = string_t(command_line%flag_value("--input-file")) @@ -23,8 +24,11 @@ program read_json print *, "Constructing a new inference_engine_t object by parameters from '"//input_file_name%string()//"'." inference_engine = inference_engine_t(file_t(input_file_name)) - print *, "num_inputs = ", inference_engine%num_inputs() - print *, "num_outputs = ", inference_engine%num_outputs() - print *, "num_hidden_layers = ", inference_engine%num_hidden_layers() - print *, "neurons_per_layer = ", inference_engine%neurons_per_layer() + print *, "number of inputs: ", inference_engine%num_inputs() + print *, "number of outputs: ", inference_engine%num_outputs() + print *, "number of hidden layers: ", inference_engine%num_hidden_layers() + print *, "number of neurons per layer: ", inference_engine%neurons_per_layer() + activation_name = inference_engine%activation_function_name() + print *, "activation function: ", activation_name%string() + print *, "using skip connections: ", merge("true ", "false", inference_engine%skip()) end program diff --git a/example/write-read-infer.f90 b/example/write-read-infer.f90 index c8b39d6bb..876446579 100644 --- a/example/write-read-infer.f90 +++ b/example/write-read-infer.f90 @@ -30,6 +30,7 @@ program write_read_infer subroutine write_read_query_infer(output_file_name) type(string_t), intent(in) :: output_file_name + type(string_t) activation_name integer i, j integer, parameter :: num_inputs = 2, num_outputs = 1, num_neurons = 3, num_hidden_layers = 2 integer, parameter :: identity(*,*,*) = & @@ -59,10 +60,12 @@ subroutine write_read_query_infer(output_file_name) inference_engine = inference_engine_t(json_input_file) print *, "Querying the new inference_engine_t object for several properties:" - print *, "num_outputs = ", inference_engine%num_outputs() - print *, "num_hidden_layers = ", inference_engine%num_hidden_layers() - print *, "neurons_per_layer = ", inference_engine%neurons_per_layer() - + print *, "number of outputs:", inference_engine%num_outputs() + print *, "number of hidden layers:", inference_engine%num_hidden_layers() + print *, "number of neurons per layer:", inference_engine%neurons_per_layer() + activation_name = inference_engine%activation_function_name() + print *, "activation function: ", activation_name%string() + print *, "using skip connections: ", merge("true ", "false", inference_engine%skip()) print *, "Performing inference:" print *, "inference_engine%infer([0.,1.]) =",inference_engine%infer([real(rkind):: 0.,1.], matmul_t()) print *, "Correct answer for the XOR neural network: ", 1. diff --git a/src/inference_engine_m.f90 b/src/inference_engine_m.f90 index 25c276e9a..19da5da82 100644 --- a/src/inference_engine_m.f90 +++ b/src/inference_engine_m.f90 @@ -49,6 +49,7 @@ module inference_engine_m procedure, private :: subtract generic :: operator(-) => subtract procedure :: skip + procedure :: activation_function_name end type interface inference_engine_t @@ -143,6 +144,12 @@ elemental module function skip(self) result(use_skip_connections) logical use_skip_connections end function + elemental module function activation_function_name(self) result(activation_name) + implicit none + class(inference_engine_t), intent(in) :: self + type(string_t) activation_name + end function + end interface end module inference_engine_m diff --git a/src/inference_engine_s.f90 b/src/inference_engine_s.f90 index 6b00ec462..b955579fe 100644 --- a/src/inference_engine_s.f90 +++ b/src/inference_engine_s.f90 @@ -45,7 +45,7 @@ case("step") inference_engine%activation_strategy_ = step_t() case default - error stop "inference_engine_t construct_from_json: unrecognized activation strategy" + error stop "inference_engine_t construct_from_components: unrecognized activation strategy" end select call assert_consistent(inference_engine) @@ -157,8 +157,9 @@ function get_key_value(line) result(value_) associate(closing_value_quotes => opening_value_quotes + index(text_after_colon(opening_value_quotes+1:), '"')) if (any([opening_value_quotes, closing_value_quotes] == 0)) then value_ = string_t(trim(adjustl((text_after_colon)))) + else + value_ = string_t(text_after_colon(opening_value_quotes+1:closing_value_quotes-1)) end if - value_ = string_t(text_after_colon(opening_value_quotes+1:closing_value_quotes-1)) end associate end associate end associate @@ -339,8 +340,8 @@ pure subroutine assert_consistent(self) lines(line) = string_t(' "activationFunction": "' // & self%metadata_(findloc(key, "activationFunction", dim=1))%string() // '",') line = line + 1 - lines(line) = string_t(' "usingSkipConnections": "' // & - self%metadata_(findloc(key, "usingSkipConnections", dim=1))%string() // '",') + lines(line) = string_t(' "usingSkipConnections": ' // & + self%metadata_(findloc(key, "usingSkipConnections", dim=1))%string()) line = line + 1 lines(line) = string_t(' },') @@ -428,4 +429,8 @@ pure subroutine assert_consistent(self) use_skip_connections = self%metadata_(findloc(key, "usingSkipConnections", dim=1))%string() == "true" end procedure + module procedure activation_function_name + activation_name = self%metadata_(findloc(key, "activationFunction", dim=1)) + end procedure + end submodule inference_engine_s diff --git a/test/asymmetric_engine_test_m.f90 b/test/asymmetric_engine_test_m.f90 index 5d2be774e..3f41580cf 100644 --- a/test/asymmetric_engine_test_m.f90 +++ b/test/asymmetric_engine_test_m.f90 @@ -46,10 +46,12 @@ function results() result(test_results) "counting the number of hidden layers", & "counting the number of neurons per layer", & "counting the number of inputs", & - "counting the number of outputs" & + "counting the number of outputs", & + "getting the activation function name" & ], & [ xor_and_2nd_input_truth_table(concurrent_dot_products_t()), xor_and_2nd_input_truth_table(matmul_t()), & - test_num_hidden_layers(), test_neurons_per_layer(), test_num_inputs(), test_num_outputs() & + test_num_hidden_layers(), test_neurons_per_layer(), test_num_inputs(), test_num_outputs(), & + test_activation_name() & ] & ) end function @@ -142,4 +144,14 @@ function test_num_outputs() result(test_passes) test_passes = inference_engine%num_outputs() == 1 end function + function test_activation_name() result(test_passes) + logical test_passes + type(string_t) :: function_name + type(inference_engine_t) inference_engine + + inference_engine = xor_and_2nd_input_network() + function_name = inference_engine%activation_function_name() + test_passes = function_name%string() == "step" + end function + end module asymmetric_engine_test_m