Search code examples
pythonwekaimplementation

Is there any way to use ADTrees on python with PYWEKA?


Hi guys I have this question because im trying to use ADTrees of weka on python using pyweka like this:

cls = Classifier(classname="weka.classifiers.trees.adtree", options=["-B", "10", "-E", "-3", "-S", "1"])
cls.build_classifier(data_modelos_1_2_csv)

but it reach this error:

Failed to instantiate weka.classifiers.trees.adtree: weka.classifiers.trees.adtree

Exception in thread "Thread-0" java.lang.ClassNotFoundException: weka.classifiers.trees.adtree
    java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
    java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    java.base/java.lang.Class.forName0(Native Method)
    java.base/java.lang.Class.forName(Class.java:398)
    weka.core.WekaPackageClassLoaderManager.forName(WekaPackageClassLoaderManager.java:198)
    weka.core.WekaPackageClassLoaderManager.forName(WekaPackageClassLoaderManager.java:178)
    weka.core.ResourceUtils.forName(ResourceUtils.java:80)
    weka.core.Utils.forName(Utils.java:1112)

    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:398)
    at weka.core.WekaPackageClassLoaderManager.forName(WekaPackageClassLoaderManager.java:198)
    at weka.core.WekaPackageClassLoaderManager.forName(WekaPackageClassLoaderManager.java:178)
    at weka.core.ResourceUtils.forName(ResourceUtils.java:80)
    at weka.core.Utils.forName(Utils.java:1112)

And this is the traceback:

AssertionError                            Traceback (most recent call last)
/tmp/ipykernel_6468/746392926.py in <module>
      1 #from weka.classifiers import alternatingDecisionTrees
      2 
----> 3 cls = Classifier(classname="weka.classifiers.trees.adtree", options=["-B", "10", "-E", "-3", "-S", "1"])
      4 cls.build_classifier(data_modelos_1_2_csv)

/usr/local/lib/python3.8/dist-packages/weka/classifiers.py in __init__(self, classname, jobject, options)
     56         if jobject is None:
     57             jobject = Classifier.new_instance(classname)
---> 58         self.enforce_type(jobject, "weka.classifiers.Classifier")
     59         self.is_updateable = self.check_type(jobject, "weka.classifiers.UpdateableClassifier")
     60         self.is_drawable = self.check_type(jobject, "weka.core.Drawable")

/usr/local/lib/python3.8/dist-packages/weka/core/classes.py in enforce_type(cls, jobject, intf_or_class)
    867         :type intf_or_class: str
    868         """
--> 869         if not cls.check_type(jobject, intf_or_class):
    870             raise TypeError("Object does not implement or subclass " + intf_or_class + ": " + get_classname(jobject))
    871 

/usr/local/lib/python3.8/dist-packages/weka/core/classes.py in check_type(cls, jobject, intf_or_class)
    855         :rtype: bool
    856         """
--> 857         return is_instance_of(jobject, intf_or_class)
    858 
    859     @classmethod

/usr/local/lib/python3.8/dist-packages/weka/core/classes.py in is_instance_of(obj, class_or_intf_name)
    283     classname = get_classname(obj)
    284     # array? retrieve component type and check that
--> 285     if is_array(obj):
    286         jarray = JavaArray(jobject=obj)
    287         classname = jarray.component_type()

/usr/local/lib/python3.8/dist-packages/weka/core/classes.py in is_array(obj)
    307     :rtype: bool
    308     """
--> 309     cls = javabridge.call(obj, "getClass", "()Ljava/lang/Class;")
    310     return javabridge.call(cls, "isArray", "()Z")
    311 

~/.local/lib/python3.8/site-packages/javabridge/jutil.py in call(o, method_name, sig, *args)
    886     '''
    887     env = get_env()
--> 888     fn = make_call(o, method_name, sig)
    889     args_sig = split_sig(sig[1:sig.find(')')])
    890     ret_sig = sig[sig.find(')')+1:]

~/.local/lib/python3.8/site-packages/javabridge/jutil.py in make_call(o, method_name, sig)
    834 
    835     '''
--> 836     assert o is not None
    837     env = get_env()
    838     if isinstance(o, basestring):

AssertionError: 

So I don't know if exist any way to use this ADTrees on Python.

I tried with "weka.classifiers.trees.adtree", "weka.classifiers.trees.ADTree", using the imports

from weka.classifiers import alternatingDecisionTrees
from weka.classifiers import ADTree
from weka.classifiers import ADTrees
from weka.classifiers import adtree
from weka.classifiers import adtrees

Don't know what more to do.


Solution

  • python-weka-wrapper3, as the name suggests, is a light-weight wrapper around Weka classes. However, it mostly only wraps abstract superclasses, not all of the thousands of classes that make up Weka.

    The weka.classifiers.Classifier class is the wrapper to use for classifiers and you need to specify the Java classname of the actual classifier that you want to wrap (in your case weka.classifiers.trees.ADTree). And, yes, just like Python, Java is also case sensitive.

    Furthermore, if you require classes from packages, then you need to start the JVM with package support (default is no package support).

    Below is an example that outputs the command-line of ADTree with its default parameters. If necessary, it installs the package first.

    import sys
    import weka.core.jvm as jvm
    from weka.core.packages import is_installed, install_package
    from weka.classifiers import Classifier
    
    jvm.start(packages=True)
    
    pkgname = "alternatingDecisionTrees"
    if not is_installed(pkgname):
        print("Package %s not installed, attempting installation..." % pkgname)
        if install_package(pkgname):
            print("Package %s installed, please rerun script!" % pkgname)
        else:
            print("Failed to install package %s!" % pkgname)
        jvm.stop()
        sys.exit(1)
    
    cls = Classifier(classname="weka.classifiers.trees.ADTree", options=[])
    print(cls.to_commandline())
    
    jvm.stop()