//
// This is just a dumping ground to exercise different capabilities
// of the API. Some idioms might be useful, some not, feel free to
//
//
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using TensorFlow;
using System.IO;
using System.Collections.Generic;
using Learn.Mnist;
using System.Linq;
namespace SampleTest
{
partial class MainClass
{
static public void Assert (bool assert, [CallerMemberName] string caller = null, string message = "")
{
if (!assert){
throw new Exception ($"{caller}: {message}");
}
}
static public void Assert (TFStatus status, [CallerMemberName] string caller = null, string message = "")
{
if (status.StatusCode != TFCode.Ok) {
throw new Exception ($"{caller}: {status.StatusMessage} {message}");
}
}
public static void p (string p)
{
Console.WriteLine (p);
}
#region Samples
//
// Samples to exercise the API usability
//
// From https://github.com/aymericdamien/TensorFlow-Examples
//
void BasicConstantOps ()
{
//
// Test the manual GetRunner, this could be simpler
// we should at some point allow Run (a+b);
//
// The session implicitly creates the graph, get it.
using (var s = new TFSession ()){
var g = s.Graph;
var a = g.Const (2);
var b = g.Const (3);
Console.WriteLine ("a=2 b=3");
// Add two constants
var results = s.GetRunner ().Run (g.Add (a, b));
var val = results.GetValue ();
Console.WriteLine ("a+b={0}", val);
// Multiply two constants
results = s.GetRunner ().Run (g.Mul (a, b));
Console.WriteLine ("a*b={0}", results.GetValue ());
// TODO: API-wise, perhaps session.Run () can have a simple
// overload where we only care about the fetched values,
// making the above:
// s.Run (g.Mul (a, b));
}
}
//
// Shows how to use placeholders to pass values
//
void BasicVariables ()
{
Console.WriteLine ("Using placerholders");
using (var g = new TFGraph ()) {
var s = new TFSession (g);
// We use "shorts" here, so notice the casting to short to get the
// tensor with the right data type.
var var_a = g.Placeholder (TFDataType.Int16);
var var_b = g.Placeholder (TFDataType.Int16);
var add = g.Add (var_a, var_b);
var mul = g.Mul (var_a, var_b);
var runner = s.GetRunner ();
runner.AddInput (var_a, new TFTensor ((short)3));
runner.AddInput (var_b, new TFTensor ((short)2));
Console.WriteLine ("a+b={0}", runner.Run (add).GetValue ());
runner = s.GetRunner ();
runner.AddInput (var_a, new TFTensor ((short)3));
runner.AddInput (var_b, new TFTensor ((short)2));
Console.WriteLine ("a*b={0}", runner.Run (mul).GetValue ());
// TODO
// Would be nice to have an API that allows me to pass the values at Run time, easily:
// s.Run (add, { var_a: 3, var_b: 2 })
// C# allows something with Dictionary constructors, but you still must provide the type
// signature.
}
}
//
// Shows the use of Variable
//
void TestVariable ()
{
Console.WriteLine ("Variables");
var status = new TFStatus ();
using (var g = new TFGraph ()) {
var initValue = g.Const (1.5);
var increment = g.Const (0.5);
TFOperation init;
TFOutput value;
var handle = g.Variable (initValue, out init, out value);
// Add 0.5 and assign to the variable.
// Perhaps using op.AssignAddVariable would be better,
// but demonstrating with Add and Assign for now.
var update = g.AssignVariableOp (handle, g.Add (value, increment));
var s = new TFSession (g);
// Must first initialize all the variables.
s.GetRunner ().AddTarget (init).Run (status);
Assert (status);
// Now print the value, run the update op and repeat
// Ignore errors.
for (int i = 0; i < 5; i++) {
// Read and update
var result = s.GetRunner ().Fetch (value).AddTarget (update).Run ();
Console.WriteLine ("Result of variable read {0} -> {1}", i, result [0].GetValue ());
}
}
}
void BasicMultidimensionalArray ()
{
Console.WriteLine ("Basic multidimensional array");
using (var g = new TFGraph ()) {
var s = new TFSession (g);
var var_a = g.Placeholder (TFDataType.Int32);
var mul = g.Mul (var_a, g.Const (2));
var a = new int[,,] { { { 0, 1 } , { 2, 3 } } , { { 4, 5 }, { 6, 7 } } };
var result = s.GetRunner ().AddInput (var_a, a).Fetch (mul).Run () [0];
var actual = (int[,,])result.GetValue ();
var expected = new int[,,] { { { 0, 2 } , { 4, 6 } } , { { 8, 10 }, { 12, 14 } } };
Console.WriteLine ("Actual: " + RowOrderJoin (actual));
Console.WriteLine ("Expected: " + RowOrderJoin (expected));
Assert(expected.Cast