Toán tử TensorFlow thô

Xem trên TensorFlow.org Xem nguồn trên GitHub

Xây dựng trên TensorFlow, Swift cho TensorFlow áp dụng một cách tiếp cận mới đối với thiết kế API. API được tuyển chọn cẩn thận từ các thư viện đã có sẵn và kết hợp với các thành ngữ ngôn ngữ mới. Điều này có nghĩa là không phải tất cả API TensorFlow đều sẽ có sẵn trực tiếp dưới dạng API Swift và việc quản lý API của chúng tôi cần thời gian và nỗ lực tận tâm để phát triển. Tuy nhiên, đừng lo lắng nếu toán tử TensorFlow yêu thích của bạn không có sẵn trong Swift -- thư viện TensorFlow Swift cung cấp cho bạn quyền truy cập minh bạch vào hầu hết các toán tử TensorFlow, trong không gian tên _Raw .

Nhập TensorFlow để bắt đầu.

import TensorFlow

Gọi các toán tử thô

Chỉ cần tìm hàm bạn cần trong không gian tên _Raw thông qua quá trình hoàn tất mã.

print(_Raw.mul(Tensor([2.0, 3.0]), Tensor([5.0, 6.0])))
[10.0, 18.0]

Xác định toán tử nhân mới

Multiply đã có sẵn dưới dạng toán tử * trên Tensor , nhưng chúng ta hãy giả sử rằng chúng ta muốn cung cấp nó dưới một tên mới là .* . Swift cho phép bạn thêm các phương thức hoặc thuộc tính được tính toán vào các kiểu hiện có bằng cách sử dụng các khai báo extension .

Bây giờ, chúng ta hãy thêm .* vào Tensor bằng cách khai báo một phần mở rộng và cung cấp nó khi kiểu Scalar của tensor phù hợp với Numeric .

infix operator .* : MultiplicationPrecedence

extension Tensor where Scalar: Numeric {
    static func .* (_ lhs: Tensor, _ rhs: Tensor) -> Tensor {
        return _Raw.mul(lhs, rhs)
    }
}

let x: Tensor<Double> = [[1.0, 2.0], [3.0, 4.0]]
let y: Tensor<Double> = [[8.0, 7.0], [6.0, 5.0]]
print(x .* y)
[[ 8.0, 14.0],
 [18.0, 20.0]]

Xác định đạo hàm của hàm được bao bọc

Bạn không chỉ có thể dễ dàng xác định API Swift cho toán tử TensorFlow thô mà còn có thể làm cho nó trở nên khác biệt để hoạt động với tính năng phân biệt tự động hạng nhất của Swift.

Để làm cho .* có thể phân biệt được, hãy sử dụng thuộc tính @derivative trên hàm đạo hàm và chỉ định hàm ban đầu làm đối số thuộc tính dưới nhãn of: Vì toán tử .* được xác định khi loại chung Scalar tuân theo Numeric , nên việc làm cho Tensor<Scalar> tuân theo giao thức Differentiable là không đủ. Sinh ra với sự an toàn về kiểu, Swift sẽ nhắc nhở chúng ta thêm một ràng buộc chung trên thuộc tính @differentiable để yêu cầu Scalar tuân thủ giao thức TensorFlowFloatingPoint , điều này sẽ làm cho Tensor<Scalar> tuân thủ Differentiable .

@differentiable(where Scalar: TensorFlowFloatingPoint)
infix operator .* : MultiplicationPrecedence

extension Tensor where Scalar: Numeric {
    @differentiable(where Scalar: TensorFlowFloatingPoint)
    static func .* (_ lhs: Tensor,  _ rhs: Tensor) -> Tensor {
        return _Raw.mul(lhs, rhs)
    }
}

extension Tensor where Scalar : TensorFlowFloatingPoint { 
    @derivative(of: .*)
    static func multiplyDerivative(
        _ lhs: Tensor, _ rhs: Tensor
    ) -> (value: Tensor, pullback: (Tensor) -> (Tensor, Tensor)) {
        return (lhs * rhs, { v in
            ((rhs * v).unbroadcasted(to: lhs.shape),
            (lhs * v).unbroadcasted(to: rhs.shape))
        })
    }
}

// Now, we can take the derivative of a function that calls `.*` that we just defined.
print(gradient(at: x, y) { x, y in
    (x .* y).sum()
})
(0.0, 0.0)

Thêm ví dụ

let matrix = Tensor<Float>([[1, 2], [3, 4]])

print(_Raw.matMul(matrix, matrix, transposeA: true, transposeB: true))
print(_Raw.matMul(matrix, matrix, transposeA: true, transposeB: false))
print(_Raw.matMul(matrix, matrix, transposeA: false, transposeB: true))
print(_Raw.matMul(matrix, matrix, transposeA: false, transposeB: false))
[[ 7.0, 15.0],
 [10.0, 22.0]]
[[10.0, 14.0],
 [14.0, 20.0]]
[[ 5.0, 11.0],
 [11.0, 25.0]]
[[ 7.0, 10.0],
 [15.0, 22.0]]