Пример #1
0
        /// <summary>
        /// Найти решение
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public int Decide(Item item)
        {
            DecisionNode current_node = Root;

            while (current_node.Decision == null)
            {
                for (int i = 0; i < item.Values.Count(); ++i)
                {
                    if (current_node.Attribute == item.Values[i].Attribute)
                    {
                        current_node = current_node.Compute(item.Values[i].Value);
                        break;
                    }
                }
            }

            return((int)current_node.Decision);
        }
Пример #2
0
        static DecisionNode ID3(Item[] instances, AttributeVariable target_attribute, AttributeVariable[] attributes)
        {
            int yes_cnt = 0, no_cnt = 0;

            for (int i = 0; i < instances.Count(); ++i)
            {
                double?value = instances[i].FindAttributeValue(target_attribute);
                if (value == null)
                {
                    throw new Exception("Не инициализировано значение атрибута " + target_attribute + " в " + i + " примере");
                }
                if (value == 0)
                {
                    ++no_cnt;
                }
                else
                if (value == 1)
                {
                    ++yes_cnt;
                }
                else
                {
                    throw new Exception("Значение атрибута " + target_attribute + " должно быть 0 или 1");
                }
            }

            // если все значения target_attribute - ноль, дерево будет состоять из единственного узла, приволящим к решению 0
            if (no_cnt == instances.Count())
            {
                return(new DecisionNode(0));
            }
            // аналогично, если все значения - 1
            if (yes_cnt == instances.Count())
            {
                return(new DecisionNode(1));
            }

            // Если список атрибутов пуст - выводится узел, состоящий из наиболее встречающегося значения
            if (attributes.Count() == 0)
            {
                if (yes_cnt > no_cnt)
                {
                    return(new DecisionNode(1));
                }
                else
                {
                    return(new DecisionNode(0));
                }
            }

            // Ищем атрибут, который лучше всего классифицирует примеры
            double            max_gain = 0, current_gain;
            AttributeVariable best_attribute = attributes[0];

            for (int i = 0; i < attributes.Count(); ++i)
            {
                current_gain = Gain(instances, target_attribute, attributes[i]);
                if (current_gain > max_gain)
                {
                    best_attribute = attributes[i];
                    max_gain       = current_gain;
                }
            }

            List <double?> node_values       = new List <double?>();

            foreach (double n in best_attribute.Range)
            {
                node_values.Add(n);
            }

            List <DecisionNode> Branches     = new List <DecisionNode>();
            int k = 0;

            // для каждого значения атрибута добавляем ветку
            foreach (double n in best_attribute.Range)
            {
                List <Item> Examples = new List <Item>();
                // выделяем примеры, которые соответсвуют текущему значению атрибуты
                for (int i = 0; i < instances.Count(); ++i)
                {
                    if (instances[i].FindAttributeValue(best_attribute) == n)
                    {
                        Examples.Add(instances[i]);
                    }
                }
                // если не найдено примеров, добавляем лист с наиболее встречающимся значением
                if (Examples.Count() == 0)
                {
                    if (yes_cnt > no_cnt)
                    {
                        Branches.Add(new DecisionNode(ComparisonKind.Equal, (double)node_values[k], 1));
                    }
                    else
                    {
                        Branches.Add(new DecisionNode(ComparisonKind.Equal, (double)node_values[k], 0));
                    }
                }
                else
                {
                    List <AttributeVariable> new_attributes_list = attributes.ToList();
                    new_attributes_list.Remove(best_attribute);
                    Branches.Add(ID3(Examples.ToArray(), target_attribute, new_attributes_list.ToArray()));
                    Branches.Last().Value      = node_values[k];
                    Branches.Last().Comparison = ComparisonKind.Equal;
                }
                ++k;
            }

            DecisionNode root = new DecisionNode(best_attribute);

            root.Branches = Branches.ToArray();
            return(root);
        }
        static DecisionNode C45(Item[] instances, AttributeVariable target_attribute, AttributeVariable[] attributes)
        {
            int yes_cnt = 0, no_cnt = 0;

            for (int i = 0; i < instances.Count(); ++i)
            {
                double?value = instances[i].FindAttributeValue(target_attribute);
                if (value == null)
                {
                    throw new Exception("Не инициализировано значение атрибута " + target_attribute + " в " + i + " примере");
                }
                if (value == 0)
                {
                    ++no_cnt;
                }
                else
                if (value == 1)
                {
                    ++yes_cnt;
                }
                else
                {
                    throw new Exception("Значение атрибута " + target_attribute + " должно быть 0 или 1");
                }
            }

            // если все значения target_attribute - ноль, дерево будет состоять из единственного узла, приволящим к решению 0
            if (no_cnt == instances.Count())
            {
                return(new DecisionNode(0));
            }
            // аналогично, если все значения - 1
            if (yes_cnt == instances.Count())
            {
                return(new DecisionNode(1));
            }

            // Если список атрибутов пуст - выводится узел, состоящий из наиболее встречающегося значения
            if (attributes.Count() == 0)
            {
                if (yes_cnt > no_cnt)
                {
                    return(new DecisionNode(1));
                }
                else
                {
                    return(new DecisionNode(0));
                }
            }

            // Ищем атрибут, который лучше всего классифицирует примеры
            double            max_gain = 0, current_gain;
            AttributeVariable best_attribute = attributes[0];
            double            node_value     = best_attribute.Range[0];
            int        m                     = Convert.ToInt32(Math.Sqrt(attributes.Length));
            List <int> randomNumbers         = Enumerable.Range(0, attributes.Length).OrderBy(x => rnd.Next()).Take(m).ToList();

            //for (int i = 0; i < attributes.Count(); ++i)
            foreach (int index in randomNumbers)
            {
                double _node_value;
                current_gain = Gain(instances, target_attribute, attributes[index], out _node_value);
                if (current_gain > max_gain)
                {
                    best_attribute = attributes[index];
                    max_gain       = current_gain;
                    node_value     = _node_value;
                }
            }

            List <DecisionNode> Branches = new List <DecisionNode>();

            if (best_attribute.Nature == DecisionVariableKind.Discrete)
            {
                List <double?> node_values = new List <double?>();

                foreach (double n in best_attribute.Range)
                {
                    node_values.Add(n);
                }

                int k = 0;
                // для каждого значения атрибута добавляем ветку
                foreach (double n in best_attribute.Range)
                {
                    List <Item> Examples = new List <Item>();
                    // выделяем примеры, которые соответсвуют текущему значению атрибуты
                    for (int i = 0; i < instances.Count(); ++i)
                    {
                        if (instances[i].FindAttributeValue(best_attribute) == n)
                        {
                            Examples.Add(instances[i]);
                        }
                    }
                    // если не найдено примеров, добавляем лист с наиболее встречающимся значением
                    if (Examples.Count() == 0)
                    {
                        if (yes_cnt > no_cnt)
                        {
                            Branches.Add(new DecisionNode(ComparisonKind.Equal, (double)node_values[k], 1));
                        }
                        else
                        {
                            Branches.Add(new DecisionNode(ComparisonKind.Equal, (double)node_values[k], 0));
                        }
                    }
                    else
                    {
                        List <AttributeVariable> new_attributes_list = attributes.ToList();
                        new_attributes_list.Remove(best_attribute);
                        Branches.Add(C45(Examples.ToArray(), target_attribute, new_attributes_list.ToArray()));
                        Branches.Last().Value      = node_values[k];
                        Branches.Last().Comparison = ComparisonKind.Equal;
                    }
                    ++k;
                }
            }
            else // атрибут непрерывный
            {
                List <Item> Examples = new List <Item>();

                // выделяем примеры, которые меньше либо равны текущего значения атрибута
                for (int i = 0; i < instances.Count(); ++i)
                {
                    if (ComparisonExtensions.Compare(ComparisonKind.LessThanOrEqual, (double)instances[i].FindAttributeValue(best_attribute), node_value))
                    {
                        Examples.Add(instances[i]);
                    }
                }
                // если не найдено примеров, добавляем лист с наиболее встречающимся значением
                if (Examples.Count() == 0)
                {
                    if (yes_cnt > no_cnt)
                    {
                        Branches.Add(new DecisionNode(ComparisonKind.LessThanOrEqual, (double)node_value, 1));
                    }
                    else
                    {
                        Branches.Add(new DecisionNode(ComparisonKind.LessThanOrEqual, (double)node_value, 0));
                    }
                }
                else
                {
                    List <AttributeVariable> new_attributes_list = attributes.ToList();
                    new_attributes_list.Remove(best_attribute);
                    Branches.Add(C45(Examples.ToArray(), target_attribute, new_attributes_list.ToArray()));
                    Branches.Last().Value      = node_value;
                    Branches.Last().Comparison = ComparisonKind.LessThanOrEqual;
                }

                Examples.Clear();
                // аналогично для значений, которые больше заданного
                for (int i = 0; i < instances.Count(); ++i)
                {
                    if (ComparisonExtensions.Compare(ComparisonKind.GreaterThan, (double)instances[i].FindAttributeValue(best_attribute), node_value))
                    {
                        Examples.Add(instances[i]);
                    }
                }
                if (Examples.Count() == 0)
                {
                    if (yes_cnt > no_cnt)
                    {
                        Branches.Add(new DecisionNode(ComparisonKind.GreaterThan, (double)node_value, 1));
                    }
                    else
                    {
                        Branches.Add(new DecisionNode(ComparisonKind.GreaterThan, (double)node_value, 0));
                    }
                }
                else
                {
                    List <AttributeVariable> new_attributes_list = attributes.ToList();
                    new_attributes_list.Remove(best_attribute);
                    Branches.Add(C45(Examples.ToArray(), target_attribute, new_attributes_list.ToArray()));
                    Branches.Last().Value      = node_value;
                    Branches.Last().Comparison = ComparisonKind.GreaterThan;
                }
            }

            DecisionNode root = new DecisionNode(best_attribute);

            root.Branches = Branches.ToArray();
            return(root);
        }
Пример #4
0
 public DecisionTree(DecisionNode root)
 {
     this.Root = root;
 }