Model nodes

Index

API

Mill.ArrayModelType
ArrayModel{T} <: AbstractMillModel

A model node for processing ArrayNodes. It applies a (sub)model m stored in it to data in an ArrayNode.

Examples

julia> Random.seed!(0);
julia> n = ArrayNode(randn(Float32, 2, 2))
2×2 ArrayNode{Matrix{Float32}, Nothing}:
 0.94... 1.53...
 0.13... 0.12...
julia> m = ArrayModel(Dense(2, 2))
ArrayModel(Dense(2 => 2))  2 arrays, 6 params, 112 bytes
julia> m(n)
2×2 Matrix{Float32}:
 -0.50... -0.77...
  0.25...  0.49...

See also: AbstractMillModel, ArrayNode.

source
Mill.BagModelType
BagModel{T <: AbstractMillModel, A <: Union{AbstractAggregation, BagCount}, U}
    <: AbstractMillModel

A model node for processing AbstractBagNodes. It first applies its "instance (sub)model" im on every instance, then performs elementwise segmented aggregation a and finally applies the final model bm on the aggregated representation of every bag in the data node.

Examples

julia> Random.seed!(0);

julia> n = BagNode(ArrayNode(randn(Float32, 3, 2)), bags([0:-1, 1:2]))
BagNode  2 obs
  ╰── ArrayNode(3×2 Array with Float32 elements)  2 obs

julia> m = BagModel(ArrayModel(Dense(3, 2)), SegmentedMeanMax(2), Dense(4, 2))
BagModel ↦ [SegmentedMean(2); SegmentedMax(2)] ↦ Dense(4 => 2)  4 arrays, 14 params, 224 bytes
  ╰── ArrayModel(Dense(3 => 2))  2 arrays, 8 params, 120 bytes

julia> m(n)
2×2 Matrix{Float32}:
 0.0  1.05...
 0.0  0.49...

julia> m(n) == m.bm(m.a(m.im(n.data), n.bags))
true

See also: AbstractMillModel, AbstractAggregation, AbstractBagNode, BagNode, WeightedBagNode.

source
Mill.BagModelMethod
BagModel(im, a, bm=identity)

Construct a BagModel from the arguments. im should be AbstractMillModel, a AbstractAggregation or BagCount, and bm ArrayModel.

It is also possible to pass any function as im instead of a model node. In that case, it is wrapped into an ArrayNode.

Examples

julia> m = BagModel(ArrayModel(Dense(3, 2)), SegmentedMeanMax(2), Dense(4, 2))
BagModel ↦ [SegmentedMean(2); SegmentedMax(2)] ↦ Dense(4 => 2)  4 arrays, 14 params, 224 bytes
  ╰── ArrayModel(Dense(3 => 2))  2 arrays, 8 params, 120 bytes

julia> m = BagModel(Dense(4, 3), BagCount(SegmentedMean(3)))
BagModel ↦ BagCount(SegmentedMean(3)) ↦ identity  1 arrays, 3 params (all zero), 52 bytes
  ╰── ArrayModel(Dense(4 => 3))  2 arrays, 15 params, 148 bytes

See also: AbstractMillModel, AbstractAggregation, BagCount, AbstractBagNode, BagNode, WeightedBagNode.

source
Mill.ProductModelType
ProductModel{T <: Mill.VecOrTupOrNTup{<:AbstractMillModel}, U} <: AbstractMillModel

A model node for processing ProductNodes. For each subtree of the data node it applies one (sub)model from ms and then applies m on the concatenation of results.

Examples

julia> Random.seed!(0);

julia> n = ProductNode(a=ArrayNode([0 1; 2 3]), b=ArrayNode([4 5; 6 7]))
ProductNode  2 obs
  ├── a: ArrayNode(2×2 Array with Int64 elements)  2 obs
  ╰── b: ArrayNode(2×2 Array with Int64 elements)  2 obs

julia> m1 = ProductModel(a=ArrayModel(Dense(2, 2)), b=ArrayModel(Dense(2, 2)))
ProductModel ↦ identity
  ├── a: ArrayModel(Dense(2 => 2))  2 arrays, 6 params, 112 bytes
  ╰── b: ArrayModel(Dense(2 => 2))  2 arrays, 6 params, 112 bytes
julia> m1(n)
4×2 Matrix{Float32}:
 -2.36...  -3.58...
 -2.11...  -3.40...
 -6.31...  -7.61...
 -2.54...  -2.66...
julia> m2 = ProductModel(a=identity, b=identity)
ProductModel ↦ identity
  ├── a: ArrayModel(identity)
  ╰── b: ArrayModel(identity)

julia> m2(n)
4×2 Matrix{Int64}:
 0  1
 2  3
 4  5
 6  7

See also: AbstractMillModel, AbstractProductNode, ProductNode.

source
Mill.ProductModelMethod
ProductModel(ms, m=identity)
ProductModel(m=identity; ms...)

Construct a ProductModel from the arguments. ms should an iterable (Tuple, NamedTuple or Vector) of one or more AbstractMillModels.

It is also possible to pass any function as elements of ms. In that case, it is wrapped into an ArrayNode.

Examples

julia> ProductModel(a=ArrayModel(Dense(2, 2)), b=identity)
ProductModel ↦ identity
  ├── a: ArrayModel(Dense(2 => 2))  2 arrays, 6 params, 112 bytes
  ╰── b: ArrayModel(identity)

julia> ProductModel(Dense(4, 2); a=ArrayModel(Dense(2, 2)), b=Dense(2, 2))
ProductModel ↦ Dense(4 => 2)  2 arrays, 10 params, 128 bytes
  ├── a: ArrayModel(Dense(2 => 2))  2 arrays, 6 params, 112 bytes
  ╰── b: ArrayModel(Dense(2 => 2))  2 arrays, 6 params, 112 bytes

julia> ProductModel((identity, BagModel(ArrayModel(Dense(2, 2)), SegmentedMean(2), identity)))
ProductModel ↦ identity
  ├── ArrayModel(identity)
  ╰── BagModel ↦ SegmentedMean(2) ↦ identity  1 arrays, 2 params (all zero), 48 bytes
        ╰── ArrayModel(Dense(2 => 2))  2 arrays, 6 params, 112 bytes

julia> ProductModel(identity)
ProductModel ↦ identity
  ╰── ArrayModel(identity)

See also: AbstractMillModel, AbstractProductNode, ProductNode.

source
Mill.LazyModelType
LazyModel{Name, T} <: AbstractMillModel

A model node for processing LazyNodes. It applies a (sub)model m stored in it to data of the LazyNode after calling Mill.unpack2mill.

Examples

julia> function Mill.unpack2mill(ds::LazyNode{:Sentence})
    s = split.(ds.data, " ")
    x = NGramMatrix(reduce(vcat, s))
    BagNode(x, Mill.length2bags(length.(s)))
end
julia> Random.seed!(0);

julia> n = LazyNode{:Sentence}(["foo", "bar", "baz"])
LazyNode{:Sentence, Vector{String}, Nothing}:
 "foo"
 "bar"
 "baz"

julia> m = LazyModel{:Sentence}(BagModel(Dense(2053, 3), SegmentedMean(3), identity))
LazyModel{Sentence}
  ╰── BagModel ↦ SegmentedMean(3) ↦ identity  1 arrays, 3 params (all zero), 52 bytes
        ╰── ArrayModel(Dense(2053 => 3))  2 arrays, 6_162 params, 24.156 KiB
julia> m(n)
3×3 Matrix{Float32}:
 -0.06... -0.03... -0.04...
  0.02...  0.00... -0.07...
 -0.00...  0.06... -0.07...

See also: AbstractMillModel, LazyNode, Mill.unpack2mill.

source
Mill.LazyModelMethod
LazyModel([Name::Symbol], m::AbstractMillModel)
LazyModel{Name}(m::AbstractMillModel)

Construct a new LazyModel with name Name, and model m.

It is also possible to pass any function as m instead of a model node. In that case, it is wrapped into an ArrayNode.

Examples

julia> LazyModel{:Sentence}(ArrayModel(Dense(2, 2)))
LazyModel{Sentence}
  ╰── ArrayModel(Dense(2 => 2))  2 arrays, 6 params, 112 bytes

julia> LazyModel(:Sentence, Dense(2, 2))
LazyModel{Sentence}
  ╰── ArrayModel(Dense(2 => 2))  2 arrays, 6 params, 112 bytes

See also: AbstractMillModel, LazyNode, Mill.unpack2mill.

source
Mill.reflectinmodelFunction
reflectinmodel(x::AbstractMillNode, fm=d -> Dense(d, 10), fa=BagCount ∘ SegmentedMeanMax;
    fsm=Dict(), fsa=Dict(), single_key_identity=true, single_scalar_identity=true, all_imputing=false)

Build a Mill.jl model capable of processing x.

All inner Dense layers are constructed using fm, a function accepting input dimension d and returning a suitable model. All aggregation operators are constructed using fa in a similar manner.

More fine-grained control can be achieved with fsm and fsa keyword arguments, which should be Dicts of c => f pairs, where c is a String traversal code from HierarchicalUtils.jl and f is a function. These definitions override fm and fa.

If a ProductNode with only a single child (subtree) is encountered, its final m model is instantiated as identity instead of using fm and fsm. This can be controlled with single_key_identity.

Similarly, if an ArrayNode contains data X where size(X, 1) is 1, the corresponding model is instantiated as identity unless single_scalar_identity is false.

By default, reflectinmodel makes first Dense layers in leafs imputing only if the datatype suggests that missing data is present. This applies to

types with eltype of {Union{Missing, T}} where T. If all_imputing is true, all leaf Dense layers in these types are replaced by their imputing variants.

Examples

julia> n1 = ProductNode(a=ArrayNode(NGramMatrix(["a", missing])))
ProductNode  2 obs
  ╰── a: ArrayNode(2053×2 NGramMatrix with Union{Missing, Int64} elements)  2 obs

julia> n2 = ProductNode((ArrayNode([0 1]), BagNode(ArrayNode([0 1; 2 3]), bags([1:1, 2:2]))))
ProductNode  2 obs
  ├── ArrayNode(1×2 Array with Int64 elements)  2 obs
  ╰── BagNode  2 obs
        ╰── ArrayNode(2×2 Array with Int64 elements)  2 obs

julia> n = ProductNode((n1, n2))
ProductNode  2 obs
  ├── ProductNode  2 obs
  │     ╰── a: ArrayNode(2053×2 NGramMatrix with Union{Missing, Int64} elements)  2 obs
  ╰── ProductNode  2 obs
        ├── ArrayNode(1×2 Array with Int64 elements)  2 obs
        ╰── BagNode  2 obs
              ╰── ArrayNode(2×2 Array with Int64 elements)  2 obs

julia> reflectinmodel(n)
ProductModel ↦ Dense(20 => 10)  2 arrays, 210 params, 928 bytes
  ├── ProductModel ↦ identity
  │     ╰── a: ArrayModel([postimputing]Dense(2053 => 10))  3 arrays, 20_550 params, 80.398 KiB
  ╰── ProductModel ↦ Dense(11 => 10)  2 arrays, 120 params, 568 bytes
        ├── ArrayModel(identity)
        ╰── BagModel ↦ BagCount([SegmentedMean(10); SegmentedMax(10)]) ↦ Dense(21 => 10)  4 arrays, 240 params, 1.102 KiB
              ╰── ArrayModel(Dense(2 => 10))  2 arrays, 30 params, 208 bytes

julia> reflectinmodel(n, d -> Dense(d, 3), SegmentedMean, all_imputing=true)
ProductModel ↦ Dense(6 => 3)  2 arrays, 21 params, 172 bytes
  ├── ProductModel ↦ identity
  │     ╰── a: ArrayModel([postimputing]Dense(2053 => 3))  3 arrays, 6_165 params, 24.207 KiB
  ╰── ProductModel ↦ Dense(4 => 3)  2 arrays, 15 params, 148 bytes
        ├── ArrayModel([preimputing]Dense(1 => 1))  3 arrays, 3 params, 140 bytes
        ╰── BagModel ↦ SegmentedMean(3) ↦ Dense(3 => 3)  3 arrays, 15 params, 188 bytes
              ╰── ArrayModel([preimputing]Dense(2 => 3))  3 arrays, 11 params, 172 bytes

julia> printtree(n; trav=true)
ProductNode [""]  2 obs
  ├── ProductNode ["E"]  2 obs
  │     ╰── a: ArrayNode(2053×2 NGramMatrix with Union{Missing, Int64} elements) ["M"]  2 obs
  ╰── ProductNode ["U"]  2 obs
        ├── ArrayNode(1×2 Array with Int64 elements) ["Y"]  2 obs
        ╰── BagNode ["c"]  2 obs
              ╰── ArrayNode(2×2 Array with Int64 elements) ["e"]  2 obs

julia> reflectinmodel(n, d -> Dense(d, 3), SegmentedMean;
                        fsm=Dict("e" => d -> Chain(Dense(d, 2), Dense(2, 2))),
                        fsa=Dict("c" => SegmentedLSE),
                        single_key_identity=false,
                        single_scalar_identity=false)
ProductModel ↦ Dense(6 => 3)  2 arrays, 21 params, 172 bytes
  ├── ProductModel ↦ Dense(3 => 3)  2 arrays, 12 params, 136 bytes
  │     ╰── a: ArrayModel([postimputing]Dense(2053 => 3))  3 arrays, 6_165 params, 24.207 KiB
  ╰── ProductModel ↦ Dense(6 => 3)  2 arrays, 21 params, 172 bytes
        ├── ArrayModel(Dense(1 => 3))  2 arrays, 6 params, 112 bytes
        ╰── BagModel ↦ SegmentedLSE(2) ↦ Dense(2 => 3)  4 arrays, 13 params, 220 bytes
              ╰── ArrayModel(Chain(Dense(2 => 2), Dense(2 => 2)))  4 arrays, 12 params, 224 bytes

See also: AbstractMillNode, AbstractMillModel, ProductNode, BagNode, ArrayNode.

source
Mill.modelsummaryFunction
modelsummary(m::AbstractMillModel)

Print summary of parameters of model m.

Examples

julia> m = ProductModel(ArrayModel(Dense(2, 3)))
ProductModel ↦ identity
  ╰── ArrayModel(Dense(2 => 3))  2 arrays, 9 params, 124 bytes

julia> modelsummary(m)
"Model summary: 2 arrays, 9 params, 124 bytes"

See also: datasummary.

source