-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathsimple_model.swift
102 lines (88 loc) · 2.9 KB
/
simple_model.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
import StdlibUnittest
var SimpleModelTests = TestSuite("SimpleModel")
struct DenseLayer : Equatable {
@differentiable
let w: Float
@differentiable
let b: Float
}
extension DenseLayer : Differentiable, VectorProtocol {
typealias TangentVector = DenseLayer
typealias Scalar = Float
static var zero: DenseLayer {
return DenseLayer(w: 0, b: 0)
}
static func + (lhs: DenseLayer, rhs: DenseLayer) -> DenseLayer {
return DenseLayer(w: lhs.w + rhs.w, b: lhs.b + rhs.b)
}
static func - (lhs: DenseLayer, rhs: DenseLayer) -> DenseLayer {
return DenseLayer(w: lhs.w - rhs.w, b: lhs.b - rhs.b)
}
static func * (lhs: DenseLayer, rhs: DenseLayer) -> DenseLayer {
return DenseLayer(w: lhs.w * rhs.w, b: lhs.b * rhs.b)
}
static func * (lhs: Float, rhs: DenseLayer) -> DenseLayer {
return DenseLayer(w: lhs * rhs.w, b: lhs * rhs.b)
}
}
extension DenseLayer {
func prediction(for input: Float) -> Float {
return input * w + b
}
}
struct Model : Equatable {
@differentiable
let l1: DenseLayer
@differentiable
let l2: DenseLayer
@differentiable
let l3: DenseLayer
}
extension Model : Differentiable, VectorProtocol {
typealias TangentVector = Model
typealias Scalar = Float
static var zero: Model {
return Model(l1: DenseLayer.zero, l2: DenseLayer.zero, l3: DenseLayer.zero)
}
static func + (lhs: Model, rhs: Model) -> Model {
return Model(l1: lhs.l1 + rhs.l1, l2: lhs.l2 + rhs.l2, l3: lhs.l3 + rhs.l3)
}
static func - (lhs: Model, rhs: Model) -> Model {
return Model(l1: lhs.l1 - rhs.l1, l2: lhs.l2 - rhs.l2, l3: lhs.l3 - rhs.l3)
}
static func * (lhs: Model, rhs: Model) -> Model {
return Model(l1: lhs.l1 * rhs.l1, l2: lhs.l2 * rhs.l2, l3: lhs.l3 * rhs.l3)
}
static func * (lhs: Float, rhs: Model) -> Model {
return Model(l1: lhs * rhs.l1, l2: lhs * rhs.l2, l3: lhs * rhs.l3)
}
}
extension Model {
func prediction(for input: Float) -> Float {
// This "model" is silly because it doesn't have nonlinearities. But it's
// simple and good enough for testing purposes.
let activation1 = l1.prediction(for: input)
let activation2 = l2.prediction(for: activation1)
return l3.prediction(for: activation2)
}
func loss(of prediction: Float, from label: Float) -> Float {
return (prediction - label) * (prediction - label)
}
}
SimpleModelTests.test("gradient") {
let layer = DenseLayer(w: 1.0, b: 0.0)
let model = Model(l1: layer, l2: layer, l3: layer)
let label: Float = 3
let input: Float = 1
let gradModel = model.gradient { model -> Float in
let pred = model.prediction(for: input)
return model.loss(of: pred, from: label)
}
let expectedGrad = Model(l1: DenseLayer(w: -4, b: -4),
l2: DenseLayer(w: -4, b: -4),
l3: DenseLayer(w: -4, b: -4))
expectEqual(expectedGrad, gradModel)
}
runAllTests()