Доступ к случайному подмножеству кортежа в C ++ 17 во время выполнения - PullRequest
0 голосов
/ 09 апреля 2019

Я реализую дерево решений в C ++ 17.У меня есть каждая запись из моего набора данных, хранящаяся как кортеж, и вектор, содержащий каждый из этих кортежей.

Мне нужно создать подмножество кортежей для каждого уникального значения, найденного в поле кортежа.

Я понимаю, что доступ к элементам в кортеже осуществляется во время компиляции, поэтому мне интересно, есть ли какие-нибудь приемы, которые можно было бы использовать, или мне следует полностью отказаться от кортежа для этого конкретного проекта.

Кроме того, мне нужно убрать лучший атрибут из рассмотрения в будущих итерациях при разбиении моего дерева.Я думал, что использование index_sequence может сработать, но любые случаи, когда это делается онлайн, были на последовательных числах (например, 1, 2, 3, 4, 5) вместо случайных подмножеств (например, 1, 3, 5)

Функция zip_recordset берет вектор кортежей (RecordSet) и создает кортеж векторов.Я подумал, что это будет полезно, но мне все еще нужен какой вектор для доступа во время выполнения.

#ifndef __DECISION_TREE
#define __DECISION_TREE

#include <algorithm>
#include <set>
#include <map>

#include "common.h"

namespace ml::dt {
    struct Node {
        bool leaf;
        size_t attr;
        size_t label;
        std::vector<Node> children;
    };

    template<typename T>
    class DecisionTree {
        using RecordSet = typename T::RecordSet;
        using Record = typename T::Record;

        Node head;

        template<typename U>
        double entropy(std::vector<U> attrVec) {
            std::map<U, std::size_t> valMap {};
            for(auto i=0; i<attrVec.size(); ++i) {
                if(valMap.count(attrVec[i]) == 0) {
                    valMap[attrVec[i]] = 1;
                } else {
                    valMap[attrVec[i]]++;
                }
            }

            int totalSize = 0;
            for(auto& [key, val] : valMap) {
                totalSize += val;
            }

            double entropy = 0;
            for(auto& [key, val] : valMap) {
                double p = (static_cast<double>(val)/totalSize);
                entropy += p * std::log2(p);
            }

            return entropy;
        }

        template<auto target>
        Node learn_impl(RecordSet trainSet, std::set<std::size_t> attrList) {
            int pos = 0;
            int neg = 0;
            for(auto& rec : trainSet) {
                if(std::get<target>(rec) == 0) {
                    neg++;
                } else {
                    pos++;
                }
            }

            // If all examples are positive, return +
            if(neg == 0) {
                return Node {true, 0, 1, {}};
            }

            // If all examples are negative, return -
            if(pos == 0) {
                return Node {true, 0, 0, {}};
            }

            // If attr is empty, return label Mode(examples)
            if(attrList.empty()) {
                size_t label = 0;
                if(neg < pos)
                    label = 1;
                return Node {true, 0, label, {}};
            }

            // Get Best Attribute
            size_t bestAttr = 0;
            std::vector<double> entropy_values {};
            auto trainSetVec = T::zip_recordset(trainSet);
            auto clVec = std::get<T::size-1>(trainSetVec);

            std::apply([&](auto& ...v) {
                (entropy_values.emplace_back(entropy(v)),...);
            }, trainSetVec);

            bestAttr = std::distance(entropy_values.begin(), std::min_element(entropy_values.begin(), entropy_values.end()));

            // For every value of attr

                // examples_new = values with attr
                // if examples_new empty
                    // leaf node = mode(examples)
                // else
                    // learn_impl<target>(examples_new, attrList - bestAttr)
        }

    public:
        DecisionTree() = default;

        template<auto target>
        void learn(RecordSet trainSet) {
            std::set<std::size_t> attrList {};
            for(auto i=0; i<T::size; ++i) {
                attrList.emplace(i);
            }
            head = learn_impl<target>(trainSet, attrList);
        }
    };
}

#endif // __DECISION_TREE

Есть ли способ сделать это?

Обновление

Добавлено дольшепример кодаРасширенное объяснение доступа к элементам кортежа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...