Introduction to TensorFlow.NET
Overview
TensorFlow.NET (TF.NET) is a .NET Standard binding for TensorFlow, a popular machine learning library developed by Google. The project aims to bring the power of TensorFlow to the .NET platform, enabling developers to create, train, and deploy machine learning models using C#. With the intention to provide a complete implementation of TensorFlow in C#, TensorFlow.NET gives .NET developers seamless access to one of the most advanced tools for machine learning.
TF.NET also includes a high-level interface for Keras, which is available as a separate package called TensorFlow.Keras. This interface simplifies the design and testing of neural network models, making it easier for developers to transition from Python to .NET without losing out on valuable tools and functions.
Unique Features
Why Choose TensorFlow.NET?
TensorFlow.NET is part of the SciSharp STACK, which aims to bring cutting-edge data science and machine learning technologies into the .NET ecosystem. The alignment of TensorFlow.NET’s API with the original TensorFlow API means that developers can quickly translate TensorFlow scripts written in Python into C# code with minimal changes. This seamless adaptation ensures that there is little to no learning curve for developers already familiar with TensorFlow, making it a powerful resource for leveraging existing machine learning codebases in .NET applications.
While other projects like TensorFlowSharp provide access to low-level APIs of TensorFlow, they often require models to be pre-built in Python. In contrast, TensorFlow.NET empowers developers to construct and execute both training and inference pipelines directly in C# and F#. In addition, TensorFlow.NET’s integration with TensorFlow.Keras facilitates the transition of Keras code from Python, providing a more accessible and streamlined experience for .NET developers.
Moreover, TensorFlow.NET is employed as one of the backends in ML.NET for model training and inference, showcasing its applicability and integration capability within the broader .NET machine learning landscape.
Documentation and Resources
To get started with TensorFlow.NET, developers can refer to its comprehensive documentation:
- TensorFlow.NET Documents offer introductory guides and basic usage examples.
- The Definitive Guide to TensorFlow.NET provides in-depth documentation for those seeking a deeper understanding.
- TensorFlow.NET Examples displays various practical implementations and use cases.
For any installation or runtime issues, the TensorFlow.NET FAQ offers troubleshooting advice.
Installation
TensorFlow.NET is available as a package through NuGet. Installation is straightforward, and it supports both CPU and GPU computation depending on your hardware and system configuration:
# Install TensorFlow.NET
PM> Install-Package TensorFlow.NET
# Install TensorFlow.Keras
PM> Install-Package TensorFlow.Keras
# Install appropriate computing support
# CPU version for Windows and Linux
PM> Install-Package SciSharp.TensorFlow.Redist
# CPU and GPU Versions for other systems
PM> Install-Package SciSharp.TensorFlow.Redist-OSX
PM> Install-Package SciSharp.TensorFlow.Redist-Windows-GPU
PM> Install-Package SciSharp.TensorFlow.Redist-Linux-GPU
Example Usage
TensorFlow.NET allows the development of models just like in Python, demonstrated in the following C# examples.
Linear Regression Example:
using static Tensorflow.Binding;
using static Tensorflow.KerasApi;
using Tensorflow;
using Tensorflow.NumPy;
// Parameters
var training_steps = 1000;
var learning_rate = 0.01f;
var display_step = 100;
// Sample data
var X = np.array(3.3f, 4.4f, 5.5f, 6.71f, 6.93f, 4.168f, 9.779f, 6.182f, 7.59f, 2.167f,
7.042f, 10.791f, 5.313f, 7.997f, 5.654f, 9.27f, 3.1f);
var Y = np.array(1.7f, 2.76f, 2.09f, 3.19f, 1.694f, 1.573f, 3.366f, 2.596f, 2.53f, 1.221f,
2.827f, 3.465f, 1.65f, 2.904f, 2.42f, 2.94f, 1.3f);
var n_samples = X.shape[0];
// Initializing parameters
var W = tf.Variable(-0.06f, name: "weight");
var b = tf.Variable(-0.73f, name: "bias");
var optimizer = keras.optimizers.SGD(learning_rate);
// Training loop
foreach (var step in range(1, training_steps + 1))
{
// Automatic differentiation
using var g = tf.GradientTape();
var pred = W * X + b;
var loss = tf.reduce_sum(tf.pow(pred - Y, 2)) / (2 * n_samples);
var gradients = g.gradient(loss, (W, b));
optimizer.apply_gradients(zip(gradients, (W, b)));
if (step % display_step == 0)
{
pred = W * X + b;
loss = tf.reduce_sum(tf.pow(pred - Y, 2)) / (2 * n_samples);
print($"step: {step}, loss: {loss.numpy()}, W: {W.numpy()}, b: {b.numpy()}");
}
}
ResNet Example:
using static Tensorflow.Binding;
using static Tensorflow.KerasApi;
using Tensorflow;
using Tensorflow.NumPy;
var layers = keras.layers;
var inputs = keras.Input(shape: (32, 32, 3), name: "img");
var x = layers.Conv2D(32, 3, activation: "relu").Apply(inputs);
x = layers.Conv2D(64, 3, activation: "relu").Apply(x);
var block_1_output = layers.MaxPooling2D(3).Apply(x);
x = layers.Conv2D(64, 3, activation: "relu", padding: "same").Apply(block_1_output);
x = layers.Conv2D(64, 3, activation: "relu", padding: "same").Apply(x);
var block_2_output = layers.Add().Apply(new Tensors(x, block_1_output));
x = layers.Conv2D(64, 3, activation: "relu", padding: "same").Apply(block_2_output);
x = layers.Conv2D(64, 3, activation: "relu", padding: "same").Apply(x);
var block_3_output = layers.Add().Apply(new Tensors(x, block_2_output));
x = layers.Conv2D(64, 3, activation: "relu").Apply(block_3_output);
x = layers.GlobalAveragePooling2D().Apply(x);
x = layers.Dense(256, activation: "relu").Apply(x);
x = layers.Dropout(0.5f).Apply(x);
var outputs = layers.Dense(10).Apply(x);
var model = keras.Model(inputs, outputs, name: "toy_resnet");
model.summary();
model.compile(optimizer: keras.optimizers.RMSprop(1e-3f),
loss: keras.losses.SparseCategoricalCrossentropy(from_logits: true),
metrics: new[] { "acc" });
var ((x_train, y_train), (x_test, y_test)) = keras.datasets.cifar10.load_data();
x_train = x_train / 255.0f;
model.fit(x_train[new Slice(0, 2000)], y_train[new Slice(0, 2000)], batch_size: 64, epochs: 10, validation_split: 0.2f);
model.save("./toy_resnet_model");
Contribution and Support
TensorFlow.NET invites contributions from the community. Individuals interested in enhancing their understanding of TensorFlow or eager to contribute can help through various ways such as:
- Porting TensorFlow unit tests and examples into C# or F#.
- Reporting missing API functions or bugs.
- Working on documentation improvements.
- Debugging and fixing tests marked as Ignored.
The best way to align their contributions with the project's progress and needs is to maintain their repository’s sync with the official TF.NET GitHub. Support for the project can also be provided by purchasing related books that help sustain open-source projects.
For support and discussions, join the communities on Discord and Gitter.