【问题标题】:Machine Learning Algorithm using recursion使用递归的机器学习算法
【发布时间】:2019-05-03 22:06:19
【问题描述】:

我目前正在研究 ID3 机器学习算法的初学者版本。我被困在如何递归地调用我的 build_tree 函数来实际制作决策树的其余部分并以良好的格式输出它。我已经计算了增益、熵、增益比等,但我不知道如何将递归集成到我的函数中。

给我一​​个数据集,在完成上述所有计算后,将其拆分为两个数据集。现在我需要能够递归地调用它,直到左右数据集都变成纯的[可以通过我编写的名为 dataset.is_pure() 的函数轻松检查],同时跟踪每个节点的阈值。我知道我所有的计算和拆分方法都在工作,因为我已经对它们进行了单独的测试。这只是我遇到麻烦的递归部分。

这是我做递归噩梦的 build_tree 函数。我目前正在使用 g++ 编译器在 linux 环境中工作。我现在拥有的代码可以编译,但是运行时会给我一个分段错误。任何和所有的帮助将不胜感激!

   struct node
    {
            vector<vector<string>> data;
            double atrb;
            node* parent;
            node* left = NULL;
            node* right = NULL;

            node(node* parent) : parent(parent) {}
    };

    node* root = new node(NULL);

    void build_tree(node* current, dataset data_set)
    {
            vector<vector<string>> l_d;
            vector<vector<string>> r_d;

            double global_entropy = calc_entropy(data_set.get_col(data_set.n_col()-1));

            int best_col = this->get_best_col(data_set, global_entropy);

            hash_map selected_atrb(data_set.n_row(), data_set.truncate(best_col));
            double threshold = get_threshold(selected_atrb, global_entropy);
            cout << threshold << "\n";

            split_data(threshold, best_col, data_set, l_d, r_d);

            dataset right_data(r_d);
            dataset left_data(l_d);

            right_data.delete_col(best_col);
            left_data.delete_col(best_col);

            if(left_data.is_pure())
                    return;
            else
            {
                    node* new_left = new node(current);
                    new_left->atrb = threshold;
                    current->left = new_left;
                    new_left->data = l_d;
                    return build_tree(new_left, left_data);
            }

            if(right_data.is_pure())
                    return;
            else
            {
                    node* new_right = new node(current);
                    new_right->atrb = threshold;
                    current->right = new_right;
                    new_right->data = r_d;
                    return build_tree(new_right, right_data);
            }
    }

    id3(dataset data)
    {
            build_tree(root, data);
    }

};

这只是我课程的一部分。如果您想查看任何其他代码,请告诉我!

【问题讨论】:

  • 这看起来不像java;它看起来像 C++。您确定您的问题标记正确吗?
  • @ErwinBolwidt 很抱歉。当我发布问题时大约是凌晨 3 点:/ 我已经更新了标签,感谢您指出!

标签: c++ linux algorithm recursion machine-learning


【解决方案1】:

问候,

我会用pseudocodigo 向你解释reclusive 函数是如何工作的,我也会留下你用javascript 编写的代码来实现所述算法。

在详细介绍之前,我会提到您使用的某些概念和类。

  • 属性:数据集的特征,通常是数据集的列名。
  • 类:决策特征,一般是二进制值,通常是数据集的最后一列。
  • 值:数据集中属性的可能值,例如(晴天、阴天、雨天)
  • 树: 具有多个相互关联的节点的类。
  • 节点:负责存储属性(问题)的实体,也有一个带有弧的列表。

  • 弧:包含一个属性的值,并且有一个属性将包含以下子节点。

  • Leaf : 包含一个类。此节点是决策的结果,例如(是或否)。

  • 最佳特征:信息增益最高的属性。

从一组数据创建树的函数:

  • 获取一个类的值。
  • 评估数据集中是否只有一种类型的类,例如(是)。
  • 如果为真,那么我们创建一个 Leaf 对象并返回这个对象
  • 获取当前每个属性的信息增益。
  • 选择信息增益最高的属性。
  • 创建具有最佳特征的节点。
  • 获取最佳特征的值。
  • 迭代这些值的列表。

    • 过滤列表,以便只有具有我们正在迭代的值的记录(将其保存在临时变量中)

    • 使用该值创建一个弧。 - 将以下属性分配给 Arc:(这里是递归)再次调用您发送的唯一函数(过滤的记录列表、类、没有最佳特征的属性列表、没有最佳特征的属性)

    • 将圆弧添加到节点。
  • 返回节点。

这将是负责创建树的代码段

let crearArbol = (ejemplosLista, clase, atributos, valores) => {
        let valoresClase = obtenerValoresAtributo(ejemplosLista, clase);
        if (valoresClase.length == 1) {
            autoIncremental++;
            return new Hoja(valoresClase[0], autoIncremental);
        }

        if (atributos.length == 0) {
            let claseDominante = claseMayoritaria(ejemplosLista);
            return new Atributo();
        }

        let gananciaAtributos = obtenerGananciaAtributos(ejemplosLista, valores, atributos);
        let atributoMaximo = atributos[maximaGanancia(gananciaAtributos)];

        autoIncremental++;
        let nodo = new Atributo(atributoMaximo, [], autoIncremental);
        let valoresLista = obtenerValoresAtributo(ejemplosLista, atributoMaximo);

        valoresLista.forEach((valor) => {
            let ejemplosFiltrados = arrayDistincAtributos(ejemplosLista, atributoMaximo, valor);
            let arco = new Arco(valor);
            arco.sigNodo = crearArbol(ejemplosFiltrados, clase, [...eliminarAtributo(atributoMaximo, atributos)], [...eliminarValores(atributoMaximo, valores)]);
            nodo.hijos.push(arco);
        });

        return nodo;
    };

很遗憾,代码只有西班牙语。 这是包含我的项目的存储库,此实现 Source code of id3

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-01
    • 1970-01-01
    • 2017-07-11
    • 2021-09-02
    • 2012-03-14
    • 2015-10-06
    • 2014-06-23
    • 2017-08-21
    相关资源
    最近更新 更多