@@ -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}
0 commit comments