Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrating torchsharp functionality into Bonsai #48

Open
wants to merge 75 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
b1be644
Added tensors library
ncguilbeault Aug 23, 2024
158f682
Added arange function
ncguilbeault Aug 23, 2024
ceabd85
Added concat class
ncguilbeault Aug 23, 2024
0c33017
Added arange function
ncguilbeault Aug 23, 2024
518a989
Added linspace
ncguilbeault Aug 23, 2024
004db9b
Added meshgrid
ncguilbeault Aug 23, 2024
a8e4a83
Added ones
ncguilbeault Aug 23, 2024
d5bf196
Added zeros
ncguilbeault Aug 23, 2024
9f22932
Added device initialization
ncguilbeault Aug 23, 2024
7da5f09
Added ability to move tensor to device
ncguilbeault Aug 23, 2024
a6dc975
Added permute
ncguilbeault Aug 23, 2024
111e97e
Added reshape
ncguilbeault Aug 23, 2024
2776c09
Added set
ncguilbeault Aug 23, 2024
1bb5311
Updated csproj with opencv.net package
ncguilbeault Aug 23, 2024
747f8d1
Added concatenate class
ncguilbeault Aug 23, 2024
78aa6be
Added convert data type
ncguilbeault Aug 23, 2024
829545e
Added create tensor method
ncguilbeault Aug 23, 2024
65347bd
Added index method and updated set method
ncguilbeault Aug 23, 2024
5fea7bf
Defined tensor data types as subset of ScalarType
ncguilbeault Aug 23, 2024
7d1abd4
Added to array method
ncguilbeault Aug 23, 2024
34f4857
Added tensor data type helper
ncguilbeault Aug 23, 2024
97e2fe7
Added methods to convert OpenCV types
ncguilbeault Aug 23, 2024
9d932e5
Refactored to torch namespace instead of tensors
ncguilbeault Aug 27, 2024
ba7f53b
Removed previous Bonsai.ML.Tensors directory and contents
ncguilbeault Aug 27, 2024
10aa92b
Updated solution to reflect change
ncguilbeault Aug 27, 2024
f7e372c
Moved Tensors namespace to main Torch namespace
ncguilbeault Aug 27, 2024
3692cb3
Updated to reflect new namespace
ncguilbeault Aug 27, 2024
b51fb53
Removed unfinished classes
ncguilbeault Aug 27, 2024
3c1838c
Updated to use common Bonsai.ML.Data project
ncguilbeault Sep 4, 2024
c548469
Added additional overloads to process method
ncguilbeault Sep 4, 2024
a594f04
Updated to use common data tools
ncguilbeault Sep 4, 2024
3a15591
Updated tensor data type and helper
ncguilbeault Sep 4, 2024
279d6b7
Updated formatting
ncguilbeault Sep 4, 2024
3910867
Removed bonsai core dependency in favor of bonsai.ml dependency
ncguilbeault Sep 26, 2024
f002c6f
Fixed bugs with create tensor method and updated to use string formatter
ncguilbeault Sep 26, 2024
9ffb9f0
Added empty tensor creator
ncguilbeault Sep 26, 2024
200057a
Moved index helper to main library
ncguilbeault Sep 26, 2024
0438eb2
Moved opencv helper to main library
ncguilbeault Sep 26, 2024
37acfc4
Removed opencv helper from helpers subfolder
ncguilbeault Sep 26, 2024
d52af6c
Updated with new index helper
ncguilbeault Sep 26, 2024
15a586d
Updated with opencv helper
ncguilbeault Sep 26, 2024
30d5c67
Added process overload for generating on input
ncguilbeault Sep 26, 2024
3e6797b
Added xml ignore tag on device
ncguilbeault Sep 27, 2024
9bfe4e3
Updated to use shared module interface
ncguilbeault Oct 16, 2024
0b22a07
Modified to use Module interface
ncguilbeault Oct 30, 2024
804aaf9
Removed unnecessary null string
ncguilbeault Oct 30, 2024
77caa53
Added a common interface
ncguilbeault Nov 1, 2024
4013613
Added swap axes function
ncguilbeault Nov 6, 2024
ee95aea
Added tile function
ncguilbeault Nov 6, 2024
6b3d178
Updated model loading and model forward procedure
ncguilbeault Nov 6, 2024
1e5f99f
Added backward function for running online gradient descent with spec…
ncguilbeault Nov 14, 2024
fe6eb7d
Added function to save model
ncguilbeault Nov 14, 2024
811d031
Changed name to indicate loading from an existing architecture
ncguilbeault Jan 20, 2025
978194b
Added descriptions and documentation
ncguilbeault Jan 20, 2025
6286f61
Added some useful classes for linear algebra
ncguilbeault Jan 20, 2025
c363b5b
Adding classes for creating tensor indexes
ncguilbeault Jan 20, 2025
b2bebb8
Updated MNIST model architecture with correct fully connected layer size
ncguilbeault Jan 20, 2025
e261425
Added class to explicitly create a clone of a tensor
ncguilbeault Jan 20, 2025
98a65fd
Update to use correct width for an IplImage based on widthstep rather…
ncguilbeault Jan 20, 2025
4e2ae53
Explicitly use static torch.Tensor type for defining expressions
ncguilbeault Jan 20, 2025
12ec59e
Update set with process overloads to handle passing in tensor index
ncguilbeault Jan 20, 2025
5630f01
Fixed incorrectly generating ones instead of zeros
ncguilbeault Jan 20, 2025
69efcbf
Updated to correctly parse colons in string
ncguilbeault Jan 20, 2025
556e1ad
Updated to use collection expressions
ncguilbeault Jan 20, 2025
f2ceb9d
Added documentation
ncguilbeault Jan 20, 2025
ff8e902
Updated to use collection expressions
ncguilbeault Jan 21, 2025
189aff1
Add process overload to initialize device on input
ncguilbeault Jan 21, 2025
9bb600f
Added documentation
ncguilbeault Jan 21, 2025
4d3297d
Added file name editor attribute to model path
ncguilbeault Jan 21, 2025
6969a7c
Updated to latest torchsharp version
ncguilbeault Jan 21, 2025
e35980f
Update class name to reflect file name
ncguilbeault Jan 21, 2025
4465a3c
Added documentation to package
ncguilbeault Jan 23, 2025
da81e8b
Fixed issue with MNIST model not accepting num classes
ncguilbeault Jan 23, 2025
d06a4c2
Made slight correction to GPU documentation
ncguilbeault Jan 24, 2025
139488e
Modified torch module classes to be internel
ncguilbeault Jan 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Bonsai.ML.sln
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bonsai.ML.LinearDynamicalSy
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bonsai.ML.HiddenMarkovModels.Design", "src\Bonsai.ML.HiddenMarkovModels.Design\Bonsai.ML.HiddenMarkovModels.Design.csproj", "{FC395DDC-62A4-4E14-A198-272AB05B33C7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bonsai.ML.Torch", "src\Bonsai.ML.Torch\Bonsai.ML.Torch.csproj", "{06FCC9AF-CE38-44BB-92B3-0D451BE88537}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -72,6 +74,10 @@ Global
{FC395DDC-62A4-4E14-A198-272AB05B33C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC395DDC-62A4-4E14-A198-272AB05B33C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC395DDC-62A4-4E14-A198-272AB05B33C7}.Release|Any CPU.Build.0 = Release|Any CPU
{06FCC9AF-CE38-44BB-92B3-0D451BE88537}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{06FCC9AF-CE38-44BB-92B3-0D451BE88537}.Debug|Any CPU.Build.0 = Debug|Any CPU
{06FCC9AF-CE38-44BB-92B3-0D451BE88537}.Release|Any CPU.ActiveCfg = Release|Any CPU
{06FCC9AF-CE38-44BB-92B3-0D451BE88537}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -86,6 +92,7 @@ Global
{39A4414F-52B1-42D7-82FA-E65DAD885264} = {12312384-8828-4786-AE19-EFCEDF968290}
{A135C7DB-EA50-4FC6-A6CB-6A5A5CC5FA13} = {12312384-8828-4786-AE19-EFCEDF968290}
{17DF50BE-F481-4904-A4C8-5DF9725B2CA1} = {12312384-8828-4786-AE19-EFCEDF968290}
{06FCC9AF-CE38-44BB-92B3-0D451BE88537} = {12312384-8828-4786-AE19-EFCEDF968290}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B6468F13-97CD-45E0-9E1E-C122D7F1E09F}
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ Facilitates inference using Hidden Markov Models (HMMs). It interfaces with the
### Bonsai.ML.HiddenMarkovModels.Design
Visualizers and editor features for the HiddenMarkovModels package.

### Bonsai.ML.Torch
Interfaces with the [TorchSharp](https://github.com/dotnet/TorchSharp) package, a C# wrapper around the torch library. Provides tooling for manipulating tensors, performing linear algebra, training and inference with deep neural networks, and more.

> [!NOTE]
> Bonsai.ML packages can be installed through Bonsai's integrated package manager and are generally ready for immediate use. However, some packages may require additional installation steps. Refer to the specific package section for detailed installation guides and documentation.

Expand Down
13 changes: 13 additions & 0 deletions docs/articles/Torch/torch-getting-started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Getting Started

The aim of the `Bonsai.ML.Torch` package is to integrate the [TorchSharp](https://github.com/dotnet/TorchSharp) package, a C# wrapper around the powerful libtorch library, into Bonsai. In the current version, the package primarily provides tooling and functionality for users to interact with and manipulate `Tensor`s, the core data type of libtorch which underlies many of the advanced torch operations. Additionally, the package provides some capabilities for defining neural network architectures, running forward inference, and learning via back propogation.

## 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 single array) or the `ToNDArray` node (for preserving multidimensional array shapes). Furthermore, the `Tensor` data types contains many extension methods which can be used via scripting, such as using `ExpressionTransform` (for example, it.sum() to sum a tensor, or it.T to transpose), and works with overloaded operators, for example, `Zip` -> `Multiply`. Thus, `ExpressionTransform` can also be used to access individual elements of a tensor, using the syntax `it.data<T>.ReadCpuT(0)` where `T` is a primitive .NET data type.


## Running on the GPU
Users must be explicit about running tensors on the GPU. First, the `InitializeDeviceType` node must run with a CUDA-compatible GPU. Afterwards, tensors are moved to the GPU using the `ToDevice` node. Converting tensors back to .NET data types requires moving the tensor back to the CPU before converting.

## Neural Networks
The package provides initial support for working with torch `Module`s, the conventional object for deep neural networks. The `LoadModuleFromArchitecture` node allows users to select from a list of common architectures, and can optionally load in pretrained weights from disk. Additionally, the package supports loading `TorchScript` modules with the `LoadScriptModule` node, which enables users to use torch modules saved in the `.pt` file format. Users can then use the `Forward` node to run inference and the `Backward` node to run back propogation.
27 changes: 27 additions & 0 deletions docs/articles/Torch/torch-overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Bonsai.ML.Torch Overview

The Torch package provides a Bonsai interface to interact with the [TorchSharp](https://github.com/dotnet/TorchSharp) package, a C# implementation of the torch library.

## General Guide

The Bonsai.ML.Torch package can be installed through the Bonsai Package Manager and depends on the TorchSharp library. Additionally, running the package requires installing the specific torch DLLs needed for your desired application. The steps for installing are outlined below.

### Running on the CPU
For running the package using the CPU, the `TorchSharp-cpu` library can be installed though the `nuget` package source.

### Running on the GPU
To run torch on the GPU, you first need to ensure that you have a CUDA compatible device installed on your system.

Next, you must follow the [CUDA installation guide for Windows](https://docs.nvidia.com/cuda/cuda-installation-guide-microsoft-windows/index.html) or the [guide for Linux](https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html). Make sure to install the correct `CUDA v12.1` version [found here](https://developer.nvidia.com/cuda-12-1-0-download-archive). Ensure that you have the correct CUDA version (v12.1) installed, as `TorchSharp` currently only supports this version.

Next, you need to install the `cuDNN v9` library following the [guide for Windows](https://docs.nvidia.com/deeplearning/cudnn/latest/installation/windows.html) or the [guide for Linux](https://docs.nvidia.com/deeplearning/cudnn/latest/installation/linux.html). Again, you need to ensure you have the correct version installed (v9). You should consult [nvidia's support matrix](https://docs.nvidia.com/deeplearning/cudnn/latest/reference/support-matrix.html) to ensure the versions of CUDA and cuDNN you installed are compatible with your specific OS, graphics driver, and hardware.

Once complete, you need to install the cuda-compatible torch libraries and place them into the correct location. You can download the libraries from [the pytorch website](https://pytorch.org/get-started/locally/) with the following options selected:

- PyTorch Build: Stable (2.5.1)
- OS: [Your OS]
- Package: LibTorch
- Language: C++/Java
- Compute Platform: CUDA 12.1

Finally, extract the zip folder and copy the contents of the `lib` folder into the `Extensions` folder of your bonsai installation directory.
7 changes: 6 additions & 1 deletion docs/articles/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,9 @@
- name: Overview
href: HiddenMarkovModels/hmm-overview.md
- name: Getting Started
href: HiddenMarkovModels/hmm-getting-started.md
href: HiddenMarkovModels/hmm-getting-started.md
- name: Torch
- name: Overview
href: Torch/torch-overview.md
- name: Getting Started
href: Torch/torch-getting-started.md
43 changes: 43 additions & 0 deletions src/Bonsai.ML.Torch/Arange.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using System.ComponentModel;
using System.Reactive.Linq;
using static TorchSharp.torch;
using TorchSharp;

namespace Bonsai.ML.Torch
{
/// <summary>
/// Creates a 1-D tensor of values within a given range given the start, end, and step.
/// </summary>
[Combinator]
[Description("Creates a 1-D tensor of values within a given range given the start, end, and step.")]
[WorkflowElementCategory(ElementCategory.Source)]
public class Arange
{
/// <summary>
/// The start of the range.
/// </summary>
[Description("The start of the range.")]
public int Start { get; set; } = 0;

/// <summary>
/// The end of the range.
/// </summary>
[Description("The end of the range.")]
public int End { get; set; } = 10;

/// <summary>
/// The step size between values.
/// </summary>
[Description("The step size between values.")]
public int Step { get; set; } = 1;

/// <summary>
/// Generates an observable sequence of 1-D tensors created with the <see cref="arange(Scalar, Scalar, Scalar, ScalarType?, Device?, bool)"/> function.
/// </summary>
public IObservable<Tensor> Process()
{
return Observable.Defer(() => Observable.Return(arange(Start, End, Step)));
}
}
}
19 changes: 19 additions & 0 deletions src/Bonsai.ML.Torch/Bonsai.ML.Torch.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Title>Bonsai.ML.Torch</Title>
<Description>A Bonsai package for TorchSharp tensor manipulations.</Description>
<PackageTags>Bonsai Rx ML Tensors TorchSharp</PackageTags>
<TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OpenCV.Net" Version="3.4.2" />
<PackageReference Include="TorchSharp" Version="0.105.0" />
<PackageReference Include="TorchVision" Version="0.105.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Bonsai.ML\Bonsai.ML.csproj" />
<ProjectReference Include="..\Bonsai.ML.Data\Bonsai.ML.Data.csproj" />
<ProjectReference Include="..\Bonsai.ML.Python\Bonsai.ML.Python.csproj" />
</ItemGroup>
</Project>
25 changes: 25 additions & 0 deletions src/Bonsai.ML.Torch/Clone.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.ComponentModel;
using System.Reactive.Linq;
using static TorchSharp.torch;

namespace Bonsai.ML.Torch;

/// <summary>
/// Clones the input tensor.
/// </summary>
[Combinator]
[Description("Clones the input tensor.")]
[WorkflowElementCategory(ElementCategory.Transform)]
public class Clone
{
/// <summary>
/// Clones the input tensor.
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public IObservable<Tensor> Process(IObservable<Tensor> source)
{
return source.Select(tensor => tensor.clone());
}
}
100 changes: 100 additions & 0 deletions src/Bonsai.ML.Torch/Concat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
using System;
using System.ComponentModel;
using System.Linq;
using System.Reactive.Linq;
using System.Collections.Generic;
using static TorchSharp.torch;

namespace Bonsai.ML.Torch
{
/// <summary>
/// Concatenates tensors along a given dimension.
/// </summary>
[Combinator]
[Description("Concatenates tensors along a given dimension.")]
[WorkflowElementCategory(ElementCategory.Combinator)]
public class Concat
{
/// <summary>
/// The dimension along which to concatenate the tensors.
/// </summary>
[Description("The dimension along which to concatenate the tensors.")]
public long Dimension { get; set; } = 0;

/// <summary>
/// Takes any number of observable sequences of tensors and concatenates the input tensors along the specified dimension by zipping each tensor together.
/// </summary>
public IObservable<Tensor> Process(params IObservable<Tensor>[] sources)
{
return sources.Aggregate((current, next) =>
current.Zip(next, (tensor1, tensor2) =>
cat([tensor1, tensor2], Dimension)));
}

/// <summary>
/// Concatenates the input tensors along the specified dimension.
/// </summary>
public IObservable<Tensor> Process(IObservable<Tuple<Tensor, Tensor>> source)
{
return source.Select(value =>
{
return cat([value.Item1, value.Item2], Dimension);
});
}

/// <summary>
/// Concatenates the input tensors along the specified dimension.
/// </summary>
public IObservable<Tensor> Process(IObservable<Tuple<Tensor, Tensor, Tensor>> source)
{
return source.Select(value =>
{
return cat([value.Item1, value.Item2, value.Item3], Dimension);
});
}

/// <summary>
/// Concatenates the input tensors along the specified dimension.
/// </summary>
public IObservable<Tensor> Process(IObservable<Tuple<Tensor, Tensor, Tensor, Tensor>> source)
{
return source.Select(value =>
{
return cat([value.Item1, value.Item2, value.Item3, value.Item4], Dimension);
});
}

/// <summary>
/// Concatenates the input tensors along the specified dimension.
/// </summary>
public IObservable<Tensor> Process(IObservable<Tuple<Tensor, Tensor, Tensor, Tensor, Tensor>> source)
{
return source.Select(value =>
{
return cat([value.Item1, value.Item2, value.Item3, value.Item4, value.Item5], Dimension);
});
}

/// <summary>
/// Concatenates the input tensors along the specified dimension.
/// </summary>
public IObservable<Tensor> Process(IObservable<Tuple<Tensor, Tensor, Tensor, Tensor, Tensor, Tensor>> source)
{
return source.Select(value =>
{
return cat([value.Item1, value.Item2, value.Item3, value.Item4, value.Item5, value.Item6], Dimension);
});
}

/// <summary>
/// Concatenates the input tensors along the specified dimension.
/// </summary>
public IObservable<Tensor> Process(IObservable<IEnumerable<Tensor>> source)
{
return source.Select(value =>
{
return cat(value.ToList(), Dimension);
});
}
}
}
33 changes: 33 additions & 0 deletions src/Bonsai.ML.Torch/ConvertDataType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.ComponentModel;
using System.Reactive.Linq;
using static TorchSharp.torch;

namespace Bonsai.ML.Torch
{
/// <summary>
/// Converts the input tensor to the specified scalar type.
/// </summary>
[Combinator]
[Description("Converts the input tensor to the specified scalar type.")]
[WorkflowElementCategory(ElementCategory.Transform)]
public class ConvertDataType
{
/// <summary>
/// The scalar type to which to convert the input tensor.
/// </summary>
[Description("The scalar type to which to convert the input tensor.")]
public ScalarType Type { get; set; } = ScalarType.Float32;

/// <summary>
/// Returns an observable sequence that converts the input tensor to the specified scalar type.
/// </summary>
public IObservable<Tensor> Process(IObservable<Tensor> source)
{
return source.Select(tensor =>
{
return tensor.to_type(Type);
});
}
}
}
Loading