Browse Source

Add metric of HammingLoss.

tags/v0.100.4-load-saved-model
Haiping Chen 2 years ago
parent
commit
c72f47990e
8 changed files with 122 additions and 2 deletions
  1. +2
    -0
      src/TensorFlowNET.Core/APIs/tf.math.cs
  2. +14
    -1
      src/TensorFlowNET.Core/Keras/Metrics/IMetricsApi.cs
  3. +12
    -0
      src/TensorFlowNET.Core/Operations/math_ops.cs
  4. +1
    -1
      src/TensorFlowNET.Core/Tensorflow.Binding.csproj
  5. +15
    -0
      src/TensorFlowNET.Keras/Metrics/HammingLoss.cs
  6. +3
    -0
      src/TensorFlowNET.Keras/Metrics/MetricsApi.cs
  7. +30
    -0
      src/TensorFlowNET.Keras/Metrics/metrics_utils.cs
  8. +45
    -0
      test/TensorFlowNET.Keras.UnitTest/Metrics/MetricsTest.cs

+ 2
- 0
src/TensorFlowNET.Core/APIs/tf.math.cs View File

@@ -24,6 +24,8 @@ namespace Tensorflow
public Tensor argmax(Tensor input, Axis axis = null, string name = null, int? dimension = null, TF_DataType output_type = TF_DataType.TF_INT64) public Tensor argmax(Tensor input, Axis axis = null, string name = null, int? dimension = null, TF_DataType output_type = TF_DataType.TF_INT64)
=> gen_math_ops.arg_max(input, axis, name: name, output_type: output_type); => gen_math_ops.arg_max(input, axis, name: name, output_type: output_type);


public Tensor count_nonzero(Tensor input, Axis? axis = null, bool? keepdims = null, TF_DataType dtype = TF_DataType.TF_INT64, string name = null)
=> math_ops.count_nonzero_v2(input, axis: axis, keepdims: keepdims ?? false, dtype: dtype);
public Tensor log(Tensor x, string name = null) public Tensor log(Tensor x, string name = null)
=> gen_math_ops.log(x, name); => gen_math_ops.log(x, name);




+ 14
- 1
src/TensorFlowNET.Core/Keras/Metrics/IMetricsApi.cs View File

@@ -91,7 +91,20 @@ public interface IMetricsApi
float? threshold = null, float? threshold = null,
string name = "fbeta_score", string name = "fbeta_score",
TF_DataType dtype = TF_DataType.TF_FLOAT); TF_DataType dtype = TF_DataType.TF_FLOAT);

/// <summary>
/// Computes hamming loss.
/// </summary>
/// <param name="mode">multiclass or multilabel</param>
/// <param name="threshold"></param>
/// <param name="name"></param>
/// <param name="dtype"></param>
/// <returns></returns>
IMetricFunc HammingLoss(string mode,
float? threshold = null,
string name = "hamming_loss",
TF_DataType dtype = TF_DataType.TF_FLOAT);

/// <summary> /// <summary>
/// Computes how often targets are in the top K predictions. /// Computes how often targets are in the top K predictions.
/// </summary> /// </summary>


+ 12
- 0
src/TensorFlowNET.Core/Operations/math_ops.cs View File

@@ -821,6 +821,18 @@ namespace Tensorflow
.SetAttributes(new { adj_x, adj_y })); .SetAttributes(new { adj_x, adj_y }));
}); });


public static Tensor count_nonzero_v2(Tensor input,
Axis? axis,
bool keepdims = false,
string name = null,
TF_DataType dtype = TF_DataType.TF_INT64)
=> tf_with(ops.name_scope(name, "count_nonzero", input), scope =>
{
name = scope;
var zero = array_ops.zeros(Shape.Scalar, dtype: input.dtype);
return reduce_sum(cast(gen_math_ops.not_equal(input, zero), dtype), axis: axis, keepdims: keepdims);
});

public static Tensor bincount(Tensor arr, Tensor weights = null, public static Tensor bincount(Tensor arr, Tensor weights = null,
Tensor minlength = null, Tensor minlength = null,
Tensor maxlength = null, Tensor maxlength = null,


+ 1
- 1
src/TensorFlowNET.Core/Tensorflow.Binding.csproj View File

@@ -109,7 +109,7 @@ https://tensorflownet.readthedocs.io</Description>
<ItemGroup> <ItemGroup>
<PackageReference Include="MethodBoundaryAspect.Fody" Version="2.0.148" /> <PackageReference Include="MethodBoundaryAspect.Fody" Version="2.0.148" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="Protobuf.Text" Version="0.6.0" />
<PackageReference Include="Protobuf.Text" Version="0.6.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

+ 15
- 0
src/TensorFlowNET.Keras/Metrics/HammingLoss.cs View File

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

public class HammingLoss : MeanMetricWrapper
{
public HammingLoss(string mode,
NDArray threshold = null,
string name = "hamming_loss",
TF_DataType dtype = TF_DataType.TF_FLOAT)
: base((yt, yp) => metrics_utils.hamming_loss_fn(yt, yp, threshold, mode),
name: name,
dtype: dtype)
{
_dtype = dtype;
}
}

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

@@ -92,6 +92,9 @@
public IMetricFunc FBetaScore(int num_classes, string? average = null, float beta = 0.1F, float? threshold = null, string name = "fbeta_score", TF_DataType dtype = TF_DataType.TF_FLOAT) public IMetricFunc FBetaScore(int num_classes, string? average = null, float beta = 0.1F, float? threshold = null, string name = "fbeta_score", TF_DataType dtype = TF_DataType.TF_FLOAT)
=> new FBetaScore(num_classes, average: average,beta: beta, threshold: threshold, name: name, dtype: dtype); => new FBetaScore(num_classes, average: average,beta: beta, threshold: threshold, name: name, dtype: dtype);


public IMetricFunc HammingLoss(string mode, float? threshold = null, string name = "hamming_loss", TF_DataType dtype = TF_DataType.TF_FLOAT)
=> new HammingLoss(mode, threshold: threshold, name: name, dtype: dtype);

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




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

@@ -24,6 +24,36 @@ public class metrics_utils
return tf.reduce_sum(y_true * y_pred, axis: axis ?? -1); return tf.reduce_sum(y_true * y_pred, axis: axis ?? -1);
} }


public static Tensor hamming_loss_fn(Tensor y_true, Tensor y_pred, Tensor threshold, string mode)
{
if (threshold == null)
{
threshold = tf.reduce_max(y_pred, axis: -1, keepdims: true);
// make sure [0, 0, 0] doesn't become [1, 1, 1]
// Use abs(x) > eps, instead of x != 0 to check for zero
y_pred = tf.logical_and(y_pred >= threshold, tf.abs(y_pred) > 1e-12);
}
else
{
y_pred = y_pred > threshold;
}


y_true = tf.cast(y_true, tf.int32);
y_pred = tf.cast(y_pred, tf.int32);

if (mode == "multiclass")
{
var nonzero = tf.cast(tf.math.count_nonzero(y_true * y_pred, axis: -1), tf.float32);
return 1.0 - nonzero;
}
else
{
var nonzero = tf.cast(tf.math.count_nonzero(y_true - y_pred, axis: -1), tf.float32);
return nonzero / y_true.shape[-1];
}
}
/// <summary> /// <summary>
/// Creates float Tensor, 1.0 for label-prediction match, 0.0 for mismatch. /// Creates float Tensor, 1.0 for label-prediction match, 0.0 for mismatch.
/// </summary> /// </summary>


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

@@ -142,6 +142,51 @@ public class MetricsTest : EagerModeTestBase
Assert.AreEqual(r, new[] { 0.3846154f, 0.90909094f, 0.8333334f }); Assert.AreEqual(r, new[] { 0.3846154f, 0.90909094f, 0.8333334f });
} }


/// <summary>
/// https://www.tensorflow.org/addons/api_docs/python/tfa/metrics/HammingLoss
/// </summary>
[TestMethod]
public void HammingLoss()
{
// multi-class hamming loss
var y_true = np.array(new[,]
{
{ 1, 0, 0, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 1 },
{ 0, 1, 0, 0 }
});
var y_pred = np.array(new[,]
{
{ 0.8f, 0.1f, 0.1f, 0.0f },
{ 0.2f, 0.0f, 0.8f, 0.0f },
{ 0.05f, 0.05f, 0.1f, 0.8f },
{ 1.0f, 0.0f, 0.0f, 0.0f }
});
var m = tf.keras.metrics.HammingLoss(mode: "multiclass", threshold: 0.6f);
m.update_state(y_true, y_pred);
var r = m.result().numpy();
Assert.AreEqual(r, 0.25f);

// multi-label hamming loss
y_true = np.array(new[,]
{
{ 1, 0, 1, 0 },
{ 0, 1, 0, 1 },
{ 0, 0, 0, 1 }
});
y_pred = np.array(new[,]
{
{ 0.82f, 0.5f, 0.9f, 0.0f },
{ 0f, 1f, 0.4f, 0.98f },
{ 0.89f, 0.79f, 0f, 0.3f }
});
m = tf.keras.metrics.HammingLoss(mode: "multilabel", threshold: 0.8f);
m.update_state(y_true, y_pred);
r = m.result().numpy();
Assert.AreEqual(r, 0.16666667f);
}

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


Loading…
Cancel
Save