From 9292d65fe43e5679e8ec2988cbccd0c92165376c Mon Sep 17 00:00:00 2001 From: dartrisen Date: Wed, 21 Aug 2024 17:20:58 +0200 Subject: [PATCH] update v 1.0.1 --- CHANGELOG.md | 14 ++++ .../{layer.swift => Core/Layer.swift} | 0 .../SwiftGrad/{mlp.swift => Core/MLP.swift} | 0 .../{module.swift => Core/Module.swift} | 0 .../{neuron.swift => Core/Neuron.swift} | 0 Sources/SwiftGrad/Core/Value.swift | 61 +++++++++++++++ .../Value+BinaryOperations.swift} | 75 +------------------ .../Extensions/Value+UnaryOperations.swift | 27 +++++++ .../{ => Protocols}/BinaryOperations.swift | 0 .../{ => Protocols}/UnaryOperations.swift | 0 10 files changed, 106 insertions(+), 71 deletions(-) create mode 100644 CHANGELOG.md rename Sources/SwiftGrad/{layer.swift => Core/Layer.swift} (100%) rename Sources/SwiftGrad/{mlp.swift => Core/MLP.swift} (100%) rename Sources/SwiftGrad/{module.swift => Core/Module.swift} (100%) rename Sources/SwiftGrad/{neuron.swift => Core/Neuron.swift} (100%) create mode 100644 Sources/SwiftGrad/Core/Value.swift rename Sources/SwiftGrad/{value.swift => Extensions/Value+BinaryOperations.swift} (50%) create mode 100644 Sources/SwiftGrad/Extensions/Value+UnaryOperations.swift rename Sources/SwiftGrad/{ => Protocols}/BinaryOperations.swift (100%) rename Sources/SwiftGrad/{ => Protocols}/UnaryOperations.swift (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..f4341d5 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,14 @@ +# CHANGELOG + +## 1.0.1 (XX / XX / 2024) + +#### Miscellaneous +- protocols `BinaryOperations` and `UnaryOperations` have been separated from the Value implementation +- project has been restructurized + +## 1.0.0 (8 / 20 / 2024) + +#### Features +- Value, Module, Neuron, Layer, MLP classes have been added +- **binary operations** : + - * / +- **unary operations** : tanh, exp diff --git a/Sources/SwiftGrad/layer.swift b/Sources/SwiftGrad/Core/Layer.swift similarity index 100% rename from Sources/SwiftGrad/layer.swift rename to Sources/SwiftGrad/Core/Layer.swift diff --git a/Sources/SwiftGrad/mlp.swift b/Sources/SwiftGrad/Core/MLP.swift similarity index 100% rename from Sources/SwiftGrad/mlp.swift rename to Sources/SwiftGrad/Core/MLP.swift diff --git a/Sources/SwiftGrad/module.swift b/Sources/SwiftGrad/Core/Module.swift similarity index 100% rename from Sources/SwiftGrad/module.swift rename to Sources/SwiftGrad/Core/Module.swift diff --git a/Sources/SwiftGrad/neuron.swift b/Sources/SwiftGrad/Core/Neuron.swift similarity index 100% rename from Sources/SwiftGrad/neuron.swift rename to Sources/SwiftGrad/Core/Neuron.swift diff --git a/Sources/SwiftGrad/Core/Value.swift b/Sources/SwiftGrad/Core/Value.swift new file mode 100644 index 0000000..50b27f1 --- /dev/null +++ b/Sources/SwiftGrad/Core/Value.swift @@ -0,0 +1,61 @@ +import Foundation + +infix operator **: MultiplicationPrecedence + +/// Represents a value in the computational graph, with support for automatic differentiation. +final class Value: CustomStringConvertible { + var data: Double + var grad: Double = 0.0 + var _backward: () -> () = {} + var _prev: Set + var _op: String + var label: String + + /// Initializes a new `Value` instance. + /// + /// - Parameters: + /// - data: The scalar value. + /// - _children: The values that this `Value` depends on. + /// - _op: The operation that produced this value. + init(_ data: Double, _children: [Value] = [], _op: String = "", label: String = "") { + self.data = data + self._prev = Set(_children) + self._op = _op + self.label = label + } + + var description: String { + return "Value(label: \(label), data: \(data), grad: \(grad))" + } + + func backward() { + var topo: [Value] = [] + var visited: Set = [] + + func buildTopo(_ v: Value) { + if !visited.contains(v) { + visited.insert(v) + for child in v._prev { + buildTopo(child) + } + topo.append(v) + } + } + + buildTopo(self) + self.grad = 1.0 + for v in topo.reversed() { + v._backward() + } + } +} + +extension Value: Hashable { + static func == (lhs: Value, rhs: Value) -> Bool { + return ObjectIdentifier(lhs) == ObjectIdentifier(rhs) + } + + func hash(into hasher: inout Hasher) { + hasher.combine(ObjectIdentifier(self)) + } +} diff --git a/Sources/SwiftGrad/value.swift b/Sources/SwiftGrad/Extensions/Value+BinaryOperations.swift similarity index 50% rename from Sources/SwiftGrad/value.swift rename to Sources/SwiftGrad/Extensions/Value+BinaryOperations.swift index 240f809..4f03096 100644 --- a/Sources/SwiftGrad/value.swift +++ b/Sources/SwiftGrad/Extensions/Value+BinaryOperations.swift @@ -1,79 +1,12 @@ import Foundation -infix operator **: MultiplicationPrecedence - -/// Represents a value in the computational graph, with support for automatic differentiation. -final class Value: CustomStringConvertible, UnaryOperations { - var data: Double - var grad: Double = 0.0 - var _backward: () -> () = {} - var _prev: Set - var _op: String - var label: String - - init(_ data: Double, _children: [Value] = [], _op: String = "", label: String = "") { - self.data = data - self._prev = Set(_children) - self._op = _op - self.label = label - } - - var description: String { - return "Value(label: \(label), data: \(data), grad: \(grad))" - } - - func exp() -> Value { - let out = Value(Foundation.exp(data), _children: [self], _op: "exp") - - out._backward = { - self.grad += out.data * out.grad - } - return out - } - - func tanh() -> Value { - let t = Foundation.tanh(data) - let out = Value(t, _children: [self], _op: "tanh") - out._backward = { [weak self] in - guard let self = self else { return } - self.grad += (1 - t * t) * out.grad - } - return out - } - - func backward() { - var topo: [Value] = [] - var visited: Set = [] - - func buildTopo(_ v: Value) { - if !visited.contains(v) { - visited.insert(v) - for child in v._prev { - buildTopo(child) - } - topo.append(v) - } - } - - buildTopo(self) - self.grad = 1.0 - for v in topo.reversed() { - v._backward() - } - } -} - -extension Value: Hashable { - static func == (lhs: Value, rhs: Value) -> Bool { - return ObjectIdentifier(lhs) == ObjectIdentifier(rhs) - } - - func hash(into hasher: inout Hasher) { - hasher.combine(ObjectIdentifier(self)) - } +enum ValueError: Error { + case divisionByZero + case invalidOperation(String) } extension Value: BinaryOperations { + static func + (lhs: Value, rhs: Value) -> Value { let out = Value(lhs.data + rhs.data, _children: [lhs, rhs], _op: "+") out._backward = { [weak lhs, weak rhs] in diff --git a/Sources/SwiftGrad/Extensions/Value+UnaryOperations.swift b/Sources/SwiftGrad/Extensions/Value+UnaryOperations.swift new file mode 100644 index 0000000..7e07126 --- /dev/null +++ b/Sources/SwiftGrad/Extensions/Value+UnaryOperations.swift @@ -0,0 +1,27 @@ +import Foundation + +extension Value: UnaryOperations { + + /// Applies the exponential function to a `Value` and returns a new `Value`. + /// + /// - Returns: A new `Value` representing the result of `exp`. + func exp() -> Value { + let out = Value(Foundation.exp(self.data), _children: [self], _op: "exp") + out._backward = { + self.grad += out.data * out.grad + } + return out + } + + /// Applies the hyperbolic tangent function to a `Value` and returns a new `Value`. + /// + /// - Returns: A new `Value` representing the result of `tanh`. + func tanh() -> Value { + let t = Foundation.tanh(self.data) + let out = Value(t, _children: [self], _op: "tanh") + out._backward = { [weak self] in + self?.grad += (1 - t * t) * out.grad + } + return out + } +} diff --git a/Sources/SwiftGrad/BinaryOperations.swift b/Sources/SwiftGrad/Protocols/BinaryOperations.swift similarity index 100% rename from Sources/SwiftGrad/BinaryOperations.swift rename to Sources/SwiftGrad/Protocols/BinaryOperations.swift diff --git a/Sources/SwiftGrad/UnaryOperations.swift b/Sources/SwiftGrad/Protocols/UnaryOperations.swift similarity index 100% rename from Sources/SwiftGrad/UnaryOperations.swift rename to Sources/SwiftGrad/Protocols/UnaryOperations.swift