@@ -192,8 +192,8 @@ namespace Tensorflow | |||||
{ | { | ||||
if (!pending_count.ContainsKey(x.op.Name)) | if (!pending_count.ContainsKey(x.op.Name)) | ||||
pending_count[x.op.Name] = 0; | pending_count[x.op.Name] = 0; | ||||
else | |||||
pending_count[x.op.Name] -= 1; | |||||
pending_count[x.op.Name] -= 1; | |||||
var ready = pending_count[x.op.Name] == 0; | var ready = pending_count[x.op.Name] == 0; | ||||
@@ -288,7 +288,7 @@ namespace Tensorflow | |||||
} | } | ||||
} | } | ||||
if (is_stop_op) | if (is_stop_op) | ||||
stop_ops.Add(op); | |||||
stop_ops.Insert(0, op); | |||||
} | } | ||||
stop_ops.AddRange(stop_gradient_ops.Where(x => !stop_ops.Contains(x))); | stop_ops.AddRange(stop_gradient_ops.Where(x => !stop_ops.Contains(x))); | ||||
return stop_ops.ToArray(); | return stop_ops.ToArray(); | ||||
@@ -1,5 +1,6 @@ | |||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Linq; | |||||
using System.Text; | using System.Text; | ||||
namespace Tensorflow | namespace Tensorflow | ||||
@@ -13,8 +14,67 @@ namespace Tensorflow | |||||
{ | { | ||||
var x = op.inputs[0]; | var x = op.inputs[0]; | ||||
var y = op.inputs[1]; | var y = op.inputs[1]; | ||||
if (grad is Tensor && _ShapesFullySpecifiedAndEqual(x, y, grad)) | |||||
return (grad, grad); | |||||
return (grad, grad); | |||||
var sx = array_ops.shape(x); | |||||
var sy = array_ops.shape(y); | |||||
var (rx, ry) = gen_array_ops.broadcast_gradient_args(sx, sy); | |||||
var r1 = gen_array_ops.reshape(math_ops.reduce_sum(grad, rx), sx); | |||||
var r2 = gen_array_ops.reshape(math_ops.reduce_sum(grad, ry), sy); | |||||
return (r1, r2); | |||||
} | |||||
public static (Tensor, Tensor) _IdGrad(Operation op, Tensor grad) | |||||
{ | |||||
return (grad, null); | |||||
} | |||||
public static (Tensor, Tensor) _MulGrad(Operation op, Tensor grad) | |||||
{ | |||||
var x = op.inputs[0]; | |||||
var y = op.inputs[1]; | |||||
if (grad is Tensor && _ShapesFullySpecifiedAndEqual(x, y, grad) && | |||||
new TF_DataType[] { tf.int32, tf.float32 }.Contains(grad.dtype)) | |||||
return (gen_math_ops.mul(grad, y), gen_math_ops.mul(grad, x)); | |||||
var sx = array_ops.shape(x); | |||||
var sy = array_ops.shape(y); | |||||
var (rx, ry) = gen_array_ops.broadcast_gradient_args(sx, sy); | |||||
x = math_ops.conj(x); | |||||
y = math_ops.conj(y); | |||||
var r1 = math_ops.reduce_sum(gen_math_ops.mul(grad, y), rx); | |||||
var r2 = math_ops.reduce_sum(gen_math_ops.mul(x, grad), ry); | |||||
return (gen_array_ops.reshape(r1, sx), gen_array_ops.reshape(r2, sy)); | |||||
} | |||||
public static (Tensor, Tensor) _SubGrad(Operation op, Tensor grad) | |||||
{ | |||||
var x = op.inputs[0]; | |||||
var y = op.inputs[1]; | |||||
if (grad is Tensor && _ShapesFullySpecifiedAndEqual(x, y, grad)) | |||||
return (grad, -grad); | |||||
var sx = array_ops.shape(x); | |||||
var sy = array_ops.shape(y); | |||||
var (rx, ry) = gen_array_ops.broadcast_gradient_args(sx, sy); | |||||
var r1 = gen_array_ops.reshape(math_ops.reduce_sum(grad, rx), sx); | |||||
var r2 = gen_array_ops.reshape(-math_ops.reduce_sum(grad, ry), sy); | |||||
return (r1, r2); | |||||
} | |||||
public static bool _ShapesFullySpecifiedAndEqual(Tensor x, Tensor y, Tensor grad) | |||||
{ | |||||
return false; | |||||
/*return string.Join(",", x.shape).Equals(string.Join(",", y.shape)) && | |||||
string.Join(",", x.shape).Equals(string.Join(",", grad.shape));*/ | |||||
} | } | ||||
public static (Tensor, Tensor) _SumGrad(Operation op, Tensor grad) | public static (Tensor, Tensor) _SumGrad(Operation op, Tensor grad) | ||||
@@ -71,8 +131,7 @@ namespace Tensorflow | |||||
x = math_ops.conj(x); | x = math_ops.conj(x); | ||||
y = math_ops.conj(y); | y = math_ops.conj(y); | ||||
y = math_ops.conj(z); | y = math_ops.conj(z); | ||||
var gx = gen_array_ops.reshape(math_ops.reduce_sum(grad * y * gen_math_ops.pow(x, y - 1), rx), sx); | |||||
var gx = gen_array_ops.reshape(math_ops.reduce_sum(grad * y * gen_math_ops.pow(x, y - 1.0), rx), sx); | |||||
Tensor log_x = null; | Tensor log_x = null; | ||||
// Avoid false singularity at x = 0 | // Avoid false singularity at x = 0 | ||||
if (x.dtype.is_complex()) | if (x.dtype.is_complex()) | ||||
@@ -81,7 +140,9 @@ namespace Tensorflow | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
log_x = array_ops.where(x > 0, gen_array_ops.log(x), array_ops.zeros_like(x)); | |||||
var x1 = gen_array_ops.log(x); | |||||
var y1 = array_ops.zeros_like(x); | |||||
log_x = array_ops.where(x > 0.0, x1, y1); | |||||
} | } | ||||
var gy = gen_array_ops.reshape(math_ops.reduce_sum(grad * z * log_x, ry), sy); | var gy = gen_array_ops.reshape(math_ops.reduce_sum(grad * z * log_x, ry), sy); | ||||
@@ -147,7 +147,27 @@ namespace Tensorflow | |||||
public static Tensor zeros_like(Tensor tensor, TF_DataType dtype = TF_DataType.DtInvalid, string name = "", bool optimize = true) | public static Tensor zeros_like(Tensor tensor, TF_DataType dtype = TF_DataType.DtInvalid, string name = "", bool optimize = true) | ||||
{ | { | ||||
throw new NotImplementedException("zeros_like"); | |||||
return Python.with<ops.name_scope, Tensor>(new ops.name_scope(name, "zeros_like", new Tensor[] { tensor }), scope => | |||||
{ | |||||
name = scope; | |||||
tensor = ops.convert_to_tensor(tensor, name: "tensor"); | |||||
// is_fully_defined return unexpected value. | |||||
if (optimize && tensor_util.to_shape(tensor.shape).is_fully_defined() && dtype != TF_DataType.TF_VARIANT) | |||||
{ | |||||
} | |||||
if(dtype != TF_DataType.DtInvalid && dtype != tensor.dtype && dtype != TF_DataType.TF_VARIANT) | |||||
{ | |||||
throw new NotImplementedException("zeros_like"); | |||||
// return zeros(shape_internal(tensor, optimize: optimize), dtype: dtype, name: name); | |||||
} | |||||
else | |||||
{ | |||||
return gen_array_ops.zeros_like(tensor, name: name); | |||||
} | |||||
}); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -106,9 +106,9 @@ namespace Tensorflow | |||||
throw new NotImplementedException("where"); | throw new NotImplementedException("where"); | ||||
} | } | ||||
public static Tensor select(Tensor condition, Tensor x, Tensor y, string name = "") | |||||
public static Tensor select(Tensor condition, Tensor t, Tensor e, string name = "") | |||||
{ | { | ||||
var _op = _op_def_lib._apply_op_helper("Select", name, new { condition, x, y }); | |||||
var _op = _op_def_lib._apply_op_helper("Select", name, new { condition, t, e }); | |||||
return _op.outputs[0]; | return _op.outputs[0]; | ||||
} | } | ||||
@@ -24,7 +24,7 @@ namespace Tensorflow | |||||
return _op.outputs[0]; | return _op.outputs[0]; | ||||
} | } | ||||
public static Tensor sub(Tensor x, Tensor y, string name = "") | |||||
public static Tensor sub<Tx, Ty>(Tx x, Ty y, string name = "") | |||||
{ | { | ||||
var _op = _op_def_lib._apply_op_helper("Sub", name, args: new { x, y }); | var _op = _op_def_lib._apply_op_helper("Sub", name, args: new { x, y }); | ||||
@@ -89,7 +89,7 @@ namespace Tensorflow | |||||
return _op.outputs[0]; | return _op.outputs[0]; | ||||
} | } | ||||
public static Tensor pow(Tensor x, double y, string name = "") | |||||
public static Tensor pow<Tx, Ty>(Tx x, Ty y, string name = "") | |||||
{ | { | ||||
var _op = _op_def_lib._apply_op_helper("Pow", name, args: new { x, y }); | var _op = _op_def_lib._apply_op_helper("Pow", name, args: new { x, y }); | ||||
@@ -23,15 +23,10 @@ namespace Tensorflow | |||||
}); | }); | ||||
} | } | ||||
public static Tensor operator -(Tensor t1) | |||||
{ | |||||
return gen_math_ops.neg(t1); | |||||
} | |||||
public static Tensor operator -(Tensor t1, Tensor t2) | |||||
{ | |||||
return gen_math_ops.sub(t1, t2); | |||||
} | |||||
public static Tensor operator -(Tensor t1) => gen_math_ops.neg(t1); | |||||
public static Tensor operator -(Tensor t1, Tensor t2) => gen_math_ops.sub(t1, t2); | |||||
public static Tensor operator -(Tensor t1, int t2) => gen_math_ops.sub(t1, t2); | |||||
public static Tensor operator -(Tensor t1, double t2) => gen_math_ops.sub(t1, t2); | |||||
public static Tensor operator *(double x, Tensor y) | public static Tensor operator *(double x, Tensor y) | ||||
{ | { | ||||
@@ -85,14 +80,9 @@ namespace Tensorflow | |||||
}); | }); | ||||
} | } | ||||
public static Tensor operator >(Tensor x, int y) | |||||
{ | |||||
return gen_array_ops.greater(x, y); | |||||
} | |||||
public static Tensor operator <(Tensor x, int y) | |||||
{ | |||||
return gen_array_ops.less(x, y); | |||||
} | |||||
public static Tensor operator >(Tensor x, int y) => gen_array_ops.greater(x, y); | |||||
public static Tensor operator >(Tensor x, double y) => gen_array_ops.greater(x, y); | |||||
public static Tensor operator <(Tensor x, int y) => gen_array_ops.less(x, y); | |||||
public static Tensor operator <(Tensor x, double y) => gen_array_ops.less(x, y); | |||||
} | } | ||||
} | } |
@@ -294,8 +294,16 @@ namespace Tensorflow | |||||
{ | { | ||||
case "Add": | case "Add": | ||||
return math_grad._AddGrad(oper, out_grads); | return math_grad._AddGrad(oper, out_grads); | ||||
case "Identity": | |||||
return math_grad._IdGrad(oper, out_grads); | |||||
case "Mul": | |||||
return math_grad._MulGrad(oper, out_grads); | |||||
case "Sum": | case "Sum": | ||||
return math_grad._SumGrad(oper, out_grads); | return math_grad._SumGrad(oper, out_grads); | ||||
case "Sub": | |||||
return math_grad._SubGrad(oper, out_grads); | |||||
case "Pow": | |||||
return math_grad._PowGrad(oper, out_grads); | |||||
case "RealDiv": | case "RealDiv": | ||||
return math_grad._RealDivGrad(oper, out_grads); | return math_grad._RealDivGrad(oper, out_grads); | ||||
default: | default: | ||||