JovanPapi

[SNZ - Exercises ] Точност на наивен баесов класификатор

Nov 12th, 2019
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 16.08 KB | None | 0 0
  1. train_data = [
  2.     ("""I like Rhythm and Blue music.""", 'formal'),
  3.     ("""Back in my day Emo was a comedian :/""", 'informal'),
  4.     ("""Why sit and listen to Locke, Jack, or Syead?""", 'informal'),
  5.     ("""There's nothing he needs to change.""", 'formal'),
  6.     ("""It does not exist.""", 'formal'),
  7.     ("""I like when the Prime Minister goes door to door to find the girl!""", 'informal'),
  8.     ("""Mine is book by Steve Martin called 'The Pleasure of my Company'.""", 'formal'),
  9.     ("""What differentiates a mosquitoo from a blonde?""", 'formal'),
  10.     ("""They're pretty good. Also, that's a good song.""", 'formal'),
  11.     ("""And every time I hear that song I get butterflies in my stomach!""", 'informal'),
  12.     ("""It's the biggest load of crap I've seen for ages.""", 'informal'),
  13.     ("""I do not think Beyonce can sing, dance, or act. You mentioned Rihanna, who is that?""", 'formal'),
  14.     ("""as i lay dying is far far away from christ definitaly!""", 'informal'),
  15.     ("""I was unaware that you were in law enforcement, as well.""", 'formal'),
  16.     ("""I might be seeing them in a few months!""", 'informal'),
  17.     ("""I called to say 'I Love You""", 'formal'),
  18.     ("""that´s why they needed to open that hatch so much!""", 'informal'),
  19.     (
  20.         """I would most likely not vote for him, although I believe Melania would be the most attractive First Lady in our country's history.""",
  21.         'formal'),
  22.     ("""I do not hate him.""", 'formal'),
  23.     ("""He's supposed to be in jail!""", 'informal'),
  24.     ("""i thought that she did an outstanding job in the movie""", 'informal'),
  25.     ("""Nicole Kidman, I love her eyes""", 'informal'),
  26.     ("""Youtube.com also features many of the current funny ads.""", 'formal'),
  27.     ("""I enjoy watching my companion attempt to role-play with them.""", 'formal'),
  28.     ("""omg i love that song im listening to it right now""", 'informal'),
  29.     ("""Some of my favorite television series are Monk, The Dukes of Hazzard, Miami Vice, and The Simpsons.""",
  30.      'formal'),
  31.     ("""I have a desire to produce videos on Full Metal Alchemist.""", 'formal'),
  32.     ("""tell him you want a 3 way with another hot girl""", 'informal'),
  33.     (
  34.         """I would travel to that location and physically assault you at this very moment, however, I am unable to swim.""",
  35.         'formal'),
  36.     ("""No, no, no that was WITNESS...""", 'informal'),
  37.     ("""aneways shonenjump.com is cool and yeah narutos awsum""", 'informal'),
  38.     (
  39.         """Your mother is so unintelligent that she was hit by a cup and told the police that she was mugged.""",
  40.         'formal'),
  41.     ("""You must be creative and find something to challange us.""", 'formal'),
  42.     ("""i think they would have, quite a shame isn't it""", 'informal'),
  43.     ("""I am watching it right now.""", 'formal'),
  44.     ("""I do not know; the person who invented the names had attention deficit disorder.""", 'formal'),
  45.     ("""im a huge green day fan!!!!!""", 'informal'),
  46.     ("""I believe, rather, that they are not very smart on this topic.""", 'formal'),
  47.     ("""Of course it is Oprah, because she has been providing better advice for a longer time.""", 'formal'),
  48.     ("""Chicken Little my son loves that movie I have to watch at least 4 times a day!""", 'informal'),
  49.     ("""That is the key point, that you fell asleep.""", 'formal'),
  50.     ("""A brunette female, a blonde, and person with red hair walked down a street.""", 'formal'),
  51.     ("""who is your best bet for american idol season five""", 'informal'),
  52.     ("""That is funny.  Girls need to be a part of everything.""", 'formal'),
  53.     ("""In point of fact, Chris's performance looked like the encoure performed at a Genesis concert.""", 'formal'),
  54.     ("""In my time, Emo was a comedian.""", 'formal'),
  55.     ("""my age gas prices and my blood pressure  LOL""", 'informal'),
  56.     ("""Moriarty and so forth, but what character did the Peruvian actor portray?""", 'formal'),
  57.     ("""What did the beaver say to the log?""", 'formal'),
  58.     ("""Where in the world do you come up with these questions????""", 'informal'),
  59.     ("""even though i also agree that the girls on Love Hina are pretty scrumptious""", 'informal'),
  60.     ("""I miss Aaliyah, she was a great singer.""", 'formal'),
  61.     ("""and the blond says Great they already put me on my first murder mystery case""", 'informal'),
  62. ]
  63.  
  64. import re
  65.  
  66.  
  67. def get_words(doc, words_to_ignore=None):
  68.     """Поделба на документот на зборови. Стрингот се дели на зборови според
  69.    празните места и интерпукциските знаци
  70.  
  71.    :param doc: документ
  72.    :type doc: str
  73.    :return: множество со зборовите кои се појавуваат во дадениот документ
  74.    :rtype: set(str)
  75.    """
  76.     # подели го документот на зборови и конвертирај ги во мали букви
  77.     # па потоа стави ги во резултатот ако нивната должина е >2 и <20
  78.     words = set()
  79.     letters_only = re.sub("[^a-zA-Z]",  # Search for all non-letters
  80.                           " ",  # Replace all non-letters with spaces
  81.                           str(doc))
  82.     for word in re.split('\\W+', letters_only):
  83.         if words_to_ignore is None:
  84.             if 2 < len(word) < 20:
  85.                 words.add(word.lower())
  86.         else:
  87.             if 2 < len(word) < 20 and word.lower() not in words_to_ignore:
  88.                 words.add(word.lower())
  89.     return words
  90.  
  91.  
  92. class DocumentClassifier:
  93.     def __init__(self, get_features):
  94.         # број на парови атрибут/категорија (feature/category)
  95.         self.feature_counts_per_category = {}
  96.         # број на документи во секоја категорија
  97.         self.category_counts = {}
  98.         # функција за добивање на атрибутите (зборовите) во документот
  99.         self.get_features = get_features
  100.  
  101.     def increment_feature_counts_per_category(self, current_feature, current_category):
  102.         """Зголемување на бројот на парови атрибут/категорија
  103.  
  104.        :param current_feature: даден атрибут
  105.        :param current_category: дадена категорија
  106.        :return: None
  107.        """
  108.         self.feature_counts_per_category.setdefault(current_feature, {})
  109.         self.feature_counts_per_category[current_feature].setdefault(current_category, 0)
  110.         self.feature_counts_per_category[current_feature][current_category] += 1
  111.  
  112.     def increment_category_counts(self, cat):
  113.         """Зголемување на бројот на предмети (документи) во категорија
  114.  
  115.        :param cat: категорија
  116.        :return: None
  117.        """
  118.         self.category_counts.setdefault(cat, 0)
  119.         self.category_counts[cat] += 1
  120.  
  121.     def get_feature_counts_per_category(self, current_feature, current_category):
  122.         """Добивање на бројот колку пати одреден атрибут се има појавено во
  123.        одредена категорија
  124.  
  125.        :param current_feature: атрибут
  126.        :param current_category: категорија
  127.        :return: None
  128.        """
  129.         if current_feature in self.feature_counts_per_category \
  130.                 and current_category in self.feature_counts_per_category[current_feature]:
  131.             return float(self.feature_counts_per_category[current_feature][current_category])
  132.         return 0.0
  133.  
  134.     def get_category_count(self, current_category):
  135.         """Добивање на бројот на предмети (документи) во категорија
  136.  
  137.        :param current_category: категорија
  138.        :return: број на предмети (документи)
  139.        """
  140.         if current_category in self.category_counts:
  141.             return float(self.category_counts[current_category])
  142.         return 0
  143.  
  144.     def get_total_count(self):
  145.         """Добивање на вкупниот број на предмети"""
  146.         return sum(self.category_counts.values())
  147.  
  148.     def categories(self):
  149.         """Добивање на листа на сите категории"""
  150.         return self.category_counts.keys()
  151.  
  152.     def train(self, item, current_category, words_to_ignore=None):
  153.         """Тренирање на класификаторот. Новиот предмет (документ)
  154.  
  155.        :param item: нов предмет (документ)
  156.        :param current_category: категорија
  157.        :return: None
  158.        """
  159.         # Се земаат атрибутите (зборовите) во предметот (документот)
  160.         features = self.get_features(item, words_to_ignore)
  161.         # Се зголемува бројот на секој атрибут во оваа категорија
  162.         for current_feature in features:
  163.             self.increment_feature_counts_per_category(current_feature, current_category)
  164.  
  165.         # Се зголемува бројот на предмети (документи) во оваа категорија
  166.         self.increment_category_counts(current_category)
  167.  
  168.     def get_feature_per_category_probability(self, current_feature, current_category):
  169.         """Веројатноста е вкупниот број на пати кога даден атрибут f (збор) се појавил во
  170.        дадена категорија поделено со вкупниот број на предмети (документи) во категоријата
  171.  
  172.        :param current_feature: атрибут
  173.        :param current_category: карактеристика
  174.        :return: веројатност на појавување
  175.        """
  176.         if self.get_category_count(current_category) == 0:
  177.             return 0
  178.         return self.get_feature_counts_per_category(current_feature, current_category) \
  179.                / self.get_category_count(
  180.             current_category)
  181.  
  182.     def weighted_probability(self, current_feature, current_category, prf, weight=1.0, ap=0.5):
  183.         """Пресметка на тежински усогласената веројатност
  184.  
  185.        :param current_feature: атрибут
  186.        :param current_category: категорија
  187.        :param prf: функција за пресметување на основната веројатност
  188.        :param weight: тежина
  189.        :param ap: претпоставена веројатност
  190.        :return: тежински усогласена веројатност
  191.        """
  192.         # Пресметај ја основната веројатност
  193.         basic_prob = prf(current_feature, current_category)
  194.         # Изброј колку пати се има појавено овој атрибут (збор) во сите категории
  195.         totals = sum([self.get_feature_counts_per_category(current_feature, currentCategory) for currentCategory in
  196.                       self.categories()])
  197.         # Пресметај ја тежински усредената веројатност
  198.         bp = ((weight * ap) + (totals * basic_prob)) / (weight + totals)
  199.         return bp
  200.  
  201.  
  202. class NaiveBayes(DocumentClassifier):
  203.     def __init__(self, get_features):
  204.         super().__init__(get_features)
  205.         self.thresholds = {}
  206.  
  207.     def set_threshold(self, current_category, threshold):
  208.         """Поставување на праг на одлучување за категорија
  209.  
  210.        :param current_category: категорија
  211.        :param threshold: праг на одлучување
  212.        :return: None
  213.        """
  214.         self.thresholds[current_category] = threshold
  215.  
  216.     def get_threshold(self, current_category):
  217.         """Добивање на прагот на одлучување за дадена класа
  218.  
  219.        :param current_category: категорија
  220.        :return: праг на одлучување за дадената категорија
  221.        """
  222.         if current_category not in self.thresholds:
  223.             return 1.0
  224.         return self.thresholds[current_category]
  225.  
  226.     def calculate_document_probability_in_class(self, item, current_category, words_to_ignore=None):
  227.         """Ја враќа веројатноста на документот да е од класата current_category
  228.        (current_category е однапред позната)
  229.  
  230.        :param item: документ
  231.        :param current_category: категорија
  232.        :return:
  233.        """
  234.         # земи ги зборовите од документот item
  235.         features = self.get_features(item, words_to_ignore)
  236.         # помножи ги веројатностите на сите зборови
  237.         p = 1
  238.         for currentFeature in features:
  239.             p *= self.weighted_probability(currentFeature, current_category,
  240.                                            self.get_feature_per_category_probability)
  241.  
  242.         return p
  243.  
  244.     def get_category_probability_for_document(self, item, current_category, words_to_ignore=None):
  245.         """Ја враќа веројатноста на класата ако е познат документот
  246.  
  247.        :param item: документ
  248.        :param current_category: категорија
  249.        :return: веројатност за документот во категорија
  250.        """
  251.         cat_prob = self.get_category_count(current_category) / self.get_total_count()
  252.         calculate_document_probability_in_class = self.calculate_document_probability_in_class(item, current_category,
  253.                                                                                                words_to_ignore)
  254.         # Bayes Theorem
  255.         return calculate_document_probability_in_class * cat_prob / (1.0 / self.get_total_count())
  256.  
  257.     def classify_document(self, item, default=None, words_to_ignore=None):
  258.         """Класифицирање на документ
  259.  
  260.        :param item: документ
  261.        :param default: подразбирана (default) класа
  262.        :return:
  263.        """
  264.         probs = {}
  265.         # најди ја категоријата (класата) со најголема веројатност
  266.         max = 0.0
  267.         for cat in self.categories():
  268.             probs[cat] = self.get_category_probability_for_document(item, cat, words_to_ignore)
  269.             if probs[cat] > max:
  270.                 max = probs[cat]
  271.                 best = cat
  272.  
  273.         # провери дали веројатноста е поголема од threshold*next best (следна најдобра)
  274.         for cat in probs:
  275.             if cat == best:
  276.                 continue
  277.             if probs[cat] * self.get_threshold(best) > probs[best]: return default
  278.  
  279.         return best
  280.  
  281.  
  282. import math
  283.  
  284. if __name__ == '__main__':
  285.     sample = input()
  286.  
  287.     number1 = math.floor((40 / 100) * len(train_data))
  288.     number2 = number1 * 2
  289.  
  290.     baesov_classificator1 = train_data[:number1]
  291.     baesov_classificator2 = train_data[number1:number2]
  292.     test_case = train_data[number2:]
  293.  
  294.     train_model1 = NaiveBayes(get_words)
  295.     train_model2 = NaiveBayes(get_words)
  296.  
  297.     for item in baesov_classificator1:
  298.         train_model1.train(item[0], item[1])
  299.  
  300.     for item in baesov_classificator2:
  301.         train_model2.train(item[0], item[1])
  302.  
  303.     counter = 0
  304.     for row in test_case:
  305.         predicted_class1 = train_model1.classify_document(row)
  306.         predicted_class2 = train_model2.classify_document(row)
  307.         if row[-1] == predicted_class1 and row[-1] == predicted_class2 and predicted_class1 == predicted_class2:
  308.             counter += 1
  309.  
  310.  
  311.     accuracy = counter / len(test_case)
  312.     predicted_class1 = train_model1.classify_document(sample)
  313.     predicted_class2 = train_model2.classify_document(sample)
  314.  
  315.     print(accuracy)
  316.     if predicted_class1 == predicted_class2:
  317.         print(predicted_class1)
  318.     else:
  319.         print("unknown")
Add Comment
Please, Sign In to add comment