# Two-level operators¶

Training WOperators with large windows requires big training sets to avoid overfitting. Two-level operators mitigate this problem by combining the output of many individual WOperators into a second level pattern, which is then classified again to obtain the final pixel value. The resulting operator uses, indirectly, information from the union the windows of all operators combined. More information about two level operators can be found at Nina S. T. Hirata, “Multilevel Training of Binary Morphological Operators” at IEEE Transactions on Pattern Analysis and Machine Intelligence, 2009.

In TRIOSlib two-level operators can be implemented using the CombinationPattern Feature Extractors. This class receives as input a set of WOperators and assembles the second level pattern with their outputs. In the example below we combine windows generated randomly, but more interesting and powerful combination methods are available in the literature.

from trios.classifiers import SKClassifier
from sklearn.tree import DecisionTreeClassifier
from trios.feature_extractors import RAWFeatureExtractor, CombinationPattern
import trios
import numpy as np

import trios.shortcuts.persistence as p
import trios.shortcuts.window as w

if __name__ == '__main__':
np.random.seed(10)

domain = np.ones((7, 7), np.uint8)
ops = []
for i in range(5):
win = w.random_win(domain, 40, True)
op = trios.WOperator(win, SKClassifier(DecisionTreeClassifier()), RAWFeatureExtractor)
print('Training...', i)
op.train(images)
ops.append(op)

comb = CombinationPattern(*ops)
wop2 = trios.WOperator(comb.window, SKClassifier(DecisionTreeClassifier(), ordered=True), comb, batch=True)
print('Training 2nd level')
wop2.train(images2)

# save trained operator
p.save_gzip(wop2, 'dt-tl-jung.op')
# and load it later