TENSORFLOWCSHARP

本文通过一系列示例展示了如何使用 TensorFlowSharp 进行基本操作,包括常量运算、变量使用、矩阵运算等,并提供了线性回归等更复杂示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

还是看源代码,示例比较好

https://github.com/migueldeicaza/TensorFlowSharp

https://github.com/migueldeicaza/TensorFlowSharp/blob/master/SampleTest/SampleTest.cs

//
// 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);

				// Test Zeros, Ones
		                var o = g.Ones(new TFShape(4, 4));
		                var r = g.RandomNormal(new TFShape(4, 4));
		                var z = g.Zeros(new TFShape(4, 4));
		                var m = g.Mul(o, r);
		                var res1 = s.GetRunner().Run(m);
		                var res2 = s.GetRunner().Run(g.Mul(g.Mul(o, r), z));
		                
		                //Test Constants
		                var co = g.Constant(1.0, new TFShape(4, 4), TFDataType.Double);
		                var cz = g.Constant(0.0, new TFShape(4, 4), TFDataType.Double);
		                var cr = g.RandomNormal(new TFShape(4, 4));
		                var cm = g.Mul(co, cr);
		                var cres1 = s.GetRunner().Run(cm);
		                var cres2 = s.GetRunner().Run(g.Mul(g.Mul(co, cr), cz));

		                var so = g.Ones(new TFShape(4, 3));
		                var sr = g.RandomNormal(new TFShape(3, 5));
		                var sz = g.Zeros(new TFShape(5, 6));
		                var sm = g.MatMul(so, sr);
		                var sres1 = s.GetRunner().Run(sm);
		                var sres2 = s.GetRunner().Run(g.MatMul(g.MatMul(so, sr), sz));

				// Multiply two constants
				results = s.GetRunner ().Run (g.Mul (a, b));
				Console.WriteLine ("a*b={0}", results.GetValue ());

				Console.WriteLine ("graph to string: " + g.ToString ());
				// 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<int> ().SequenceEqual (actual.Cast<int> ()));
			};
		}

		private static string RowOrderJoin(int[,,] array) => string.Join (", ", array.Cast<int> ());

		void BasicMatrix ()
		{
			Console.WriteLine ("Basic matrix");
			using (var g = new TFGraph ()) {
				var s = new TFSession (g);

				// 1x2 matrix
				var matrix1 = g.Const (new double [,] { { 3, 3 } });
				// 2x1 matrix
				var matrix2 = g.Const (new double [,] { { 2 }, { 2 } });

				// multiply
				var product = g.MatMul (matrix1, matrix2);


				var result = s.GetRunner ().Run (product);
				Console.WriteLine ("Tensor ToString=" + result);
				Console.WriteLine ("Value [0,0]=" + ((double[,])result.GetValue ())[0,0]);

			};
		}

		int ArgMax (float [,] array, int idx)
		{
			float max = -1;
			int maxIdx = -1;
			var l = array.GetLength (1);
			for (int i = 0; i < l; i++)
				if (array [idx, i] > max) {
					maxIdx = i;
					max = array [idx, i];
				}
			return maxIdx;
		}

		public float [] Extract (float [,] array, int index)
		{
			var n = array.GetLength (1);
			var ret = new float [n];

			for (int i = 0; i < n; i++)
				ret [i] = array [index,i];
			return ret;
		}

		// This sample has a bug, I suspect the data loaded is incorrect, because the returned
		// values in distance is wrong, and so is the prediction computed from it.
		void NearestNeighbor ()
		{
			// Get the Mnist data

			var mnist = Mnist.Load ();

			// 5000 for training
			const int trainCount = 5000;
			const int testCount = 200;
			(var trainingImages, var trainingLabels) = mnist.GetTrainReader ().NextBatch (trainCount);
			(var testImages, var testLabels) = mnist.GetTestReader ().NextBatch (testCount);

			Console.WriteLine ("Nearest neighbor on Mnist images");
			using (var g = new TFGraph ()) {
				var s = new TFSession (g);


				TFOutput trainingInput = g.Placeholder (TFDataType.Float, new TFShape (-1, 784));

				TFOutput xte = g.Placeholder (TFDataType.Float, new TFShape (784));

				// Nearest Neighbor calculation using L1 Distance
				// Calculate L1 Distance
				TFOutput distance = g.ReduceSum (g.Abs (g.Add (trainingInput, g.Neg (xte))), axis: g.Const (1));

				// Prediction: Get min distance index (Nearest neighbor)
				TFOutput pred = g.ArgMin (distance, g.Const (0));

				var accuracy = 0f;
				// Loop over the test data
				for (int i = 0; i < testCount; i++) {
					var runner = s.GetRunner ();

					// Get nearest neighbor

					var result = runner.Fetch (pred).Fetch (distance).AddInput (trainingInput, trainingImages).AddInput (xte, Extract (testImages, i)).Run ();
					var r = result [0].GetValue ();
					var tr = result [1].GetValue ();
					var nn_index = (int)(long) result [0].GetValue ();

					// Get nearest neighbor class label and compare it to its true label
					Console.WriteLine ($"Test {i}: Prediction: {ArgMax (trainingLabels, nn_index)} True class: {ArgMax (testLabels, i)} (nn_index={nn_index})");
					if (ArgMax (trainingLabels, nn_index) == ArgMax (testLabels, i))
						accuracy += 1f/ testImages.Length;
				}
				Console.WriteLine ("Accuracy: " + accuracy);
			}
		}

#if true
		// 
		// Port of https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/2_BasicModels/linear_regression.py
		//
		void LinearRegression ()
		{
			Console.WriteLine ("Linear regression");
			// Parameters
			var learning_rate = 0.001f;
			var training_epochs = 100;
			var display_step = 50;

			// Training data
			var train_x = new double [] {
				3.3, 4.4, 5.5, 6.71, 6.93, 4.168, 9.779, 6.182, 7.59, 2.167,
				7.042, 10.791, 5.313, 7.997, 5.654, 9.27, 3.1
			};
			var train_y = new double [] {
				1.7,2.76,2.09,3.19,1.694,1.573,3.366,2.596,2.53,1.221,
			 	2.827,3.465,1.65,2.904,2.42,2.94,1.3
			};
			var n_samples = train_x.Length;
			using (var g = new TFGraph ()) {
				var s = new TFSession (g);
		 		var rng = new Random (0);
				// tf Graph Input

				var X = g.Placeholder (TFDataType.Double);
				var Y = g.Placeholder (TFDataType.Double);

				var W = g.Variable (g.Const (rng.NextDouble ()), operName: "weight");
				var b = g.Variable (g.Const (rng.NextDouble ()), operName: "bias");
				var pred = g.Add (g.Mul (X, W.Read, "x_w"), b.Read);

				var cost = g.Div (g.ReduceSum (g.Pow (g.Sub (pred, Y), g.Const (2.0))), g.Mul (g.Const (2.0), g.Const ((double)n_samples), "2_n_samples"));

                // SOLVED
                // STuck here: TensorFlow bindings need to surface gradient support
                // waiting on Google for this
                // https://github.com/migueldeicaza/TensorFlowSharp/issues/25

                var sgd = new SGD(g, learning_rate);
                var updateOps = sgd.Minimize(cost);

                using (var sesssion = new TFSession(g))
                {
                    sesssion.GetRunner().AddTarget(g.GetGlobalVariablesInitializer()).Run();

                    for (int i = 0; i < training_epochs; i++)
                    {
                        double avgLoss = 0;
                        for (int j = 0; j < n_samples; j++)
                        {
                            var tensors = sesssion.GetRunner()
                               .AddInput(X, new TFTensor(train_x[j]))
                               .AddInput(Y, new TFTensor(train_y[j]))
                               .AddTarget(updateOps).Fetch(sgd.Iterations.Read, cost, W.Read, b.Read, sgd.LearningRate.Read).Run();
                            avgLoss += (double)tensors[1].GetValue();
                        }
                        var tensors2 = sesssion.GetRunner()
                               .Fetch(W.Read, b.Read).Run();
                        var output = $"Epoch: {i+1:D}, loss: {avgLoss / n_samples:F4}, W: {tensors2[0].GetValue():F4}, b: {tensors2[1].GetValue():F4}";
                        Console.WriteLine(output);
                    }
                }
            }
		}
#endif
		#endregion
		public static void Main (string [] args)
		{
			Console.WriteLine (Environment.CurrentDirectory);
			Console.WriteLine ("TensorFlow version: " + TFCore.Version);

			//var b = TFCore.GetAllOpList ();


			var t = new MainClass ();
			t.LinearRegression ();
			t.TestParametersWithIndexes ();
			t.AddControlInput ();
			t.TestImportGraphDef ();
			t.TestSession ();
			t.TestOperationOutputListSize ();
			t.TestVariable ();

			// Current failing test
			t.TestOutputShape ();
			//t.AttributesTest ();
			t.GetAttributesTest ();
			t.WhileTest ();

			//var n = new Mnist ();
			//n.ReadDataSets ("/Users/miguel/Downloads", numClasses: 10);

			t.BasicConstantOps ();
			t.BasicVariables ();
			t.BasicMultidimensionalArray ();
			t.BasicMatrix ();

			t.NearestNeighbor ();

		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值