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))); }
/// <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); }
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);
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))) );
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]; }
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))); }
/// <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)); }
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 }); }
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); }