Weka算法Classifier-tree-J48源码分析(二)ClassifierTree

本文详细探讨了Weka的ClassifierTree和C45PruneableClassifierTree的实现,包括如何处理缺失值、离散化连续值和剪枝策略。通过对`BuildClassifier`方法的分析,揭示了分类树构建过程中的关键步骤,如`buildTree`、`collapse`和`prune`函数。同时,文章解答了如何控制分类树精度及分类树剪枝的依据。


一、问题

主要带着四个问题去研究J48的实现。

1、如何控制分类树的精度。

2、如何处理缺失的值(MissingValue)

3、如何对连续值进行离散化。

4、如何进行分类树的剪枝。


二、BuildClassifier

每一个分类器都会实现这个方法,传入一个Instances对象,在这个对象基础上进行来构建分类树。核心代码如下:

public void buildClassifier(Instances instances) 
       throws Exception {

    ModelSelection modSelection;	 

    if (m_binarySplits)
      modSelection = new BinC45ModelSelection(m_minNumObj, instances);
    else
      modSelection = new C45ModelSelection(m_minNumObj, instances);
    if (!m_reducedErrorPruning)
      m_root = new C45PruneableClassifierTree(modSelection, !m_unpruned, m_CF,
					    m_subtreeRaising, !m_noCleanup);
    else
      m_root = new PruneableClassifierTree(modSelection, !m_unpruned, m_numFolds,
					   !m_noCleanup, m_Seed);
    m_root.buildClassifier(instances);
    if (m_binarySplits) {
      ((BinC45ModelSelection)modSelection).cleanup();
    } else {
      ((C45ModelSelection)modSelection).cleanup();
    }
  }
可以看到这段代码逻辑非常清楚,首先根据是否是一个二分树(即每个节点只有是否两种选择)来构造一个ModelSelection,随后根据是否有m_reduceErrorPruning标志来构造相应的ClassifierTree,在这个tree上真正的构建模型,最后清理数据(主要是做释放指针的工作,防止Tree持有Instances指针导致GC不能在上层调用者想释放Instances的时候进行释放)。


三、C45PruneableClassifierTree

(1)该类也实现了BuildCClassifier方法来构建分类器,先看一下这个方法的主逻辑,代码如下:

  public void buildClassifier(Instances data) throws Exception {

    // can classifier tree handle the data?
    getCapabilities().testWithFail(data);

    // remove instances with missing class
    data = new Instances(data);
    data.deleteWithMissingClass();
    
   buildTree(data, m_subtreeRaising || !m_cleanup);
   collapse();
   if (m_pruneTheTree) {
     prune();
   }
   if (m_cleanup) {
     cleanup(new Instances(data, 0));
   }
  }
首先testWithFail是检测一下传入的data是否能用该分类器进行分类,比如C45只能对要分类的属性的取值是离散值的Instance
WEKA(Waikato Environment for Knowledge Analysis)是一款广泛用于数据挖掘任务的开源软件。当处理超大数据集时,可采用以下方法: ### 流式学习 WEKA支持流式学习算法,这些算法可以一次处理一个或一批数据实例,而不是将整个数据集加载到内存中。例如,使用 Hoeffding 树(HoeffdingTree)等增量式分类器,它们可以在数据不断流入时进行实时学习和分类。以下是使用 WEKA API 进行流式学习的简单示例代码: ```java import weka.classifiers.trees.HoeffdingTree; import weka.core.Instances; import weka.core.converters.ConverterUtils.DataSource; public class StreamingLearningExample { public static void main(String[] args) throws Exception { // 加载数据集 DataSource source = new DataSource("your_large_dataset.arff"); Instances data = source.getDataSet(); if (data.classIndex() == -1) { data.setClassIndex(data.numAttributes() - 1); } // 创建 Hoeffding 树分类器 HoeffdingTree tree = new HoeffdingTree(); // 进行流式学习 for (int i = 0; i < data.numInstances(); i++) { tree.updateClassifier(data.instance(i)); } // 可以进行预测等操作 } } ``` ### 数据采样 如果数据集过大无法全部加载到内存中,可以对数据进行采样。WEKA 提供了多种采样方法,如随机采样(Random Sampling)、分层采样(Stratified Sampling)等。可以使用 `weka.filters.supervised.instance.Resample` 过滤器进行采样。以下是使用 Java 代码进行随机采样的示例: ```java import weka.core.Instances; import weka.core.converters.ConverterUtils.DataSource; import weka.filters.supervised.instance.Resample; public class DataSamplingExample { public static void main(String[] args) throws Exception { // 加载数据集 DataSource source = new DataSource("your_large_dataset.arff"); Instances data = source.getDataSet(); if (data.classIndex() == -1) { data.setClassIndex(data.numAttributes() - 1); } // 创建采样过滤器 Resample resample = new Resample(); resample.setSampleSizePercent(10); // 采样 10% 的数据 resample.setInputFormat(data); // 应用过滤器进行采样 Instances sampledData = weka.filters.Filter.useFilter(data, resample); // 可以对采样后的数据进行分析 } } ``` ### 分布式计算 可以将 WEKA 与分布式计算框架(如 Apache Hadoop、Apache Spark)结合使用,以处理超大数据集。例如,使用 Spark-WEKA 集成,将数据分布在多个节点上进行并行处理。以下是一个简单的 Spark-WEKA 集成示例: ```python from pyspark import SparkContext from pyspark.sql import SparkSession from weka.core.converters import Loader from weka.classifiers import Classifier # 创建 Spark 上下文和会话 sc = SparkContext("local", "WEKA on Spark") spark = SparkSession.builder.appName("WEKA on Spark").getOrCreate() # 加载数据集 loader = Loader(classname="weka.core.converters.ArffLoader") data = loader.load_file("your_large_dataset.arff") data.class_is_last() # 创建 WEKA 分类器 classifier = Classifier(classname="weka.classifiers.trees.J48") # 将数据转换为 RDD 并进行分布式处理 rdd = sc.parallelize(data.to_instances().to_list()) # 可以进行分布式训练和预测等操作 # 停止 Spark 上下文 sc.stop() ``` ### 内存管理 合理配置 WEKA 的内存使用,通过调整 Java 虚拟机(JVM)的堆内存大小来避免内存溢出。可以在启动 WEKA 时使用 `-Xmx` 参数指定最大堆内存大小,例如: ```sh java -Xmx4g -jar weka.jar ``` 上述代码将 WEKA 的最大堆内存设置为 4GB。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值