Skip to content

Commit 9e68b94

Browse files
committed
Operator overloading between Variable and Tensor should return Tensor.
1 parent aebf7a9 commit 9e68b94

4 files changed

Lines changed: 63 additions & 91 deletions

File tree

README.md

Lines changed: 28 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111

1212
*master branch is based on tensorflow 2.2 now, v0.15-tensorflow1.15 is from tensorflow1.15.*
1313

14-
TF.NET is a member project of [SciSharp STACK](https://github.com/SciSharp).
15-
1614

1715
![tensors_flowing](docs/assets/tensors_flowing.gif)
1816

@@ -56,59 +54,40 @@ using static Tensorflow.Binding;
5654
Linear Regression:
5755

5856
```c#
59-
// We can set a fixed init value in order to debug
57+
// Parameters
58+
int training_steps = 1000;
59+
float learning_rate = 0.01f;
60+
int display_step = 100;
61+
62+
// We can set a fixed init value in order to demo
6063
var W = tf.Variable(-0.06f, name: "weight");
6164
var b = tf.Variable(-0.73f, name: "bias");
65+
var optimizer = tf.optimizers.SGD(learning_rate);
6266

63-
// Construct a linear model
64-
var pred = tf.add(tf.multiply(X, W), b);
65-
66-
// Mean squared error
67-
var cost = tf.reduce_sum(tf.pow(pred - Y, 2.0f)) / (2.0f * n_samples);
68-
69-
// Gradient descent
70-
// Note, minimize() knows to modify W and b because Variable objects are trainable=True by default
71-
var optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost);
72-
73-
// Initialize the variables (i.e. assign their default value)
74-
var init = tf.global_variables_initializer();
75-
76-
// Start training
77-
using(tf.Session())
67+
// Run training for the given number of steps.
68+
foreach (var step in range(1, training_steps + 1))
7869
{
79-
// Run the initializer
80-
sess.run(init);
81-
82-
// Fit all training data
83-
for (int epoch = 0; epoch < training_epochs; epoch++)
70+
// Run the optimization to update W and b values.
71+
// Wrap computation inside a GradientTape for automatic differentiation.
72+
using var g = tf.GradientTape();
73+
// Linear regression (Wx + b).
74+
var pred = W * X + b;
75+
// Mean square error.
76+
var loss = tf.reduce_sum(tf.pow(pred - Y, 2)) / (2 * n_samples);
77+
// should stop recording
78+
// Compute gradients.
79+
var gradients = g.gradient(loss, (W, b));
80+
81+
// Update W and b following gradients.
82+
optimizer.apply_gradients(zip(gradients, (W, b)));
83+
84+
if (step % display_step == 0)
8485
{
85-
foreach (var (x, y) in zip<float>(train_X, train_Y))
86-
sess.run(optimizer, (X, x), (Y, y));
87-
88-
// Display logs per epoch step
89-
if ((epoch + 1) % display_step == 0)
90-
{
91-
var c = sess.run(cost, (X, train_X), (Y, train_Y));
92-
Console.WriteLine($"Epoch: {epoch + 1} cost={c} " + $"W={sess.run(W)} b={sess.run(b)}");
93-
}
86+
pred = W * X + b;
87+
loss = tf.reduce_sum(tf.pow(pred - Y, 2)) / (2 * n_samples);
88+
print($"step: {step}, loss: {loss.numpy()}, W: {W.numpy()}, b: {b.numpy()}");
9489
}
95-
96-
Console.WriteLine("Optimization Finished!");
97-
var training_cost = sess.run(cost, (X, train_X), (Y, train_Y));
98-
Console.WriteLine($"Training cost={training_cost} W={sess.run(W)} b={sess.run(b)}");
99-
100-
// Testing example
101-
var test_X = np.array(6.83f, 4.668f, 8.9f, 7.91f, 5.7f, 8.7f, 3.1f, 2.1f);
102-
var test_Y = np.array(1.84f, 2.273f, 3.2f, 2.831f, 2.92f, 3.24f, 1.35f, 1.03f);
103-
Console.WriteLine("Testing... (Mean square loss Comparison)");
104-
var testing_cost = sess.run(tf.reduce_sum(tf.pow(pred - Y, 2.0f)) / (2.0f * test_X.shape[0]),
105-
(X, test_X), (Y, test_Y));
106-
Console.WriteLine($"Testing cost={testing_cost}");
107-
var diff = Math.Abs((float)training_cost - (float)testing_cost);
108-
Console.WriteLine($"Absolute mean square loss difference: {diff}");
109-
110-
return diff < 0.01;
111-
});
90+
}
11291
```
11392

11493
Run this example in [Jupyter Notebook](https://github.com/SciSharp/SciSharpCube).

src/TensorFlowNET.Core/Operations/gen_math_ops.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,19 @@ public static Tensor _clip_by_value(Tensor t, Tensor clip_value_min, Tensor clip
551551

552552
public static Tensor greater<Tx, Ty>(Tx x, Ty y, string name = null)
553553
{
554+
if (tf.context.executing_eagerly())
555+
{
556+
var results = EagerTensorPass.Create();
557+
var inputs = EagerTensorPass.From(x, y);
558+
Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name,
559+
"Greater", name,
560+
inputs.Points, inputs.Length,
561+
null, null,
562+
results.Points, results.Length);
563+
status.Check(true);
564+
return results[0].Resolve();
565+
}
566+
554567
var _op = _op_def_lib._apply_op_helper("Greater", name: name, args: new { x, y });
555568

556569
return _op.outputs[0];

src/TensorFlowNET.Core/Variables/ResourceVariable.Operators.cs

Lines changed: 21 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,24 @@ public partial class ResourceVariable
2424
{
2525
public static OpDefLibrary _op_def_lib = new OpDefLibrary();
2626

27-
public static ResourceVariable operator +(ResourceVariable x, int y) => op_helper("add", x, y);
28-
public static ResourceVariable operator +(ResourceVariable x, float y) => op_helper("add", x, y);
29-
public static ResourceVariable operator +(ResourceVariable x, double y) => op_helper("add", x, y);
30-
public static ResourceVariable operator +(ResourceVariable x, ResourceVariable y) => op_helper("add", x, y);
31-
public static ResourceVariable operator -(ResourceVariable x, int y) => op_helper("sub", x, y);
32-
public static ResourceVariable operator -(ResourceVariable x, float y) => op_helper("sub", x, y);
33-
public static ResourceVariable operator -(ResourceVariable x, double y) => op_helper("sub", x, y);
34-
public static ResourceVariable operator -(ResourceVariable x, Tensor y) => op_helper("sub", x, y);
35-
public static ResourceVariable operator -(ResourceVariable x, ResourceVariable y) => op_helper("sub", x, y);
27+
public static Tensor operator +(ResourceVariable x, int y) => op_helper("add", x, y);
28+
public static Tensor operator +(ResourceVariable x, float y) => op_helper("add", x, y);
29+
public static Tensor operator +(ResourceVariable x, double y) => op_helper("add", x, y);
30+
public static Tensor operator +(ResourceVariable x, ResourceVariable y) => op_helper("add", x, y);
31+
public static Tensor operator -(ResourceVariable x, int y) => op_helper("sub", x, y);
32+
public static Tensor operator -(ResourceVariable x, float y) => op_helper("sub", x, y);
33+
public static Tensor operator -(ResourceVariable x, double y) => op_helper("sub", x, y);
34+
public static Tensor operator -(ResourceVariable x, Tensor y) => op_helper("sub", x, y);
35+
public static Tensor operator -(ResourceVariable x, ResourceVariable y) => op_helper("sub", x, y);
3636

37-
public static ResourceVariable operator *(ResourceVariable x, ResourceVariable y) => op_helper("mul", x, y);
38-
public static ResourceVariable operator *(ResourceVariable x, NDArray y) => op_helper("mul", x, y);
37+
public static Tensor operator *(ResourceVariable x, ResourceVariable y) => op_helper("mul", x, y);
38+
public static Tensor operator *(ResourceVariable x, NDArray y) => op_helper("mul", x, y);
3939

40-
public static ResourceVariable operator <(ResourceVariable x, Tensor y) => less(x.value(), y);
40+
public static Tensor operator <(ResourceVariable x, Tensor y) => op_helper("less", x, y);
4141

42-
public static ResourceVariable operator >(ResourceVariable x, Tensor y) => greater(x.value(), y);
42+
public static Tensor operator >(ResourceVariable x, Tensor y) => op_helper("greater", x, y);
4343

44-
private static ResourceVariable op_helper<T>(string default_name, ResourceVariable x, T y)
44+
private static Tensor op_helper<T>(string default_name, ResourceVariable x, T y)
4545
=> tf_with(ops.name_scope(null, default_name, new { x, y }), scope =>
4646
{
4747
string name = scope;
@@ -61,39 +61,19 @@ private static ResourceVariable op_helper<T>(string default_name, ResourceVariab
6161
case "mul":
6262
result = gen_math_ops.mul(xVal, yTensor, name: name);
6363
break;
64+
case "less":
65+
result = gen_math_ops.less(xVal, yTensor, name);
66+
break;
67+
case "greater":
68+
result = gen_math_ops.greater(xVal, yTensor, name);
69+
break;
6470
default:
6571
throw new NotImplementedException("");
6672
}
6773

6874
// x.assign(result);
6975
// result.ResourceVar = x;
70-
return tf.Variable(result);
76+
return result;
7177
});
72-
73-
private static ResourceVariable less<Tx, Ty>(Tx x, Ty y, string name = null)
74-
{
75-
if (tf.context.executing_eagerly())
76-
{
77-
var results = EagerTensorPass.Create();
78-
var inputs = EagerTensorPass.From(x, y);
79-
Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name,
80-
"Less", name,
81-
inputs.Points, inputs.Length,
82-
null, null,
83-
results.Points, results.Length);
84-
status.Check(true);
85-
return tf.Variable(results[0].Resolve());
86-
}
87-
88-
var _op = _op_def_lib._apply_op_helper("Less", name: name, args: new { x, y });
89-
90-
return tf.Variable(_op.outputs[0]);
91-
}
92-
private static ResourceVariable greater<Tx, Ty>(Tx x, Ty y, string name = null)
93-
{
94-
var _op = _op_def_lib._apply_op_helper("Greater", name: name, args: new { x, y });
95-
96-
return tf.Variable(_op.outputs[0]);
97-
}
9878
}
9979
}

test/TensorFlowNET.UnitTest/Basics/VariableTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public void Accumulation()
5757
{
5858
var x = tf.Variable(10, name: "x");
5959
for (int i = 0; i < 5; i++)
60-
x = x + 1;
60+
x.assign(x + 1);
6161

6262
Assert.AreEqual(15, (int)x.numpy());
6363
}

0 commit comments

Comments
 (0)