[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/feelsyt/TensorFlow.NET/master/src/TensorflowNET.Hub/KerasLayer.cs [Back]  [Original]

using System;
using System.Collections.Generic;
using System.Linq;
using Tensorflow.Common.Types;
using Tensorflow.Keras.Engine;
using Tensorflow.Train;
using Tensorflow.Training;
using Tensorflow.Training.Saving.SavedModel;
using static Tensorflow.Binding;

namespace Tensorflow.Hub
{
    public class KerasLayer : Layer
    {
        private string _handle;
        private LoadOptions? _load_options;
        private Trackable _func;
        private Func _callable;

        public KerasLayer(string handle, bool trainable = false, LoadOptions? load_options = null) :
            base(new Keras.ArgsDefinition.LayerArgs() { Trainable = trainable })
        {
            _handle = handle;
            _load_options = load_options;

            _func = load_module(_handle, _load_options);
            _track_trackable(_func, "_func");
            // TODO(Rinne): deal with _is_hub_module_v1.

            _callable = _get_callable();
            _setup_layer(trainable);
        }

        private void _setup_layer(bool trainable = false)
        {
            HashSet trainable_variables;
            if (_func is Layer layer)
            {
                foreach (var v in layer.TrainableVariables)
                {
                    _add_existing_weight(v, true);
                }
                trainable_variables = new HashSet(layer.TrainableVariables.Select(v => v.UniqueId));
            }
            else if (_func.CustomizedFields.TryGetValue("trainable_variables", out var obj) && obj is IEnumerable trackables)
            {
                foreach (var trackable in trackables)
                {
                    if (trackable is IVariableV1 v)
                    {
                        _add_existing_weight(v, true);
                    }
                }
                trainable_variables = new HashSet(trackables.Where(t => t is IVariableV1).Select(t => (t as IVariableV1).UniqueId));
            }
            else
            {
                trainable_variables = new HashSet();
            }

            if (_func is Layer)
            {
                layer = (Layer)_func;
                foreach (var v in layer.Variables)
                {
                    if (!trainable_variables.Contains(v.UniqueId))
                    {
                        _add_existing_weight(v, false);
                    }
                }
            }
            else if (_func.CustomizedFields.TryGetValue("variables", out var obj) && obj is IEnumerable total_trackables)
            {
                foreach (var trackable in total_trackables)
                {
                    if (trackable is IVariableV1 v && !trainable_variables.Contains(v.UniqueId))
                    {
                        _add_existing_weight(v, false);
                    }
                }
            }

            if (_func.CustomizedFields.ContainsKey("regularization_losses"))
            {
                if ((_func.CustomizedFields["regularization_losses"] as ListWrapper)?.Count > 0)
                {
                    throw new NotImplementedException("The regularization_losses loading has not been supported yet, " +
                        "please submit an issue to https://github.com/SciSharp/TensorFlow.NET/issues to let us know and add a feature.");
                }
            }
        }

        protected override Tensors Call(Tensors inputs, Tensors state = null, bool? training = null, IOptionalArgs? optionalArgs = null)
        {
            _check_trainability();

            // TODO(Rinne): deal with training_argument

            var result = _callable(inputs);

            return _apply_output_shape_if_set(inputs, result);
        }

        private void _check_trainability()
        {
            if (!Trainable) return;

            // TODO(Rinne): deal with _is_hub_module_v1 and signature

            if (TrainableWeights is null || TrainableWeights.Count == 0)
            {
                tf.Logger.Error("hub.KerasLayer is trainable but has zero trainable weights.");
            }
        }

        private Tensors _apply_output_shape_if_set(Tensors inputs, Tensors result)
        {
            // TODO(Rinne): implement it.
            return result;
        }

        private void _add_existing_weight(IVariableV1 weight, bool? trainable = null)
        {
            bool is_trainable;
            if (trainable is null)
            {
                is_trainable = weight.Trainable;
            }
            else
            {
                is_trainable = trainable.Value;
            }
            add_weight(weight.Name, weight.shape, weight.dtype, trainable: is_trainable, getter: x => weight);
        }

        private Func _get_callable()
        {
            if (_func is Layer layer)
            {
                return x => layer.Apply(x);
            }
            if (_func.CustomizedFields.ContainsKey("__call__"))
            {
                if (_func.CustomizedFields["__call__"] is RestoredFunction function)
                {
                    return x => function.Apply(x);
                }
            }
            throw new ValueError("Cannot get the callable from the model.");
        }

        private static Trackable load_module(string handle, LoadOptions? load_options = null)
        {
            //var set_load_options = load_options ?? LoadContext.get_load_option();
            return module_v2.load(handle, load_options);
        }
    }
}

Web Proxy Viewer  |  New URL  |  Original Page