Browse Source

Add SparseCategoricalCrossentropy and SparseCategoricalAccuracy.

tags/v0.100.4-load-saved-model
Haiping Chen 2 years ago
parent
commit
45f26269d8
8 changed files with 205 additions and 1 deletions
  1. +40
    -0
      src/TensorFlowNET.Core/Keras/Metrics/IMetricsApi.cs
  2. +58
    -0
      src/TensorFlowNET.Keras/BackendImpl.cs
  3. +14
    -0
      src/TensorFlowNET.Keras/Metrics/MetricsApi.cs
  4. +11
    -0
      src/TensorFlowNET.Keras/Metrics/SparseCategoricalAccuracy.cs
  5. +16
    -0
      src/TensorFlowNET.Keras/Metrics/SparseCategoricalCrossentropy.cs
  6. +11
    -0
      src/TensorFlowNET.Keras/Metrics/SparseTopKCategoricalAccuracy.cs
  7. +1
    -1
      src/TensorFlowNET.Keras/Metrics/metrics_utils.cs
  8. +54
    -0
      test/TensorFlowNET.Keras.UnitTest/Metrics/MetricsTest.cs

+ 40
- 0
src/TensorFlowNET.Core/Keras/Metrics/IMetricsApi.cs View File

@@ -22,6 +22,20 @@ public interface IMetricsApi
/// <returns>Sparse categorical accuracy values.</returns>
Tensor sparse_categorical_accuracy(Tensor y_true, Tensor y_pred);

/// <summary>
/// Computes the sparse categorical crossentropy loss.
/// </summary>
/// <param name="y_true"></param>
/// <param name="y_pred"></param>
/// <param name="from_logits"></param>
/// <param name="ignore_class"></param>
/// <param name="axis"></param>
/// <returns></returns>
Tensor sparse_categorical_crossentropy(Tensor y_true, Tensor y_pred,
bool from_logits = false,
int? ignore_class = null,
Axis? axis = null);

/// <summary>
/// Computes how often targets are in the top `K` predictions.
/// </summary>
@@ -56,6 +70,16 @@ public interface IMetricsApi
float label_smoothing = 0f,
Axis? axis = null);

/// <summary>
/// Computes the crossentropy metric between the labels and predictions.
/// </summary>
/// <returns></returns>
IMetricFunc SparseCategoricalCrossentropy(string name = "sparse_categorical_crossentropy",
TF_DataType dtype = TF_DataType.TF_FLOAT,
bool from_logits = false,
int? ignore_class = null,
Axis? axis = null);

/// <summary>
/// Computes the crossentropy metric between the labels and predictions.
/// </summary>
@@ -63,6 +87,13 @@ public interface IMetricsApi
IMetricFunc CategoricalAccuracy(string name = "categorical_accuracy",
TF_DataType dtype = TF_DataType.TF_FLOAT);

/// <summary>
/// Calculates how often predictions match integer labels.
/// </summary>
/// <returns></returns>
IMetricFunc SparseCategoricalAccuracy(string name = "sparse_categorical_accuracy",
TF_DataType dtype = TF_DataType.TF_FLOAT);

/// <summary>
/// Computes the cosine similarity between the labels and predictions.
/// </summary>
@@ -114,6 +145,15 @@ public interface IMetricsApi
string name = "top_k_categorical_accuracy",
TF_DataType dtype = TF_DataType.TF_FLOAT);

/// <summary>
/// Computes how often integer targets are in the top K predictions.
/// </summary>
/// <param name="k"></param>
/// <returns></returns>
IMetricFunc SparseTopKCategoricalAccuracy(int k = 5,
string name = "sparse_top_k_categorical_accuracy",
TF_DataType dtype = TF_DataType.TF_FLOAT);

/// <summary>
/// Computes the precision of the predictions with respect to the labels.
/// </summary>


+ 58
- 0
src/TensorFlowNET.Keras/BackendImpl.cs View File

@@ -276,6 +276,64 @@ namespace Tensorflow.Keras
return -math_ops.reduce_sum(target * math_ops.log(output), new Axis(axis));
}

public Tensor sparse_categorical_crossentropy(Tensor target, Tensor output, bool from_logits = false, int axis = -1, int? ignore_class = null)
{
target = tf.cast(target, tf.int64);
if (!from_logits)
{
var epsilon_ = constant_op.constant(epsilon(), output.dtype.as_base_dtype());
output = tf.clip_by_value(output, epsilon_, 1 - epsilon_);
output = tf.math.log(output);
}
var output_rank = output.shape.ndim;
if (output_rank > -1)
{
axis = Math.Abs(axis) % output_rank;
if (axis != output_rank - 1)
{
/*var permutation = list(
itertools.chain(
range(axis), range(axis + 1, output_rank), [axis]
)
);
output = tf.transpose(output, perm: permutation);*/
throw new NotImplementedException("");
}

}

var output_shape = tf.shape(output);
var target_rank = target.shape.ndim;
var update_shape = target_rank > -1 && output_rank > -1 && target_rank != output_rank - 1;
if (update_shape)
{
/*var target = flatten(target);
output = tf.reshape(output, [-1, output_shape[-1]]);*/
throw new NotImplementedException("");
}

if (ignore_class.HasValue)
{
throw new NotImplementedException("");
}

var res = tf.nn.sparse_softmax_cross_entropy_with_logits(labels: target, logits: output);

if (ignore_class.HasValue)
{
throw new NotImplementedException("");
}

if (update_shape && output_rank >= 3)
{
// If our output includes timesteps or
// spatial dimensions we need to reshape
res = tf.reshape(res, output_shape[":-1"]);
}

return res;
}

public Tensor binary_crossentropy(Tensor target, Tensor output, bool from_logits = false)
{
if (from_logits)


+ 14
- 0
src/TensorFlowNET.Keras/Metrics/MetricsApi.cs View File

@@ -27,6 +27,11 @@
return keras.backend.categorical_crossentropy(y_true, y_pred, from_logits: from_logits, axis: axis);
}

public Tensor sparse_categorical_crossentropy(Tensor y_true, Tensor y_pred, bool from_logits = false, int? ignore_class = null, Axis? axis = null)
{
return keras.backend.sparse_categorical_crossentropy(y_true, y_pred, from_logits: from_logits, axis: axis ?? -1, ignore_class: ignore_class);
}

/// <summary>
/// Calculates how often predictions matches integer labels.
/// </summary>
@@ -103,5 +108,14 @@

public IMetricFunc Recall(float thresholds = 0.5f, int top_k = 0, int class_id = 0, string name = "recall", TF_DataType dtype = TF_DataType.TF_FLOAT)
=> new Recall(thresholds: thresholds, top_k: top_k, class_id: class_id, name: name, dtype: dtype);

public IMetricFunc SparseCategoricalCrossentropy(string name = "sparse_categorical_crossentropy", TF_DataType dtype = TF_DataType.TF_FLOAT, bool from_logits = false, int? ignore_class = null, Axis? axis = null)
=> new SparseCategoricalCrossentropy(name: name, dtype: dtype, from_logits: from_logits, ignore_class: ignore_class, axis: axis ?? -1);

public IMetricFunc SparseTopKCategoricalAccuracy(int k = 5, string name = "sparse_top_k_categorical_accuracy", TF_DataType dtype = TF_DataType.TF_FLOAT)
=> new SparseTopKCategoricalAccuracy(k: k, name: name, dtype: dtype);

public IMetricFunc SparseCategoricalAccuracy(string name = "sparse_categorical_accuracy", TF_DataType dtype = TF_DataType.TF_FLOAT)
=> new SparseCategoricalAccuracy(name: name, dtype: dtype);
}
}

+ 11
- 0
src/TensorFlowNET.Keras/Metrics/SparseCategoricalAccuracy.cs View File

@@ -0,0 +1,11 @@
namespace Tensorflow.Keras.Metrics;

public class SparseCategoricalAccuracy : MeanMetricWrapper
{
public SparseCategoricalAccuracy(string name = "sparse_categorical_accuracy", TF_DataType dtype = TF_DataType.TF_FLOAT)
: base((yt, yp) => metrics_utils.sparse_categorical_matches(yt, yp),
name: name,
dtype: dtype)
{
}
}

+ 16
- 0
src/TensorFlowNET.Keras/Metrics/SparseCategoricalCrossentropy.cs View File

@@ -0,0 +1,16 @@
namespace Tensorflow.Keras.Metrics;

public class SparseCategoricalCrossentropy : MeanMetricWrapper
{
public SparseCategoricalCrossentropy(string name = "sparse_categorical_crossentropy",
TF_DataType dtype = TF_DataType.TF_FLOAT,
bool from_logits = false,
int? ignore_class = null,
Axis? axis = null)
: base((yt, yp) => keras.metrics.sparse_categorical_crossentropy(
yt, yp, from_logits: from_logits, ignore_class: ignore_class, axis: axis ?? -1),
name: name,
dtype: dtype)
{
}
}

+ 11
- 0
src/TensorFlowNET.Keras/Metrics/SparseTopKCategoricalAccuracy.cs View File

@@ -0,0 +1,11 @@
namespace Tensorflow.Keras.Metrics;

public class SparseTopKCategoricalAccuracy : MeanMetricWrapper
{
public SparseTopKCategoricalAccuracy(int k = 5, string name = "sparse_top_k_categorical_accuracy", TF_DataType dtype = TF_DataType.TF_FLOAT)
: base((yt, yp) => metrics_utils.sparse_top_k_categorical_matches(yt, yp, k),
name: name,
dtype: dtype)
{
}
}

+ 1
- 1
src/TensorFlowNET.Keras/Metrics/metrics_utils.cs View File

@@ -73,7 +73,7 @@ public class metrics_utils
y_true = tf.squeeze(y_true, new Shape(-1));
}
y_pred = tf.math.argmax(y_pred, axis: -1);
y_pred = tf.cast(y_pred, y_true.dtype);
var matches = tf.cast(
tf.equal(y_true, y_pred),
dtype: keras.backend.floatx()


+ 54
- 0
test/TensorFlowNET.Keras.UnitTest/Metrics/MetricsTest.cs View File

@@ -74,6 +74,26 @@ public class MetricsTest : EagerModeTestBase
Assert.AreEqual(r, 0.3f);
}

/// <summary>
/// https://www.tensorflow.org/api_docs/python/tf/keras/metrics/SparseCategoricalAccuracy
/// </summary>
[TestMethod]
public void SparseCategoricalAccuracy()
{
var y_true = np.array(new[] { 2, 1 });
var y_pred = np.array(new[,] { { 0.1f, 0.6f, 0.3f }, { 0.05f, 0.95f, 0f } });
var m = tf.keras.metrics.SparseCategoricalAccuracy();
m.update_state(y_true, y_pred);
var r = m.result().numpy();
Assert.AreEqual(r, 0.5f);

m.reset_states();
var weights = np.array(new[] { 0.7f, 0.3f });
m.update_state(y_true, y_pred, sample_weight: weights);
r = m.result().numpy();
Assert.AreEqual(r, 0.3f);
}

/// <summary>
/// https://www.tensorflow.org/api_docs/python/tf/keras/metrics/CategoricalCrossentropy
/// </summary>
@@ -94,6 +114,20 @@ public class MetricsTest : EagerModeTestBase
Assert.AreEqual(r, 1.6271976f);
}

/// <summary>
/// https://www.tensorflow.org/api_docs/python/tf/keras/metrics/SparseCategoricalCrossentropy
/// </summary>
[TestMethod]
public void SparseCategoricalCrossentropy()
{
var y_true = np.array(new[] { 1, 2 });
var y_pred = np.array(new[,] { { 0.05f, 0.95f, 0f }, { 0.1f, 0.8f, 0.1f } });
var m = tf.keras.metrics.SparseCategoricalCrossentropy();
m.update_state(y_true, y_pred);
var r = m.result().numpy();
Assert.AreEqual(r, 1.1769392f);
}

/// <summary>
/// https://www.tensorflow.org/api_docs/python/tf/keras/metrics/CosineSimilarity
/// </summary>
@@ -207,6 +241,26 @@ public class MetricsTest : EagerModeTestBase
Assert.AreEqual(r, 0.3f);
}

/// <summary>
/// https://www.tensorflow.org/api_docs/python/tf/keras/metrics/SparseTopKCategoricalAccuracy
/// </summary>
[TestMethod]
public void SparseTopKCategoricalAccuracy()
{
var y_true = np.array(new[] { 2, 1 });
var y_pred = np.array(new[,] { { 0.1f, 0.9f, 0.8f }, { 0.05f, 0.95f, 0f } });
var m = tf.keras.metrics.SparseTopKCategoricalAccuracy(k: 1);
m.update_state(y_true, y_pred);
var r = m.result().numpy();
Assert.AreEqual(r, 0.5f);

m.reset_states();
var weights = np.array(new[] { 0.7f, 0.3f });
m.update_state(y_true, y_pred, sample_weight: weights);
r = m.result().numpy();
Assert.AreEqual(r, 0.3f);
}

/// <summary>
/// https://www.tensorflow.org/api_docs/python/tf/keras/metrics/top_k_categorical_accuracy
/// </summary>


Loading…
Cancel
Save