Weka bridge for TuiML.
Importing this package registers the wrapped Weka learners into the TuiML hub under weka. keys, so they never collide with the native TuiML algorithms of the same name — "J48" is not a native TuiML key, but "RandomForest" would collide without the namespace.
The wrapper modules mirror Weka's own taxonomy rather than TuiML's, so a learner sits where a Weka user expects to find it:
trees — J48, REPTree, RandomTree, RandomForest, LMT, M5P.
rules — ZeroR, OneR, JRip, PART, DecisionTable, M5Rules.
lazy — IBk, KStar, LWL.
functions — SMO, SMOreg, Logistic, LinearRegression, MLP.
bayes — NaiveBayes, NaiveBayesMultinomial, BayesNet.
meta — AdaBoostM1, Bagging, Vote, Stacking, and friends.
clusterers — SimpleKMeans, EM, Canopy, Cobweb.
Weka is an optional dependency, and it needs a Java runtime (11+) on PATH as well, because Weka runs on the JVM:
java -version # must succeed first pip install 'tuiml[weka]' # or: uv pip install 'tuiml[weka]'
If it is not installed, importing this package still succeeds (the wrapper classes are defined and registered), but calling fit raises a clear ImportError pointing at the extra.
The wrappers take and return numpy arrays like any other TuiML algorithm:
>>> from tuiml.weka import J48
>>> from tuiml.datasets import load_iris
>>> data = load_iris()
>>> clf = J48(confidence_factor=0.25).fit(data.X, data.y)
>>> clf.predict(data.X[:3]).shape
(3,)
They are also addressable by hub key, as "weka.<ClassName>", which is the
form train and an agent over MCP both use:
>>> import tuiml
>>> import tuiml.weka # registers the weka.* keys
>>> model = tuiml.train({
... "model": {"name": "weka.J48"},
... "data": {"source": "iris", "target": "class"},
... "evaluation": {"test_size": 0.3},
... })
>>> "accuracy_score" in model.metrics_
True
Weka distinguishes nominal from numeric attributes in its ARFF header, and its tree and rule learners use genuinely different logic for the two. TuiML passes plain numeric arrays, so declare which columns hold category codes:
>>> from tuiml.weka import J48 >>> clf = J48(nominal_features=[0, 3]) # columns 0 and 3 are categorical
Left undeclared, a categorical column is treated as a continuous scale, and Weka will split it with <= tests that imply an order the codes do not have.
Every wrapper exposes Weka's own model dump, which is often the reason to reach for Weka rather than a native implementation:
>>> print(clf.fit(data.X, data.y).to_weka_string()) # doctest: +SKIP
The JVM starts lazily on the first fit and is never stopped, because JPype cannot restart one inside the same process. To choose a heap size, call ensure_jvm before the first fit:
>>> from tuiml.weka import ensure_jvm >>> ensure_jvm(max_heap_size="4096m") # doctest: +SKIP
Weka Bayesian classifier wrappers....
Weka clusterer wrappers....
Weka function-based learner wrappers....
Weka instance-based (lazy) learner wrappers....
Weka meta-learner wrappers....
Weka rule-learner wrappers....
Weka tree wrappers....