|
4 | 4 | use nf_flatten_layer, only: flatten_layer |
5 | 5 | use nf_input1d_layer, only: input1d_layer |
6 | 6 | use nf_input3d_layer, only: input3d_layer |
| 7 | + use nf_io_hdf5, only: get_hdf5_dataset |
7 | 8 | use nf_keras, only: get_keras_h5_layers, keras_layer |
8 | 9 | use nf_layer, only: layer |
9 | 10 | use nf_layer_constructors, only: dense, input |
@@ -55,6 +56,8 @@ module function network_from_keras(filename) result(res) |
55 | 56 | type(network) :: res |
56 | 57 | type(keras_layer), allocatable :: keras_layers(:) |
57 | 58 | type(layer), allocatable :: layers(:) |
| 59 | + character(:), allocatable :: layer_name |
| 60 | + character(:), allocatable :: object_name |
58 | 61 | integer :: n |
59 | 62 |
|
60 | 63 | keras_layers = get_keras_h5_layers(filename) |
@@ -89,7 +92,44 @@ module function network_from_keras(filename) result(res) |
89 | 92 |
|
90 | 93 | res = network(layers) |
91 | 94 |
|
92 | | - !TODO read weights and biases from Keras file and set here |
| 95 | + ! Loop over layers and read weights and biases from the Keras h5 file |
| 96 | + ! for each; currently only dense layers are implemented. |
| 97 | + do n = 2, size(res % layers) |
| 98 | + |
| 99 | + layer_name = keras_layers(n) % name |
| 100 | + |
| 101 | + if (keras_layers(n) % class == 'Dense') then |
| 102 | + select type(this_layer => res % layers(n) % p) |
| 103 | + |
| 104 | + type is(dense_layer) |
| 105 | + |
| 106 | + ! Read biases from file |
| 107 | + object_name = '/model_weights/' // layer_name // '/' & |
| 108 | + // layer_name // '/bias:0' |
| 109 | + call get_hdf5_dataset(filename, object_name, this_layer % biases) |
| 110 | + |
| 111 | + ! Read weights from file |
| 112 | + object_name = '/model_weights/' // layer_name // '/' & |
| 113 | + // layer_name // '/kernel:0' |
| 114 | + call get_hdf5_dataset(filename, object_name, this_layer % weights) |
| 115 | + |
| 116 | + ! TODO Multidimensional arrays are stored in HDF5 in C-order. |
| 117 | + ! TODO Here we transpose the array to get to the Fortran order. |
| 118 | + ! TODO There may be a way to do this without re-allocating. |
| 119 | + ! TODO It probably doesn't matter much since we do this once. |
| 120 | + ! TODO Figure it out later. |
| 121 | + this_layer % weights = transpose(this_layer % weights) |
| 122 | + |
| 123 | + class default |
| 124 | + error stop 'Internal error in network_from_keras(); ' & |
| 125 | + // 'mismatch in layer types between the Keras and ' & |
| 126 | + // 'neural-fortran model layers.' |
| 127 | + |
| 128 | + end select |
| 129 | + |
| 130 | + end if |
| 131 | + |
| 132 | + end do |
93 | 133 |
|
94 | 134 | end function network_from_keras |
95 | 135 |
|
|
0 commit comments