مشاهده در TensorFlow.org | مشاهده منبع در GitHub |
با تکیه بر TensorFlow، Swift for TensorFlow رویکرد جدیدی به طراحی API دارد. API ها با دقت از کتابخانه های تاسیس شده و با اصطلاحات زبان جدید ترکیب شده اند. این بدان معنی است که همه APIهای TensorFlow مستقیماً به عنوان APIهای Swift در دسترس نخواهند بود و تنظیم 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]]
تعریف یک مشتق از یک تابع پیچیده
نه تنها میتوانید به راحتی یک API Swift را برای یک اپراتور خام TensorFlow تعریف کنید، بلکه میتوانید آن را برای کار با تمایز خودکار درجه یک سوئیفت متمایز کنید.
برای متمایز کردن .*
، از صفت @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]]