diff --git a/CHANGELOG.md b/CHANGELOG.md index ec239f55..c9fb8b6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file. ## [unreleased] +📚 **docs:** PropertyListEncoder by default ([#51](https://github.com/owkin/GrAIdient/pull/51))\ 🐛 **fix:** use buffers for neuron selection in SelectNeurons1D ([#50](https://github.com/owkin/GrAIdient/pull/50))\ 🪜 **feat:** Softmax1D, DotProduct1D & Constant1D ([#49](https://github.com/owkin/GrAIdient/pull/49))\ 🪜 **feat:** remove activation from layer ([#47](https://github.com/owkin/GrAIdient/pull/47))\ diff --git a/Docs/Concepts/MODEL.md b/Docs/Concepts/MODEL.md index 251781bc..18a55f74 100644 --- a/Docs/Concepts/MODEL.md +++ b/Docs/Concepts/MODEL.md @@ -135,10 +135,9 @@ Let us imagine the two models have been trained and we want to save them to the disk: ```swift -// Use JSONEncoder to encode a readable file -// or PropertyListEncoder to encode a binary file -// (takes less space on the disk). -let encoder = JSONEncoder() +// Use PropertyListEncoder to encode a binary file (readable with Xcode) +// or JSONEncoder to encode a json file (takes more space on the disk). +let encoder = PropertyListEncoder() // Encode first model. var data = try! encoder.encode(cnn) @@ -166,8 +165,8 @@ let baseCNN = try! JSONDecoder().decode( // Load the data of our second model from the disk. data = try! Data(contentsOf: URL(fileURLWithPath: "/path/to/model2.plist")) // Initialize a base model ouf of it. -// Use PropertyListDecoder instead to decode a binary file. -let baseClassifier = try! JSONDecoder().decode( +// Use JSONDecoder instead to decode a json file. +let baseClassifier = try! PropertyListDecoder().decode( BaseModel.self, from: data ) diff --git a/README.md b/README.md index 66e80261..0695587a 100644 --- a/README.md +++ b/README.md @@ -24,26 +24,24 @@ Ready for the grAIt descent?
GrAIdient is a framework that exposes the graph of layers as its unique way to design deep learning models. This "flattened" vision enforces -great understanding, control and reproducibility with the models human interact -with. +great understanding, control and reproducibility over these models. -Though deeply grounded to the data driven way of life, the goal is to challenge +Though deeply grounded to the data driven pipeline, the goal is to challenge the very understanding of deep learning models and inject human intelligence to go from black box models to white box models. Let us find our grAI between them both!

-Key features: +## ✨ Key Features -- what you do is what you get +- flat design with direct access to the graph of layers and the backward pass - run natively on Mac Intel GPU, eGPU, Mac M1, M2... - compiled language - gradient checking -- extendable design - PyTorch interoperability -- compute gradients per batch & per sample (differential privacy) -- debugging at the neuron level +- gradients per batch & per sample (ready for differential privacy) +- debug at the neuron level ## 📦 Swift Package Manager diff --git a/Sources/GrAIdient/Core/Layer/LayerNormalization.swift b/Sources/GrAIdient/Core/Layer/LayerNormalization.swift index 23fe2cfd..53b57e1f 100644 --- a/Sources/GrAIdient/Core/Layer/LayerNormalization.swift +++ b/Sources/GrAIdient/Core/Layer/LayerNormalization.swift @@ -148,12 +148,12 @@ public class BatchNormalization: BatchNormalizationBase let _Ɛ: Double = 1e-5 /// - /// Arrays of weights to scale the normalization result. + /// Array of weights to scale the normalization result. /// Shape ~ (nbNeurons,). /// var _Ɣ: WeightArrays! = nil /// - /// Arrays of biases to add to the normalization result. + /// Array of biases to add to the normalization result. /// Shape ~ (nbNeurons,). /// var _β: WeightArrays! = nil @@ -521,15 +521,15 @@ public class BatchNormalization: BatchNormalizationBase class BatchNormalizationGPU: BatchNormalizationBase { /// - /// Buffers of weights to scale the normalization result. + /// Buffer of weights to scale the normalization result. /// Shape ~ (nbNeurons,). /// - var _ƔBuffers: IWeightBuffers! = nil + var _Ɣ: IWeightBuffers! = nil /// - /// Buffers of biases to add to the normalization result. + /// Buffer of biases to add to the normalization result. /// Shape ~ (nbNeurons,). /// - var _βBuffers: IWeightBuffers! = nil + var _β: IWeightBuffers! = nil /// /// Buffer of averages of data for the different independent batch normalization units. @@ -576,16 +576,16 @@ class BatchNormalizationGPU: BatchNormalizationBase override var weights: [Float] { get { - if _ƔBuffers == nil + if _Ɣ == nil { return super.weights } - MetalKernel.get.download([_βBuffers.w_p!, _ƔBuffers.w_p!]) + MetalKernel.get.download([_β.w_p!, _Ɣ.w_p!]) var weightsTmp = [Float]() - weightsTmp += _ƔBuffers.w_p!.shared.array - weightsTmp += _βBuffers.w_p!.shared.array + weightsTmp += _Ɣ.w_p!.shared.array + weightsTmp += _β.w_p!.shared.array return weightsTmp } set { @@ -645,8 +645,8 @@ class BatchNormalizationGPU: BatchNormalizationBase _sum1 = nil _sum2 = nil - _ƔBuffers?.reset() - _βBuffers?.reset() + _Ɣ?.reset() + _β?.reset() } /// @@ -669,11 +669,11 @@ class BatchNormalizationGPU: BatchNormalizationBase /// func initWeights() { - _βBuffers = WeightBuffers(nbElems: _nbNeurons, deviceID: _deviceID) - _ƔBuffers = WeightBuffers(nbElems: _nbNeurons, deviceID: _deviceID) + _β = WeightBuffers(nbElems: _nbNeurons, deviceID: _deviceID) + _Ɣ = WeightBuffers(nbElems: _nbNeurons, deviceID: _deviceID) - let βPtr = _βBuffers.w_p!.shared.buffer - let ƔPtr = _ƔBuffers.w_p!.shared.buffer + let βPtr = _β.w_p!.shared.buffer + let ƔPtr = _Ɣ.w_p!.shared.buffer if _weightsList.count == 0 { @@ -693,7 +693,7 @@ class BatchNormalizationGPU: BatchNormalizationBase _weightsList = [] } - MetalKernel.get.upload([_βBuffers.w_p!, _ƔBuffers.w_p!]) + MetalKernel.get.upload([_β.w_p!, _Ɣ.w_p!]) } /// Initialize stats in the GPU execution context. @@ -848,8 +848,8 @@ class BatchNormalizationGPU: BatchNormalizationBase let command = MetalKernel.get.createCommand( "forwardBNConvTraining", deviceID: _deviceID ) - command.setBuffer(_βBuffers.w.metal, atIndex: 0) - command.setBuffer(_ƔBuffers.w.metal, atIndex: 1) + command.setBuffer(_β.w.metal, atIndex: 0) + command.setBuffer(_Ɣ.w.metal, atIndex: 1) command.setBuffer(_μ.metal, atIndex: 2) command.setBuffer(_σ2.metal, atIndex: 3) command.setBytes(pNbChannels, atIndex: 4) @@ -886,8 +886,8 @@ class BatchNormalizationGPU: BatchNormalizationBase "forwardBNConvInference", deviceID: _deviceID ) - command.setBuffer(_βBuffers.w.metal, atIndex: 0) - command.setBuffer(_ƔBuffers.w.metal, atIndex: 1) + command.setBuffer(_β.w.metal, atIndex: 0) + command.setBuffer(_Ɣ.w.metal, atIndex: 1) command.setBuffer(_Eμ.metal, atIndex: 2) command.setBuffer(_Eσ2.metal, atIndex: 3) command.setBytes(pNbChannels, atIndex: 4) @@ -939,15 +939,15 @@ class BatchNormalizationGPU: BatchNormalizationBase ) command.setBuffer(layer.delta.metal, atIndex: 0) command.setBuffer(_xHat.metal, atIndex: 1) - command.setBuffer(_ƔBuffers.w.metal, atIndex: 2) + command.setBuffer(_Ɣ.w.metal, atIndex: 2) command.setBytes(pNbChannels, atIndex: 3) command.setBytes(pNbBatch, atIndex: 4) command.setBytes(pDimensions, atIndex: 5) command.setBytes(pAccumulate, atIndex: 6) command.setBuffer(_sum1.metal, atIndex: 7) command.setBuffer(_sum2.metal, atIndex: 8) - command.setBuffer(_ƔBuffers.g.metal, atIndex: 9) - command.setBuffer(_βBuffers.g.metal, atIndex: 10) + command.setBuffer(_Ɣ.g.metal, atIndex: 9) + command.setBuffer(_β.g.metal, atIndex: 10) command.dispatchThreads(_nbNeurons) command.enqueue() @@ -971,7 +971,7 @@ class BatchNormalizationGPU: BatchNormalizationBase ) command.setBuffer(_σ2.metal, atIndex: 0) command.setBuffer(_xHat.metal, atIndex: 1) - command.setBuffer(_ƔBuffers.w.metal, atIndex: 2) + command.setBuffer(_Ɣ.w.metal, atIndex: 2) command.setBuffer(_sum1.metal, atIndex: 3) command.setBuffer(_sum2.metal, atIndex: 4) command.setBytes(pNbChannels, atIndex: 5) @@ -1001,7 +1001,7 @@ class BatchNormalizationGPU: BatchNormalizationBase let command = MetalKernel.get.createCommand( "backwardBNConvInference", deviceID: _deviceID ) - command.setBuffer(_ƔBuffers.w.metal, atIndex: 0) + command.setBuffer(_Ɣ.w.metal, atIndex: 0) command.setBuffer(_Eσ2.metal, atIndex: 1) command.setBytes(pNbChannels, atIndex: 2) command.setBytes(pNbBatch, atIndex: 3) @@ -1019,6 +1019,6 @@ class BatchNormalizationGPU: BatchNormalizationBase /// Get the weights in the GPU execution context. func collectWeights() -> [IWeightBuffers] { - return [_ƔBuffers, _βBuffers] + return [_Ɣ, _β] } } diff --git a/Tests/GrAIExamples/VGGExample.swift b/Tests/GrAIExamples/VGGExample.swift index b72b57f4..f3f1cbab 100644 --- a/Tests/GrAIExamples/VGGExample.swift +++ b/Tests/GrAIExamples/VGGExample.swift @@ -163,7 +163,7 @@ final class VGGExample: XCTestCase // Decode it as a base model // (model where `layerPrev` links are not initialized). - let baseModel = try! JSONDecoder().decode( + let baseModel = try! PropertyListDecoder().decode( BaseModel.self, from: data ) @@ -351,7 +351,7 @@ final class VGGExample: XCTestCase XCTAssert(ratio < 60) // Encode the model. - let encoder = JSONEncoder() + let encoder = PropertyListEncoder() let data = try! encoder.encode(vgg) // Save it to the disk. @@ -486,7 +486,7 @@ final class VGGExample: XCTestCase } // Encode the trained model. - let encoder = JSONEncoder() + let encoder = PropertyListEncoder() let data = try! encoder.encode(vgg) // Save it to the disk.