Module delta.ml.io
Functions for IO specific to ML.
Expand source code
# Copyright © 2020, United States Government, as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All rights reserved.
#
# The DELTA (Deep Earth Learning, Tools, and Analysis) platform is
# licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0.
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Functions for IO specific to ML.
"""
import os
import h5py
import numpy as np
from packaging import version
import tensorflow.keras.backend as K #pylint: disable=no-name-in-module
import tensorflow
from delta.config import config
from delta.config.extensions import custom_objects
def save_model(model, filename):
"""
Save a model. Includes DELTA configuration.
Parameters
----------
model: tensorflow.keras.models.Model
The model to save.
filename: str
Output filename.
"""
if str(filename).endswith('.h5'):
model.save(filename, save_format='h5')
with h5py.File(filename, 'r+') as f:
f.attrs['delta'] = config.export()
else: # SavedModel format
model.save(filename)
# Record the config values into a subfolder of the savedmodel output folder
config_copy_folder = os.path.join(filename, 'assets.extra')
config_copy_path = os.path.join(config_copy_folder, 'delta_config.yaml')
if not os.path.exists(config_copy_folder):
os.mkdir(config_copy_folder)
with open(config_copy_path, 'w') as f:
f.write(config.export())
def load_model(filename):
"""
Load a model.
Parameters
----------
filename: str
Input filename.
"""
cm = custom_objects()
if version.parse(tensorflow.__version__) < version.parse('2.2'): # need to load newer models
# renamed to Model from Functional in newer versions.
# Also added Conv2D groups parameter
class OldModel(tensorflow.keras.models.Model): # pylint: disable=too-many-ancestors
@classmethod
def from_config(cls, config, custom_objects=None): #pylint: disable=redefined-outer-name
for l in config['layers']:
if l['class_name'] == 'Conv2D' and 'groups' in l['config']:
del l['config']['groups']
return tensorflow.keras.models.Model.from_config(config, custom_objects)
cm.update({'Functional': OldModel})
model = tensorflow.keras.models.load_model(filename, compile=False, custom_objects=cm)
return model
def print_layer(l):
"""
Print a layer to stdout.
l: tensorflow.keras.layers.Layer
The layer to print.
"""
s = f"{l.name:<25} {str(l.input_shape):<20} -> {str(l.output_shape):20}"
c = l.get_config()
if 'strides' in c:
s += f" s: {str(c['strides'])}"
if 'kernel_size' in c:
s += f" ks: {str(c['kernel_size'])}"
print(s)
def print_network(a, tile_shape=None):
"""
Print a model to stdout.
a: tensorflow.keras.models.Model
The model to print.
tile_shape: Optional[Tuple[int, int]]
If specified, print layer output sizes (necessary for FCN only).
"""
for l in a.layers:
print_layer(l)
in_shape = a.layers[0].input_shape[0]
if tile_shape is not None:
in_shape = (in_shape[0], tile_shape[0], tile_shape[1], in_shape[3])
out_shape = a.compute_output_shape(in_shape)
print('Size: ' + str(in_shape[1:]) + ' --> ' + str(out_shape[1:]))
if out_shape[1] is not None and out_shape[2] is not None:
print('Compression Rate - ', out_shape[1] * out_shape[2] * out_shape[3] /
(in_shape[1] * in_shape[2] * in_shape[3]))
print('Layers - ', len(a.layers))
print('Trainable Parameters - ', np.sum([K.count_params(w) for w in a.trainable_weights]))
Functions
def load_model(filename)
-
Load a model.
Parameters
filename
:str
- Input filename.
Expand source code
def load_model(filename): """ Load a model. Parameters ---------- filename: str Input filename. """ cm = custom_objects() if version.parse(tensorflow.__version__) < version.parse('2.2'): # need to load newer models # renamed to Model from Functional in newer versions. # Also added Conv2D groups parameter class OldModel(tensorflow.keras.models.Model): # pylint: disable=too-many-ancestors @classmethod def from_config(cls, config, custom_objects=None): #pylint: disable=redefined-outer-name for l in config['layers']: if l['class_name'] == 'Conv2D' and 'groups' in l['config']: del l['config']['groups'] return tensorflow.keras.models.Model.from_config(config, custom_objects) cm.update({'Functional': OldModel}) model = tensorflow.keras.models.load_model(filename, compile=False, custom_objects=cm) return model
def print_layer(l)
-
Print a layer to stdout.
l: tensorflow.keras.layers.Layer The layer to print.
Expand source code
def print_layer(l): """ Print a layer to stdout. l: tensorflow.keras.layers.Layer The layer to print. """ s = f"{l.name:<25} {str(l.input_shape):<20} -> {str(l.output_shape):20}" c = l.get_config() if 'strides' in c: s += f" s: {str(c['strides'])}" if 'kernel_size' in c: s += f" ks: {str(c['kernel_size'])}" print(s)
def print_network(a, tile_shape=None)
-
Print a model to stdout.
a: tensorflow.keras.models.Model The model to print. tile_shape: Optional[Tuple[int, int]] If specified, print layer output sizes (necessary for FCN only).
Expand source code
def print_network(a, tile_shape=None): """ Print a model to stdout. a: tensorflow.keras.models.Model The model to print. tile_shape: Optional[Tuple[int, int]] If specified, print layer output sizes (necessary for FCN only). """ for l in a.layers: print_layer(l) in_shape = a.layers[0].input_shape[0] if tile_shape is not None: in_shape = (in_shape[0], tile_shape[0], tile_shape[1], in_shape[3]) out_shape = a.compute_output_shape(in_shape) print('Size: ' + str(in_shape[1:]) + ' --> ' + str(out_shape[1:])) if out_shape[1] is not None and out_shape[2] is not None: print('Compression Rate - ', out_shape[1] * out_shape[2] * out_shape[3] / (in_shape[1] * in_shape[2] * in_shape[3])) print('Layers - ', len(a.layers)) print('Trainable Parameters - ', np.sum([K.count_params(w) for w in a.trainable_weights]))
def save_model(model, filename)
-
Save a model. Includes DELTA configuration.
Parameters
model
:tensorflow.keras.models.Model
- The model to save.
filename
:str
- Output filename.
Expand source code
def save_model(model, filename): """ Save a model. Includes DELTA configuration. Parameters ---------- model: tensorflow.keras.models.Model The model to save. filename: str Output filename. """ if str(filename).endswith('.h5'): model.save(filename, save_format='h5') with h5py.File(filename, 'r+') as f: f.attrs['delta'] = config.export() else: # SavedModel format model.save(filename) # Record the config values into a subfolder of the savedmodel output folder config_copy_folder = os.path.join(filename, 'assets.extra') config_copy_path = os.path.join(config_copy_folder, 'delta_config.yaml') if not os.path.exists(config_copy_folder): os.mkdir(config_copy_folder) with open(config_copy_path, 'w') as f: f.write(config.export())