下面的代码,因为最初声明的 是整数类型 ,所以如果将 赋值给 时,会出现类型不匹配的问题,Swift 将会报错:
报错输出:
- Cannot assign value of type 'String' to type 'Int'
下面是一个使用 TensorFlow 计算的基础示例:
- import TensorFlow
- // 声明两个Tensor
- let x = Tensor<Float>([1])
- let y = Tensor<Float>([2])
- // 对两个 Tensor 做加法运算
- let w = x + y
- // 输出结果
- print(w)
在基础的 Tensorflow API 上,Swift 封装了 Tensorflow 的标准 API 接口。比如看一下处理数字的代码,API 与 Tensorflow 高度保持了一致:
- let x = Tensor<BFloat16>(zeros: [32, 128])
- let h1 = sigmoid(x • w1 + b1)
- let h2 = tanh(h1 • w1 + b1)
- let h3 = softmax(h2 • w1 + b1)
再比如 Data API ,也是同名函数直接改写为 Swift 语法即可直接使用:
借助 S4TF 强大的集成能力,从 Python 迁移到 Swift 非常简单。您可以逐步迁移 Python 代码(或继续使用 Python 代码库),因为 S4TF 支持直接在代码中加载 Python 原生代码库,使得开发者可以继续使用熟悉的语法在 Swift 中调用 Python 中已经完成的功能。
下面我们以 NumPy 为例,看一下如何在 Swift 语言中,直接加载 Python 的 NumPy 代码库,并且直接进行调用:
- import Python
- let np = Python.import("numpy")
- let x = np.array([[1, 2], [3, 4]])
- let y = np.array([11, 12])
- print(x.dot(y))
输出:
- [35 81]
除了能够直接调用 Python 之外,Swift 也快成直接调用系统函数库。比如下面的代码例子展示了我们可以在 Swift 中直接加载 Glibc 的动态库,然后调用系统底层的 malloc 和 memcpy 函数,对变量直接进行操作。
- let x = malloc(18)
- memcpy(x, "memcpy from Glibc", 18)
- free(x)
通过 Swift 强大的集成能力,针对 C/C++ 语言库的加载和调用,处理起来也将会是非常简单高效。
输出:
- -4.0
本小节的源代码可以在 <> 找到。加载 MNIST 数据集使用了作者封装的 Swift Module swift-MNIST)。
更方便的是在 Google Colab 上直接打开本例子的 Jupyter 直接运行,地址: (推荐)
- import TensorFlow
- import Python
- import Foundation
- /**
- * The Swift Module for MNIST Dataset:
- * https://github.com/huan/swift-MNIST
- */
- import MNIST
- struct MLP: Layer {
- typealias Input = Tensor<Float>
- typealias Output = Tensor<Float>
- var flatten = Flatten<Float>()
- var dense = Dense<Float>(inputSize: 784, outputSize: 10)
- @differentiable
- public func callAsFunction(_ input: Input) -> Output {
- return input.sequenced(through: flatten, dense)
- }
- }
- let optimizer = Adam(for: model)
- let mnist = MNIST()
- let ((trainImages, trainLabels), (testImages, testLabels)) = mnist.loadData()
- let imageBatch = Dataset(elements: trainImages).batched(32)
- let labelBatch = Dataset(elements: trainLabels).batched(32)
- for (X, y) in zip(imageBatch, labelBatch) {
- // Caculate the gradient
- let (_, grads) = valueWithGradient(at: model) { model -> Tensor<Float> in
- let logits = model(X)
- return softmaxCrossEntropy(logits: logits, labels: y)
- }
- // Update parameters by optimizer
- optimizer.update(&model.self, along: grads)
- }
- let logits = model(testImages)
- let acc = mnist.getAccuracy(y: testLabels, logits: logits)
- print("Test Accuracy: \(acc)" )
以上程序运行输出为:
- Downloading train-images-idx3-ubyte ...
- Downloading train-labels-idx1-ubyte ...
- Reading data.
- Constructing data tensors.