Transformation interface
{style="opacity:60%;"} src/base.jl
The transformation interface is the centrepiece of this library. Beside straightforward transform application it also enables stochasticity, composition and buffering.
A transformation is a type that subtypes Transform. The only required function to implement for your transformation type T is
apply(tfm::T, item::I; randstate)Applies the transformation
tfmto itemitem. Implemented methods can of course dispatch on the type ofitem.randstateencapsulates the random state needed for stochastic transformations. Theapplymethod implementation itself should be deterministic.You may dispatch on a specific item type
Ior use the abstractItemif one implementation works for all item types.
You may additionally also implement:
DataAugmentation.getrandstate(tfm)for stochastic transformationsGenerates random state to be used inside
apply. Callingapply(tfm, item)is equivalent toapply(tfm, item; randstate = getrandstate(tfm)). It defaults tonothing, so we need not implement it for deterministic transformations.apply!(bufitem, tfm::T, item; randstate)to support bufferingBuffered version of
applythat mutatesbufitem. If not implemented, falls back to regularapply.DataAugmentation.compose(tfm1, tfm2)for custom composition with other transformationsComposes transformations. By default, returns a
Sequencetransformation that applies the transformations one after the other.
Example
The implementation of the MapElem transformation illustrates this interface well. It transforms any item with array data by mapping a function over the array's elements, just like Base.map.
struct MapElem <: Transform
f
endThe apply implementation dispatches on DataAugmentation.AbstractArrayItem, an abstract item type for items that wrap arrays. Note that the randstate keyword argument needs to be given even for implementations of deterministic transformations. We also make use of the DataAugmentation.setdata helper to update the item data.
function apply(tfm::MapElem, item::AbstractArrayItem; randstate = nothing)
a = itemdata(item)
a_ = map(tfm.f, a)
return setdata(item, a_)
endThe buffered version applies the function inplace using Base.map!:
function apply!(
bufitem::I,
tfm::MapElem,
item::I;
randstate = nothing) where I <: AbstractArrayItem
map!(tfm.f, itemdata(bufitem), itemdata(item))
return bufitem
endFinally, a MapElem can also be composed nicely with other MapElems. Instead of applying them sequentially, the functions are fused and applied once.
compose(tfm1::MapElem, tfm2::MapElem2) = MapElem(tfm2.f ∘ tfm1.f)