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
tfm
to itemitem
. Implemented methods can of course dispatch on the type ofitem
.randstate
encapsulates the random state needed for stochastic transformations. Theapply
method implementation itself should be deterministic.You may dispatch on a specific item type
I
or use the abstractItem
if 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
apply
that mutatesbufitem
. If not implemented, falls back to regularapply
.DataAugmentation.compose
(tfm1, tfm2)
for custom composition with other transformationsComposes transformations. By default, returns a
Sequence
transformation 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
end
The 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_)
end
The 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
end
Finally, a MapElem
can also be composed nicely with other MapElem
s. Instead of applying them sequentially, the functions are fused and applied once.
compose(tfm1::MapElem, tfm2::MapElem2) = MapElem(tfm2.f ∘ tfm1.f)