Spark-MLlib的快速使用之七(决策树-分类)

(1)数据

1,2011-01-01,1,0,1,0,0,6,0,1,0.24,0.2879,0.81,0,3,13,16

2,2011-01-01,1,0,1,1,0,6,0,1,0.22,0.2727,0.8,0,8,32,40

3,2011-01-01,1,0,1,2,0,6,0,1,0.22,0.2727,0.8,0,5,27,32

含义

instant,dteday,season,yr,mnth,holiday,weekday,workingday,weathersit,temp,atemp,hum,windspeed,casual,registered,cnt

 

(2)代码

 

public class HWDecisionTreeClass {

//【3--15】 为向量

//【16】为特征

private static class ParsePoint implements Function<String, LabeledPoint> {

private static final Pattern SPACE = Pattern.compile(",");

 

@Override

public LabeledPoint call(String line) {

String[] parts = line.split(",");

double[] v = new double[parts.length - 3];

for (int i = 0; i < parts.length - 3; i++)

v[i] = Double.parseDouble(parts[i + 2]);

return new LabeledPoint(Double.parseDouble(parts[16]), Vectors.dense(v));

}

}

 

public static void main(String[] args) {

 

SparkConf sparkConf = new SparkConf().setAppName("JavaDecisionTreeClassificationExample").setMaster("local");

JavaSparkContext jsc = new JavaSparkContext(sparkConf);

 

// 加载与解析数据

String datapath = "hour.txt";

 

JavaRDD<String> lines = jsc.textFile(datapath);

JavaRDD<LabeledPoint> traindata = lines.map(new ParsePoint());

List<LabeledPoint> take = traindata.take(3);

for (LabeledPoint labeledPoint : take) {

System.out.println("----->" + labeledPoint.features());

System.out.println("----->" + labeledPoint.label());

}

// 70%的数据用于训练,30%的数据用于测试

JavaRDD<LabeledPoint>[] splits = traindata.randomSplit(new double[] { 0.9, 0.1 });

// 训练数据

JavaRDD<LabeledPoint> trainingData = splits[0];

// 测试数据

JavaRDD<LabeledPoint> testData = splits[1];

// 设置参数 ,空的categoricalFeaturesInfo表示所有功能都是连续的。

Integer numClasses = 1900;

Map<Integer, Integer> categoricalFeaturesInfo = new HashMap<Integer, Integer>();

String impurity = "gini";

Integer maxDepth = 20;

Integer maxBins = 32;

// 训练DecisionTree模型进行分类。

final DecisionTreeModel model = DecisionTree.trainClassifier(trainingData, numClasses, categoricalFeaturesInfo,

impurity, maxDepth, maxBins);

// 使用模型进程预测,并和实际值比较

JavaPairRDD<Double, Double> predictionAndLabel =

testData.mapToPair(new PairFunction<LabeledPoint, Double, Double>() {

@Override

public Tuple2<Double, Double> call(LabeledPoint p) {

return new Tuple2<Double, Double>(model.predict(p.features()), p.label());

}

});

System.out.println(predictionAndLabel.take(10));

Double testErr = 1.0 * predictionAndLabel.filter(new Function<Tuple2<Double, Double>, Boolean>() {

@Override

public Boolean call(Tuple2<Double, Double> pl) {

return !pl._1().equals(pl._2());

}

}).count() / testData.count();

System.out.println("Test Error: -------------------------------------------------------------------" + testErr);

System.out.println("Learned classification tree model:\n-------------------------------------------"

+ model.toDebugString());

}

}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会尽力回答你的问题。 首先,让我们简单介绍一下ID3决策树分类算法。ID3算法是一种基于信息熵的分类算法,用于从一个给定的数据集构建决策树模型。它的基本思想是通过计算每个特征对数据集的熵值,选择熵值最小的特征作为分类标准,并将数据集分为不同的子集。然后,对每个子集重复上述过程,直到所有的数据都被正确分类或者达到预设的停止条件。 接下来,让我们使用Scala编写一个基于ID3算法的决策树分类器,代码如下: ``` import org.apache.spark.mllib.tree.DecisionTree import org.apache.spark.mllib.tree.model.DecisionTreeModel import org.apache.spark.mllib.util.MLUtils // 定义一个case class,用于存储数据的标签和特征值 case class DataPoint(label: Double, features: Array[Double]) object ID3DecisionTreeClassifier { // 定义一个方法,用于将数据集转换成LabeledPoint类型 def toLabeledPoint(data: DataPoint): org.apache.spark.mllib.regression.LabeledPoint = { org.apache.spark.mllib.regression.LabeledPoint(data.label, org.apache.spark.mllib.linalg.Vectors.dense(data.features)) } // 定义一个方法,用于将LabeledPoint类型的数据集转换成DataPoint类型 def fromLabeledPoint(data: org.apache.spark.mllib.regression.LabeledPoint): DataPoint = { DataPoint(data.label, data.features.toArray) } // 定义一个方法,用于计算数据集的信息熵 def entropy(data: Seq[DataPoint]): Double = { val labels = data.map(_.label) val distinctLabels = labels.distinct val labelCounts = distinctLabels.map(label => labels.count(_ == label)) val probabilities = labelCounts.map(count => count.toDouble / labels.size) probabilities.map(p => -p * math.log(p) / math.log(2)).sum } // 定义一个方法,用于计算给定特征对数据集的信息增益 def informationGain(data: Seq[DataPoint], featureIndex: Int): Double = { val featureValues = data.map(_.features(featureIndex)) val distinctFeatureValues = featureValues.distinct val subsets = distinctFeatureValues.map(value => data.filter(_.features(featureIndex) == value)) val entropyValues = subsets.map(subset => entropy(subset) * subset.size / data.size) entropy(data) - entropyValues.sum } // 定义一个方法,用于选择最佳的特征作为分类标准 def chooseBestFeature(data: Seq[DataPoint], remainingFeatures: Set[Int]): Int = { remainingFeatures.map(featureIndex => (featureIndex, informationGain(data, featureIndex))).maxBy(_._2)._1 } // 定义一个方法,用于构建决策树模型 def buildDecisionTree(data: Seq[DataPoint], remainingFeatures: Set[Int]): DecisionTreeModel = { val labels = data.map(_.label) if (labels.distinct.size == 1) { // 如果所有数据都属于同一类别,则返回一个叶节点 new DecisionTreeModel(1, Array(0.0), Array.empty, Array.empty, Array.empty) } else if (remainingFeatures.isEmpty) { // 如果没有剩余的特征了,则返回一个叶节点,其类别为出现次数最多的类别 val labelCounts = labels.groupBy(identity).mapValues(_.size) val maxLabel = labelCounts.maxBy(_._2)._1 new DecisionTreeModel(1, Array(maxLabel), Array.empty, Array.empty, Array.empty) } else { // 选择最佳的特征作为分类标准 val bestFeature = chooseBestFeature(data, remainingFeatures) val distinctFeatureValues = data.map(_.features(bestFeature)).distinct val subsets = distinctFeatureValues.map(value => data.filter(_.features(bestFeature) == value)) // 递归构建子树 val childTrees = subsets.map(subset => buildDecisionTree(subset, remainingFeatures - bestFeature)) new DecisionTreeModel(1, Array.empty, Array(bestFeature), childTrees.toArray, distinctFeatureValues.toArray) } } // 定义一个方法,用于预测新的数据 def predict(model: DecisionTreeModel, data: DataPoint): Double = { if (model.numNodes == 1) { model.predict(0) } else { val featureIndex = model.split.get.feature val childIndex = model.predict(data.features(featureIndex)) val childModel = model.subtree(childIndex.toInt) predict(childModel, data) } } def main(args: Array[String]): Unit = { // 加载数据集 val data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt").map(point => DataPoint(point.label, point.features.toArray)).collect() // 将数据集转换成LabeledPoint类型 val labeledData = data.map(toLabeledPoint) // 将数据集划分为训练集和测试集 val splits = labeledData.randomSplit(Array(0.7, 0.3)) val (trainingData, testData) = (splits(0), splits(1)) // 构建决策树模型 val model = buildDecisionTree(trainingData.map(fromLabeledPoint), (0 until trainingData.first.features.size).toSet) // 在测试集上测试模型的准确率 val accuracy = testData.map(point => (predict(model, fromLabeledPoint(point)), point.label)).filter(pair => pair._1 == pair._2).count.toDouble / testData.count println("Test accuracy: " + accuracy) } } ``` 这段代码使用Spark MLlib的DecisionTree类和DecisionTreeModel类,用于构建和训练决策树模型。我们首先定义了一个case class DataPoint,用于存储数据的标签和特征值。然后,我们定义了一些辅助方法,用于将数据集转换成LabeledPoint类型、计算数据集的信息熵、计算给定特征对数据集的信息增益、选择最佳的特征作为分类标准、构建决策树模型和预测新的数据。最后,我们加载了一个样本数据集,并将其划分为训练集和测试集,使用训练集构建了决策树模型,并在测试集上测试了模型的准确率。 希望这段代码能够帮助你理解ID3决策树分类算法的基本思想,以及如何使用Scala和Spark MLlib实现它。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值