build_graph_outputs Subroutine

subroutine build_graph_outputs(network, ifmt, graph_outputs, num_outputs)

Build the ONNX graph output tensor specifications.

Arguments

Type IntentOptional Attributes Name
class(network_type), intent(in) :: network

Instance of the network

integer, intent(in) :: ifmt

Export format selector

type(onnx_tensor_type), intent(inout) :: graph_outputs(:)

Graph output tensor specifications

integer, intent(inout) :: num_outputs

Number of graph outputs


Source Code

  subroutine build_graph_outputs(network, ifmt, graph_outputs, num_outputs)
    !! Build the ONNX graph output tensor specifications.
    implicit none

    ! Arguments
    class(network_type), intent(in) :: network
    !! Instance of the network
    integer, intent(in) :: ifmt
    !! Export format selector
    type(onnx_tensor_type), intent(inout) :: graph_outputs(:)
    !! Graph output tensor specifications
    integer, intent(inout) :: num_outputs
    !! Number of graph outputs

    ! Local variables
    integer :: i, j, layer_id
    !! Loop indices and current layer identifier
    character(:), allocatable :: suffix
    !! Optional activation suffix for output names

    if(ifmt .eq. 2)then
       layer_id = 0
       do i = 1, network%auto_graph%num_vertices
          j = network%vertex_order(i)
          if(all(network%leaf_vertices(:) .ne. j)) cycle
          layer_id = network%auto_graph%vertex(j)%id
          exit
       end do

       if(layer_id .eq. 0) return

       num_outputs = 1
       graph_outputs(1)%name = 'output'
       graph_outputs(1)%elem_type = 1
       if(allocated(graph_outputs(1)%dims)) deallocate(graph_outputs(1)%dims)
       if(allocated(graph_outputs(1)%dim_params))then
          deallocate(graph_outputs(1)%dim_params)
       end if
       allocate(graph_outputs(1)%dims(2))
       allocate(graph_outputs(1)%dim_params(2))
       graph_outputs(1)%dim_params(1) = 'batch_size'
       graph_outputs(1)%dims(1) = -1
       graph_outputs(1)%dim_params(2) = ''
       graph_outputs(1)%dims(2) = network%model(layer_id)%layer%output_shape(1)
       return
    end if

    do i = 1, size(network%leaf_vertices, dim=1)
       layer_id = network%auto_graph%vertex(network%leaf_vertices(i))%id
       suffix = ''

       select type(layer => network%model(layer_id)%layer)
       class is(learnable_layer_type)
          if(layer%activation%name .ne. 'none')then
             suffix = '_' // trim(adjustl(layer%activation%name))
          end if
       end select

       num_outputs = num_outputs + 1
       write(graph_outputs(num_outputs)%name, '("node_",I0,A,"_output")') &
            network%model(layer_id)%layer%id, trim(adjustl(suffix))
       graph_outputs(num_outputs)%elem_type = 1
       allocate(graph_outputs(num_outputs)%dims( &
            size(network%model(layer_id)%layer%output_shape) + 1))
       allocate(graph_outputs(num_outputs)%dim_params( &
            size(network%model(layer_id)%layer%output_shape) + 1))
       graph_outputs(num_outputs)%dim_params(1) = 'batch_size'
       graph_outputs(num_outputs)%dims(1) = -1

       do j = 1, size(network%model(layer_id)%layer%output_shape)
          graph_outputs(num_outputs)%dim_params(j+1) = ''
          graph_outputs(num_outputs)%dims(j+1) = &
               network%model(layer_id)%layer%output_shape(j)
       end do
    end do

  end subroutine build_graph_outputs