بناءً على 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]]