Esempio n. 1
0
        static Tensor TopLogits(Tensor logits, int topK)
        {
            if (topK == 0)
            {
                // no truncation
                return(logits);
            }

            Tensor TopK()
            {
                var valuesIndices = tf.nn.top_k_dyn(logits, k: topK);
                var values        = valuesIndices.Item1;
                var minValues     = values[Range.All, -1, tf.newaxis];

                return(tf.where_dyn(((dynamic)logits).__lt__(minValues),
                                    tf.ones_like(logits, dtype: logits.dtype) * -1e10,
                                    logits));
            }

            Tensor isTopKZero = tf.equal(topK, 0);

            return(tf.cond_dyn(isTopKZero,
                               PythonFunctionContainer.Of(() => logits),
                               PythonFunctionContainer.Of(TopK)));
        }
Esempio n. 2
0
        /// <summary>
        /// Creates a dense neural network
        /// </summary>
        public static Tensor MultiLayerPreceptron(Tensor input, int[] hiddenSizes,
                                                  PythonFunctionContainer innerActivation,
                                                  PythonFunctionContainer?outputActivation)
        {
            if (input is null)
            {
                throw new ArgumentNullException(nameof(input));
            }
            if (hiddenSizes is null)
            {
                throw new ArgumentNullException(nameof(hiddenSizes));
            }
            if (innerActivation is null)
            {
                throw new ArgumentNullException(nameof(innerActivation));
            }

            for (int layer = 0; layer < hiddenSizes.Length; layer++)
            {
                input = tf.layers.dense(input,
                                        units: hiddenSizes[layer],
                                        activation: layer == hiddenSizes.Length - 1 ? outputActivation : innerActivation
                                        );
            }
            return(input);
        }
Esempio n. 3
0
 static ActorCritic ActorCriticFactory(
     Tensor input, Tensor action, int[] hiddenSizes,
     PyFunc innerActivation, PyFunc?outputActivation,
     Func <Tensor, int, int[], PyFunc, PyFunc?, Policy> policyFactory,
     float actionLimit)
 => new ActorCritic(input, action, hiddenSizes,
                    innerActivation, outputActivation,
                    policyFactory, actionLimit);
Esempio n. 4
0
 public override dynamic __call__(IGraphNodeBase step)
 => tf.cond(step < this.warmupSteps,
            PythonFunctionContainer.Of <Tensor>(() => (step / this.warmupSteps) * this.initialLR),
            PythonFunctionContainer.Of <Tensor>(() => this.finalLR
                                                + 0.5f * (this.initialLR - this.finalLR)
                                                * (1 + tf.cos(
                                                       (step - this.warmupSteps) / (this.totalSteps - this.warmupSteps)
                                                       * Math.PI)))
            );
Esempio n. 5
0
        public ResNetBlock(int kernelSize, int[] filters, PythonFunctionContainer?activation = null)
        {
            this.activation = activation ?? tf.keras.activations.relu_fn;
            for (int part = 0; part < PartCount; part++)
            {
                this.convs.Add(this.Track(part == 1
                    ? Conv2D.NewDyn(filters: filters[part], kernel_size: kernelSize, padding: "same")
                    : Conv2D.NewDyn(filters[part], kernel_size: (1, 1))));
                this.batchNorms.Add(this.Track(new BatchNormalization()));
            }

            this.outputChannels = filters[PartCount - 1];
        }
Esempio n. 6
0
            public static Callback Create(EventHandler <EpochEndEventArgs> onLossImproved)
            {
                double bestLoss = double.PositiveInfinity;

                void on_epoch_end(int epoch, IDictionary <string, dynamic> logs)
                {
                    if (logs["loss"] < bestLoss)
                    {
                        bestLoss = logs["loss"];
                        onLossImproved?.Invoke(null, new EpochEndEventArgs {
                            Epoch = epoch,
                            Logs  = logs,
                        });
                    }
                }

                var callbackFn = new Action <int, IDictionary <string, dynamic> >(on_epoch_end);

                // using LabmdaCallback is more performant, as it does not require TF to call on_batch_begin
                return(new LambdaCallback(on_epoch_end: PythonFunctionContainer.Of(callbackFn)));
            }
Esempio n. 7
0
        /// <summary>
        /// Creates a dense neural network, that learns a gaussian distribution over desired actions.
        /// <para>See also: https://www.reddit.com/r/MachineLearning/comments/7fgzfl/d_what_is_gaussian_mlp_policy/ </para>
        /// </summary>
        /// <param name="input">Tensor, representing agent observations</param>
        /// <param name="actionDimensions">Number of action dimentions (e.g. how many degrees
        /// of joystick control the network has)</param>
        /// <param name="hiddenSizes">In a dense layer, sizes of inner layers</param>
        /// <param name="innerActivation">Activation function to use for inner layers of
        /// policy and reward estimation networks. Typically a variant of ReLU (circa 2019).</param>
        /// <param name="outputActivation">Optional extra activation function to use for the output
        /// of policy network. Not needed (e.g. <c>null</c>) circa 2019.</param>
        public static Policy GaussianPolicyNetwork(Tensor input, int actionDimensions, int[] hiddenSizes,
                                                   PythonFunctionContainer innerActivation,
                                                   PythonFunctionContainer?outputActivation)
        {
            if (input is null)
            {
                throw new ArgumentNullException(nameof(input));
            }
            if (hiddenSizes is null)
            {
                throw new ArgumentNullException(nameof(hiddenSizes));
            }
            if (innerActivation is null)
            {
                throw new ArgumentNullException(nameof(innerActivation));
            }

            var    network = MultiLayerPreceptron(input, hiddenSizes, innerActivation, innerActivation);
            Tensor mu      = tf.layers.dense(network, units: actionDimensions, activation: outputActivation, name: "mu");

            Tensor logStd;

            using (new variable_scope("logStd").StartUsing()) {
                logStd = tf.layers.dense(network, units: actionDimensions, activation: tf.tanh_fn);
                logStd = tf.clip_by_value(logStd, clip_value_min: LogStdMin, clip_value_max: LogStdMax);
            }

            Tensor std = tf.exp(logStd, name: "std");
            Tensor pi;

            using (new variable_scope("pi").StartUsing())
                pi = tf.add(mu, tf.random_normal(tf.shape(mu)) * std, name: "pi");
            var logpPi = GaussianLikelihood(input: pi, mu: mu, logStd: logStd, name: "logpPi");

            return(new Policy(mu: mu, pi: pi, logProbPi: logpPi));
        }
Esempio n. 8
0
        static void Main(string[] args)
        {
            GradientEngine.UseEnvironmentFromVariable();
            TensorFlowSetup.Instance.EnsureInitialized();

            // this allows SIREN to oversaturate channels without adding to the loss
            var clampToValidChannelRange = PythonFunctionContainer.Of <Tensor, Tensor>(ClampToValidChannelValueRange);
            var siren = new Sequential(new object[] {
                new GaussianNoise(stddev: 1f / (128 * 1024)),
                new Siren(2, Enumerable.Repeat(256, 5).ToArray()),
                new Dense(units: 4, activation: clampToValidChannelRange),
                new GaussianNoise(stddev: 1f / 128),
            });

            siren.compile(
                // too slow to converge
                //optimizer: new SGD(momentum: 0.5),
                // lowered learning rate to avoid destabilization
                optimizer: new Adam(learning_rate: 0.00032),
                loss: "mse");

            if (args.Length == 0)
            {
                siren.load_weights("sample.weights");
                Render(siren, 1034 * 3, 1536 * 3, "sample6X.png");
                return;
            }

            foreach (string imagePath in args)
            {
                using var original = new Bitmap(imagePath);
                byte[,,] image     = ToBytesHWC(original);
                int height   = image.GetLength(0);
                int width    = image.GetLength(1);
                int channels = image.GetLength(2);
                Debug.Assert(channels == 4);

                var imageSamples = PrepareImage(image);

                var coords = ImageTools.Coord(height, width).ToNumPyArray()
                             .reshape(new[] { width *height, 2 });

                var upscaleCoords = ImageTools.Coord(height * 2, width * 2).ToNumPyArray();

                var improved = ImprovedCallback.Create((sender, eventArgs) => {
                    if (eventArgs.Epoch < 10)
                    {
                        return;
                    }
                    ndarray <float> upscaled = siren.predict(
                        upscaleCoords.reshape(new[] { height *width * 4, 2 }),
                        batch_size: 1024);
                    upscaled         = (ndarray <float>)upscaled.reshape(new[] { height * 2, width * 2, channels });
                    using var bitmap = ToImage(RestoreImage(upscaled));
                    bitmap.Save("sample4X.png", ImageFormat.Png);

                    siren.save_weights("sample.weights");

                    Console.WriteLine();
                    Console.WriteLine("saved!");
                });

                siren.fit(coords, imageSamples, epochs: 100, batchSize: 16 * 1024,
                          shuffleMode: TrainingShuffleMode.Epoch,
                          callbacks: new ICallback[] { improved });
            }
        }
        public CharRNNModel(CharRNNModelParameters parameters, bool training = true)
        {
            this.parameters = parameters ?? throw new ArgumentNullException(nameof(parameters));
            if (!training)
            {
                this.parameters.BatchSize = 1;
                this.parameters.SeqLength = 1;
            }

            if (!ModelTypeToCellFunction.TryGetValue(parameters.ModelType, out this.cellFactory))
            {
                throw new NotSupportedException(parameters.ModelType.ToString());
            }

            for (int i = 0; i < parameters.LayerCount; i++)
            {
                RNNCell cell = this.cellFactory(parameters.RNNSize);
                if (training && (parameters.KeepOutputProbability < 1 || parameters.KeepInputProbability < 1))
                {
                    cell = new DropoutWrapper(cell,
                                              input_keep_prob: parameters.KeepInputProbability,
                                              output_keep_prob: parameters.KeepOutputProbability);
                }
                this.cells.Add(cell);
            }
            this.rnn          = new MultiRNNCell(this.cells, state_is_tuple: true);
            this.inputData    = tf.placeholder(tf.int32, new TensorShape(parameters.BatchSize, parameters.SeqLength));
            this.targets      = tf.placeholder(tf.int32, new TensorShape(parameters.BatchSize, parameters.SeqLength));
            this.initialState = this.rnn.zero_state(parameters.BatchSize, tf.float32);

            Variable softmax_W = null, softmax_b = null;

            new variable_scope("rnnlm").UseSelf(_ => {
                softmax_W = tf.get_variable("softmax_w", new TensorShape(parameters.RNNSize, parameters.VocabularySize));
                softmax_b = tf.get_variable("softmax_b", new TensorShape(parameters.VocabularySize));
            });

            Variable embedding = tf.get_variable("embedding", new TensorShape(parameters.VocabularySize, parameters.RNNSize));
            Tensor   input     = tf.nn.embedding_lookup(embedding, this.inputData);

            // dropout beta testing: double check which one should affect next line
            if (training && parameters.KeepOutputProbability < 1)
            {
                input = tf.nn.dropout(input, parameters.KeepOutputProbability);
            }

            IList <Tensor> inputs = tf.split(input, parameters.SeqLength, axis: 1);

            inputs = inputs.Select(i => (Tensor)tf.squeeze(i, axis: 1)).ToList();

            dynamic Loop(dynamic prev, dynamic _)
            {
                prev = tf.matmul(prev, softmax_W) + softmax_b;
                var prevSymbol = tf.stop_gradient(tf.argmax(prev, 1));

                return(tf.nn.embedding_lookup(embedding, prevSymbol));
            }

            var decoder = tensorflow.contrib.legacy_seq2seq.legacy_seq2seq.rnn_decoder_dyn(
                decoder_inputs: inputs,
                initial_state: this.initialState.Items(),
                cell: this.rnn,
                loop_function: training ? null : PythonFunctionContainer.Of(new Func <dynamic, dynamic, dynamic>(Loop)), scope: "rnnlm");
            IList <Tensor> outputs             = decoder.Item1;
            var            lastState           = (seq2seqState)decoder.Item2;
            dynamic        contatenatedOutputs = tf.concat(outputs, 1);
            var            output = tensorflow.tf.reshape(contatenatedOutputs, new[] { -1, parameters.RNNSize });

            this.logits = tf.matmul(output, softmax_W) + softmax_b;
            this.probs  = tf.nn.softmax(new[] { this.logits });
            this.loss   = tensorflow.contrib.legacy_seq2seq.legacy_seq2seq.sequence_loss_by_example_dyn(
                logits: new[] { this.logits },
                targets: new[] { tf.reshape(this.targets, new[] { -1 }) },
                weights: new[] { tf.ones(new[] { parameters.BatchSize *parameters.SeqLength }) });

            Tensor cost = null;

            new name_scope("cost").UseSelf(_ => {
                cost = tf.reduce_sum(this.loss) / parameters.BatchSize / parameters.SeqLength;
            });
            this.cost         = cost;
            this.finalState   = lastState;
            this.learningRate = new Variable(0.0, trainable: false);
            var tvars = tf.trainable_variables();

            IEnumerable <object> grads     = tf.clip_by_global_norm(tf.gradients(this.cost, tvars), parameters.GradientClip).Item1;
            AdamOptimizer        optimizer = null;

            new name_scope("optimizer").UseSelf(_ => optimizer = new AdamOptimizer(this.learningRate));
            this.trainOp = optimizer.apply_gradients(grads.Zip(tvars, (grad, @var) => (dynamic)(grad, @var)));

            tf.summary.histogram("logits", new[] { this.logits });
            tf.summary.histogram("loss", new[] { this.loss });
            tf.summary.histogram("train_loss", new[] { this.cost });
        }
Esempio n. 10
0
        public static Tensor SampleSequence(HParams hParams, int length,
                                            string startToken = null, int?batchSize = null, dynamic context = null,
                                            float temperature = 1, int topK         = 0)
        {
            if (((startToken == null) ^ (context == null)) == false)
            {
                throw new ArgumentException($"Exactly one of {nameof(startToken)} or {nameof(context)} has to be specified");
            }

            SortedDictionary <string, dynamic> Step(HParams @params, Tensor tokens, dynamic past = null)
            {
                var lmOutput = Gpt2Model.Model(hParams: @params, input: tokens, past: past, reuse: _ReuseMode.AUTO_REUSE);

                var    logits   = lmOutput["logits"][Range.All, Range.All, Range.EndAt((int)@params.get("n_vocab"))];
                Tensor presents = lmOutput["present"];

                int?[] pastShape = Gpt2Model.PastShape(hParams: @params, batchSize: batchSize);
                presents.set_shape_(pastShape.Cast <object>());

                return(new SortedDictionary <string, object>
                {
                    ["logits"] = logits,
                    ["presents"] = presents,
                });
            }

            Tensor result = null;

            new name_scope("sample_sequence").Use(_ =>
            {
                // Don't feed the last context token -- leave that to the loop below
                // TODO: Would be slightly faster if we called step on the entire context,
                // rather than leaving the last token transformer calculation to the while loop.
                var contextOutput = Step(hParams, context[Range.All, Range.EndAt(new Index(1, fromEnd: true))]);

                Tensor[] Body(object past, dynamic prev, object output)
                {
                    var nextOutputs = Step(hParams, prev[Range.All, tf.newaxis], past: past);
                    Tensor logits   = nextOutputs["logits"][Range.All, -1, Range.All] / tf.to_float(temperature);
                    logits          = TopLogits(logits, topK: topK);
                    var samples     = tf.multinomial_dyn(logits, num_samples: 1, output_dtype: tf.int32);
                    return(new Tensor[]
                    {
                        tf.concat(new [] { past, nextOutputs["presents"] }, axis: -2),
                        tf.squeeze(samples, axis: new[] { 1 }),
                        tf.concat(new [] { output, samples }, axis: 1),
                    });
                }

                bool True(object _a, object _b, object _c) => true;

                dynamic[] loopVars = new[] {
                    contextOutput["presents"],
                    context[Range.All, -1],
                    context,
                };
                TensorShape[] shapeInvariants = new[] {
                    new TensorShape(Gpt2Model.PastShape(hParams: hParams, batchSize: batchSize)),
                    new TensorShape(batchSize),
                    new TensorShape((int?)batchSize, (int?)null),
                };
                result = tf.while_loop(
                    cond: PythonFunctionContainer.Of <object, object, object, bool>(True),
                    body: PythonFunctionContainer.Of(new Func <object, object, object, Tensor[]>(Body)),
                    parallel_iterations: 10,
                    swap_memory: false,
                    name: null,
                    maximum_iterations: tf.constant(length),
                    loop_vars: loopVars,
                    shape_invariants: shapeInvariants,
                    back_prop: false)
                         [2];
            });
            return(result);
        }