Skip to content

Integrating torchsharp functionality into Bonsai#48

Merged
glopesdev merged 143 commits intomainfrom
dev/torchsharp
Apr 11, 2025
Merged

Integrating torchsharp functionality into Bonsai#48
glopesdev merged 143 commits intomainfrom
dev/torchsharp

Conversation

@ncguilbeault
Copy link
Copy Markdown
Collaborator

@ncguilbeault ncguilbeault commented Jan 21, 2025

Overview

This pull request introduces a new package, Bonsai.ML.Torch, which adds functionality from the TorchSharp package into Bonsai. It adds functions to perform basic tensor manipulations, linear algebra, inference with neural networks, and more. The Bonsai.ML.Torch package is still under heavy development and there are still many features in the TorchSharp package which have not been included. For the first release, this PR focuses on operators that support creating, manipulating, and transforming Tensor objects.

Summary of Changes

Addition of New Bonsai.ML.Torch Package:

  • The Bonsai.ML.Torch project was added to the solution file Bonsai.ML.sln.
  • Bonsai.ML.Torch adds a reference to the TorchSharp package.

Tensor Operations:

  • Many common .NET data types (double, float, arrays, etc.) can be converted to Tensor objects using the ToTensor class.
  • ToTensor has overloads for key OpenCV.Net data types (IplImage, Mat). IplImage and Mat data types can be converted to Tensor objects using zero-copy, but current conversions from Tensor to Mat or IplImage objects require a complete data copy. One possible solution to this: Support zero-copy OpenCV <-> TorchSharp conversions #55.
  • Tensor objects can be initialized in various ways, including initializing tensors with Ones, Zeros, ARange, LinSpace, Empty, etc. Custom tensors can be defined using the CreateTensor class and specifying the values using Python-like syntax(e.g. "[0]" for 1D tensor with a single value, "[[0, 1]]" for a 1x2 tensor, "1.4" for single values, or "[]" for a 1D empty tensor).
  • Tensor objects can be converted back to .NET arrays using the ConvertToArray node (for flattening data) and the ConvertToNDArray node (for specifying ranked multidimensional arrays).
  • Tensor objects can be manipulated in various ways. For example, Reshape can be used to change the dimensions of a Tensor, Concat can be used to concatenate tensors along a specified dimension, ConvertScalarType can convert the data type of a Tensor, etc.
  • GPU processing is supported by using the InitializeDeviceType with CUDA-compatible GPUs on startup. From there, the CUDA object can be passed to the Device parameter of many Tensor creation methods. Alternatively computed Tensor objects can be transferred to/from CUDA devices using the ToDevice node and setting the Device parameter using the desired device object.
  • The Tensor object contains many static extension methods which can be accessed using the ExpressionTransform node. For example, it is possible to call it.sum() to sum all elements of a tensor, or it.T to transpose a tensor.
  • Many existing reactive operators will also work with overloaded Tensor operators. For example, two Tensor objects can be passed to Zip -> Multiply.
  • Specific elements of Tensor objects can be indexed using the Index class. The Index node allows specifying the indices using Python-like syntax. It is also possible to define tensor indices explicitly (e.g., BooleanIndex, ColonIndex, etc.), and use standard Bonsai reactive operators for indexing (e.g., Zip -> Index).

Neural Networks:

  • This PR adds some initial support for the nn.Module class, the base class for instantiating neural network objects.
  • A Module object can be loaded from predefined architectures (e.g., AlexNet, MNIST, and MobileNet) and can optionally load a set of weights from disk. The weights must come from a model with an identical architecture. Model weights can be saved using SaveModel. For more information about this and how to convert PyTorch modules to the correct format, see this wiki article.
  • Running inference with a Module object can be done using the Forward node. Currently, the Forward method will always work by transforming a Tensor object as input into a Tensor output.
  • Training a Module can be done using the Backward class. At this time, only a very small subset of optimizers (Adam), loss functions (NegativeLogLikelihood), and learning rate schedulers are supported. in the future, we plan to bring additional support for customizing training protocols in Bonsai workflows.
  • The package provides an ITorchModule interface and an adapter class, TorchModuleAdapter, to allow both nn.Module objects and jit.ScriptModule objects to be loaded and used in a similar way.

Linear Algebra:

  • Several functions are added to allow complex algebraic computations, such as calculating the Determinant, EigenvalueDecomposition, Inverse, etc.

Vision:

  • Adds a single node, Normalize, for transforming image tensors using means and standard deviations for each channel.

@ncguilbeault ncguilbeault requested a review from glopesdev March 14, 2025 16:45
Copy link
Copy Markdown
Member

@glopesdev glopesdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ncguilbeault This all looks great, only very few things I noticed for this round, it's in great shape and almost there I think!

…fixed property validation for single-valued tensors, and updated `BuildTensorFromScalarValue` method to use the return type and corrected call to `Expression.Block`.
@ncguilbeault ncguilbeault requested a review from glopesdev March 19, 2025 12:48
…e input tensor to the correct `ScalarType` before copying to the output array and changed class names to `ConvertToArray` and `ConvertToNDArray` arrays to convey this. Updated `ScalarTypeConverter` to only handle `ScalarType` conversions and changed properties to ScalarType instead of .NET type.
…ement. Replaced approach of validating string values inside of the class in favour of using the `TensorConverter` class to return the correctly formatted Tensor automatically. Adjusted Process methods to return a single copy of the tensor but ensure that the tensor is moved to the correct device once the device has been initialized.
…String` methods in `TensorConverter` class to public to allow tensor conversion operations outside of package namespace
… classes with ScalarType `Type` property instead of locking it to `CreateTensor` class
@ncguilbeault ncguilbeault requested a review from glopesdev April 4, 2025 14:10
The `Bonsai.ML.Torch` package primarily provides tooling and functionality for users to interact with and manipulate `Tensor` objects, the core data type of torch which underlies most advanced operations. Additionally, the package provides some capabilities for defining neural network architectures, running forward inference, and learning via back propagation.

## Tensor Operations
The package provides several ways to work with tensors. Users can initialize tensors, (`Ones`, `Zeros`, etc.), create tensors from .NET data types, (`ToTensor`), and define custom tensors using Python-like syntax (`CreateTensor`). Tensors can be converted back to .NET types using the `ToArray` node (for flattening tensors into a unidimensional array) or the `ToNDArray` node (for preserving multidimensional array shapes). Furthermore, the `Tensor` object contains many extension methods which can be used via scripting with `ExpressionTransform` (for example, `it.sum()` to sum a tensor, or `it.T` to transpose), and works with overloaded operators (for example, `Zip` -> `Multiply`). It is also possible to use the `ExpressionTransform` node to access individual elements of a tensor, using the syntax `it.ReadCpuT(0)` where `T` is a primitive .NET data type (i.e. `Single`, `Double`, `Int64`, etc.).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a really nice overview of available operations, I wonder if we should include docfx xref links to each operator so that people would be able to navigate to them directly from here, but not strictly necessary at this point.

Copy link
Copy Markdown
Member

@glopesdev glopesdev Apr 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example syntax:

[`ToTensor`](xref:Bonsai.ML.Torch.ToTensor)

@ncguilbeault ncguilbeault added this to the v0.4.0 milestone Apr 7, 2025
…ly passed to creation of the `ScriptModule` if it is not null
@glopesdev glopesdev merged commit 5311d2f into main Apr 11, 2025
2 checks passed
@glopesdev glopesdev deleted the dev/torchsharp branch April 11, 2025 11:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New planned feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants