Dockerized Swift for TensorFlow. This image is available now on Docker Hub at zachgray/swift-tensorflow:4.2
.
This image will allow you to easily take the official Swift for TensorFlow for a test drive without worrying about installing dependencies, changing your path, and interfering with your existing Swift/Xcode config.
Note: when running this interactive container with the standard -it
, we also must run without the default seccomp profile with --security-opt seccomp:unconfined
to allow the Swift REPL access to ptrace
and run correctly.
docker run --rm --security-opt seccomp:unconfined -itv ${PWD}:/usr/src \
zachgray/swift-tensorflow:4.2 \
swift
Welcome to Swift version 4.2-dev (LLVM fd66ce58db, Clang cca52e8396, Swift 280486afdc).
Type :help for assistance.
1>
1> import TensorFlow
2> var x = Tensor<Float>([[1, 2], [3, 4]])
x: TensorFlow.Tensor<Float> = [[1.0, 2.0], [3.0, 4.0]]
3> x + x
$R2: TensorFlow.Tensor<Float> = [[2.0, 4.0], [6.0, 8.0]]
4> :exit
Assuming you've added a swift file, like this one copied from official docs in your current directory with the name inference.swift
:
import TensorFlow
struct MLPClassifier {
var w1 = Tensor<Float>(shape: [2, 4], repeating: 0.1)
var w2 = Tensor<Float>(shape: [4, 1], scalars: [0.4, -0.5, -0.5, 0.4])
var b1 = Tensor<Float>([0.2, -0.3, -0.3, 0.2])
var b2 = Tensor<Float>([[0.4]])
func prediction(for x: Tensor<Float>) -> Tensor<Float> {
let o1 = tanh(matmul(x, w1) + b1)
return tanh(matmul(o1, w2) + b2)
}
}
let input = Tensor<Float>([[0.2, 0.8]])
let classifier = MLPClassifier()
let prediction = classifier.prediction(for: input)
print(prediction)
To use the interpreter:
docker run --rm -v ${PWD}:/usr/src \
zachgray/swift-tensorflow:4.2 \
swift -O /usr/src/inference.swift
docker run --rm -v ${PWD}:/usr/src zachgray/swift-tensorflow:4.2 \
swiftc -O /usr/src/inference.swift -ltensorflow
Importing third-party packages in the REPL requires a few additional steps, but it's possible if we make use of SPM and a dynamic library.
For the sake of simplicity we'll run all of these commands in interactive mode from within the Docker container. Keep in mind that since we've mounted the current directory as a container volume which we're working in, changes here will be reflected in your host filesystem.
Note: if you wanted to run these commands from outside of the container, as we did the previous examples, you'd simple include the following before each swift
binary interaction: docker run --rm -v ${PWD}:/usr/src zachgray/swift-tensorflow:4.2
.
docker run --rm -itv ${PWD}:/usr/src \
zachgray/swift-tensorflow:4.2 \
/bin/bash
mkdir TFExample
cd TFExample
swift package init --type library
3) Add some third-party dependencies to Package.swift
, and make the library dynamic so we can import it and it's dependencies. Here's an example:
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "TFExample",
products: [
.library(
name: "TFExample",
type: .dynamic, // allow use of this package and it's deps from the REPL
targets: ["TFExample"]
)
],
dependencies: [
.package(url: "https://github.com/ReactiveX/RxSwift.git", "4.0.0" ..< "5.0.0")
],
targets: [
.target(
name: "TFExample",
dependencies: ["RxSwift"]),
.testTarget(
name: "TFExampleTests",
dependencies: ["TFExample"]),
]
)
swift package update
swift build
exit
Notice that we start the REPL in a similar manner to the examples above, but this time link to the built package.
docker run --rm --security-opt seccomp:unconfined -itv ${PWD}:/usr/src \
zachgray/swift-tensorflow:4.2 \
swift \
-I/usr/lib/swift/clang/include \
-I/usr/src/TFExample/.build/debug \
-L/usr/src/TFExample/.build/debug \
-lswiftPython \
-lswiftTensorFlow \
-lTFExample
Now we can import dependences into the REPL session!
Welcome to Swift version 4.2-dev (LLVM 04bdb56f3d, Clang b44dbbdf44). Type :help for assistance.
1> import RxSwift
2> import Python
3> import TensorFlow
4> var x = Tensor([[1, 2], [3, 4]])
x: TensorFlow.Tensor<Double> = [[1.0, 2.0], [3.0, 4.0]]
5> _ = Observable.from([1,2]).subscribe(onNext: { print($0) })
1
2
6> var x: PyValue = [1, "hello", 3.14]
x: Python.PyValue = [1, 'hello', 3.14]
7> :exit
Note: the Swift-related -l
flags are currently necessary (see discussion here) but may eventually become redundant. Also, while they're relevant, the order in which the flags are passed matters! Be sure to link your dynamic library after the Swift libs.
This project is MIT Licensed.