Skip to content

Commit e4c9437

Browse files
ZeroFraction core function impl done! Control Flow is not implemented with AddControlInput and UpdateEdge which is not exposed as C_API. Need to implement it seperately.
1 parent a0fc3f8 commit e4c9437

File tree

7 files changed

+128
-12
lines changed

7 files changed

+128
-12
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace Tensorflow.Graphs
6+
{
7+
/// <summary>
8+
/// Lots of other functions required for Operation control flow like AddControlInput, UpdateEdge, RemoveAllControlInputs etc are not exposed via C_API and there is a C implementation of it.
9+
/// https://github.com/tensorflow/tensorflow/blob/r1.14/tensorflow/c/python_api.h
10+
/// https://github.com/tensorflow/tensorflow/blob/r1.14/tensorflow/c/python_api.cc
11+
///
12+
/// </summary>
13+
public class python_api
14+
{
15+
public static void UpdateEdge(Graph graph, TF_Output new_src, TF_Input dst, Status status)
16+
{
17+
18+
}
19+
}
20+
}

src/TensorFlowNET.Core/Operations/gen_math_ops.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,23 @@ public static Tensor equal<Tx, Ty>(Tx x, Ty y, string name = null)
389389
return _op.outputs[0];
390390
}
391391

392+
/// <summary>
393+
/// Returns the truth value of (x != y) element-wise.
394+
/// </summary>
395+
/// <typeparam name="Tx">The type of the x.</typeparam>
396+
/// <typeparam name="Ty">The type of the y.</typeparam>
397+
/// <param name="x">The x.</param>
398+
/// <param name="y">The y.</param>
399+
/// <param name="name">The name.</param>
400+
/// <returns></returns>
401+
public static Tensor not_equal<Tx, Ty>(Tx x, Ty y, string name = null)
402+
{
403+
var _op = _op_def_lib._apply_op_helper("NotEqual", name, args: new { x, y });
404+
405+
return _op.outputs[0];
406+
}
407+
408+
392409
public static Tensor atan2(Tensor y, Tensor x, string name = null)
393410
{
394411
var _op = _op_def_lib._apply_op_helper("Atan2", name, args: new { y, x });
@@ -566,5 +583,18 @@ public static Tensor rsqrt(Tensor x, string name = null)
566583

567584
return _op.outputs[0];
568585
}
586+
587+
/// <summary>
588+
/// Returns the fraction of zeros in value.
589+
/// </summary>
590+
/// <param name="value">A tensor of numeric type.</param>
591+
/// <param name="name">A name for the operation (optional).</param>
592+
/// <returns>The fraction of zeros in value, with type float32.</returns>
593+
public static Tensor zero_fraction(Tensor value, string name = null)
594+
{
595+
var _op = _op_def_lib._apply_op_helper("zero_fraction", name, new { value, name });
596+
597+
return _op.outputs[0];
598+
}
569599
}
570600
}

src/TensorFlowNET.Core/Operations/nn_impl.py.cs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,57 @@ public static Tensor[] fused_batch_norm(Tensor x,
101101
name);
102102
}
103103

104-
public static Tensor zero_fraction(Tensor t)
104+
/// <summary>
105+
/// Same as math_ops.count_nonzero.
106+
/// The reduction is done in dtype, which can be faster for 32-bit dtypes.
107+
/// </summary>
108+
/// <param name="input_tensor">The numeric tensor.</param>
109+
/// <param name="dtype">The reduction dtype.</param>
110+
/// <returns>number of nonzero values with type dtype</returns>
111+
private static Tensor _count_nonzero(Tensor input_tensor, TF_DataType dtype = TF_DataType.TF_INT64)
112+
{
113+
return with(ops.name_scope("count_nonzero", "count_nonzero", new { input_tensor }), scope =>
114+
{
115+
var zero = array_ops.zeros(new NumSharp.Shape(), dtype: input_tensor.dtype);
116+
var nonzero_count = math_ops.reduce_sum(
117+
math_ops.cast(gen_math_ops.not_equal(input_tensor, zero), dtype: dtype), name: "nonzero_count");
118+
return nonzero_count;
119+
});
120+
}
121+
122+
/// <summary>
123+
/// Returns the fraction of zeros in value.
124+
/// </summary>
125+
/// <param name="value">A tensor of numeric type.</param>
126+
/// <param name="name">A name for the operation (optional).</param>
127+
/// <returns>The fraction of zeros in value, with type float32.</returns>
128+
public static Tensor zero_fraction(Tensor value, string name = null)
105129
{
106-
throw new NotImplementedException();
130+
return with(ops.name_scope(name, "zero_fraction", new { value }), scope =>
131+
{
132+
133+
value = ops.convert_to_tensor(value, name: "value");
134+
Tensor size = array_ops.size(value, out_type: dtypes.int64);
135+
Func<ITensorOrOperation> fu_true = () => math_ops.cast(_count_nonzero(value, dtype: dtypes.int32));
136+
Tensor zero_fraction_float32 = null;
137+
138+
size = gen_math_ops.less_equal(size, dtypes.int32.max());
139+
Tensor num_nonzero = control_flow_ops.cond(
140+
size,
141+
() => math_ops.cast(_count_nonzero(value, dtype: dtypes.int32)),
142+
() => _count_nonzero(value, dtype: dtypes.int64)
143+
);
144+
145+
with(ops.name_scope("counts_to_fraction"), count_scope =>
146+
{
147+
var num_zero = size - num_nonzero;
148+
var num_zero_float32 = math_ops.cast(num_zero, dtype: dtypes.float32);
149+
var size_float32 = math_ops.cast(size, dtype: dtypes.float32);
150+
zero_fraction_float32 = num_zero_float32 / size_float32;
151+
});
152+
153+
return array_ops.identity(zero_fraction_float32, "fraction");
154+
});
107155
}
108156
}
109157
}

src/TensorFlowNET.Core/Tensors/dtypes.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ namespace Tensorflow
77
public static class dtypes
88
{
99
public static TF_DataType int8 = TF_DataType.TF_INT8;
10+
public static TF_DataType int32 = TF_DataType.TF_INT32;
11+
public static TF_DataType int64 = TF_DataType.TF_INT64;
1012
public static TF_DataType float32 = TF_DataType.TF_FLOAT; // is that float32?
1113
public static TF_DataType float16 = TF_DataType.TF_HALF;
14+
public static TF_DataType float64 = TF_DataType.TF_DOUBLE;
1215

1316
public static Type as_numpy_datatype(this TF_DataType type)
1417
{
@@ -126,12 +129,24 @@ public static TF_DataType as_ref(this TF_DataType type)
126129
type;
127130
}
128131

129-
public static int max(this TF_DataType type)
132+
public static long max(this TF_DataType type)
130133
{
131134
switch (type)
132135
{
136+
case TF_DataType.TF_INT8:
137+
return sbyte.MaxValue;
138+
case TF_DataType.TF_INT16:
139+
return short.MaxValue;
140+
case TF_DataType.TF_INT32:
141+
return int.MaxValue;
142+
case TF_DataType.TF_INT64:
143+
return long.MaxValue;
133144
case TF_DataType.TF_UINT8:
134-
return 255;
145+
return byte.MaxValue;
146+
case TF_DataType.TF_UINT16:
147+
return ushort.MaxValue;
148+
case TF_DataType.TF_UINT32:
149+
return uint.MaxValue;
135150
default:
136151
throw new NotImplementedException($"max {type.name()}");
137152
}

src/TensorFlowNET.Core/Tensors/tensor_util.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,12 @@ public static TensorProto make_tensor_proto(object values, TF_DataType dtype = T
176176
else
177177
nparray = Convert.ToInt32(values);
178178
break;
179+
case "Int64":
180+
if (values.GetType().IsArray)
181+
nparray = np.array((int[])values, np_dt);
182+
else
183+
nparray = Convert.ToInt64(values);
184+
break;
179185
case "Single":
180186
if (values.GetType().IsArray)
181187
nparray = np.array((float[])values, np_dt);

src/TensorFlowNET.Core/ops.py.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -188,17 +188,17 @@ public static (IntPtr, IntPtr) _create_c_op<T>(Graph graph, NodeDef node_def, T[
188188
{
189189
var op_desc = graph.NewOperation(node_def.Op, node_def.Name);
190190

191+
//TODO: Implement TF_SetDevice
192+
//if node_def.device:
193+
// c_api.TF_SetDevice(op_desc, compat.as_str(node_def.device))
191194
// Add inputs
192195
foreach (var op_input in inputs)
193196
{
194197
if (op_input is Tensor[] op_inputs)
195198
c_api.TF_AddInputList(op_desc, op_inputs.Select(x => x._as_tf_output()).ToArray(), op_inputs.Length);
196199
else if (op_input is Tensor op_input1)
197200
{
198-
if (op_input1.op == null)
199-
c_api.TF_AddInput(op_desc, new TF_Output(op_desc, 0));
200-
else
201-
c_api.TF_AddInput(op_desc, op_input1._as_tf_output());
201+
c_api.TF_AddInput(op_desc, op_input1._as_tf_output());
202202
}
203203
else
204204
throw new NotImplementedException("_create_c_op");

test/TensorFlowNET.UnitTest/nn_test/ZeroFractionTest.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,12 @@ protected double _ZeroFraction(NDArray x)
2323
return 1.0 - nonzeros / (double)total_elements;
2424
}
2525

26-
[Ignore("TODO implement nn_impl.zero_fraction")]
2726
[TestMethod]
2827
public void testZeroFraction()
2928
{
3029
var x_shape = new Shape(5, 17);
3130
var x_np = np.random.randint(0, 2, x_shape);
32-
x_np.astype(np.float32);
31+
//x_np.astype(np.float32);
3332
var y_np = this._ZeroFraction(x_np);
3433

3534
var x_tf = constant_op.constant(x_np);
@@ -41,7 +40,6 @@ public void testZeroFraction()
4140
self.assertAllClose(y_tf_np, y_np, eps);
4241
}
4342

44-
[Ignore("TODO implement nn_impl.zero_fraction")]
4543
[TestMethod]
4644
public void testZeroFractionEmpty()
4745
{
@@ -60,7 +58,6 @@ public void testZeroFraction2_27Zeros()
6058
self.assertAllClose(1.0, self.evaluate<NDArray>(sparsity));
6159
}
6260

63-
[Ignore("TODO implement nn_impl.zero_fraction")]
6461
[TestMethod]
6562
public void testZeroFraction2_27Ones()
6663
{

0 commit comments

Comments
 (0)