├── .gitignore ├── 4.2 ├── .dockerignore └── Dockerfile ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .idea/ 3 | run.sh 4 | build.sh 5 | inference.swift 6 | inference 7 | TFExample -------------------------------------------------------------------------------- /4.2/.dockerignore: -------------------------------------------------------------------------------- 1 | 2 | /.idea/ 3 | run.sh 4 | build.sh 5 | inference 6 | TFExample -------------------------------------------------------------------------------- /4.2/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | MAINTAINER Zach Gray (zgray@scal.io) 4 | LABEL maintainer="Zach Gray " 5 | LABEL Description="Dockerized Swift for TensorFlow" 6 | 7 | # Install related packages and set LLVM 3.8 as the compiler 8 | RUN apt-get -q update && \ 9 | apt-get -q install -y \ 10 | make \ 11 | libc6-dev \ 12 | clang-3.8 \ 13 | curl \ 14 | libedit-dev \ 15 | libpython2.7 \ 16 | libpython-dev \ 17 | libncurses5-dev \ 18 | libicu-dev \ 19 | libssl-dev \ 20 | libxml2 \ 21 | tzdata \ 22 | git \ 23 | libcurl4-openssl-dev \ 24 | pkg-config \ 25 | && update-alternatives --quiet --install /usr/bin/clang clang /usr/bin/clang-3.8 100 \ 26 | && update-alternatives --quiet --install /usr/bin/clang++ clang++ /usr/bin/clang++-3.8 100 \ 27 | && rm -r /var/lib/apt/lists/* 28 | 29 | # Install Swift for TensorFlow: 30 | 31 | # Define SWIFT_TF_URL as an arg that can be passed by users if needed 32 | ARG SWIFT_TF_URL=https://storage.googleapis.com/swift-tensorflow/ubuntu16.04/swift-tensorflow-DEVELOPMENT-2019-01-04-a-ubuntu16.04.tar.gz 33 | 34 | RUN curl -fSsL $SWIFT_TF_URL -o swift-tensorflow.tar.gz \ 35 | && tar xzf swift-tensorflow.tar.gz --directory / \ 36 | && rm swift-tensorflow.tar.gz 37 | 38 | # Version DEVELOPMENT-2019-01-04 needs this fix 39 | RUN mv -n /usr/lib/libBlocksRuntime.so /usr/lib/libBlocksRuntime.so.0 && ldconfig 40 | 41 | RUN swift --version 42 | 43 | RUN cd /usr/src 44 | WORKDIR /usr/src 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Zach Gray 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # swift-tensorflow 2 | 3 | Dockerized [Swift for TensorFlow](https://github.com/tensorflow/swift). This image is available now on Docker Hub at `zachgray/swift-tensorflow:4.2`. 4 | 5 | ## Overview 6 | 7 | This image will allow you to easily take the official [Swift for TensorFlow](https://github.com/tensorflow/swift) for a test drive without worrying about installing dependencies, changing your path, and interfering with your existing Swift/Xcode config. 8 | 9 | ## Run 10 | ### Run a REPL 11 | 12 | *Note: when running this interactive container with the standard `-it`, we also must [run without the default seccomp profile](https://docs.docker.com/engine/security/seccomp/) with `--security-opt seccomp:unconfined` to allow the Swift REPL access to `ptrace` and run correctly.* 13 | 14 | #### Run the `swift-tensorflow` container: 15 | 16 | ```bash 17 | docker run --rm --security-opt seccomp:unconfined -itv ${PWD}:/usr/src \ 18 | zachgray/swift-tensorflow:4.2 \ 19 | swift 20 | ``` 21 | 22 | #### Observe the output: 23 | 24 | ``` 25 | Welcome to Swift version 4.2-dev (LLVM fd66ce58db, Clang cca52e8396, Swift 280486afdc). 26 | Type :help for assistance. 27 | 1> 28 | ``` 29 | 30 | #### Interact with TensorFlow: 31 | 32 | ``` 33 | 1> import TensorFlow 34 | 2> var x = Tensor([[1, 2], [3, 4]]) 35 | x: TensorFlow.Tensor = [[1.0, 2.0], [3.0, 4.0]] 36 | 3> x + x 37 | $R2: TensorFlow.Tensor = [[2.0, 4.0], [6.0, 8.0]] 38 | 4> :exit 39 | ``` 40 | 41 | ### Run the Interpreter 42 | 43 | Assuming you've added a swift file, like this one copied from [official docs](https://github.com/tensorflow/swift/blob/master/Usage.md#interpreter) in your current directory with the name `inference.swift`: 44 | 45 | ```swift 46 | import TensorFlow 47 | 48 | struct MLPClassifier { 49 | var w1 = Tensor(shape: [2, 4], repeating: 0.1) 50 | var w2 = Tensor(shape: [4, 1], scalars: [0.4, -0.5, -0.5, 0.4]) 51 | var b1 = Tensor([0.2, -0.3, -0.3, 0.2]) 52 | var b2 = Tensor([[0.4]]) 53 | 54 | func prediction(for x: Tensor) -> Tensor { 55 | let o1 = tanh(matmul(x, w1) + b1) 56 | return tanh(matmul(o1, w2) + b2) 57 | } 58 | } 59 | let input = Tensor([[0.2, 0.8]]) 60 | let classifier = MLPClassifier() 61 | let prediction = classifier.prediction(for: input) 62 | print(prediction) 63 | ``` 64 | 65 | To use the interpreter: 66 | 67 | ```bash 68 | docker run --rm -v ${PWD}:/usr/src \ 69 | zachgray/swift-tensorflow:4.2 \ 70 | swift -O /usr/src/inference.swift 71 | ``` 72 | 73 | ### Run the Compiler 74 | 75 | ```bash 76 | docker run --rm -v ${PWD}:/usr/src zachgray/swift-tensorflow:4.2 \ 77 | swiftc -O /usr/src/inference.swift -ltensorflow 78 | ``` 79 | 80 | ## Run with Dependencies (advanced) 81 | 82 | Importing third-party packages in the REPL requires a few additional steps, but it's possible if we make use of [SPM](https://swift.org/package-manager/) and a dynamic library. 83 | 84 | ### Package Manager Tutorial 85 | 86 | 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. 87 | 88 | *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`.* 89 | 90 | #### 1) Start the interactive session: 91 | 92 | ```bash 93 | docker run --rm -itv ${PWD}:/usr/src \ 94 | zachgray/swift-tensorflow:4.2 \ 95 | /bin/bash 96 | ``` 97 | 98 | #### 2) Create a library called `example`: 99 | 100 | ```bash 101 | mkdir TFExample 102 | cd TFExample 103 | swift package init --type library 104 | ``` 105 | 106 | #### 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: 107 | 108 | ```swift 109 | // swift-tools-version:4.0 110 | 111 | import PackageDescription 112 | 113 | let package = Package( 114 | name: "TFExample", 115 | products: [ 116 | .library( 117 | name: "TFExample", 118 | type: .dynamic, // allow use of this package and it's deps from the REPL 119 | targets: ["TFExample"] 120 | ) 121 | ], 122 | dependencies: [ 123 | .package(url: "https://github.com/ReactiveX/RxSwift.git", "4.0.0" ..< "5.0.0") 124 | ], 125 | targets: [ 126 | .target( 127 | name: "TFExample", 128 | dependencies: ["RxSwift"]), 129 | .testTarget( 130 | name: "TFExampleTests", 131 | dependencies: ["TFExample"]), 132 | ] 133 | ) 134 | ``` 135 | 136 | #### 4) Now fetch package dependencies: 137 | 138 | ```bash 139 | swift package update 140 | ``` 141 | 142 | #### 5) Build the package: 143 | 144 | ```bash 145 | swift build 146 | ``` 147 | 148 | #### 6) Once the build is complete, we will exit our interactive session: 149 | 150 | ``` 151 | exit 152 | ``` 153 | 154 | #### 7) Start the REPL in a container: 155 | 156 | Notice that we start the REPL in a similar manner to the examples above, but this time link to the built package. 157 | 158 | ```bash 159 | docker run --rm --security-opt seccomp:unconfined -itv ${PWD}:/usr/src \ 160 | zachgray/swift-tensorflow:4.2 \ 161 | swift \ 162 | -I/usr/lib/swift/clang/include \ 163 | -I/usr/src/TFExample/.build/debug \ 164 | -L/usr/src/TFExample/.build/debug \ 165 | -lswiftPython \ 166 | -lswiftTensorFlow \ 167 | -lTFExample 168 | ``` 169 | 170 | #### 8) Interact with the REPL: 171 | 172 | Now we can import dependences into the REPL session! 173 | 174 | ``` 175 | Welcome to Swift version 4.2-dev (LLVM 04bdb56f3d, Clang b44dbbdf44). Type :help for assistance. 176 | 1> import RxSwift 177 | 2> import Python 178 | 3> import TensorFlow 179 | 4> var x = Tensor([[1, 2], [3, 4]]) 180 | x: TensorFlow.Tensor = [[1.0, 2.0], [3.0, 4.0]] 181 | 5> _ = Observable.from([1,2]).subscribe(onNext: { print($0) }) 182 | 1 183 | 2 184 | 6> var x: PyValue = [1, "hello", 3.14] 185 | x: Python.PyValue = [1, 'hello', 3.14] 186 | 7> :exit 187 | ``` 188 | 189 | *Note: the Swift-related `-l` flags are currently necessary ([see discussion here](https://github.com/google/swift/issues/4)) 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.* 190 | 191 | ## License 192 | 193 | This project is [MIT Licensed](https://github.com/zachgrayio/swift-tensorflow/blob/master/LICENSE). 194 | --------------------------------------------------------------------------------