{"id":19009031,"url":"https://github.com/kevmal/mxnetsharp","last_synced_at":"2025-10-11T01:21:03.266Z","repository":{"id":52667143,"uuid":"213020923","full_name":"kevmal/MXNetSharp","owner":"kevmal","description":"MXNet bindings for .NET/F#","archived":false,"fork":false,"pushed_at":"2021-05-26T15:08:51.000Z","size":13292,"stargazers_count":15,"open_issues_count":7,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-14T12:54:30.271Z","etag":null,"topics":["deep-learning","deep-neural-networks","distributed","fsharp","machine-learning","mxnet"],"latest_commit_sha":null,"homepage":"","language":"F#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kevmal.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-10-05T15:13:05.000Z","updated_at":"2023-12-24T01:26:31.000Z","dependencies_parsed_at":"2022-08-21T15:00:42.601Z","dependency_job_id":null,"html_url":"https://github.com/kevmal/MXNetSharp","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kevmal%2FMXNetSharp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kevmal%2FMXNetSharp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kevmal%2FMXNetSharp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kevmal%2FMXNetSharp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kevmal","download_url":"https://codeload.github.com/kevmal/MXNetSharp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249303562,"owners_count":21247696,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deep-learning","deep-neural-networks","distributed","fsharp","machine-learning","mxnet"],"created_at":"2024-11-08T19:06:17.476Z","updated_at":"2025-10-11T01:20:58.225Z","avatar_url":"https://github.com/kevmal.png","language":"F#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MXNet bindings for .NET [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/kevmal/MXNetSharp/master?urlpath=lab)\n\n## Prerequisites \n\nMXNet binaries need to be on library search path, bindings were generated against libmxnet 1.6.0 so older versions of libmxnet may not support all operators present. For GPU support, relevant CUDA libraries also need to be accessible. \n\n## Examples\n- [Temporal Convolutional Networks (TCN)](Examples/TCN)\n- [DQN](Examples/DQN)\n- [CGAN](Examples/CGAN.fsx)\n- [Variational Autoencoder](Examples/MNIST%20VAE.fsx)\n- [Neural style transfer](Examples/Neural%20Style%20Transfer.fsx)\n\nNote: Samples which use UI (CGAN, VAE) need to specifically reference either net46 or netcore assemblies. By default they're loading net46, to use netcore uncomment the \".NET core\" section in loadui.fsx in the Examples directory and comment the Net46 section.\n\n## Quick start \n\n### Basics\n```fsharp\nopen MXNetSharp\n\n// Symbol API\nlet x = Variable \"x\" // Symbol\nlet y = Variable \"y\" // Symbol\n\n// elementwise multiplication\nlet z = x * y //x and y will be infered to have the same shape\n\n// broadcast multiplication\nlet z2 = x .* y // x and y shapes can differ according to the rules of MXNet broadcasting\n\n// scalar multiplication, overloads are for type `double` but will match type of x\nlet z3 = 4.0*x\n\n// broadcast operators for +, -, /, and such are analogous to above\n// comparison operators at the moment are by default prefixed with a `.` and have no broadcast equivalents\nlet z4 = x .= y // elementwise\n\n// logical operators do have broadcast equivalents\nlet z5 = x .\u0026\u0026 y // elementwise\nlet z6 = x ..\u0026\u0026 y // broadcast\n\n// For operators sqrt, exp, pow and such we need to open MXNetSharp.PrimitiveOperators\nopen MXNetSharp.PrimitiveOperators\nlet z7 = exp x\n\n\n// Create an NDArray from a .NET array\n\nlet a = NDArray.CopyFrom([|1.f .. 10.f|], [5;2], GPU 0)\n\n// This is the same as above\nlet a2 = GPU(0).CopyFrom([|1.f .. 10.f|], [5;2])\n\n\n// NDArray's do not need the MXNetSharp.PrimitiveOperators namespace\nlet b = sqrt(a + 20.0)\n\nlet v : float32 [] = b.ToArray\u003c_\u003e() //Copy back to CPU in managed array\nlet v2 = b.ToFloat32Array() //Same as above\nlet v3 = b.ToDoubleArray() // Float32 -\u003e Double conversion happens implicitly\n\n// val v : float32 [] =\n//  [|4.5825758f; 4.69041586f; 4.79583168f; 4.89897966f; 5.0f; 5.09901953f;\n//    5.19615221f; 5.29150248f; 5.38516474f; 5.47722578f|]\n\n// NDArray Operators exist in MXNEtSharp.MX\n\nMX.Mean(b).ToFloat32Scalar()\n\n// val it : float32 = 5.04168653f\n\n// Slicing\n\n// following are equivalent\nb.[2..4,*].ToFloat32Array()\nb.[2..4].ToFloat32Array()\n//val it : float32 [] =\n// [|5.0f; 5.09901953f; 5.19615221f; 5.29150248f; 5.38516474f; 5.47722578f|]\n\n// Note that the range is startIndex..endIndex (F# style) as oppose to MXNet slcing where slice stops just up to the end\nb.[2..2,*].ToFloat32Array()\n//val it : float32 [] = [|5.0f; 5.09901953f|]\n\n// With negative slicing then 'end' value behaves the same as MXNet. startIndex .. -dropCount\nb.[2..-2,1].ToFloat32Array()\n// val it : float32 [] = [|5.29150248f|]\n\n// Steping syntax is more verbose (the following are all equivalent)\n\nb.[SliceRange(0L, 4L, 2L), *].ToFloat32Array()\nb.[SliceRange(stop = 4L, step = 2L), *].ToFloat32Array()\nb.[SliceRange(start = 0L, step = 2L), *].ToFloat32Array()\nb.[SliceRange(step = 2L), *].ToFloat32Array()\n\n// val it : float32 [] =\n// [|4.5825758f; 4.69041586f; 5.0f; 5.09901953f; 5.38516474f; 5.47722578f|]\n\n```\n\n### Linear Regression \n```fsharp\n\nopen MXNetSharp\nopen MXNetSharp.SymbolOperators\nopen MXNetSharp.PrimitiveOperators\nopen MXNetSharp.Interop\n\nlet ctx = CPU 0\nlet X = ctx.Arange(1.0, 11.0) // values 1, 2, .. 9, 10\nlet actualY = 2.5*X + 0.7\nMXLib.randomSeed 1000\nlet observedY = actualY + MX.RandomNormalLike(actualY, 0.0, 0.1)\nactualY.ToFloat32Array()\n// val it : float32 [] =\n// [|3.20000005f; 5.69999981f; 8.19999981f; 10.6999998f; 13.1999998f;\n//   15.6999998f; 18.2000008f; 20.7000008f; 23.2000008f; 25.7000008f|]\nobservedY.ToFloat32Array()\n//val it : float32 [] =\n//  [|2.95296192f; 5.40489101f; 7.96742868f; 10.7032785f; 13.0787563f;\n//    15.9071894f; 18.0810871f; 20.7377892f; 23.1656361f; 25.6353264f|]\n\nlet input = Input(\"x\", ndarray = X)\nlet label = Input(\"y\", ndarray = observedY)\nlet m = Parameter(\"m\",ndarray = ctx.RandomUniform([1], -1.0, 1.0), \n                      grad = ctx.Zeros(shape = [1]), \n                      opReqType = OpReqType.WriteTo)\nlet b = Parameter(\"b\",ndarray = ctx.RandomUniform([1], -1.0, 1.0), \n                      grad = ctx.Zeros(shape = [1]), \n                      opReqType = OpReqType.WriteTo)\nlet model = m.*input .+ b\n\nlet loss = MakeLoss(Mean(Square(model - label)))\nlet execOutput = SymbolGroup(loss, MX.BlockGrad(model))\nlet executor = execOutput.Bind(ctx)\nexecutor.Forward(true)\n\n// Loss with initial parameters:\nexecutor.Outputs.[0].ToFloat32Array()\n// val it : float32 [] = [|425.663239f|]\n\n// Model output:\nexecutor.Outputs.[1].ToFloat32Array()\n//val it : float32 [] =\n// [|-0.605032206f; -1.35715616f; -2.10928011f; -2.86140394f; -3.61352777f;\n//   -4.36565208f; -5.11777592f; -5.86989975f; -6.62202358f; -7.37414742f|]\n\nexecutor.Backward()\nm.Grad.Value.ToFloat32Array()\n// val it : float32 [] = [|-256.021332f|]\nb.Grad.Value.ToFloat32Array()\n// val it : float32 [] = [|-36.7060509f|]\n\n\n\n// SGD update\nlet lr = 0.01   //learning rate\n\nm.NDArray.Value.ToFloat32Array()\n// val it : float32 [] = [|-0.752123952f|]\nMX.SgdUpdate([m.NDArray.Value], m.NDArray.Value, m.Grad.Value, lr)\nm.NDArray.Value.ToFloat32Array()\n// val it : float32 [] = [|1.80808938f|]\n\nb.NDArray.Value.ToFloat32Array()\n// val it : float32 [] = [|0.147091746f|]\nMX.SgdUpdate([b.NDArray.Value], b.NDArray.Value, b.Grad.Value, lr)\nb.NDArray.Value.ToFloat32Array()\n// val it : float32 [] = [|0.514152288f|]\n\n// Run with new parameters and expect a lower loss (\u003c 425.663239)\nexecutor.Forward(false)\nexecutor.Outputs.[0].ToFloat32Array()\n// val it : float32 [] = [|19.5483208f|]\n\n// \"Train\" in loop\nfor i = 1 to 5 do \n    executor.Forward(true)\n    executor.Backward()\n    MX.SgdUpdate([m.NDArray.Value], m.NDArray.Value, m.Grad.Value, lr)\n    MX.SgdUpdate([b.NDArray.Value], b.NDArray.Value, b.Grad.Value, lr)\n    printfn \"%3d Loss: %f\" i (executor.Outputs.[0].ToDoubleScalar())\n//1 Loss: 19.548321\n//2 Loss: 0.915147\n//3 Loss: 0.060186\n//4 Loss: 0.020915\n//5 Loss: 0.019071\n\n// Trained parameters\n// True values: m = 2.5 and b = 0.7\n\nm.NDArray.Value.ToDoubleScalar()\n// val it : double = 2.50611043\n\nb.NDArray.Value.ToDoubleScalar()\n// val it : double = 0.611009717\n\n```\n\n\n## MXNet \n\n[MXNet](https://mxnet.apache.org) supports has both a symbolic interface (Symbol API) as well as an imperative interface (NDArray API). The NDArray API can be used on it's own and gradients can be calculated using the Autodiff API. The Symbol API alows a computation graph to be defined and optimizations to take place before NDArray's are bound to it's inputs. An Executor is a Symbol bound to NDArrays, data can be copied into and out of these NDArrays and the graph can be executed foward/backward.\n\n### Low level interop\n\nThough ideally not needed, low level access to libmxnet is available in the following namespaces:\n- [MXNetSharp.Interop.CApi](MXNetSharp/capi.fs) ([c_api.h](https://github.com/apache/incubator-mxnet/blob/master/include/mxnet/c_api.h))\n- [MXNetSharp.Interop.CPredictApi](MXNetSharp/cpredictapi.fs) ([c_predict_api.h](https://github.com/apache/incubator-mxnet/blob/master/include/mxnet/c_predict_api.h))\n- [MXNetSharp.Interop.CNNVMApi](MXNetSharp/cpredictapi.fs) ([cnnvmapi.h](https://github.com/apache/incubator-tvm/blob/master/nnvm/include/nnvm/c_api.h))\n\nWith F# friendly wrappers in [MXNetSharp.Interop](MXNetSharp/interop.fs) with the following modules\n- MXLib\n- MXSymbol\n- MXNDArray\n- MXExecutor\n- MXNDList\n- NNVM\n- NNGraph\n- MXDataIter\n- MXAutograd\n- MXRtc\n- MXEngine\n- MXRecordIO\n\n\n## Symbol API\n\nCurrently each MXNet operation is represented as a type inheriting from `SymbolOperator` and are generated in the `MXNetSharp.SymbolOperators` namespace.\n\n\nActual creation of the `Symbol` (at the MXNet level) is delayed until the symbol handle is needed. This is to allow for delayed naming and late input binding.\n```fsharp\nopen MXNetSharp\nopen MXNetSharp.SymbolOperators\n\nlet x = Variable \"x\"\nlet y = Variable \"y\"\n\nlet z = \n    x\n    .\u003e\u003e FullyConnected(1024)\n    .\u003e\u003e FullyConnected(1024)\n    .\u003e\u003e FullyConnected(32)\n    .\u003e\u003e FullyConnected(1)\n\nlet loss = MakeLoss(Sum(Square(x-y))) \n\nloss.SymbolHandle // MXNet Symbol handle is created at this point \n\n```\n\nSince each operation retains it's type, F# operators such as `exp` do not work on their own and so `MXNetSharp.PrimitiveOperators` provides operators for use with\nthe `Symbol` type such as `tanh`, `exp`, `pow`.\n\n```fsharp\n\nopen MXNetSharp\nopen MXNetSharp.SymbolOperators\nopen MXNetSharp.PrimitiveOperators\n\nlet x = Variable \"x\"\n\nlet y = exp(2.0*x + 33.0) // y is of type `Exp`\nlet y2 = Exp(2.0*x + 33.0) // same as above but explicitly creates the `Exp` symbol type\n\n```\n\n## NDArray API (TODO)\nMXNetSharp.NDArray class. Please see samples and quickstart section.\n\n### Autodiff (TODO)\n\n```fsharp\nopen MXNetSharp\nlet x = (CPU 0).Arange(1.0,5.0).Reshape(2,2)\nx.AttachGradient()\nlet y,z = \n    Autograd.record\n        (fun () -\u003e\n            let y = x*2.0\n            let z = y*x\n            y,z\n        )\nz.Backward()\n\nx.Grad.Value.ToFloat32Array()\n// val it : float32 [] = [|4.0f; 8.0f; 12.0f; 16.0f|]\n```\n\nHigher order gradients (currently limited in MXNet):\n```fsharp\n\nopen MXNetSharp\nlet x = (CPU 0).CopyFrom([|1.f;2.f;3.f|], [1;1;-1])\nx.AttachGradient()\nlet yGrad = \n    Autograd.record \n        (fun () -\u003e\n            let y = sin x\n            let yGrad = Autograd.grad false true true Array.empty [y] [x]\n            yGrad.[0]\n        )\nyGrad.Backward()\n\nx.Grad.Value.ToFloat32Array()\n// val it : float32 [] = [|-0.841470957f; -0.909297407f; -0.141120002f|]\n(-sin x).ToFloat32Array() \n// val it : float32 [] = [|-0.841470957f; -0.909297407f; -0.141120002f|]\n\n```\n\n\n## Executor (TODO)\nMXNetSharp.Executor class. Please see samples.\n\n\n## Data loaders (TODO)\nMXNetSharp.IO.CSVIter and MXNetSharp.IO.MNISTIter. MNISTIter is used in the VAE and CGAN examples.\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkevmal%2Fmxnetsharp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkevmal%2Fmxnetsharp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkevmal%2Fmxnetsharp/lists"}