Build a standard, non-GNN network from parsed JSON data.
Synthetic value_info entries are created for layers whose output shape can be inferred from initialisers or simple attributes before calling build_from_onnx.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(network_type), | intent(inout) | :: | network |
Network to populate from parsed ONNX content |
||
| type(onnx_node_type), | intent(in) | :: | nodes(:) |
Parsed ONNX nodes |
||
| integer, | intent(in) | :: | num_nodes |
Number of valid entries in nodes |
||
| type(onnx_initialiser_type), | intent(in) | :: | inits(:) |
Parsed ONNX initialisers |
||
| integer, | intent(in) | :: | num_inits |
Number of valid entries in inits |
||
| type(onnx_tensor_type), | intent(in) | :: | inputs(:) |
Parsed graph input tensors |
||
| integer, | intent(in) | :: | num_inputs |
Number of valid entries in inputs |
||
| integer, | intent(in) | :: | verbose_ |
Effective verbosity level |
subroutine build_network_from_json_standard( & network, nodes, num_nodes, inits, num_inits, inputs, num_inputs, & verbose_) !! Build a standard, non-GNN network from parsed JSON data. !! !! Synthetic value_info entries are created for layers whose output shape !! can be inferred from initialisers or simple attributes before calling !! build_from_onnx. implicit none ! Arguments type(network_type), intent(inout) :: network !! Network to populate from parsed ONNX content type(onnx_node_type), intent(in) :: nodes(:) !! Parsed ONNX nodes integer, intent(in) :: num_nodes !! Number of valid entries in nodes type(onnx_initialiser_type), intent(in) :: inits(:) !! Parsed ONNX initialisers integer, intent(in) :: num_inits !! Number of valid entries in inits type(onnx_tensor_type), intent(in) :: inputs(:) !! Parsed graph input tensors integer, intent(in) :: num_inputs !! Number of valid entries in inputs integer, intent(in) :: verbose_ !! Effective verbosity level ! Local variables type(onnx_tensor_type), allocatable :: value_infos(:) !! Synthesised tensor value_info entries integer :: i, j, k, num_vi, ndims, n_kernel_dims !! Loop indices and temporary dimension counters character(128) :: out_name !! Current node output tensor name character(32) :: op_type_name !! Current node ONNX op type if(is_onnx_expanded_nop_graph(nodes, num_nodes))then call build_network_from_json_onnx_expanded_nop( & network, nodes, num_nodes, inits, num_inits, verbose_) return end if if(is_onnx_expanded_gnn_graph(nodes, num_nodes))then call build_network_from_json_onnx_expanded_gnn( & network, nodes, num_nodes, & inits, num_inits, & inputs, num_inputs, verbose_) return end if allocate(value_infos(num_nodes)) num_vi = 0 node_loop: do i = 1, num_nodes if(.not.allocated(nodes(i)%outputs)) cycle if(nodes(i)%num_outputs .lt. 1) cycle out_name = trim(nodes(i)%outputs(1)) op_type_name = trim(adjustl(nodes(i)%op_type)) do j = 1, nodes(i)%num_inputs do k = 1, num_inits if(trim(nodes(i)%inputs(j)) .ne. trim(inits(k)%name)) cycle if(.not.allocated(inits(k)%dims)) cycle if(size(inits(k)%dims) .lt. 2) cycle num_vi = num_vi + 1 value_infos(num_vi)%name = out_name value_infos(num_vi)%elem_type = 1 ndims = size(inits(k)%dims) if(op_type_name .eq. 'Conv' .and. ndims .ge. 3)then allocate(value_infos(num_vi)%dims(ndims)) value_infos(num_vi)%dims(1) = 1 value_infos(num_vi)%dims(2) = inits(k)%dims(ndims) value_infos(num_vi)%dims(3:ndims) = 0 else allocate(value_infos(num_vi)%dims(2)) value_infos(num_vi)%dims(1) = 1 value_infos(num_vi)%dims(2) = inits(k)%dims(1) end if cycle node_loop end do end do if(index(op_type_name, 'Pool', back=.true.) .eq. & len_trim(op_type_name) - 3)then n_kernel_dims = 0 if(allocated(nodes(i)%attributes))then do j = 1, size(nodes(i)%attributes) if(trim(adjustl(nodes(i)%attributes(j)%name)) .ne. & 'kernel_shape') cycle block character(256) :: kval integer :: kpos, kstat, ktemp kval = trim(adjustl(nodes(i)%attributes(j)%val)) kpos = 1 do while(kpos .le. len_trim(kval)) do while(kpos .le. len_trim(kval) .and. & kval(kpos:kpos) .eq. ' ') kpos = kpos + 1 end do if(kpos .gt. len_trim(kval)) exit read(kval(kpos:), *, iostat=kstat) ktemp if(kstat .ne. 0) exit n_kernel_dims = n_kernel_dims + 1 do while(kpos .le. len_trim(kval) .and. & kval(kpos:kpos) .ne. ' ') kpos = kpos + 1 end do end do end block exit end do end if if(n_kernel_dims .gt. 0)then num_vi = num_vi + 1 value_infos(num_vi)%name = out_name value_infos(num_vi)%elem_type = 1 allocate(value_infos(num_vi)%dims(n_kernel_dims + 2)) value_infos(num_vi)%dims = 0 end if end if end do node_loop call network%build_from_onnx( & nodes(1:num_nodes), inits(1:num_inits), inputs(1:num_inputs), & value_infos(1:num_vi), verbose=verbose_) end subroutine build_network_from_json_standard