| @@ -39,6 +39,9 @@ namespace Tensorflow | |||||
| public Tensor sum(Tensor x, Axis? axis = null, string name = null) | public Tensor sum(Tensor x, Axis? axis = null, string name = null) | ||||
| => math_ops.reduce_sum(x, axis: axis, name: name); | => math_ops.reduce_sum(x, axis: axis, name: name); | ||||
| public Tensor in_top_k(Tensor predictions, Tensor targets, int k, string name = "InTopK") | |||||
| => nn_ops.in_top_k(predictions, targets, k, name); | |||||
| /// <summary> | /// <summary> | ||||
| /// | /// | ||||
| /// </summary> | /// </summary> | ||||
| @@ -3,6 +3,7 @@ using System.Collections.Generic; | |||||
| using System.Text; | using System.Text; | ||||
| using Tensorflow.Keras.Layers; | using Tensorflow.Keras.Layers; | ||||
| using Tensorflow.Keras.Losses; | using Tensorflow.Keras.Losses; | ||||
| using Tensorflow.Keras.Metrics; | |||||
| namespace Tensorflow.Keras | namespace Tensorflow.Keras | ||||
| { | { | ||||
| @@ -10,6 +11,7 @@ namespace Tensorflow.Keras | |||||
| { | { | ||||
| public ILayersApi layers { get; } | public ILayersApi layers { get; } | ||||
| public ILossesApi losses { get; } | public ILossesApi losses { get; } | ||||
| public IMetricsApi metrics { get; } | |||||
| public IInitializersApi initializers { get; } | public IInitializersApi initializers { get; } | ||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,29 @@ | |||||
| namespace Tensorflow.Keras.Metrics; | |||||
| public interface IMetricsApi | |||||
| { | |||||
| Tensor binary_accuracy(Tensor y_true, Tensor y_pred); | |||||
| Tensor categorical_accuracy(Tensor y_true, Tensor y_pred); | |||||
| Tensor mean_absolute_error(Tensor y_true, Tensor y_pred); | |||||
| Tensor mean_absolute_percentage_error(Tensor y_true, Tensor y_pred); | |||||
| /// <summary> | |||||
| /// Calculates how often predictions matches integer labels. | |||||
| /// </summary> | |||||
| /// <param name="y_true">Integer ground truth values.</param> | |||||
| /// <param name="y_pred">The prediction values.</param> | |||||
| /// <returns>Sparse categorical accuracy values.</returns> | |||||
| Tensor sparse_categorical_accuracy(Tensor y_true, Tensor y_pred); | |||||
| /// <summary> | |||||
| /// Computes how often targets are in the top `K` predictions. | |||||
| /// </summary> | |||||
| /// <param name="y_true"></param> | |||||
| /// <param name="y_pred"></param> | |||||
| /// <param name="k"></param> | |||||
| /// <returns></returns> | |||||
| Tensor top_k_categorical_accuracy(Tensor y_true, Tensor y_pred, int k = 5); | |||||
| } | |||||
| @@ -240,16 +240,8 @@ namespace Tensorflow.Operations | |||||
| /// <param name="name"></param> | /// <param name="name"></param> | ||||
| /// <returns>A `Tensor` of type `bool`.</returns> | /// <returns>A `Tensor` of type `bool`.</returns> | ||||
| public static Tensor in_top_kv2(Tensor predictions, Tensor targets, int k, string name = null) | public static Tensor in_top_kv2(Tensor predictions, Tensor targets, int k, string name = null) | ||||
| { | |||||
| var _op = tf.OpDefLib._apply_op_helper("InTopKV2", name: name, args: new | |||||
| { | |||||
| predictions, | |||||
| targets, | |||||
| k | |||||
| }); | |||||
| return _op.output; | |||||
| } | |||||
| => tf.Context.ExecuteOp("InTopKV2", name, | |||||
| new ExecuteOpArgs(predictions, targets, k)); | |||||
| public static Tensor leaky_relu(Tensor features, float alpha = 0.2f, string name = null) | public static Tensor leaky_relu(Tensor features, float alpha = 0.2f, string name = null) | ||||
| => tf.Context.ExecuteOp("LeakyRelu", name, | => tf.Context.ExecuteOp("LeakyRelu", name, | ||||
| @@ -121,6 +121,11 @@ namespace Tensorflow | |||||
| if (dtype == TF_DataType.TF_INT32) | if (dtype == TF_DataType.TF_INT32) | ||||
| values = long_values.Select(x => (int)Convert.ChangeType(x, new_system_dtype)).ToArray(); | values = long_values.Select(x => (int)Convert.ChangeType(x, new_system_dtype)).ToArray(); | ||||
| } | } | ||||
| else if (values is double[] double_values) | |||||
| { | |||||
| if (dtype == TF_DataType.TF_FLOAT) | |||||
| values = double_values.Select(x => (float)Convert.ChangeType(x, new_system_dtype)).ToArray(); | |||||
| } | |||||
| else | else | ||||
| values = Convert.ChangeType(values, new_system_dtype); | values = Convert.ChangeType(values, new_system_dtype); | ||||
| @@ -27,7 +27,7 @@ namespace Tensorflow.Keras | |||||
| ThreadLocal<BackendImpl> _backend = new ThreadLocal<BackendImpl>(() => new BackendImpl()); | ThreadLocal<BackendImpl> _backend = new ThreadLocal<BackendImpl>(() => new BackendImpl()); | ||||
| public BackendImpl backend => _backend.Value; | public BackendImpl backend => _backend.Value; | ||||
| public OptimizerApi optimizers { get; } = new OptimizerApi(); | public OptimizerApi optimizers { get; } = new OptimizerApi(); | ||||
| public MetricsApi metrics { get; } = new MetricsApi(); | |||||
| public IMetricsApi metrics { get; } = new MetricsApi(); | |||||
| public ModelsApi models { get; } = new ModelsApi(); | public ModelsApi models { get; } = new ModelsApi(); | ||||
| public KerasUtils utils { get; } = new KerasUtils(); | public KerasUtils utils { get; } = new KerasUtils(); | ||||
| @@ -2,7 +2,7 @@ | |||||
| namespace Tensorflow.Keras.Metrics | namespace Tensorflow.Keras.Metrics | ||||
| { | { | ||||
| public class MetricsApi | |||||
| public class MetricsApi : IMetricsApi | |||||
| { | { | ||||
| public Tensor binary_accuracy(Tensor y_true, Tensor y_pred) | public Tensor binary_accuracy(Tensor y_true, Tensor y_pred) | ||||
| { | { | ||||
| @@ -53,5 +53,12 @@ namespace Tensorflow.Keras.Metrics | |||||
| var diff = (y_true - y_pred) / math_ops.maximum(math_ops.abs(y_true), keras.backend.epsilon()); | var diff = (y_true - y_pred) / math_ops.maximum(math_ops.abs(y_true), keras.backend.epsilon()); | ||||
| return 100f * keras.backend.mean(math_ops.abs(diff), axis: -1); | return 100f * keras.backend.mean(math_ops.abs(diff), axis: -1); | ||||
| } | } | ||||
| public Tensor top_k_categorical_accuracy(Tensor y_true, Tensor y_pred, int k = 5) | |||||
| { | |||||
| return metrics_utils.sparse_top_k_categorical_matches( | |||||
| tf.math.argmax(y_true, axis: -1), y_pred, k | |||||
| ); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,39 @@ | |||||
| using Tensorflow.NumPy; | |||||
| namespace Tensorflow.Keras.Metrics; | |||||
| public class metrics_utils | |||||
| { | |||||
| public static Tensor sparse_top_k_categorical_matches(Tensor y_true, Tensor y_pred, int k = 5) | |||||
| { | |||||
| var reshape_matches = false; | |||||
| var y_true_rank = y_true.shape.ndim; | |||||
| var y_pred_rank = y_pred.shape.ndim; | |||||
| var y_true_org_shape = tf.shape(y_true); | |||||
| if (y_pred_rank > 2) | |||||
| { | |||||
| y_pred = tf.reshape(y_pred, (-1, y_pred.shape[-1])); | |||||
| } | |||||
| if (y_true_rank > 1) | |||||
| { | |||||
| reshape_matches = true; | |||||
| y_true = tf.reshape(y_true, new Shape(-1)); | |||||
| } | |||||
| var matches = tf.cast( | |||||
| tf.math.in_top_k( | |||||
| predictions: y_pred, targets: tf.cast(y_true, np.int32), k: k | |||||
| ), | |||||
| dtype: keras.backend.floatx() | |||||
| ); | |||||
| if (reshape_matches) | |||||
| { | |||||
| return tf.reshape(matches, shape: y_true_org_shape); | |||||
| } | |||||
| return matches; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,28 @@ | |||||
| using Microsoft.VisualStudio.TestTools.UnitTesting; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Text; | |||||
| using System.Threading.Tasks; | |||||
| using Tensorflow; | |||||
| using Tensorflow.NumPy; | |||||
| using static Tensorflow.Binding; | |||||
| using static Tensorflow.KerasApi; | |||||
| namespace TensorFlowNET.Keras.UnitTest; | |||||
| [TestClass] | |||||
| public class MetricsTest : EagerModeTestBase | |||||
| { | |||||
| /// <summary> | |||||
| /// https://www.tensorflow.org/api_docs/python/tf/keras/metrics/top_k_categorical_accuracy | |||||
| /// </summary> | |||||
| [TestMethod] | |||||
| public void top_k_categorical_accuracy() | |||||
| { | |||||
| var y_true = np.array(new[,] { { 0, 0, 1 }, { 0, 1, 0 } }); | |||||
| var y_pred = np.array(new[,] { { 0.1f, 0.9f, 0.8f }, { 0.05f, 0.95f, 0f } }); | |||||
| var m = tf.keras.metrics.top_k_categorical_accuracy(y_true, y_pred, k: 3); | |||||
| Assert.AreEqual(m.numpy(), new[] { 1f, 1f }); | |||||
| } | |||||
| } | |||||