Advertisement
Guest User

Untitled

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