ตัวดำเนินการ Raw TensorFlow

ดูบน TensorFlow.org ดูแหล่งที่มาบน GitHub

Swift สำหรับ TensorFlow สร้างขึ้นบน TensorFlow ใช้แนวทางใหม่ในการออกแบบ API API ได้รับการดูแลจัดการอย่างระมัดระวังจากไลบรารีที่จัดตั้งขึ้นและรวมกับสำนวนภาษาใหม่ ซึ่งหมายความว่า TensorFlow API บางรายการจะพร้อมใช้งานโดยตรงในรูปแบบ Swift API และการดูแลจัดการ API ของเราต้องการเวลาและความพยายามอย่างทุ่มเทในการพัฒนา อย่างไรก็ตาม ไม่ต้องกังวลหากตัวดำเนินการ TensorFlow ที่คุณชื่นชอบไม่พร้อมใช้งานใน Swift -- ไลบรารี TensorFlow Swift ช่วยให้คุณเข้าถึงตัวดำเนินการ TensorFlow ส่วนใหญ่ได้อย่างโปร่งใสภายใต้เนมสเปซ _Raw

นำเข้า TensorFlow เพื่อเริ่มต้น

import TensorFlow

เรียกผู้ประกอบการดิบ

เพียงค้นหาฟังก์ชันที่คุณต้องการภายใต้เนมสเปซ _Raw ผ่านการเติมโค้ดให้สมบูรณ์

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

การกำหนดตัวดำเนินการคูณใหม่

Multiply มีให้บริการแล้วในฐานะโอเปอเรเตอร์ * บน Tensor แต่ให้เราแกล้งทำเป็นว่าเราต้องการทำให้มันใช้งานได้ภายใต้ชื่อใหม่ว่า .* Swift ช่วยให้คุณสามารถเพิ่มวิธีการหรือคุณสมบัติที่คำนวณย้อนหลังให้กับประเภทที่มีอยู่โดยใช้การประกาศ extension

ตอนนี้ให้เราเพิ่ม .* ให้กับ Tensor โดยการประกาศส่วนขยายและทำให้สามารถใช้งานได้เมื่อประเภท Scalar ของเทนเซอร์สอดคล้องกับ 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]]

การกำหนดอนุพันธ์ของฟังก์ชันที่ห่อไว้

ไม่เพียงแต่คุณสามารถกำหนด Swift API สำหรับตัวดำเนินการ TensorFlow แบบดิบได้เท่านั้น คุณยังสามารถสร้างความแตกต่างในการทำงานกับการสร้างความแตกต่างอัตโนมัติระดับเฟิร์สคลาสของ Swift ได้อีกด้วย

หากต้องการทำให้ .* สามารถหาอนุพันธ์ได้ ให้ใช้แอตทริบิวต์ @derivative บนฟังก์ชันอนุพันธ์ และระบุฟังก์ชันดั้งเดิมเป็นอาร์กิวเมนต์แอตทริบิวต์ภายใต้ป้ายกำกับ of: เนื่องจากตัวดำเนินการ .* ถูกกำหนดไว้เมื่อ Scalar ประเภททั่วไปสอดคล้องกับ Numeric จึงไม่เพียงพอสำหรับการทำให้ Tensor<Scalar> สอดคล้องกับโปรโตคอล Differentiable Swift จะเตือนให้เราเพิ่มข้อจำกัดทั่วไปในแอตทริบิวต์ @differentiable เพื่อกำหนดให้ Scalar สอดคล้องกับโปรโตคอล TensorFlowFloatingPoint ซึ่งจะทำให้ Tensor<Scalar> สอดคล้องกับ 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)

ตัวอย่างเพิ่มเติม

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]]