Advertisement
glavinova

[СНЗ] Точност на класификација

Jul 5th, 2020
1,585
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 18.77 KB | None | 0 0
  1. """Точност на класификација Problem 4 (1 / 4)
  2. Изградете 2 дрва на одлука. Едното дрво на одлука ќе ја користи првата половина од податочното множество, а другото дрво, втората половина. Притоа, од првичното податочно множество за тренирање отстранете ги редиците чии што индекси ги содржи листата test_indices и од тие податочни редици креирајте го тестирачкото множество. Потоа, пресметајте ја точноста на двете дрва на одлука со користење на тестирачкото множество. Доколку двете дрва имаат иста точност да се испринта "Drvata imaat ista tochnost", а во спротивно потребно да е да се испринта "Drvoto i e podobro od drvoto j".
  3.  
  4. Точност на класификатор се пресметува како:
  5.  
  6. точност = број на точно предвидени примероци / вкупен број на примероци """
  7.  
  8.  
  9. from math import log
  10. train_data = [
  11.     [6.3, 2.9, 5.6, 1.8, 'I. virginica'],
  12.     [6.5, 3.0, 5.8, 2.2, 'I. virginica'],
  13.     [7.6, 3.0, 6.6, 2.1, 'I. virginica'],
  14.     [4.9, 2.5, 4.5, 1.7, 'I. virginica'],
  15.     [7.3, 2.9, 6.3, 1.8, 'I. virginica'],
  16.     [6.7, 2.5, 5.8, 1.8, 'I. virginica'],
  17.     [7.2, 3.6, 6.1, 2.5, 'I. virginica'],
  18.     [6.5, 3.2, 5.1, 2.0, 'I. virginica'],
  19.     [6.4, 2.7, 5.3, 1.9, 'I. virginica'],
  20.     [6.8, 3.0, 5.5, 2.1, 'I. virginica'],
  21.     [5.7, 2.5, 5.0, 2.0, 'I. virginica'],
  22.     [5.8, 2.8, 5.1, 2.4, 'I. virginica'],
  23.     [6.4, 3.2, 5.3, 2.3, 'I. virginica'],
  24.     [6.5, 3.0, 5.5, 1.8, 'I. virginica'],
  25.     [7.7, 3.8, 6.7, 2.2, 'I. virginica'],
  26.     [7.7, 2.8, 6.7, 2.0, 'I. virginica'],
  27.     [6.3, 2.7, 4.9, 1.8, 'I. virginica'],
  28.     [6.7, 3.3, 5.7, 2.1, 'I. virginica'],
  29.     [7.2, 3.2, 6.0, 1.8, 'I. virginica'],
  30.     [6.2, 2.8, 4.8, 1.8, 'I. virginica'],
  31.     [6.1, 3.0, 4.9, 1.8, 'I. virginica'],
  32.     [6.4, 2.8, 5.6, 2.1, 'I. virginica'],
  33.     [7.2, 3.0, 5.8, 1.6, 'I. virginica'],
  34.     [7.4, 2.8, 6.1, 1.9, 'I. virginica'],
  35.     [7.9, 3.8, 6.4, 2.0, 'I. virginica'],
  36.     [6.4, 2.8, 5.6, 2.2, 'I. virginica'],
  37.     [6.3, 2.8, 5.1, 1.5, 'I. virginica'],
  38.     [6.1, 2.6, 5.6, 1.4, 'I. virginica'],
  39.     [7.7, 3.0, 6.1, 2.3, 'I. virginica'],
  40.     [6.3, 3.4, 5.6, 2.4, 'I. virginica'],
  41.     [5.1, 3.5, 1.4, 0.2, 'I. setosa'],
  42.     [4.9, 3.0, 1.4, 0.2, 'I. setosa'],
  43.     [4.7, 3.2, 1.3, 0.2, 'I. setosa'],
  44.     [4.6, 3.1, 1.5, 0.2, 'I. setosa'],
  45.     [5.0, 3.6, 1.4, 0.2, 'I. setosa'],
  46.     [5.4, 3.9, 1.7, 0.4, 'I. setosa'],
  47.     [4.6, 3.4, 1.4, 0.3, 'I. setosa'],
  48.     [5.0, 3.4, 1.5, 0.2, 'I. setosa'],
  49.     [4.4, 2.9, 1.4, 0.2, 'I. setosa'],
  50.     [4.9, 3.1, 1.5, 0.1, 'I. setosa'],
  51.     [5.4, 3.7, 1.5, 0.2, 'I. setosa'],
  52.     [4.8, 3.4, 1.6, 0.2, 'I. setosa'],
  53.     [4.8, 3.0, 1.4, 0.1, 'I. setosa'],
  54.     [4.3, 3.0, 1.1, 0.1, 'I. setosa'],
  55.     [5.8, 4.0, 1.2, 0.2, 'I. setosa'],
  56.     [5.1, 3.8, 1.5, 0.3, 'I. setosa'],
  57.     [5.4, 3.4, 1.7, 0.2, 'I. setosa'],
  58.     [5.1, 3.7, 1.5, 0.4, 'I. setosa'],
  59.     [4.6, 3.6, 1.0, 0.2, 'I. setosa'],
  60.     [5.1, 3.3, 1.7, 0.5, 'I. setosa'],
  61.     [4.8, 3.4, 1.9, 0.2, 'I. setosa'],
  62.     [5.0, 3.0, 1.6, 0.2, 'I. setosa'],
  63.     [5.0, 3.4, 1.6, 0.4, 'I. setosa'],
  64.     [5.2, 3.5, 1.5, 0.2, 'I. setosa'],
  65.     [5.2, 3.4, 1.4, 0.2, 'I. setosa'],
  66.     [5.5, 2.3, 4.0, 1.3, 'I. versicolor'],
  67.     [6.5, 2.8, 4.6, 1.5, 'I. versicolor'],
  68.     [5.7, 2.8, 4.5, 1.3, 'I. versicolor'],
  69.     [6.3, 3.3, 4.7, 1.6, 'I. versicolor'],
  70.     [4.9, 2.4, 3.3, 1.0, 'I. versicolor'],
  71.     [6.6, 2.9, 4.6, 1.3, 'I. versicolor'],
  72.     [5.2, 2.7, 3.9, 1.4, 'I. versicolor'],
  73.     [5.0, 2.0, 3.5, 1.0, 'I. versicolor'],
  74.     [5.9, 3.0, 4.2, 1.5, 'I. versicolor'],
  75.     [6.0, 2.2, 4.0, 1.0, 'I. versicolor'],
  76.     [6.1, 2.9, 4.7, 1.4, 'I. versicolor'],
  77.     [5.6, 2.9, 3.6, 1.3, 'I. versicolor'],
  78.     [6.7, 3.1, 4.4, 1.4, 'I. versicolor'],
  79.     [6.6, 3.0, 4.4, 1.4, 'I. versicolor'],
  80.     [6.8, 2.8, 4.8, 1.4, 'I. versicolor'],
  81.     [6.7, 3.0, 5.0, 1.7, 'I. versicolor'],
  82.     [6.0, 2.9, 4.5, 1.5, 'I. versicolor'],
  83.     [5.7, 2.6, 3.5, 1.0, 'I. versicolor'],
  84.     [5.5, 2.4, 3.8, 1.1, 'I. versicolor'],
  85.     [5.5, 2.4, 3.7, 1.0, 'I. versicolor'],
  86.     [5.8, 2.7, 3.9, 1.2, 'I. versicolor'],
  87.     [6.0, 2.7, 5.1, 1.6, 'I. versicolor'],
  88.     [5.4, 3.0, 4.5, 1.5, 'I. versicolor'],
  89.     [6.0, 3.4, 4.5, 1.6, 'I. versicolor'],
  90.     [6.7, 3.1, 4.7, 1.5, 'I. versicolor'],
  91.     [6.3, 2.3, 4.4, 1.3, 'I. versicolor'],
  92.     [5.6, 3.0, 4.1, 1.3, 'I. versicolor'],
  93.     [5.5, 2.5, 4.0, 1.3, 'I. versicolor'],
  94.     [5.5, 2.6, 4.4, 1.2, 'I. versicolor'],
  95.     [6.1, 3.0, 4.6, 1.4, 'I. versicolor'],
  96.     [5.8, 2.6, 4.0, 1.2, 'I. versicolor'],
  97.     [5.0, 2.3, 3.3, 1.0, 'I. versicolor'],
  98.     [5.6, 2.7, 4.2, 1.3, 'I. versicolor'],
  99.     [5.7, 3.0, 4.2, 1.2, 'I. versicolor'],
  100.     [5.7, 2.9, 4.2, 1.3, 'I. versicolor'],
  101.     [6.2, 2.9, 4.3, 1.3, 'I. versicolor'],
  102.     [5.1, 2.5, 3.0, 1.1, 'I. versicolor'],
  103.     [5.7, 2.8, 4.1, 1.3, 'I. versicolor'],
  104.     [6.4, 3.1, 5.5, 1.8, 'I. virginica'],
  105.     [6.0, 3.0, 4.8, 1.8, 'I. virginica'],
  106.     [6.9, 3.1, 5.4, 2.1, 'I. virginica'],
  107.     [6.7, 3.1, 5.6, 2.4, 'I. virginica'],
  108.     [6.9, 3.1, 5.1, 2.3, 'I. virginica'],
  109.     [5.8, 2.7, 5.1, 1.9, 'I. virginica'],
  110.     [6.8, 3.2, 5.9, 2.3, 'I. virginica'],
  111.     [6.7, 3.3, 5.7, 2.5, 'I. virginica'],
  112.     [6.7, 3.0, 5.2, 2.3, 'I. virginica'],
  113.     [6.3, 2.5, 5.0, 1.9, 'I. virginica'],
  114.     [6.5, 3.0, 5.2, 2.0, 'I. virginica'],
  115.     [6.2, 3.4, 5.4, 2.3, 'I. virginica'],
  116.     [4.7, 3.2, 1.6, 0.2, 'I. setosa'],
  117.     [4.8, 3.1, 1.6, 0.2, 'I. setosa'],
  118.     [5.4, 3.4, 1.5, 0.4, 'I. setosa'],
  119.     [5.2, 4.1, 1.5, 0.1, 'I. setosa'],
  120.     [5.5, 4.2, 1.4, 0.2, 'I. setosa'],
  121.     [4.9, 3.1, 1.5, 0.2, 'I. setosa'],
  122.     [5.0, 3.2, 1.2, 0.2, 'I. setosa'],
  123.     [5.5, 3.5, 1.3, 0.2, 'I. setosa'],
  124.     [4.9, 3.6, 1.4, 0.1, 'I. setosa'],
  125.     [4.4, 3.0, 1.3, 0.2, 'I. setosa'],
  126.     [5.1, 3.4, 1.5, 0.2, 'I. setosa'],
  127.     [5.0, 3.5, 1.3, 0.3, 'I. setosa'],
  128.     [4.5, 2.3, 1.3, 0.3, 'I. setosa'],
  129.     [4.4, 3.2, 1.3, 0.2, 'I. setosa'],
  130.     [5.0, 3.5, 1.6, 0.6, 'I. setosa'],
  131.     [5.1, 3.8, 1.9, 0.4, 'I. setosa'],
  132.     [4.8, 3.0, 1.4, 0.3, 'I. setosa'],
  133.     [5.1, 3.8, 1.6, 0.2, 'I. setosa'],
  134.     [5.9, 3.0, 5.1, 1.8, 'I. virginica'],
  135.     [7.7, 2.6, 6.9, 2.3, 'I. virginica'],
  136.     [6.0, 2.2, 5.0, 1.5, 'I. virginica'],
  137.     [6.9, 3.2, 5.7, 2.3, 'I. virginica'],
  138.     [5.6, 2.8, 4.9, 2.0, 'I. virginica'],
  139.     [5.7, 4.4, 1.5, 0.4, 'I. setosa'],
  140.     [5.4, 3.9, 1.3, 0.4, 'I. setosa'],
  141.     [5.1, 3.5, 1.4, 0.3, 'I. setosa'],
  142.     [5.7, 3.8, 1.7, 0.3, 'I. setosa'],
  143.     [5.6, 3.0, 4.5, 1.5, 'I. versicolor'],
  144.     [5.8, 2.7, 4.1, 1.0, 'I. versicolor'],
  145.     [6.2, 2.2, 4.5, 1.5, 'I. versicolor'],
  146.     [5.6, 2.5, 3.9, 1.1, 'I. versicolor'],
  147.     [5.9, 3.2, 4.8, 1.8, 'I. versicolor'],
  148.     [6.1, 2.8, 4.0, 1.3, 'I. versicolor'],
  149.     [6.3, 2.5, 4.9, 1.5, 'I. versicolor'],
  150.     [6.1, 2.8, 4.7, 1.2, 'I. versicolor'],
  151.     [6.4, 2.9, 4.3, 1.3, 'I. versicolor']]
  152.  
  153. from math import log
  154.  
  155.  
  156. def unique_counts(rows):
  157.     """Креирај броење на можни резултати (последната колона
  158.    во секоја редица е класата)
  159.  
  160.    :param rows: dataset
  161.    :type rows: list
  162.    :return: dictionary of possible classes as keys and count
  163.             as values
  164.    :rtype: dict
  165.    """
  166.     results = {}
  167.     for row in rows:
  168.         # Клацата е последната колона
  169.         r = row[len(row) - 1]
  170.         if r not in results:
  171.             results[r] = 0
  172.         results[r] += 1
  173.     return results
  174.  
  175.  
  176. def gini_impurity(rows):
  177.     """Probability that a randomly placed item will
  178.    be in the wrong category
  179.  
  180.    :param rows: dataset
  181.    :type rows: list
  182.    :return: Gini impurity
  183.    :rtype: float
  184.    """
  185.     total = len(rows)
  186.     counts = unique_counts(rows)
  187.     imp = 0
  188.     for k1 in counts:
  189.         p1 = float(counts[k1]) / total
  190.         for k2 in counts:
  191.             if k1 == k2:
  192.                 continue
  193.             p2 = float(counts[k2]) / total
  194.             imp += p1 * p2
  195.     return imp
  196.  
  197.  
  198. def entropy(rows):
  199.     """Ентропијата е сума од p(x)log(p(x)) за сите
  200.    можни резултати
  201.  
  202.    :param rows: податочно множество
  203.    :type rows: list
  204.    :return: вредност за ентропијата
  205.    :rtype: float
  206.    """
  207.     log2 = lambda x: log(x) / log(2)
  208.     results = unique_counts(rows)
  209.     # Пресметка на ентропијата
  210.     ent = 0.0
  211.     for r in results.keys():
  212.         p = float(results[r]) / len(rows)
  213.         ent = ent - p * log2(p)
  214.     return ent
  215.  
  216.  
  217. class DecisionNode:
  218.     def __init__(self, col=-1, value=None, results=None, tb=None, fb=None):
  219.         """
  220.        :param col: индексот на колоната (атрибутот) од тренинг множеството
  221.                    која се претставува со оваа инстанца т.е. со овој јазол
  222.        :type col: int
  223.        :param value: вредноста на јазолот според кој се дели дрвото
  224.        :param results: резултати за тековната гранка, вредност (различна
  225.                        од None) само кај јазлите-листови во кои се донесува
  226.                        одлуката.
  227.        :type results: dict
  228.        :param tb: гранка која се дели од тековниот јазол кога вредноста е
  229.                   еднаква на value
  230.        :type tb: DecisionNode
  231.        :param fb: гранка која се дели од тековниот јазол кога вредноста е
  232.                   различна од value
  233.        :type fb: DecisionNode
  234.        """
  235.         self.col = col
  236.         self.value = value
  237.         self.results = results
  238.         self.tb = tb
  239.         self.fb = fb
  240.  
  241.  
  242. def compare_numerical(row, column, value):
  243.     """Споредба на вредноста од редицата на посакуваната колона со
  244.    зададена нумеричка вредност
  245.  
  246.    :param row: дадена редица во податочното множество
  247.    :type row: list
  248.    :param column: индекс на колоната (атрибутот) од тренирачкото множество
  249.    :type column: int
  250.    :param value: вредност на јазелот во согласност со кој се прави
  251.                  поделбата во дрвото
  252.    :type value: int or float
  253.    :return: True ако редицата >= value, инаку False
  254.    :rtype: bool
  255.    """
  256.     return row[column] >= value
  257.  
  258.  
  259. def compare_nominal(row, column, value):
  260.     """Споредба на вредноста од редицата на посакуваната колона со
  261.    зададена номинална вредност
  262.  
  263.    :param row: дадена редица во податочното множество
  264.    :type row: list
  265.    :param column: индекс на колоната (атрибутот) од тренирачкото множество
  266.    :type column: int
  267.    :param value: вредност на јазелот во согласност со кој се прави
  268.                  поделбата во дрвото
  269.    :type value: str
  270.    :return: True ако редицата == value, инаку False
  271.    :rtype: bool
  272.    """
  273.     return row[column] == value
  274.  
  275.  
  276. def divide_set(rows, column, value):
  277.     """Поделба на множеството според одредена колона. Може да се справи
  278.    со нумерички или номинални вредности.
  279.  
  280.    :param rows: тренирачко множество
  281.    :type rows: list(list)
  282.    :param column: индекс на колоната (атрибутот) од тренирачкото множество
  283.    :type column: int
  284.    :param value: вредност на јазелот во зависност со кој се прави поделбата
  285.                  во дрвото за конкретната гранка
  286.    :type value: int or float or str
  287.    :return: поделени подмножества
  288.    :rtype: list, list
  289.    """
  290.     # Направи функција која ни кажува дали редицата е во
  291.     # првата група (True) или втората група (False)
  292.     if isinstance(value, int) or isinstance(value, float):
  293.         # ако вредноста за споредба е од тип int или float
  294.         split_function = compare_numerical
  295.     else:
  296.         # ако вредноста за споредба е од друг тип (string)
  297.         split_function = compare_nominal
  298.  
  299.     # Подели ги редиците во две подмножества и врати ги
  300.     # за секој ред за кој split_function враќа True
  301.     set1 = [row for row in rows if
  302.             split_function(row, column, value)]
  303.     # set1 = []
  304.     # for row in rows:
  305.     #     if not split_function(row, column, value):
  306.     #         set1.append(row)
  307.     # за секој ред за кој split_function враќа False
  308.     set2 = [row for row in rows if
  309.             not split_function(row, column, value)]
  310.     return set1, set2
  311.  
  312.  
  313. def build_tree(rows, scoref=entropy):
  314.     """Градење на дрво на одлука.
  315.  
  316.    :param rows: тренирачко множество
  317.    :type rows: list(list)
  318.    :param scoref: функција за одбирање на најдобар атрибут во даден чекор
  319.    :type scoref: function
  320.    :return: коренот на изграденото дрво на одлука
  321.    :rtype: DecisionNode object
  322.    """
  323.     if len(rows) == 0:
  324.         return DecisionNode()
  325.     current_score = scoref(rows)
  326.  
  327.     # променливи со кои следиме кој критериум е најдобар
  328.     best_gain = 0.0
  329.     best_criteria = None
  330.     best_sets = None
  331.  
  332.     column_count = len(rows[0]) - 1
  333.     for col in range(0, column_count):
  334.         # за секоја колона (col се движи во интервалот од 0 до
  335.         # column_count - 1)
  336.         # Следниов циклус е за генерирање на речник од различни
  337.         # вредности во оваа колона
  338.         column_values = {}
  339.         for row in rows:
  340.             column_values[row[col]] = 1
  341.         # за секоја редица се зема вредноста во оваа колона и се
  342.         # поставува како клуч во column_values
  343.         for value in column_values.keys():
  344.             (set1, set2) = divide_set(rows, col, value)
  345.  
  346.             # Информациона добивка
  347.             p = float(len(set1)) / len(rows)
  348.             gain = current_score - p * scoref(set1) - (1 - p) * scoref(set2)
  349.             if gain > best_gain and len(set1) > 0 and len(set2) > 0:
  350.                 best_gain = gain
  351.                 best_criteria = (col, value)
  352.                 best_sets = (set1, set2)
  353.  
  354.     # Креирај ги подгранките
  355.     if best_gain > 0:
  356.         true_branch = build_tree(best_sets[0], scoref)
  357.         false_branch = build_tree(best_sets[1], scoref)
  358.         return DecisionNode(col=best_criteria[0], value=best_criteria[1],
  359.                             tb=true_branch, fb=false_branch)
  360.     else:
  361.         return DecisionNode(results=unique_counts(rows))
  362.  
  363.  
  364. def print_tree(tree, indent=''):
  365.     """Принтање на дрво на одлука
  366.  
  367.    :param tree: коренот на дрвото на одлучување
  368.    :type tree: DecisionNode object
  369.    :param indent:
  370.    :return: None
  371.    """
  372.     # Дали е ова лист јазел?
  373.     if tree.results:
  374.         print(str(tree.results))
  375.     else:
  376.         # Се печати условот
  377.         print(str(tree.col) + ':' + str(tree.value) + '? ')
  378.         # Се печатат True гранките, па False гранките
  379.         print(indent + 'T->', end='')
  380.         print_tree(tree.tb, indent + '  ')
  381.         print(indent + 'F->', end='')
  382.         print_tree(tree.fb, indent + '  ')
  383.  
  384.  
  385. def classify(observation, tree):
  386.     """Класификација на нов податочен примерок со изградено дрво на одлука
  387.  
  388.    :param observation: еден ред од податочното множество за предвидување
  389.    :type observation: list
  390.    :param tree: коренот на дрвото на одлучување
  391.    :type tree: DecisionNode object
  392.    :return: речник со класите како клуч и бројот на појавување во листот на дрвото
  393.    за класификација како вредност во речникот
  394.    :rtype: dict
  395.    """
  396.     if tree.results:
  397.         return tree.results
  398.     else:
  399.         value = observation[tree.col]
  400.         if isinstance(value, int) or isinstance(value, float):
  401.             compare = compare_numerical
  402.         else:
  403.             compare = compare_nominal
  404.  
  405.         if compare(observation, tree.col, tree.value):
  406.             branch = tree.tb
  407.         else:
  408.             branch = tree.fb
  409.  
  410.         return classify(observation, branch)
  411.  
  412.  
  413. if __name__ == "__main__":
  414.     test_indices = list(map(int, input().split(', ')))
  415.     # vashiot kod tuka
  416.     test_data=[]
  417.     for i in sorted(test_indices, reverse=True):
  418.         test_data.append(train_data[i])
  419.         del train_data[i]
  420.  
  421.     train_data1 = train_data[:int(len(train_data)*0.5)]
  422.     train_data2 = train_data[int(len(train_data)*0.5):]
  423.  
  424.     t1 = build_tree(train_data1,entropy)
  425.     t2 = build_tree(train_data2, entropy)
  426.     brojac1=0
  427.     brojac2=0
  428.     for i in test_data:
  429.         klasa1 = classify(i, t1)
  430.         klasa2 = classify(i, t2)
  431.         k1 = sorted(list(klasa1.items()),reverse=True,key=lambda x: x[1])[0][0]
  432.         k2 = sorted(list(klasa2.items()), reverse=True, key=lambda x: x[1])[0][0]
  433.         if k1 == i[-1]:
  434.             brojac1+=1
  435.         if k2 == i[-1]:
  436.             brojac2+=1
  437.     tochnost1 = brojac1/len(test_data)
  438.     tochnost2 = brojac2/len(test_data)
  439.     print("Tochnost na drvoto 1: " +str(tochnost1))
  440.     print("Tochnost na drvoto 2: " +str(tochnost2))
  441.     if tochnost1==tochnost2:
  442.         print("Drvata imaat ista tochnost")
  443.     elif tochnost1>tochnost2:
  444.         print("Drvoto 1 e podobro od drvoto 2")
  445.     elif tochnost2>tochnost1:
  446.         print("Drvoto 2 e podobro od drvoto 1")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement