Visualizza su TensorFlow.org | Visualizza la fonte su GitHub |
Basandosi su TensorFlow, Swift per TensorFlow adotta un nuovo approccio alla progettazione delle API. Le API sono attentamente curate da librerie consolidate e combinate con nuovi idiomi linguistici. Ciò significa che non tutte le API TensorFlow saranno direttamente disponibili come API Swift e la nostra gestione delle API richiede tempo e impegno dedicato per evolversi. Tuttavia, non preoccuparti se il tuo operatore TensorFlow preferito non è disponibile in Swift: la libreria TensorFlow Swift ti offre accesso trasparente alla maggior parte degli operatori TensorFlow, nello spazio dei nomi _Raw
.
Importa TensorFlow
per iniziare.
import TensorFlow
Chiamare gli operatori grezzi
Trova semplicemente la funzione che ti serve nello spazio dei nomi _Raw
tramite il completamento del codice.
print(_Raw.mul(Tensor([2.0, 3.0]), Tensor([5.0, 6.0])))
[10.0, 18.0]
Definizione di un nuovo operatore di moltiplicazione
Multiply è già disponibile come operatore *
su Tensor
, ma facciamo finta di volerlo rendere disponibile con un nuovo nome come .*
. Swift ti consente di aggiungere retroattivamente metodi o proprietà calcolate ai tipi esistenti utilizzando dichiarazioni extension
.
Ora aggiungiamo .*
a Tensor
dichiarando un'estensione e rendiamola disponibile quando il tipo Scalar
del tensore è conforme a 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]]
Definizione di una derivata di una funzione incapsulata
Non solo puoi definire facilmente un'API Swift per un operatore TensorFlow grezzo, ma puoi anche renderla differenziabile per lavorare con la differenziazione automatica di prima classe di Swift.
Per rendere .*
differenziabile, utilizzare l'attributo @derivative
sulla funzione derivativa e specificare la funzione originale come argomento di attributo sotto l'etichetta of:
Poiché l'operatore .*
è definito quando il tipo generico Scalar
è conforme a Numeric
, non è sufficiente per rendere Tensor<Scalar>
conforme al protocollo Differentiable
. Nato con l'indipendenza dal tipo, Swift ci ricorderà di aggiungere un vincolo generico sull'attributo @differentiable
per richiedere Scalar
di conformarsi al protocollo TensorFlowFloatingPoint
, che renderebbe Tensor<Scalar>
conforme a 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)
Altri esempi
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]]