Skip to content
This repository was archived by the owner on Apr 23, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
67f7c64
Use PascalCase for all Swift source files (#152)
kirillbobyrev May 5, 2019
35c20e8
Load config variable from `hparams.json` file so that Transformer can…
leoxzhao May 9, 2019
ad63e2b
Style fixes from #154 (#155)
saeta May 9, 2019
030153c
A few quick fixes to help unbreak swift-models. (#160)
saeta May 20, 2019
f9687bf
Unbreak models by inserting `.call`. (#161)
saeta May 20, 2019
4275c36
s/CotangentVector/TangentVector/g (#162)
brettkoonce May 24, 2019
9de3862
Add MNIST test set evaluation and change hyperparameters. (#163)
kamalkraj May 28, 2019
ed143c0
Updated models to use revised name for callable (SE-0253), fixed a fe…
leoxzhao Jun 8, 2019
cf21585
transformer: upstream api changes (#171)
brettkoonce Jun 19, 2019
edd734e
rebuild resnet block based approach (#170)
brettkoonce Jun 20, 2019
b9920ae
add gym blackjack qlearning demo (#173)
brettkoonce Jun 24, 2019
e3b8a6b
Make 'GoModel' stored properties be variables. (#174)
rxwei Jun 26, 2019
2fa11ba
Added .swift-format and updated .gitignore for Xcode 11's SwiftPM sup…
BradLarson Jul 19, 2019
08c80a5
Replaced Python with Swift in CIFAR10 dataset loading (#178)
BradLarson Jul 23, 2019
d4ccedc
Replace Autoencoder's tanh activation with sigmoid (#180)
t-ae Jul 24, 2019
d6f4496
Add GAN Example (#181)
t-ae Jul 26, 2019
7fb9185
nightlies URL: s4tf-kokoro-artifact-testing => swift-tensorflow-artif…
pschuh Jul 29, 2019
c79f62e
First steps in repository reorganization: extracting common MNIST dat…
BradLarson Jul 30, 2019
bf8f2fa
Update Dockerfile to install Python libraries (#184)
t-ae Jul 31, 2019
d34fc3c
Delete helpers.swift (#187)
mikowals Aug 2, 2019
b353333
Continuing repository reorganization: extracting common CIFAR-10 and …
BradLarson Aug 2, 2019
4d75df9
[Models] Fix enumeration of blocks in `ResidualBasicBlockStack` `init…
jon-tow Aug 7, 2019
66d442d
SqueezeNet Implementation (#189)
Andr0id100 Aug 9, 2019
e319a07
WideResNet - fix widenFactor and match model to citation (#193)
mikowals Aug 13, 2019
36fdbb1
Removal of deprecated allDifferentiableVariables. (#194)
BradLarson Aug 13, 2019
3fa05f7
Add JPEG loading / saving via Raw TF operations, removing Matplotlib …
BradLarson Aug 21, 2019
036f014
Convert MNIST classifier to use sequential (#200)
Shashi456 Aug 27, 2019
21c694d
Convert Autoencoder and Catch to use Sequential (#203)
Shashi456 Aug 28, 2019
523933f
Adding shape-based inference tests for all image classification model…
BradLarson Aug 29, 2019
c8e6347
Update deprecated APIs in Catch (#205)
Shashi456 Aug 29, 2019
9150822
Update squeezenet and add V1.1 version (#204)
Shashi456 Aug 30, 2019
db72e4d
Fix '@noDerivative' warnings. (#208)
rxwei Sep 20, 2019
3df2875
Indentation and formatting fixes in CartPole (#214)
rxwei Oct 2, 2019
3b1f373
DenseNet Implementaion (#213)
Andr0id100 Oct 2, 2019
41c4a7a
Download MNIST dataset from remote URL (#215)
spencerkohan Oct 15, 2019
ae8eac0
use enable in _vjpCausallyMasked (#218)
koen-dejonghe Oct 19, 2019
b3a1f42
Change momentum and epsilon properties to scalars. (#220)
dan-zheng Nov 7, 2019
23b88cc
Uses switch instead of ifs (#219)
valeriyvan Nov 8, 2019
8253c35
Fixes deprecation warning in MiniGo (#221)
valeriyvan Nov 12, 2019
dfa2c88
Fixing deprecation warnings on all but the MiniGo example. (#223)
BradLarson Nov 12, 2019
a1db3bb
Initial training and inference benchmarks (#222)
BradLarson Nov 14, 2019
7aa8008
Merge branch 'stable' into tensorflow-0.6
BradLarson Nov 21, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@
cifar-10-batches-py/
cifar-10-batches-bin/
output/
t10k-labels-idx1-ubyte
t10k-images-idx3-ubyte
train-labels-idx1-ubyte
train-images-idx3-ubyte
104 changes: 104 additions & 0 deletions Benchmarks/Benchmark.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright 2019 The TensorFlow Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Foundation

enum BenchmarkVariety {
case inferenceThroughput(batches: Int, batchSize: Int)
case trainingTime
}

struct BenchmarkResults {
let name: String
let iterations: Int
let timings: [Double]
let variety: BenchmarkVariety
}

extension BenchmarkResults {
var interpretedTimings: [Double] {
switch self.variety {
case let .inferenceThroughput(batches, batchSize):
return timings.map { Double(batches * batchSize) / ($0 / 1000.0) }
case .trainingTime:
return timings
}
}
}

/// Performs the specified benchmark over a certain number of iterations and provides the result to a callback function.
func benchmark(
name: String,
iterations: Int, variety: BenchmarkVariety,
operation: () -> Void,
callback: (BenchmarkResults) -> Void
) {
var timings: [Double] = []
for _ in 0..<iterations {
let timing = time(operation)
timings.append(timing)
}

let results = BenchmarkResults(
name: name, iterations: iterations,
timings: timings, variety: variety
)
callback(results)
}

/// Returns the time elapsed while running `body` in milliseconds.
func time(_ body: () -> Void) -> Double {
let divisor: Double = 1_000_000
let start = Double(DispatchTime.now().uptimeNanoseconds) / divisor
body()
let end = Double(DispatchTime.now().uptimeNanoseconds) / divisor
let elapsed = end - start
return elapsed
}

/// Provides the average and standard deviation of an array of values.
func statistics(for values: [Double]) -> (average: Double, standardDeviation: Double) {
guard values.count > 0 else { return (average: 0.0, standardDeviation: 0.0) }
guard values.count > 1 else { return (average: values.first!, standardDeviation: 0.0) }

let average = (values.reduce(0.0) { $0 + $1 }) / Double(values.count)

let standardDeviation = sqrt(
values.reduce(0.0) { $0 + ($1 - average) * ($1 - average) }
/ Double(values.count - 1))

return (average: average, standardDeviation: standardDeviation)
}

// This is a simple callback function example that only logs the result to the console.
func logResults(_ result: BenchmarkResults) {
let (average, standardDeviation) = statistics(for: result.interpretedTimings)

switch result.variety {
case .inferenceThroughput:
print(
"""
Benchmark: \(result.name):
\tAfter \(result.iterations) iterations:
\tSamples per second: \(String(format: "%.2f", average)), standard deviation: \(String(format: "%.2f", standardDeviation))
""")
case .trainingTime:
print(
"""
Benchmark: \(result.name):
\tAfter \(result.iterations) iterations:
\tAverage: \(String(format: "%.2f", average)) ms, standard deviation: \(String(format: "%.2f", standardDeviation)) ms
""")
}
}
53 changes: 53 additions & 0 deletions Benchmarks/Models/ImageClassificationInference.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2019 The TensorFlow Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import TensorFlow
import Datasets
import ImageClassificationModels

protocol ImageClassificationModel: Layer where Input == Tensor<Float>, Output == Tensor<Float> {
init()
}

extension LeNet: ImageClassificationModel {}

class ImageClassificationInference<Model> where Model: ImageClassificationModel {
// TODO: (https://github.com/tensorflow/swift-models/issues/206) Datasets should have a common
// interface to allow for them to be interchangeable in these benchmark cases.
let dataset: MNIST
var model: Model
let images: Tensor<Float>
let batches: Int
let batchSize: Int

init(batches: Int, batchSize: Int, images: Tensor<Float>? = nil) {
self.batches = batches
self.batchSize = batchSize
self.dataset = MNIST(batchSize: batchSize)
self.model = Model()
if let providedImages = images {
self.images = providedImages
} else {
self.images = Tensor<Float>(
randomNormal: [batchSize, 28, 28, 1], mean: Tensor<Float>(0.5),
standardDeviation: Tensor<Float>(0.1), seed: (0xffeffe, 0xfffe))
}
}

func performInference() {
for _ in 0..<batches {
let _ = model(images)
}
}
}
50 changes: 50 additions & 0 deletions Benchmarks/Models/ImageClassificationTraining.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2019 The TensorFlow Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import TensorFlow
import Datasets

struct ImageClassificationTraining<Model>
where Model: ImageClassificationModel, Model.TangentVector.VectorSpaceScalar == Float {
// TODO: (https://github.com/tensorflow/swift-models/issues/206) Datasets should have a common
// interface to allow for them to be interchangeable in these benchmark cases.
let dataset: MNIST
let epochs: Int
let batchSize: Int

init(epochs: Int, batchSize: Int) {
self.epochs = epochs
self.batchSize = batchSize
self.dataset = MNIST(batchSize: batchSize)
}

func train() {
var model = Model()
// TODO: Split out the optimizer as a separate specification.
let optimizer = SGD(for: model, learningRate: 0.1)

Context.local.learningPhase = .training
for _ in 1...epochs {
for i in 0..<dataset.trainingSize / batchSize {
let x = dataset.trainingImages.minibatch(at: i, batchSize: batchSize)
let y = dataset.trainingLabels.minibatch(at: i, batchSize: batchSize)
let 𝛁model = model.gradient { model -> Tensor<Float> in
let ŷ = model(x)
return softmaxCrossEntropy(logits: ŷ, labels: y)
}
optimizer.update(&model, along: 𝛁model)
}
}
}
}
22 changes: 22 additions & 0 deletions Benchmarks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Model benchmarks

Eventually, these will contain a series of benchmarks against a variety of models in the
swift-models repository. The following benchmarks have been implemented:

- Training LeNet against the MNIST dataset
- Performing inference with LeNet using MNIST-sized random images

These benchmarks should provide a baseline to judge performance improvements and regressions in
Swift for TensorFlow.

## Running benchmarks

To begin, you'll need the [latest version of Swift for
TensorFlow](https://github.com/tensorflow/swift/blob/master/Installation.md)
installed. Make sure you've added the correct version of `swift` to your path.

To run all benchmarks, type the following while in the swift-models directory:

```sh
swift run -c release Benchmarks
```
29 changes: 29 additions & 0 deletions Benchmarks/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2019 The TensorFlow Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import ImageClassificationModels

// LeNet-MNIST
let leNetTrainingBenchmark = ImageClassificationTraining<LeNet>(epochs: 1, batchSize: 128)
benchmark(
name: "LeNet-MNIST (training)",
iterations: 10, variety: .trainingTime, operation: leNetTrainingBenchmark.train,
callback: logResults)

let leNetInferenceBenchmark = ImageClassificationInference<LeNet>(batches: 1000, batchSize: 1)
benchmark(
name: "LeNet-MNIST (inference)",
iterations: 10, variety: .inferenceThroughput(batches: 1000, batchSize: 1),
operation: leNetInferenceBenchmark.performInference,
callback: logResults)
9 changes: 4 additions & 5 deletions Catch/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,11 @@ extension CatchAgent {
func perfectAction(for observation: Observation) -> Action {
let paddleX = observation.scalars[0]
let ballX = observation.scalars[1]
if paddleX > ballX {
return .right
} else if paddleX < ballX {
return .left
switch paddleX {
case ballX: return .none
case ..<ballX: return .left
default: return .right
}
return .none
}

/// Returns a random action.
Expand Down
6 changes: 3 additions & 3 deletions Datasets/CIFAR10/CIFAR10.swift
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func loadCIFARFile(named name: String, in directory: String = ".") -> CIFARExamp
let images = Tensor<UInt8>(shape: [imageCount, 3, 32, 32], scalars: bytes)

// Transpose from the CIFAR-provided N(CHW) to TF's default NHWC.
let imageTensor = Tensor<Float>(images.transposed(withPermutations: [0, 2, 3, 1]))
let imageTensor = Tensor<Float>(images.transposed(permutation: [0, 2, 3, 1]))

let mean = Tensor<Float>([0.485, 0.456, 0.406])
let std = Tensor<Float>([0.229, 0.224, 0.225])
Expand All @@ -125,8 +125,8 @@ func loadCIFARFile(named name: String, in directory: String = ".") -> CIFARExamp
func loadCIFARTrainingFiles() -> CIFARExample {
let data = (1..<6).map { loadCIFARFile(named: "data_batch_\($0).bin") }
return CIFARExample(
label: Raw.concat(concatDim: Tensor<Int32>(0), data.map { $0.label }),
data: Raw.concat(concatDim: Tensor<Int32>(0), data.map { $0.data })
label: _Raw.concat(concatDim: Tensor<Int32>(0), data.map { $0.label }),
data: _Raw.concat(concatDim: Tensor<Int32>(0), data.map { $0.data })
)
}

Expand Down
Loading