Naive Bayes

Naive Bayes

Naive Bayes algoritması, olasılık teorisine dayalı, basit ve hızlı bir makine öğrenme algoritmasıdır. Özellikle sınıflandırma problemlerinde sıkça kullanılır. Algoritmanın temel prensibi, Bayes Teoremi’ne dayanarak sınıf olasılıklarını tahmin etmektir.

Naive Bayes, bağımsızlık varsayımı (naive assumption) yapar; yani bir veri kümesindeki özelliklerin birbirinden bağımsız olduğunu kabul eder. Bu, gerçek dünyada nadiren doğru olsa da, birçok problemde etkili sonuçlar verir.

Naive Bayes, adını iki temel varsayımdan alır:

1. Bayes Teoremi

Naive Bayes algoritması Bayes Teoremi’ni temel alır. Bayes Teoremi, bir olayın olasılığını, o olaya ait gözlemlere ve diğer ilgili olayların olasılıklarına dayanarak hesaplamamıza olanak tanır. Formülü şu şekildedir: \[P(C|X) = \frac{P(X|C) * P(C)}{P(X)}\]

  • \(P(C\|X)\) : \(X\) olayının gerçekleştiği bilindiğinde \(C\) olayının gerçekleşme olasılığıdır. Yani \(X\) verisinin sınıfı \(C\) olma olasılığıdır.
  • \(P(X\|C)\) : \(C\) olayının gerçekleştiği bilindiğinde \(X\) olayının gerçekleşme olasılığıdır. Yani sınıf \(C\) verildiğinde \(X\) verisinin gözlenme olasılığıdır.
  • \(P(C)\) : Sınıf \(C\) olasılığı.
  • \(P(X)\) : \(X\) verisinin gözlenme olasılığı.

2. Naive Varsayım (Bağımsızlık Varsayımı):

Naive Bayes’in en önemli varsayımı, tüm özelliklerin (feature) birbirinden bağımsız olduğudur. Yani bir özelliğin değeri, diğer özelliklerin değeriyle bağımsızdır. Bu varsayım genellikle gerçek dünyada nadiren geçerlidir, ancak yine de çoğu durumda algoritmanın iyi performans göstermesine engel olmaz.

Naive Bayes Algoritması Türleri

Naive Bayes algoritmasının birkaç çeşidi vardır ve farklı veri dağılımlarına göre uygulanır:

Gaussian Naive Bayes

Özellikler sürekli olduğunda ve normal dağılıma uygun olduğunda kullanılır.

Multinomial Naive Bayes

Belirli sayıda kategoriye sahip veriler için kullanılır. Özellikle metin sınıflandırma problemlerinde yaygın olarak kullanılır. Kelime sayımı gibi verilerle çalışır.

Bernoulli Naive Bayes

İkili (binary) veriler için uygundur.

Avantajları

  • Hızlı ve Verimli: Hesaplama açısından çok hızlıdır ve büyük veri setleriyle bile iyi ölçeklenir.
  • Az Veriyle İyi Sonuçlar: Özellikle veri seti küçükken dahi iyi sonuçlar verebilir.
  • Kolay Uygulama: Scikit-learn gibi kütüphaneler sayesinde kolayca uygulanabilir.
  • Yüksek boyutlu verilerle iyi başa çıkar.

Dezavantajları

  • Bağımsızlık Varsayımı: Özelliklerin birbirinden bağımsız olması varsayımı gerçek dünyada genellikle geçerli olmadığından bazen yanıltıcı olabilir.
  • Sürekli Veriler İçin Zayıflık: Gaussian Naive Bayes dışında, genellikle sürekli verilerle çalışmada zayıf performans gösterebilir.

Sample App

Şimdi Naive Bayes algoritması ile sınıflandırma yaparak diabet hastalığını tahmin eden bir model geliştirelim.

Dataset

About Dataset

Bu veriseti 768 gözlem ve 8 sayısal bağımsız değişkenden oluşmaktadır.

Bağımlu ve hedef değişken OUTCOME (sonuç)’dur.

  • 1 diabet testi sonucunun pozitif,
  • 0 ise diabet testi sonucunun negtif olduğunu gösterir.

  • Pregnancies: Hastanın kaç kere hamile kaldığını gösterir.
  • Glucose: 2 saatlik oral glukoz tolerans testinde plazma glukoz konsantrasyonu.
  • BloodPressure: Diastolic kan basıncı (mm Hg)
  • SkinThickness: Triceps cilt kıvrımı kalınlığı (mm).
  • Insulin: 2 saatlik serum insülin düzeyi (mu U/ml).
  • BMI: Vücut kitle indeksi (ağırlık kg / boy m²).
  • DiabetesPedigreeFunction: Aile geçmişine dayalı olarak diyabet olasılığını hesaplayan bir fonksiyon.
  • Age: Hastanın yaşı.
  • Outcome: Diyabet durumu (0 = diyabet yok, 1 = diyabet var).

Import the necessary modules and libraries

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler

# Models
from sklearn.naive_bayes import GaussianNB

#Performance metrices
from sklearn.metrics import confusion_matrix, accuracy_score,classification_report

#For ignoring warnings
import warnings
warnings.filterwarnings("ignore")

Load the Data

data = pd.read_csv('diabetes.csv')

print(data.head())
   Pregnancies  Glucose  BloodPressure  SkinThickness  Insulin   BMI  \
0            6      148             72             35        0  33.6   
1            1       85             66             29        0  26.6   
2            8      183             64              0        0  23.3   
3            1       89             66             23       94  28.1   
4            0      137             40             35      168  43.1   

   DiabetesPedigreeFunction  Age  Outcome  
0                     0.627   50        1  
1                     0.351   31        0  
2                     0.672   32        1  
3                     0.167   21        0  
4                     2.288   33        1  

checking the number of rows and columns

print(data.shape)
(768, 9)
# getting the some information about the data

print(data.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 768 entries, 0 to 767
Data columns (total 9 columns):
 #   Column                    Non-Null Count  Dtype  
---  ------                    --------------  -----  
 0   Pregnancies               768 non-null    int64  
 1   Glucose                   768 non-null    int64  
 2   BloodPressure             768 non-null    int64  
 3   SkinThickness             768 non-null    int64  
 4   Insulin                   768 non-null    int64  
 5   BMI                       768 non-null    float64
 6   DiabetesPedigreeFunction  768 non-null    float64
 7   Age                       768 non-null    int64  
 8   Outcome                   768 non-null    int64  
dtypes: float64(2), int64(7)
memory usage: 54.1 KB
None
# checking for the missing values
print(data.isnull().sum())
Pregnancies                 0
Glucose                     0
BloodPressure               0
SkinThickness               0
Insulin                     0
BMI                         0
DiabetesPedigreeFunction    0
Age                         0
Outcome                     0
dtype: int64
# Check number of unique values in each column
for i in data.columns:
    print(i, len(data[i].unique()))
Pregnancies 17
Glucose 136
BloodPressure 47
SkinThickness 51
Insulin 186
BMI 248
DiabetesPedigreeFunction 517
Age 52
Outcome 2
# Descriptive statistics
print(data.describe())
       Pregnancies     Glucose  BloodPressure  SkinThickness     Insulin  \
count   768.000000  768.000000     768.000000     768.000000  768.000000   
mean      3.845052  120.894531      69.105469      20.536458   79.799479   
std       3.369578   31.972618      19.355807      15.952218  115.244002   
min       0.000000    0.000000       0.000000       0.000000    0.000000   
25%       1.000000   99.000000      62.000000       0.000000    0.000000   
50%       3.000000  117.000000      72.000000      23.000000   30.500000   
75%       6.000000  140.250000      80.000000      32.000000  127.250000   
max      17.000000  199.000000     122.000000      99.000000  846.000000   

              BMI  DiabetesPedigreeFunction         Age     Outcome  
count  768.000000                768.000000  768.000000  768.000000  
mean    31.992578                  0.471876   33.240885    0.348958  
std      7.884160                  0.331329   11.760232    0.476951  
min      0.000000                  0.078000   21.000000    0.000000  
25%     27.300000                  0.243750   24.000000    0.000000  
50%     32.000000                  0.372500   29.000000    0.000000  
75%     36.600000                  0.626250   41.000000    1.000000  
max     67.100000                  2.420000   81.000000    1.000000  
# Check the distribution of the target variable
print(data['Outcome'].value_counts())
Outcome
0    500
1    268
Name: count, dtype: int64

Graphical Analysis of Data

# correlation matrix
corr = data.corr()

plt.figure(figsize=(20,10))
sns.heatmap(corr, annot=True, cmap='BuPu')
plt.show()

correlation matrix for diabetes dataset

Korelasyon ısı haritasına göre;

  • Glukoz ve Outcome (diyabet durumu) arasında pozitif bir korelasyon bulunuyor, yani yüksek glukoz seviyeleri diyabetle daha çok ilişkili.
  • BMI ve Outcome arasında da bir ilişki mevcut, ancak daha zayıf.
  • Pregnancies ve outcome arasındada zayıf bir ilişki var ancak bu sütunu çıkartıyorum.
data.drop('Pregnancies', axis=1, inplace=True)
plt.figure(figsize=(8,8))
plt.scatter(data['Glucose'],data['Outcome'])
plt.xlabel('Glucose')
plt.ylabel('Diabetes')
plt.title('Glucose vs Diabetes')
plt.grid()

glucos vs diabetes

plt.figure(figsize=(8,8))
plt.scatter(data['Insulin'],data['Outcome'])
plt.xlabel('Insulin')
plt.ylabel('Diabetes')
plt.title('Insulin vs Diabetes')
plt.grid()

insulin vs diabetes

Count of Glucose

plt.figure(figsize=(40,20),dpi=90)
ax=sns.countplot(x='Glucose',data=data)
plt.xticks(rotation=90, fontsize=20)
plt.yticks(fontsize=20)
plt.xlabel('Glucose',fontsize=20)
plt.ylabel('Diabetes',fontsize=20)
plt.title('count of Glucose',fontsize=30)
plt.grid()

count of glucose

Count of BloodPressure

plt.figure(figsize=(40,20),dpi=90)
ax=sns.countplot(x='BloodPressure',data=data)
plt.xticks(rotation=90, fontsize=20)
plt.yticks(fontsize=20)
plt.xlabel('BloodPressure',fontsize=20)
plt.ylabel('Diabetes',fontsize=20)
plt.title('count of BloodPressure',fontsize=30)
plt.grid()

count of BloodPressure

Count of Age

plt.figure(figsize=(40,20),dpi=90)
ax=sns.countplot(x='Age',data=data)
plt.xticks(rotation=90, fontsize=20)
plt.yticks(fontsize=20)
plt.xlabel('Age',fontsize=20)
plt.ylabel('Diabetes',fontsize=20)
plt.title('count of Age',fontsize=30)
plt.grid()

count of age

Count of SkinThickness

plt.figure(figsize=(40,20),dpi=90)
ax=sns.countplot(x='SkinThickness',data=data)
plt.xticks(rotation=90, fontsize=20)
plt.yticks(fontsize=20)
plt.xlabel('SkinThickness',fontsize=20)
plt.ylabel('Diabetes',fontsize=20)
plt.title('count of SkinThickness',fontsize=30)
plt.grid()

count of SkinThickness

Grafikdende anlaşılacağı üzere cilt kalınlığı 0 olan aykırı değerleri çıkartıyorum.

# drop the outliers
data=data[data['SkinThickness']>0]
data=data[data['SkinThickness']<90]
plt.figure(figsize=(40,20),dpi=90)
ax=sns.countplot(x='SkinThickness',data=data)
plt.xticks(rotation=90, fontsize=20)
plt.yticks(fontsize=20)
plt.xlabel('SkinThickness',fontsize=20)
plt.ylabel('Diabetes',fontsize=20)
plt.title('count of SkinThickness',fontsize=30)
plt.grid()

count of SkinThickness

data.dropna(how='any', inplace=True) # drop the missing values

data.reset_index(drop=True, inplace=True) # reset the index
# last shape of the data
print(data.shape)
(540, 8)

pairplot

sns.pairplot(data=data, diag_kind='kde', hue='Outcome',palette='copper')
plt.show()

pairplot of diabetes dataset

Normalization

scaler = MinMaxScaler()
data_scaled = scaler.fit_transform(data)

data_scaled = pd.DataFrame(data_scaled, columns=data.columns)

Separating the independent and dependent variables

x = data_scaled.drop('Outcome', axis=1)
y = data_scaled['Outcome']

Splitting the data

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.35, random_state=0)

Create a Gaussian Classifier

model = GaussianNB()
model.fit(x_train, y_train)
GaussianNB()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.

Prediction

# Predict the response for test dataset
y_pred = model.predict(x_test)

Model Accuracy

print("Accuracy:", accuracy_score(y_test, y_pred))
Accuracy: 0.7671957671957672

confusion matrix

cm = confusion_matrix(y_test, y_pred)

plt.figure(figsize=(8,8))
sns.heatmap(cm, annot=True, fmt='d', cmap='BuPu', xticklabels=['No Diabetes', 'Diabetes'], yticklabels=['No Diabetes', 'Diabetes'])
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Confusion Matrix')
plt.show()

confusion matrix

classification report

print(classification_report(y_test, y_pred))
              precision    recall  f1-score   support

         0.0       0.84      0.81      0.83       128
         1.0       0.63      0.67      0.65        61

    accuracy                           0.77       189
   macro avg       0.73      0.74      0.74       189
weighted avg       0.77      0.77      0.77       189

Example patient

patient = [[0.6, 0.8, 0.56, 0.4, 0.5, 0.6, 0.7]]

# Making prediction
pred = model.predict(patient)

if pred[0] == 0:
    print('The patient is not diabetic')
else:
    print('The patient is diabetic')
The patient is diabetic

0.77 accuracy değerine sahip kabul edilebilir ölçüde bir model oluşturduk.

Son olarak örnek hastanın değerleri verildğinde, modelimiz bu hastanın diabet hastası olduğunu öngördü.