Last active
November 28, 2017 21:50
-
-
Save carsonfarmer/df1117bd25b97e71bc8b927af1a1b0fc to your computer and use it in GitHub Desktop.
Swift code for Medium article on Neuralyzer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Neuralyzer | |
struct IrisData: Codable { | |
let row: [Double] | |
} | |
var parsedData: [IrisData] = [] | |
if let file = Bundle.main.path(forResource: "iris", ofType: "json") { | |
do { | |
let jsonDecoder = JSONDecoder() | |
let data = try Data(contentsOf: URL(fileURLWithPath: file), options: .alwaysMapped) | |
let result = try? jsonDecoder.decode([IrisData].self, from: data) | |
if let result = result { | |
parsedData = result | |
} else { | |
print("Could not get json from file, make sure that file contains valid json.") | |
} | |
} catch let error { | |
print(error.localizedDescription) | |
} | |
} else { | |
print("Fail") | |
} | |
let array = parsedData.map { $0.row } | |
let data = Matrix<Double>(unpack: array) | |
data.columns | |
// The first 4 columns are features, the last three are one-hot classes | |
let X = Matrix(copy: data[0..<150, 0..<4]) | |
let Y = Matrix(copy: data[0..<150, 4..<7]) | |
let loss = CategoricalCrossentropy() | |
let optim = RMSProp(loss: loss, learningRate: 0.1) | |
let net = Sequential(inputSize: 4, optimizer: optim) | |
net.add(layer: Dense(units: 16, activation: Sigmoid())) | |
net.add(layer: Dense(units: 8, activation: Sigmoid())) | |
net.add(layer: Dense(units: 3, activation: Softmax())) | |
// Let's go! | |
let epochs = 20 | |
let batchSize = 10 | |
for epoch in 0..<epochs { | |
let t0 = Date() | |
var last = 0 | |
for now in stride(from: 9, to: X.rows, by: batchSize) { | |
let x = X[last...now, 0..<4] | |
let y = Y[last...now, 0..<3] | |
net.train(input: x, target: y) | |
last = now | |
} | |
let estimate = net.predict(input: X) // Grab estimates for all of X | |
let l = loss.fx(input: estimate, target: Y) // Compute loss at current epoch | |
let accuracy = evaluate(estimate: estimate, target: Y) | |
let time = Date().timeIntervalSince(t0) // How long did that take? | |
// Let's track our progress! | |
print("Epoch \(epoch+1)/\(epochs)") | |
print("\(time)s - loss: \(l) - accuracy \(accuracy)") | |
} | |
// The last example is of type Iris-Virginica | |
let input = Matrix(copy: X[149..<150, 0..<4]) | |
let names: [String] = ["Setosa", "Versicolour", "Virginica"] | |
print(net.predict(input: input)) | |
print("The last example is of type Iris-\(names[2])!") | |
var json = net.spec // Grab the spec for the network by itself | |
// Add our 'training features': optimizer and loss function | |
json["training"] = ["optimizer": optim.spec, "loss": loss.spec] | |
print(json) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment