مشغلي TensorFlow الخام

عرض على TensorFlow.org عرض المصدر على جيثب

بناءً على TensorFlow، يتبع Swift for TensorFlow منهجًا جديدًا لتصميم واجهة برمجة التطبيقات (API). يتم تنسيق واجهات برمجة التطبيقات بعناية من المكتبات القائمة ودمجها مع المصطلحات اللغوية الجديدة. وهذا يعني أنه لن تكون جميع واجهات برمجة تطبيقات TensorFlow متاحة بشكل مباشر كواجهات برمجة تطبيقات Swift، ويحتاج تنظيم واجهة برمجة التطبيقات لدينا إلى وقت وجهد مخصص للتطور. ومع ذلك، لا تقلق إذا لم يكن مشغل 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]

تحديد عامل الضرب الجديد

الضرب متاح بالفعل كعامل * على 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]]