Emit ONNX node records for a standard, non-GNN layer.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(network_type), | intent(in) | :: | network |
Instance of the network |
||
| integer, | intent(in) | :: | layer_id |
Layer identifier and vertex position |
||
| integer, | intent(in) | :: | vertex_idx |
Layer identifier and vertex position |
||
| type(onnx_node_type), | intent(inout) | :: | nodes(:) |
Exported ONNX nodes |
||
| integer, | intent(inout) | :: | num_nodes |
Node counter and allocation limit |
||
| integer, | intent(inout) | :: | max_nodes |
Node counter and allocation limit |
||
| type(onnx_initialiser_type), | intent(inout) | :: | inits(:) |
Exported ONNX initialisers |
||
| integer, | intent(inout) | :: | num_inits |
Initialiser counter and allocation limit |
||
| integer, | intent(inout) | :: | max_inits |
Initialiser counter and allocation limit |
subroutine emit_standard_node_json( & network, layer_id, vertex_idx, & nodes, num_nodes, max_nodes, & inits, num_inits, max_inits) !! Emit ONNX node records for a standard, non-GNN layer. use athena__onnx_utils, only: emit_initialisers, build_attributes_json, & emit_activation_node implicit none ! Arguments class(network_type), intent(in) :: network !! Instance of the network integer, intent(in) :: layer_id, vertex_idx !! Layer identifier and vertex position type(onnx_node_type), intent(inout) :: nodes(:) !! Exported ONNX nodes integer, intent(inout) :: num_nodes, max_nodes !! Node counter and allocation limit type(onnx_initialiser_type), intent(inout) :: inits(:) !! Exported ONNX initialisers integer, intent(inout) :: num_inits, max_inits !! Initialiser counter and allocation limit ! Local variables character(128) :: node_name, layer_name, input_name !! Temporary strings used to build node names character(:), allocatable :: suffix !! Optional activation suffix for an input tensor name integer :: j, input_layer_id, n_inputs !! Loop index, source layer identifier and input count character(128), allocatable :: input_list(:) !! Input tensor names character(4096) :: attr_json !! Pre-formatted JSON attributes write(node_name, '("node_", I0)') network%model(layer_id)%layer%id select case(trim(network%model(layer_id)%layer%type)) case('full') layer_name = 'Gemm' case('conv') layer_name = 'Conv' case('pool') layer_name = to_camel_case( & trim(adjustl(network%model(layer_id)%layer%subtype)) // '_' // & trim(adjustl(network%model(layer_id)%layer%type)), & capitalise_first_letter = .true.) case('actv') layer_name = to_camel_case( & trim(adjustl(network%model(layer_id)%layer%subtype)), & capitalise_first_letter = .true.) case('flat') layer_name = 'Flatten' case('batc') layer_name = 'BatchNormalization' case('drop') layer_name = 'Dropout' case('nop') layer_name = to_camel_case( & trim(adjustl(network%model(layer_id)%layer%name)), & capitalise_first_letter = .true.) case default layer_name = 'Unknown' end select n_inputs = 0 allocate(input_list(100)) do j = 1, network%auto_graph%num_vertices input_layer_id = network%auto_graph%vertex(j)%id if(network%auto_graph%adjacency( & j, network%vertex_order(vertex_idx)) .eq. 0) cycle if(all(network%auto_graph%adjacency(:,j) .eq. 0))then write(input_name, '("input_",I0)') & network%model(input_layer_id)%layer%id suffix = '' else write(input_name, '("node_",I0)') & network%model(input_layer_id)%layer%id suffix = '_output' select type(prev => network%model(input_layer_id)%layer) class is(learnable_layer_type) if(prev%activation%name .ne. 'none')then suffix = '_' // trim(adjustl(prev%activation%name)) // & '_output' end if end select end if n_inputs = n_inputs + 1 write(input_list(n_inputs), '(A,A)') trim(adjustl(input_name)), suffix end do select type(layer => network%model(layer_id)%layer) class is(learnable_layer_type) do j = 1, size(layer%params) n_inputs = n_inputs + 1 write(input_list(n_inputs), '(A,"_param",I0)') trim(node_name), j end do end select call build_attributes_json( & network%model(layer_id)%layer, trim(layer_name), attr_json) num_nodes = num_nodes + 1 nodes(num_nodes)%name = trim(node_name) nodes(num_nodes)%op_type = trim(layer_name) allocate(nodes(num_nodes)%inputs(n_inputs)) nodes(num_nodes)%inputs = input_list(1:n_inputs) allocate(nodes(num_nodes)%outputs(1)) write(nodes(num_nodes)%outputs(1), '(A,"_output")') trim(node_name) nodes(num_nodes)%attributes_json = attr_json select type(layer => network%model(layer_id)%layer) class is(learnable_layer_type) call emit_initialisers(layer, trim(node_name), inits, num_inits, & max_inits) if(layer%activation%name .ne. 'none')then call emit_activation_node( & layer%activation%name, trim(node_name), '', & nodes, num_nodes, max_nodes) end if end select deallocate(input_list) end subroutine emit_standard_node_json