[Compartir tecnología] Clasificación del árbol de decisiones

En este trabajo el autor: Di Yin, emitida después de la autorización.

Enlace original: https://cloud.tencent.com/developer/article/1550440

1 Teoría del árbol de decisiones

1.1 ¿Qué es un árbol de decisión?

El llamado árbol de decisión, como su nombre lo indica, es un tipo de árbol, un tipo de árbol construido sobre la base de elecciones estratégicas. En el aprendizaje automático, un árbol de decisión es un modelo predictivo; representa una relación de mapeo entre los atributos del objeto y los valores del objeto. Cada nodo en el árbol representa un objeto, y cada ruta bifurcada representa un posible valor de atributo. La ruta desde el nodo raíz hasta el nodo hoja corresponde a una secuencia de prueba de decisión. El árbol de decisión solo tiene una salida única. Si desea tener una salida compleja, puede construir un árbol de decisión independiente para manejar diferentes salidas.

1.2 Proceso de aprendizaje del árbol de decisiones

El propósito principal del aprendizaje del árbol de decisión es producir un árbol de decisión con una fuerte capacidad de generalización. El proceso básico sigue una estrategia simple y directa de "divide y vencerás". Su implementación del proceso es la siguiente:

输入:训练集 D={(x_1,y_1),(x_2,y_2),...,(x_m,y_m)};
      属性集 A={a_1,a_2,...,a_d}
过程:函数GenerateTree(D,A)
1: 生成节点node;
2: if D中样本全属于同一类别C then
3:    将node标记为C类叶节点,并返回
4: end if
5: if A为空 OR D中样本在A上取值相同 then
6:    将node标记为叶节点,其类别标记为D中样本数量最多的类,并返回
7: end if
8: 从A中选择最优划分属性 a*;    //每个属性包含若干取值,这里假设有v个取值
9: for a* 的每个值a*_v do
10:    为node生成一个分支,令D_v表示D中在a*上取值为a*_v的样本子集;
11:    if D_v 为空 then
12:       将分支节点标记为叶节点,其类别标记为D中样本最多的类,并返回
13:    else
14:       以GenerateTree(D_v,A\{a*})为分支节点
15:    end if
16: end for

La generación del árbol de decisión es un proceso recursivo. Hay tres situaciones que causarán un retorno recursivo: (1) Todas las muestras contenidas en el nodo actual pertenecen a la misma categoría. (2) El valor del atributo actual está vacío, o todas las muestras toman el mismo valor en todos los atributos. (3) El conjunto de muestra contenido en el nodo actual está vacío.

En el caso de (2), marcamos el nodo actual como un nodo hoja y establecemos su categoría en la categoría con la mayor cantidad de muestras contenidas en el nodo; en el caso de (3), también marcamos el nodo actual como una hoja Nodo, pero su categoría se establece en la categoría con más muestras en su nodo padre. Los dos procesos son esencialmente diferentes: el primero usa la distribución posterior del nodo actual, mientras que el segundo usa la distribución de muestra del nodo principal como la distribución previa del nodo actual.

1.3 Construcción del árbol de decisión

El paso clave en la construcción de un árbol de decisión es dividir los atributos (es decir, determinar diferentes valores de atributos, correspondientes a los del proceso anterior a_v). El llamado atributo dividido es construir diferentes ramas en un nodo de acuerdo con la división diferente de un determinado atributo, y su objetivo es hacer que cada subconjunto dividido sea lo más "puro" posible. Lo más "puro" posible es tratar de hacer que los elementos que se clasificarán en un subconjunto dividido pertenezcan a la misma categoría. Los atributos divididos se dividen en tres situaciones diferentes:

  • 1. Los atributos son valores discretos y no requieren la generación de árboles de decisión binarios. En este momento, cada división de atributos se usa como una rama.
  • 2. Los atributos son valores discretos y requieren la generación de árboles de decisión binarios. En este momento, se utiliza un subconjunto de atributos para la prueba, y se divide en dos ramas según "pertenecer a este subconjunto" y "no pertenecer a este subconjunto".
  • 3. El atributo es un valor continuo. En este momento, un valor se determina como un punto de división y se generan dos ramas de split_pointacuerdo con la >split_pointsuma <=split_point.

1.4 Opciones de división

En el algoritmo del árbol de decisión, cómo elegir el atributo de partición óptimo es el paso más crítico. En general, a medida que continúa el proceso de división, esperamos que las muestras contenidas en los nodos de ramificación del árbol de decisión pertenezcan a la misma categoría tanto como sea posible, es decir, la "pureza" de los nodos se vuelve más y más alta. Existen varios indicadores que miden la pureza de una colección de muestras. En MLlib, la entropía de información y el índice de Gini se usan para la clasificación del árbol de decisión, y la varianza se usa para la regresión del árbol de decisión.

1.4.1 Entropía de la información

La entropía de información es el indicador más utilizado para medir la pureza del conjunto de muestras. Suponiendo que la proporción del tipo de muestras Den el conjunto de muestras actual kes p_k, Dla entropía de información se define como:

Ent(D)Cuanto menor es el valor, Dmayor es la pureza.

1.4.2 Coeficiente de Gini

Usando los mismos símbolos que arriba, el coeficiente de Gini se puede usar para medir Dla pureza del conjunto de datos .

Intuitivamente, Gini(D)se refleja desde el conjunto de datos Dprobabilidad muestrea aleatoriamente dos muestras, su categoría inconsistente etiquetado. Por lo tanto, cuanto Gini(D)más pequeño, Dmayor es la pureza del conjunto de datos .

1.4.3 Varianza

MLlibLa variación se usa para medir la pureza. Como se muestra a continuación

1.4.4 Ganancia de información

Suponiendo que Nel conjunto Dde datos del tamaño dividido es la D_leftsuma de dos conjuntos de datos D_right, la ganancia de información se puede expresar de la siguiente manera.

En general, cuanto mayor es la ganancia de información, mayor es ala mejora de pureza obtenida mediante el uso de atributos para dividir. Por lo tanto, podemos usar la ganancia de información para seleccionar el atributo del árbol de decisión. Ese es el octavo paso en el proceso.

1.5 Ventajas y desventajas de los árboles de decisión

Las ventajas del árbol de decisión:

  • 1 El árbol de decisión es fácil de entender y explicar;
  • 2 Capaz de manejar los atributos de tipo de datos y tipo de categoría al mismo tiempo;
  • 3 El árbol de decisión es un modelo de caja blanca: dado un modelo de observación, es fácil derivar la expresión lógica correspondiente;
  • 4 Ser capaz de producir buenos resultados en datos a gran escala en un tiempo relativamente corto;
  • 5 Más adecuado para procesar muestras con valores de atributo faltantes.

Desventajas de los árboles de decisión:

  • 1 Para datos con cantidades inconsistentes de datos en varias categorías, en especies de árboles de decisión, los resultados de la ganancia de información están sesgados hacia aquellos con más características numéricas
  • 2 Fácil de sobreajustar;
  • 3 Ignore la correlación entre los atributos en el conjunto de datos.

2 Ejemplos y análisis de código fuente

2.1 Ejemplos

El siguiente ejemplo se utiliza para la clasificación.

import org.apache.spark.mllib.tree.DecisionTree
import org.apache.spark.mllib.tree.model.DecisionTreeModel
import org.apache.spark.mllib.util.MLUtils
// Load and parse the data file.
val data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt")
// Split the data into training and test sets (30% held out for testing)
val splits = data.randomSplit(Array(0.7, 0.3))
val (trainingData, testData) = (splits(0), splits(1))
// Train a DecisionTree model.
//  Empty categoricalFeaturesInfo indicates all features are continuous.
val numClasses = 2
val categoricalFeaturesInfo = Map[Int, Int]()
val impurity = "gini"
val maxDepth = 5
val maxBins = 32
val model = DecisionTree.trainClassifier(trainingData, numClasses, categoricalFeaturesInfo,
  impurity, maxDepth, maxBins)
// Evaluate model on test instances and compute test error
val labelAndPreds = testData.map { point =>
  val prediction = model.predict(point.features)
  (point.label, prediction)
}
val testErr = labelAndPreds.filter(r => r._1 != r._2).count().toDouble / testData.count()
println("Test Error = " + testErr)
println("Learned classification tree model:\n" + model.toDebugString)

El siguiente ejemplo es para regresión.

import org.apache.spark.mllib.tree.DecisionTree
import org.apache.spark.mllib.tree.model.DecisionTreeModel
import org.apache.spark.mllib.util.MLUtils
// Load and parse the data file.
val data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt")
// Split the data into training and test sets (30% held out for testing)
val splits = data.randomSplit(Array(0.7, 0.3))
val (trainingData, testData) = (splits(0), splits(1))
// Train a DecisionTree model.
//  Empty categoricalFeaturesInfo indicates all features are continuous.
val categoricalFeaturesInfo = Map[Int, Int]()
val impurity = "variance"
val maxDepth = 5
val maxBins = 32
val model = DecisionTree.trainRegressor(trainingData, categoricalFeaturesInfo, impurity,
  maxDepth, maxBins)
// Evaluate model on test instances and compute test error
val labelsAndPredictions = testData.map { point =>
  val prediction = model.predict(point.features)
  (point.label, prediction)
}
val testMSE = labelsAndPredictions.map{ case (v, p) => math.pow(v - p, 2) }.mean()
println("Test Mean Squared Error = " + testMSE)
println("Learned regression tree model:\n" + model.toDebugString)

2.2 Análisis de código fuente

En MLlib, la realización del árbol de decisión y la realización del bosque aleatorio están juntas. En la realización de bosque aleatorio, cuando el número de árboles es 1, su realización es la realización del árbol de decisión.

def run(input: RDD[LabeledPoint]): DecisionTreeModel = {
    //树个数为1
    val rf = new RandomForest(strategy, numTrees = 1, featureSubsetStrategy = "all", seed = 0)
    val rfModel = rf.run(input)
    rfModel.trees(0)
  }

Aquí strategyhay Strategyun ejemplo, contiene la siguiente información:

/**
 * Stores all the configuration options for tree construction
 * @param algo  Learning goal.  Supported:
 *              [[org.apache.spark.mllib.tree.configuration.Algo.Classification]],
 *              [[org.apache.spark.mllib.tree.configuration.Algo.Regression]]
 * @param impurity Criterion used for information gain calculation.
 *                 Supported for Classification: [[org.apache.spark.mllib.tree.impurity.Gini]],
 *                  [[org.apache.spark.mllib.tree.impurity.Entropy]].
 *                 Supported for Regression: [[org.apache.spark.mllib.tree.impurity.Variance]].
 * @param maxDepth Maximum depth of the tree.
 *                 E.g., depth 0 means 1 leaf node; depth 1 means 1 internal node + 2 leaf nodes.
 * @param numClasses Number of classes for classification.
 *                                    (Ignored for regression.)
 *                                    Default value is 2 (binary classification).
 * @param maxBins Maximum number of bins used for discretizing continuous features and
 *                for choosing how to split on features at each node.
 *                More bins give higher granularity.
 * @param quantileCalculationStrategy Algorithm for calculating quantiles.  Supported:
 *                             [[org.apache.spark.mllib.tree.configuration.QuantileStrategy.Sort]]
 * @param categoricalFeaturesInfo A map storing information about the categorical variables and the
 *                                number of discrete values they take. For example, an entry (n ->
 *                                k) implies the feature n is categorical with k categories 0,
 *                                1, 2, ... , k-1. It's important to note that features are
 *                                zero-indexed.
 * @param minInstancesPerNode Minimum number of instances each child must have after split.
 *                            Default value is 1. If a split cause left or right child
 *                            to have less than minInstancesPerNode,
 *                            this split will not be considered as a valid split.
 * @param minInfoGain Minimum information gain a split must get. Default value is 0.0.
 *                    If a split has less information gain than minInfoGain,
 *                    this split will not be considered as a valid split.
 * @param maxMemoryInMB Maximum memory in MB allocated to histogram aggregation. Default value is
 *                      256 MB.
 * @param subsamplingRate Fraction of the training data used for learning decision tree.
 * @param useNodeIdCache If this is true, instead of passing trees to executors, the algorithm will
 *                      maintain a separate RDD of node Id cache for each row.
 * @param checkpointInterval How often to checkpoint when the node Id cache gets updated.
 *                           E.g. 10 means that the cache will get checkpointed every 10 updates. If
 *                           the checkpoint directory is not set in
 *                           [[org.apache.spark.SparkContext]], this setting is ignored.
 */
class Strategy @Since("1.3.0") (
    @Since("1.0.0") @BeanProperty var algo: Algo,//选择的算法,有分类和回归两种选择
    @Since("1.0.0") @BeanProperty var impurity: Impurity,//纯度有熵、基尼系数、方差三种选择
    @Since("1.0.0") @BeanProperty var maxDepth: Int,//树的最大深度
    @Since("1.2.0") @BeanProperty var numClasses: Int = 2,//分类数
    @Since("1.0.0") @BeanProperty var maxBins: Int = 32,//最大子树个数
    @Since("1.0.0") @BeanProperty var quantileCalculationStrategy: QuantileStrategy = Sort,
    //保存类别变量以及相应的离散值。一个entry (n ->k) 表示特征n属于k个类别,分别是0,1,...,k-1
    @Since("1.0.0") @BeanProperty var categoricalFeaturesInfo: Map[Int, Int] = Map[Int, Int](),
    @Since("1.2.0") @BeanProperty var minInstancesPerNode: Int = 1,
    @Since("1.2.0") @BeanProperty var minInfoGain: Double = 0.0,
    @Since("1.0.0") @BeanProperty var maxMemoryInMB: Int = 256,
    @Since("1.2.0") @BeanProperty var subsamplingRate: Double = 1,
    @Since("1.2.0") @BeanProperty var useNodeIdCache: Boolean = false,
    @Since("1.2.0") @BeanProperty var checkpointInterval: Int = 10) extends Serializable

La realización del árbol de decisión se introduce en el tema de la clasificación aleatoria de bosques. Aquí solo necesitamos saber que cuando el número de árboles en el bosque aleatorio es 1, es un árbol de decisión, y en este momento, las características utilizadas en el entrenamiento del árbol son todas características, en lugar de algunas características seleccionadas al azar. Es decir featureSubsetStrategy = "all".

 

Comunidad profesional de desarrolladores de IA, ¡esperamos su visita!

Smart Titan AI Developer-Cloud + Community-Tencent Cloud cloud.tencent.com

Supongo que te gusta

Origin blog.csdn.net/qq_42933419/article/details/105250277
Recomendado
Clasificación