예제 #1
0
        /// <summary>
        /// Вычисление энтропии заданного атрибута, включая только определенные значения
        /// </summary>
        /// <param name="instances"></param>
        /// <param name="target_attribute"></param>
        /// <param name="attribute"></param>
        /// <param name="attribute_value"></param>
        /// <returns></returns>

        static double Entrophy(Item[] instances, AttributeVariable target_attribute, AttributeVariable attribute, double attribute_value)
        {
            double[] range    = target_attribute.Range;
            double   entrophy = 0;

            foreach (double n in range)
            {
                int cnt = 0, cnt_all = 0;
                for (int i = 0; i < instances.Count(); ++i)
                {
                    if (instances[i].FindAttributeValue(attribute) != attribute_value)
                    {
                        continue;
                    }
                    if (instances[i].FindAttributeValue(target_attribute) == n)
                    {
                        ++cnt;
                    }
                    ++cnt_all;
                }

                if (cnt != 0)
                {
                    double p = (double)cnt / (double)cnt_all;
                    entrophy -= p * Math.Log(p, 2);
                }
            }

            return(entrophy);
        }
예제 #2
0
        public static double FMeasure(Item[] instances, DecisionForest forest, AttributeVariable target_attribute, double B = 1)
        {
            double precision = Precision(instances, forest, target_attribute);
            double recall    = Recall(instances, forest, target_attribute);

            return((B * B + 1) * precision * recall / (B * B * precision + recall));
        }
예제 #3
0
 /// <summary>
 /// создание узла
 /// </summary>
 /// <param name="parent"></param>
 /// <param name="value"></param>
 /// <param name="comparison"></param>
 public DecisionNode(ComparisonKind comparison, double value, AttributeVariable attribute)
 {
     this.Value      = value;
     this.Comparison = comparison;
     this.Attribute  = attribute;
     this.Decision   = null;
 }
예제 #4
0
 /// <summary>
 /// Создание корня
 /// </summary>
 /// <param name="comparison"></param>
 public DecisionNode(AttributeVariable attribute)
 {
     this.Value      = null;
     this.Comparison = ComparisonKind.None;
     this.Attribute  = attribute;
     this.Decision   = null;
 }
예제 #5
0
        /// <summary>
        /// Находит значение заданного атрибута
        /// </summary>
        /// <param name="attribute"></param>
        /// <returns></returns>
        public double?FindAttributeValue(AttributeVariable attribute)
        {
            for (int i = 0; i < Values.Count(); ++i)
            {
                if (Values[i].Attribute.Name == attribute.Name)
                {
                    return(Values[i].Value);
                }
            }

            return(null);
        }
예제 #6
0
        private static DecisionTree[] GrowTrees(Item[] instances, AttributeVariable target_attribute, AttributeVariable[] attributes, int N)
        {
            Item[]         cur_sample;
            DecisionTree[] forest = new DecisionTree[N];

            for (int i = 0; i < N; ++i)
            {
                // сгенерируем выборку с помощью бутстрэпа
                cur_sample = Bootstrap.Aggregate(instances);

                // построим решающее дерево по этой выборке
                forest[i] = C45algorithm.CreateTree(instances, target_attribute, attributes);
            }

            return(forest);
        }
예제 #7
0
        static double Gain(Item[] instances, AttributeVariable target_attribute, AttributeVariable attribute)
        {
            double[] range = attribute.Range;
            double   gain  = Entrophy(instances, target_attribute);

            foreach (double n in range)
            {
                int cnt = 0;
                for (int i = 0; i < instances.Count(); ++i)
                {
                    if (instances[i].FindAttributeValue(attribute) == n)
                    {
                        ++cnt;
                    }
                }

                gain -= (double)cnt / (double)instances.Count() * Entrophy(instances, target_attribute, attribute, n);
            }

            return(gain);
        }
예제 #8
0
        /// <summary>
        /// Вычисление энтропии заданного атрибута
        /// </summary>
        /// <param name="instances"></param>
        /// <param name="attribute"></param>
        /// <returns></returns>
        static double Entrophy(Item[] instances, AttributeVariable target_attribute)
        {
            double[] range    = target_attribute.Range;
            double   entrophy = 0;

            foreach (double n in range)
            {
                int cnt = 0;
                for (int i = 0; i < instances.Count(); ++i)
                {
                    if (instances[i].FindAttributeValue(target_attribute) == n)
                    {
                        ++cnt;
                    }
                }

                double p = (double)cnt / (double)instances.Count();
                entrophy -= p * Math.Log(p, 2);
            }

            return(entrophy);
        }
예제 #9
0
        public static double Recall(Item[] instances, DecisionForest forest, AttributeVariable target_attribute)
        {
            int tp = 0, fn = 0;

            foreach (var item in instances)
            {
                int true_value    = (int)item.FindAttributeValue(target_attribute);
                int predict_value = (int)Math.Round(forest.Decide(item));

                if (true_value == 1)
                {
                    if (predict_value == 1)
                    {
                        ++tp;
                    }
                    else
                    {
                        ++fn;
                    }
                }
            }

            return((double)tp / (double)(tp + fn));
        }
예제 #10
0
 public AttributeValue(AttributeVariable attribute, double value)
 {
     this.Attribute = attribute;
     this.Value     = value;
 }
예제 #11
0
 /// <summary>
 /// Построить дерево
 /// </summary>
 /// <param name="instances"> Примеры </param>
 /// <param name="target_attribute"> Атрибут, для которого нужно принять решение - да или нет </param>
 /// <param name="attributes"> Перечисление всех атрибутов </param>
 /// <returns></returns>
 public static DecisionTree CreateTree(Item[] instances, AttributeVariable target_attribute, AttributeVariable[] attributes)
 {
     return(new DecisionTree(ID3(instances, target_attribute, attributes)));
 }
예제 #12
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);
        }
예제 #13
0
        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);
        }
예제 #14
0
        static double Gain(Item[] instances, AttributeVariable target_attribute, AttributeVariable attribute, out double node_value)
        {
            double[] range       = attribute.Range;
            double   gain        = Entrophy(instances, target_attribute);
            double   _node_value = range[0];

            if (attribute.Nature == DecisionVariableKind.Discrete)
            {
                foreach (double n in range)
                {
                    int cnt = 0;
                    for (int i = 0; i < instances.Count(); ++i)
                    {
                        if (instances[i].FindAttributeValue(attribute) == n)
                        {
                            ++cnt;
                        }
                    }

                    gain -= (double)cnt / (double)instances.Count() * Entrophy(instances, target_attribute, attribute, n);
                }
            }
            else
            {
                double         info, min_info = 1;
                int            cnt;
                ComparisonKind comparision;
                foreach (double n in range)
                {
                    info        = 0; cnt = 0;
                    comparision = ComparisonKind.LessThanOrEqual;
                    for (int i = 0; i < instances.Count(); ++i)
                    {
                        if (ComparisonExtensions.Compare(comparision, (double)instances[i].FindAttributeValue(attribute), n))
                        {
                            ++cnt;
                        }
                    }
                    info += (double)cnt / (double)instances.Count() * Entrophy(instances, target_attribute, attribute, n, comparision);

                    cnt         = 0;
                    comparision = ComparisonKind.GreaterThan;
                    for (int i = 0; i < instances.Count(); ++i)
                    {
                        if (ComparisonExtensions.Compare(comparision, (double)instances[i].FindAttributeValue(attribute), n))
                        {
                            ++cnt;
                        }
                    }
                    info += (double)cnt / (double)instances.Count() * Entrophy(instances, target_attribute, attribute, n, comparision);

                    if (info < min_info)
                    {
                        min_info    = info;
                        _node_value = n;
                    }
                }

                gain -= min_info;
            }

            node_value = _node_value;
            return(gain);
        }
예제 #15
0
 /// <summary>
 /// Построить ансамбль решающих деревьев
 /// </summary>
 /// <param name="instances"></param>
 /// <param name="target_attribute"></param>
 /// <param name="attributes"></param>
 /// <param name="N"> количество деревье </param>
 /// <returns></returns>
 public DecisionForest(Item[] instances, AttributeVariable target_attribute, AttributeVariable[] attributes, int N)
 {
     Trees = GrowTrees(instances, target_attribute, attributes, N);
 }