Девятый алгоритм из цикла «Топ-10 data mining адгоритмов» — Naive Bayes.
Наивный байесовский классификатор – это семейство алгоритмов классификации, которые принимают одно допущение: Каждый параметр классифицируемых данных рассматривается независимо от других параметров класса.
Что означает слово «независимо»? 2 параметра называются независимыми, когда значение одного параметра не оказывает влияния на второй.
Например:
Скажем, у вас есть набор данных о пациенте: пульс, уровень холестерина, вес, рост и почтовый индекс. Все параметры будут независимыми, если значения всех параметров не оказывают эффекта друг на друга. Для этого набора данных разумно предположить, что рост пациента и почтовый индекс независимы, поскольку рост человека и его почтовый индекс никак не связаны.
Но давайте посмотрим дальше, все ли параметры независимы?
К сожалению, ответ – нет. Есть 3 соотношения, которые зависимы:
Обычно параметры набора данных не являются полностью независимыми.
Почему метод называется наивным? Предположение, что все параметры набора данных независимы – это довольно наивное предположение. Обычно так не бывает.
Кто такой Байес? Томас Байес был английским математиком-статистиком, в честь которого была названа теорема Байеса.
По сути, теорема позволяет нам предсказать класс на основании набора параметров, используя вероятность.
Упрощенное уравнение для классификации выглядит так:
Давайте взглянем на него поподробнее.
Что означает это уравнение? Уравнение находит вероятность класса А, на основании параметров 1 и 2. Другими словами, если вы видите параметры 1 и 2, то, вероятно, это данные класса А.
Уравнение читается следующим образом: Вероятность [выявления] класса А на основании параметров 1 и 2 – это дробь.
Числитель дроби – это вероятность параметра 1, принадлежащего классу А, умноженная на вероятность параметра 2, принадлежащего классу А, умноженная на вероятность класса А.
Знаменатель – это вероятность параметра 1 умноженная на вероятность параметра 2.
Есть какой-нибудь пример реализации наивного байесовского классификатора? Ниже представлен отличный пример, взятый из треда Stack Overflow.
Вот условия:
Что мы видим в этом тренировочном наборе данных?
Если мы получим только параметры – длину, сладость и цвет фрукта (не зная его класса), то сможем вычислить вероятность того, что фрукт окажется бананом, апельсином или чем-то другим.
Предположим, что неизвестный фрукт длинный, сладкий и желтый.
Для вычисления вероятности нужно проделать 4 простых шага:
Шаг 1: Чтобы вычислить вероятность того, что неизвестный фрукт – это банан, давайте сначала решим, похож ли этот фрукт на банан. Вот как вычисляется вероятность класса «Банан» на основании параметров «длинный», «сладкий», «желтый»:
P(Banana|Long, Sweet, Yellow)
Выглядит точно так же как уравнение, описанное выше.
Шаг 2: Начнем с числителя и подставим все значения в уравнение:
P(Long|Banana) = 400/500 = 0.8
P(Sweet|Banana) = 350/500 = 0.7
P(Yellow|Banana) = 450/500 = 0.9
P(Banana) = 500/1000 = 0.5
Перемножив значения (согласно уравнению), мы получим:
0.8 x 0.7 x 0.9 x 0.5 = 0.252
Шаг 3: Проигнорируем знаменатель, поскольку он будет одинаковым для всех последующих вычислений.
Шаг 4: Проделаем те же вычисления для других классов:
P(Orange|Long, Sweet, Yellow) = 0
P(Other|Long, Sweet, Yellow) = 0.01875
Поскольку 0,252 больше, чем 0,01875, то наивный байесовский алгоритм классифицирует этот длинный, сладкий и желтый фрукт как банан.
Требует ли этот метод обучения или он самообучающийся? Этот метод требует обучения, поскольку алгоритм использует размеченный набор данных для построения таблицы.
Почему стоит использовать наивный байесовский классификатор? Как вы можете заметить в примере выше, алгоритм состоит из простой арифметики. Это простые вычисления: умножение и деление.
Когда частотные таблицы уже вычислены, классификация неизвестного фрукта включает в себя только вычисления вероятностей для всех классов, а затем выбор наибольшей вероятности.
Несмотря на простоту, наивный байесовский алгоритм может быть удивительно точным. Например, было установлено, что он может быть успешно применен для фильтрации спама.
Где он используется? Реализации алгоритма могут быть найдены в Orange, scikit-learn, Weka и R.
Байесовский классификатор (видео)
Байесовский классификатор в примерах (видео)
Реализация Naive Bayes в R
Пример 1. Пакет «e1071»
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
library(e1071) ## Categorical data only: data(HouseVotes84) model <- naiveBayes(Class ~ ., data = HouseVotes84) predict(model, HouseVotes84[1:10,-1]) predict(model, HouseVotes84[1:10,-1], type = "raw") pred <- predict(model, HouseVotes84[,-1]) table(pred, HouseVotes84$Class) ## Example of using a contingency table: data(Titanic) m <- naiveBayes(Survived ~ ., data = Titanic) m predict(m, as.data.frame(Titanic)[,1:3]) ## Example with metric predictors: data(iris) m <- naiveBayes(Species ~ ., data = iris) ## alternatively: m <- naiveBayes(iris[,-5], iris[,5]) m table(predict(m, iris[,-5]), iris[,5]) |
Пример 2. Классификация ирисов
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
library(e1071) library(caret) head(iris) names(iris) # we assign the data from column 1-4 (features) to variable x, and the class to variable y x = iris[,-5] y = iris$Species model = train(x,y,'nb',trControl=trainControl(method='cv',number=10)) # Show the summary model model # use predict for getting prediction value, and result class predict(model$finalModel,x) # we need to know how many error classified, so we need to compare the result of prediction with the class/iris species table(predict(model$finalModel,x)$class,y) # to plot the features with Naive Bayes naive_iris <- NaiveBayes(iris$Species ~ ., data = iris) plot(naive_iris) |
Другие примеры и использование пакета «naivebayes» здесь
Реализация Naive Bayes на Питоне
Пример 1. Простой (Гаусс)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#Import Library of Gaussian Naive Bayes model from sklearn.naive_bayes import GaussianNB import numpy as np #assigning predictor and target variables x= np.array([[-3,7],[1,5], [1,2], [-2,0], [2,3], [-4,0], [-1,1], [1,1], [-2,2], [2,7], [-4,1], [-2,7]]) Y = np.array([3, 3, 3, 3, 4, 3, 3, 4, 3, 4, 4, 4]) #Create a Gaussian Classifier model = GaussianNB() # Train the model using the training sets model.fit(x, y) #Predict Output predicted= model.predict([[1,2],[3,4]]) print predicted |
Пример 2. Фильтрация спама в e-mail (+ сравнение Naive Bayes и SVM)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# creating word dictionary def make_Dictionary(train_dir): emails = [os.path.join(train_dir,f) for f in os.listdir(train_dir)] all_words = [] for mail in emails: with open(mail) as m: for i,line in enumerate(m): if i == 2: #Body of email is only 3rd line of text file words = line.split() all_words += words dictionary = Counter(all_words) list_to_remove = dictionary.keys() for item in list_to_remove: if item.isalpha() == False: del dictionary[item] elif len(item) == 1: del dictionary[item] dictionary = dictionary.most_common(3000) return dictionary #feature extraction process def extract_features(mail_dir): files = [os.path.join(mail_dir,fi) for fi in os.listdir(mail_dir)] features_matrix = np.zeros((len(files),3000)) docID = 0; for fil in files: with open(fil) as fi: for i,line in enumerate(fi): if i == 2: words = line.split() for word in words: wordID = 0 for i,d in enumerate(dictionary): if d[0] == word: wordID = i features_matrix[docID,wordID] = words.count(word) docID = docID + 1 return features_matrix # training the classifiers import os import numpy as np from collections import Counter from sklearn.naive_bayes import MultinomialNB, GaussianNB, BernoulliNB from sklearn.svm import SVC, NuSVC, LinearSVC # Create a dictionary of words with its frequency train_dir = 'train-mails' dictionary = make_Dictionary(train_dir) # Prepare feature vectors per training mail and its labels train_labels = np.zeros(702) train_labels[351:701] = 1 train_matrix = extract_features(train_dir) # Training SVM and Naive bayes classifier model1 = MultinomialNB() model2 = LinearSVC() model1.fit(train_matrix,train_labels) model2.fit(train_matrix,train_labels) # Test the unseen mails for Spam test_dir = 'test-mails' test_matrix = extract_features(test_dir) test_labels = np.zeros(260) test_labels[130:260] = 1 result1 = model1.predict(test_matrix) result2 = model2.predict(test_matrix) print confusion_matrix(test_labels,result1) print confusion_matrix(test_labels,result2) |
Источник примера 2 и датасет здесь