(∷ 1+ (0 . 0))
(cudefine (1+ x) (guile:1+ x))
-(definec (identity x) x)
-(definec (∘ g f) (λc x (g (f x))))
-(definec (⊙ f g) (∘ g f))
-(definec (flip f) (λc y (λc x (f x y))))
-
(∷ adot (0 . (0 . (0 . 0))))
(cudefine (adot x y n) (v:adot x y n))
(∷ rdiff ((0 . 0) . (0 . 0)))
(cudefine (rdiff x) (v:rdiff x))
+
+(definec (identity x) x)
+(definec (∘ g f) (λc x (g (f x))))
+(definec (⊙ f g) (∘ g f))
+(definec (flip f) (λc y (λc x (f x y))))
relu
sum)
#:replace
- ((i:sqrt . sqrt)
- (i:exp . exp)
- (i:expt . expt)
- (i:log . log)
- (i:sin . sin)
- (i:cos . cos)
- (i:tan . tan)
+ ((i:* . *)
(i:+ . +)
(i:- . -)
- (i:* . *)
(i:/ . /)
- (i:max . max)
- (i:min . min)
(i:abs . abs)
- (i:identity . identity)
+ (i:array-cell-ref . array-cell-ref)
(i:array-ref . array-ref)
- (i:array-cell-ref . array-cell-ref))
- #:re-export
- (fold
- reduce))
+ (i:cos . cos)
+ (i:exp . exp)
+ (i:expt . expt)
+ (i:fold . fold)
+ (i:identity . identity)
+ (i:log . log)
+ (i:max . max)
+ (i:min . min)
+ (i:reduce . reduce)
+ (i:sin . sin)
+ (i:sqrt . sqrt)
+ (i:tan . tan)))
;;;; array utilities
(apply generator xs j i data)))
(define* (fdiff f #:optional (axis 0))
+ "Automatic differentiation in forward accumulation mode w.r.t. the
+function argument at the given index."
(lambda xs
(parameterize (((@@ (vouivre autodiff) *differentiation-mode*) 'fwd)
((@@ (vouivre autodiff) *promises*) (cons '() #f)))
a)))))))
(define* (rdiff f #:optional (axis 0))
+ "Automatic differentiation in reverse accumulation mode w.r.t. the
+function argument at the given index."
(lambda xs
(parameterize (((@@ (vouivre autodiff) *differentiation-mode*) 'rev)
((@@ (vouivre autodiff) *promises*) (cons '() #f)))
;; the head of which is as described above and the remaining elements
;; are procedures of the same arguments but returning values that are
;; then fed as extra data to the generators.
-;;
-;; NOTE: In cases where an argument isn't meant to be differentiable its
-;; corresponding generator should be `#f'.
(define (differentiable-wrapper generators proc* arg . more)
+ "Helper for defining differentiable functions.
+
+generators: A list of generating procedures that, take the given arguments
+ along with an absolute input index, an absolute output index,
+ and zero or more data points, to produce a corresponding jacobian
+ element.
+
+proc*: A list containing the function to be differentiated and zero or
+ more procedures that also take the given arguments to create,
+ in the forward pass, the data points that are latter fed to the
+ generators.
+
+arg . more: The arguments to all these procedures.
+
+NOTE: In cases where an argument isn't meant to be differentiated against, its
+ corresponding generator should be `#f'."
(define (precompute-data naked-args)
(if (procedure? proc*)
'()
'zero generators args)))))))
(define (ewise1 f)
+ "Helper for creating the jacobian generator of one argument functions created
+with the `extend' procedure."
(lambda (xs i j)
(let ((x (car xs)))
(if (number? x)
j)))))))
(define (ewise2 proc axis)
+ "Helper for creating the jacobian generators of two argument functions created
+with the `extend' procedure."
(lambda (xs i j)
(let ((x (car xs))
(y (cadr xs)))
"Differentiable RealSoftMax using the log-sum-exp trick."
(let ((c (maximum x)))
(i:+ c (i:log (sum (i:exp (i:- x c)))))))
+
+(define (i:fold f init lst . more)
+ "Differentiable fold of a differentiable function."
+ (apply fold f init lst more))
+
+(define (i:reduce f default lst)
+ "Differentiable reduce of a differentiable function."
+ (reduce f default lst))