Skip to content
H.P. Gansevoort edited this page Oct 9, 2026 · 34 revisions

DeepSharp

The best of three worlds: TensorFlow's way of describing a network, PyTorch's way of running it, and ML.NET's way of learning from a table.

Build and train neural networks in C#. Stack the layers and let the library train them, or write the forward pass yourself — either way you get the same model, trained by the same loop and saved to the same file.

DeepSharp is the C# layer over the engines that already exist. The arithmetic runs on whichever one suits the job — .NET's own vector maths out of the box, and libtorch through TorchSharp, on the processor or a graphics card, when the work gets bigger — and swapping between them does not change a line of your model. A model trained somewhere else does not have to begin here to run here: what PyTorch, Keras or an ONNX exporter saved is read into the same network.

What DeepSharp adds is everything around the engine: getting your data in, the layers, the training loop, the checkpoints, and the pictures. An engine gives you fast arithmetic; it does not give you a way to describe a network in C#, feed it real data, watch it learn and save the result.

And a table that a tree learns better than a network does not have to become a network: the same prepared data is meant for ML.NET's trainers too — see how this sits next to ML.NET, below.

Version 0.8.0 — where this is

The first release was the tensors, the second the data half, and the third made the data half strict, let a model be asked for more than one answer and gave it a notebook to look at the data in and choose its columns — in Verso, in an application of your own, or in your browser from DeepSharp's own server. The fourth learned: layers, losses, optimizers and a training loop; a network described in Keras's words or written as code, trained on the rows a pipeline prepares, measured by the pipeline's report, drawn, and kept with the pipeline as one file. The fifth learned on the engine you choose — the light one, or libtorch on the processor or a graphics card — and read what others trained, from PyTorch, Keras and ONNX; its pipeline reads Parquet files, Excel workbooks and JSON files, and runs for the learner that learns from it, saying which steps that learner does without; and the notebook's report block draws what the cell that trains a model hands back. The sixth puts the model in the pipeline: a pipeline says which network its rows are prepared for — the layers, what moves them, what judges them, when the run stops and the engine it runs on — in the words TensorFlow and Keras use or the words PyTorch uses, and running it trains exactly that network. So the whole course from a file to a validated model is one declaration, saved as one file and replayed from it, and a block of the notebook can hold the network too. Since then every per-column verb says in one line what it does to many columns, each with the kind it names, and where the features land is said once for the whole pipeline; and a gap is settled where the features are worked out — a nought, a number you choose or a refusal, none of them a value any row decided — so a feature worked out from a column with a gap is no longer a gap itself. Then came the second kind of learner: a trainer from ML.NET behind the same seam a network stands behind, so a table that a tree learns better than a network does not have to become a network, and the two are measured by one report on the same rows. This one adds a course to fill in: every step of a prepared pipeline in the order the steps belong, each waiting for what only you know — a value, a file of its own and two buttons in the notebook, so a pipeline written from nothing no longer starts from an empty chain. Then a live source was landed: the candles an exchange answers with are fetched once over a closed window and kept as a file beside a record of what was asked and what came back, so the pipeline reads them like any other file and gives the same numbers tomorrow — see Live sources. And this one is about optimizing: AdamW, RMSprop and Nadam beside Sgd and Adam, gradients clipped by their norm, a rate that warms up and a run that can be watched and stopped; a study that tries many networks on rows prepared once, chooses by the validation rows and keeps the test rows for the winner, with the test rows fixed by a seed of their own and a paired comparison that says whether a change helped — see Searching for a network; answers that are a distribution in an order, measured and trained along it; two files as one source, an id that travels with its rows, and a correlation worked out once as numbers. The pipeline's file is at version 8. What is here works and is tested; what is left out on purpose is on the Roadmap, and the changelog records what each release actually added.

What it does
Shape Says how big a tensor is — 2x3 is two rows of three. Refuses a size that cannot exist.
Tensor The numbers themselves. Never changes once made, so it is safe to reuse; its values live on a TensorStorage, this machine's memory or the engine's that made it.
ITensorBackend Which engine does the arithmetic, with the operations a network and its way back need. Your model is written against this, not against an engine. What it refuses is said once, in TensorOperandExtensions, for every engine.
CpuBackend The engine that needs no installing: the processor's vector instructions, through .NET's own maths.
RecordingBackend Works out gradients: it wraps any backend for one pass, writes down each operation as it runs it, and works back from a loss to how much each number moved it, towards the numbers asked about and no others.
Layers and networks Dense, the activations, dropout, the normalisations, and convolutions, poolings and the dropouts of whole channels along a series, an image or a volume, their window padded as TensorFlow's 'same' — or, along a series, as Keras's 'causal' — if you say so; a network written as code, or described in Keras's words and lowered onto the same thing; losses, optimizers — AdamW, RMSprop and Nadam among them — and learning-rate schedules; the training loop, with early stopping, clipping, an epoch hook, cancellation and checkpoints that name the batch size, the early stopping and the engine they were taken under; a network written down as the kinds it is made of and the numbers it learned; and network.Load, which puts numbers trained elsewhere into its slots by path, through IImporter.
DeepSharp.Learners.Networks Where a network meets a pipeline: declared in the chain that prepares its rows — .WithTorch(…) or .WithTensorflow(…), and pipeline.Train() runs it — or written as code and fitted by hand; trained on its training rows, judged by its validation rows, measured by its report, and kept with it as one file that refuses any other fit of it. What it predicts for rows served later comes back in the answer's own units, on whichever engine it is handed, naming what each row holds that the network learned nothing about.
DeepSharp.Backends.TorchSharp The arithmetic on libtorch, through TorchSharp: TorchBackend.OnCpu() or TorchBackend.OnGpu(0), held to the same contract as the light engine. Your application brings libtorch. See TorchSharp backend.
DeepSharp.Import.PyTorch, .Keras, .Onnx A model trained elsewhere, read into the same network: a safetensors file or what torch.save writes, a .keras or .h5 file, an ONNX graph. See Importing a model.
DeepSharp.Charts The charts, as SVG, drawn with MatPlotLibNet from what the loop and the measures already keep: the loss curve, the learning rate, confusion matrices, predicted against actual, the residuals, the measures as bars, and a correlation; and the report, rendered once as HTML.
DeepSharp.Pipelines The data half: say where the rows come from, see what each column's cells propose it holds, say what the columns are, which features are worked out, where the split falls, how gaps are filled and how the numbers are scaled — one line a kind, naming the columns it holds for, landing the features between minus one and one unless the pipeline says otherwise — and what a model is asked to predict, then save all of it as a file and read it back unchanged. A profile names what should not be there. It runs for the learner that learns from it, leaving out the steps that learner does without and saying which; and a declaration may name the learner it is written for, in a step that changes no column and runs nothing — the pipeline itself knows no learner, and the package that brings the verb trains once the run is done. The decisions about the columns can be saved on their own and taken over by another pipeline, and a course — every step of a prepared pipeline in the order they belong, each waiting for what only you know — is a value and a file of its own to fill in.
DeepSharp.Pipelines.Parquet, .Excel, .Json A Parquet file, a sheet of an Excel workbook, a JSON file of records: each read as a comma-separated file is, a verb of the pipeline's file too, and replayed.
DeepSharp.Pipelines.DataFrame One reader for the long tail: anything that can fill a DataFrame — a CSV, a database query, rows already in hand — comes in through it. The frame is Microsoft's own, Microsoft.Data.Analysis, reached through MatPlotLibNet.DataFrame, the same door the indicators use. A CSV comes through as the text the file writes, and a query with the kinds the database gives its columns.
DeepSharp.Pipelines.Indicators Indicators over a series, borrowed from the published MatPlotLibNet packages rather than written again.
DeepSharp.Pipelines.Binance A live source, landed: the candles of a market on Binance, fetched once over a closed window and kept as a file beside a record of what was asked and what came back, which the pipeline then reads like any other. Brings the HTTP, the retries and the pacing, so a project that only serves a model never does. See Live sources.
DeepSharp.Verso.Notebooks The same pipeline written as a Verso notebook, one block per step, the first reading a comma-separated, Parquet, Excel or JSON file, with the data, a profile and a heatmap at any block, and its columns chosen from the grid or a list — which shows what each column's cells propose — and saved beside it; a box beside a profile's alert gives its answer, and a report block draws what a C# cell that trains a model hands back. Two buttons write the steps of a course into the blocks, each waiting for what only you know. It runs in Verso's VS Code extension, in verso serve, in DeepSharp's own server and in an application of your own.
DeepSharp.Verso.Api An application of your own hosting the notebook: one open notebook for each file, however many views show it, with the notebook's parts registered by the package itself — so a program published as a single file has them too. Typing, running, a click on a block's controls and the toolbar's buttons take their turn one at a time, a run that never ends can be stopped, a file a button hands over goes to whoever pressed it, the properties panel comes back field by field, the layout, the theme and the title are changed as Verso's editors change them, the notebook opens and saves as Verso's browser editor does, every view is told what changed, version by version — what runs, whether anything is unsaved, what the kernels did, what the dashboard draws — a notebook no view shows closes by itself when nothing in it is unsaved, and the cells, and what they show, come back as plain values. A pipeline block it adds arrives as the step of the course that belongs there instead of empty.
DeepSharp.Verso.Serve DeepSharp's own server: deepsharp-serve, a .NET tool, shows a notebook or a folder of them in your browser, on Verso's engine and built on DeepSharp.Verso.Api, with nothing else to install. It listens on this computer alone and answers only the address it prints; its page does what Verso's browser editor does — the blocks, the panels, the layouts and the themes, diagrams and formulas, the keys — over one connection for each tab and with nothing fetched from anywhere, and a file a button hands over arrives as a download.

Pipeline has the verbs, in the order you write them.

Start here

Getting Started Install it, add two tensors, work out a gradient, prepare a real file and train a network on it.
Starting from a course Every step of a prepared pipeline in the order the steps belong, each waiting for what only you know: a table's and a series', as a value, a file and two buttons in the notebook.
PDD Pipeline-driven design — the idea this library is built around, and the mistake it removes.
Pipeline The verbs in the order you write them: readers, the order, the gaps settled, features, the split, the gaps filled, scales, evidence, what a model is asked to predict, the report, the handover, the file, and the column decisions saved and taken over.
Live sources A source that answers differently every time it is asked, fetched once over a closed window and landed as a file: Binance's candles, what a landing is, what it refuses, and how it keeps to a budget it shares.
Writing a step of your own A verb of your own that stands in a pipeline like the ones that ship: a record that names itself, adds columns or learns from the training rows, is taught to a catalog and is written into the file — and the leak a step that learns from the answer can make.
Searching for a network Which learning rate, how many units: a study that tries candidates on rows prepared once, chooses by the validation rows, keeps the test rows for the winner alone, and a paired comparison of two pipelines over many deals.
Networks The layers, losses, optimizers and the loop; a network in Keras's words or as code; trained behind a pipeline, measured, drawn and kept as one file.
ML.NET learner The other learner: a trainer from ML.NET behind the same seam, declared in the chain, measured by the same report on the same rows — and in a package that lets a reader of its model carry no ML.NET.
TorchSharp backend The engine on libtorch: what your application brings, what the engine is held to, and when it is the faster.
Importing a model A model PyTorch, Keras or an ONNX exporter saved, read into the same network: what each reader reads, and what it refuses.
Notebook A pipeline written block by block in Verso, with the data, a profile and a heatmap at any block, and its columns chosen from the grid or a list.
Architecture The design decisions, and what was deliberately left out.
Quality What has to be true before anything is allowed in.
Security What counts as a vulnerability here, and how to report one.
Roadmap What is done, in the order each row needed the one above it, and what is left out on purpose.

How this sits next to TorchSharp, TensorFlow.NET and ML.NET

TorchSharp and TensorFlow.NET are bindings: PyTorch's or TensorFlow's own interface, written in C#, with the original engine underneath. They are excellent at being that, and DeepSharp is happy to use one.

What they do not give you is a library that reads like C#, a way to pour your data in, a training loop you did not write yourself, or a picture of what happened. DeepSharp sits on top and provides those — and because your model talks to a backend rather than to an engine, the choice of engine stays a choice.

ML.NET is something else: Microsoft's own machine-learning library for .NET, with ready trainers for tables of data — trees, linear models and more — and a data pipeline of its own, which is fitted on whatever rows it is handed, so keeping the rows a model is measured on out of that fit is left to you. DeepSharp does not replace it. Its pipeline makes that mistake impossible and hands the prepared rows over in one form for every learner, run for what that learner needs — a tree's run leaves out the scales, and hands each category over as its place — and a trainer from ML.NET is one of the learners that handover is made for. The first learner behind it is a network — Networks — and a trainer from ML.NET is the second, in packages of its own: ML.NET learner. The data frame DeepSharp reads through is Microsoft's too: Microsoft.Data.Analysis, from the same family.

The small print on that choice: the default backend needs nothing installed and travels inside your application, while libtorch for the processor is between 56.9 MB and 128.2 MB to download for each platform you ship to, and a graphics card's runs to gigabytes. You pick per project, not per library.

Also: Repository · Changelog · Contributing.

Clone this wiki locally