18.9. Naif (Saf) Bayes¶ Open the notebook in SageMaker Studio Lab
Önceki bölümler boyunca, olasılık teorisi ve rastgele değişkenler hakkında bilgi edindik. Bu teoriyi uygulamaya koymak için, naif Bayes sınıflandırıcısını tanıtalım. Bu, rakamların sınıflandırmasını yapmamıza izin vermek için olasılık temellerinden başka hiçbir şey kullanmaz.
Öğrenme tamamen varsayımlarda bulunmakla ilgilidir. Daha önce hiç görmediğimiz yeni bir veri örneğini sınıflandırmak istiyorsak, hangi veri örneklerinin birbirine benzer olduğuna dair bazı varsayımlar yapmalıyız. Popüler ve oldukça net bir algoritma olan naif Bayes sınıflandırıcı, hesaplamayı basitleştirmek için tüm özniteliklerin birbirinden bağımsız olduğunu varsayar. Bu bölümde, imgelerdeki karakterleri tanımak için bu modeli uygulayacağız.
%matplotlib inline
import math
from d2l import mxnet as d2l
from mxnet import gluon, np, npx
npx.set_np()
d2l.use_svg_display()
%matplotlib inline
import math
import torch
import torchvision
from d2l import torch as d2l
d2l.use_svg_display()
%matplotlib inline
import math
import tensorflow as tf
from d2l import tensorflow as d2l
d2l.use_svg_display()
18.9.1. Optik Karakter Tanıma¶
MNIST (LeCun et al., 1998), yaygın olarak kullanılan veri kümelerinden biridir. Eğitim için 60.000 imge ve geçerleme için 10.000 imge içerir. Her imge, 0’dan 9’a kadar el yazısıyla yazılmış bir rakam içerir. Görev, her imgeyi karşılık gelen rakama sınıflandırmaktır.
Gluon, veri kümesini İnternet’ten otomatik olarak almak için
data.vision
modülünde bir MNIST
sınıfı sağlar. Daha sonra, Gluon
hali-hazırda indirilmiş yerel kopyayı kullanacaktır. train
parametresinin değerini sırasıyla True
veya False
olarak
ayarlayarak eğitim kümesini mi yoksa test kümesini mi talep ettiğimizi
belirtiriz. Her resim, hem genişliği hem de yüksekliği \(28\) olan
ve (\(28\), \(28\), \(1\)) şekilli gri tonlamalı bir
resimdir. Son kanal boyutunu kaldırmak için özelleştirilmiş bir dönüşüm
kullanıyoruz. Ek olarak, veri kümesi her pikseli işaretsiz \(8\)
bitlik bir tamsayı ile temsil eder. Problemi basitleştirmek için bunları
ikili öznitelikler halinde nicelendiriyoruz.
def transform(data, label):
return np.floor(data.astype('float32') / 128).squeeze(axis=-1), label
mnist_train = gluon.data.vision.MNIST(train=True, transform=transform)
mnist_test = gluon.data.vision.MNIST(train=False, transform=transform)
data_transform = torchvision.transforms.Compose([
torchvision.transforms.ToTensor(),
lambda x: torch.floor(x * 255 / 128).squeeze(dim=0)
])
mnist_train = torchvision.datasets.MNIST(
root='./temp', train=True, transform=data_transform, download=True)
mnist_test = torchvision.datasets.MNIST(
root='./temp', train=False, transform=data_transform, download=True)
((train_images, train_labels), (
test_images, test_labels)) = tf.keras.datasets.mnist.load_data()
# MNIST'in orijinal piksel değerleri 0-255 arasındadır (rakamlar uint8 olarak depolandığından).
# Bu bölüm için (orijinal imgede) 128'den büyük piksel değerleri 1'e,
# 128'den küçük değerler 0'a dönüştürülür. Nedeni için bölüm 18.9.2 ve 18.9.3'e bakın.
train_images = tf.floor(tf.constant(train_images / 128, dtype = tf.float32))
test_images = tf.floor(tf.constant(test_images / 128, dtype = tf.float32))
train_labels = tf.constant(train_labels, dtype = tf.int32)
test_labels = tf.constant(test_labels, dtype = tf.int32)
İmgeyi ve ilgili etiketi içeren belirli bir örneğe erişebiliriz.
image, label = mnist_train[2]
image.shape, label
((28, 28), array(4, dtype=int32))
image, label = mnist_train[2]
image.shape, label
(torch.Size([28, 28]), 4)
image, label = train_images[2], train_labels[2]
image.shape, label.numpy()
(TensorShape([28, 28]), 4)
Burada image
değişkeninde saklanan örneğimiz, yüksekliği ve
genişliği \(28\) piksel olan bir imgeye karşılık gelir.
image.shape, image.dtype
((28, 28), dtype('float32'))
image.shape, image.dtype
(torch.Size([28, 28]), torch.float32)
image.shape, image.dtype
(TensorShape([28, 28]), tf.float32)
Kodumuz her imgenin etiketini sayıl olarak depolar. Türü \(32\) bitlik bir tamsayıdır.
label, type(label), label.dtype
(array(4, dtype=int32), mxnet.numpy.ndarray, dtype('int32'))
label, type(label)
(4, int)
label.numpy(), label.dtype
(4, tf.int32)
Aynı anda birden fazla örneğe de erişebiliriz.
images, labels = mnist_train[10:38]
images.shape, labels.shape
((28, 28, 28), (28,))
images = torch.stack([mnist_train[i][0] for i in range(10, 38)], dim=0)
labels = torch.tensor([mnist_train[i][1] for i in range(10, 38)])
images.shape, labels.shape
(torch.Size([28, 28, 28]), torch.Size([28]))
images = tf.stack([train_images[i] for i in range(10, 38)], axis=0)
labels = tf.constant([train_labels[i].numpy() for i in range(10, 38)])
images.shape, labels.shape
(TensorShape([28, 28, 28]), TensorShape([28]))
Bu örnekleri görselleştirelim.
d2l.show_images(images, 2, 9);
d2l.show_images(images, 2, 9);
d2l.show_images(images, 2, 9);
18.9.2. Sınıflandırma için Olasılık Modeli¶
Bir sınıflandırma görevinde, bir örneği bir kategoriye eşleriz. Burada bir örnek gri tonlamalı \(28\times 28\) imge ve kategori bir rakamdır. (Daha ayrıntılı bir açıklama için bakınız Section 3.4.) Sınıflandırma görevini ifade etmenin doğal bir yolu, olasılık sorusudur: Özellikler (yani, imge pikselleri) verildiğinde en olası etiket nedir? \(\mathbf x\in\mathbb R^d\) ile örneğin özniteliklerini ve \(y\in\mathbb R\) ile etiketini belirtiriz. Burada öznitelikler, \(2\) boyutlu bir imgeyi \(d = 28 ^ 2 = 784\) büyüklüğünde bir vektöre yeniden şekillendirebileceğimiz imge pikselleri ve etiketler rakamlardır. Öznitelikleri verilen etiketin olasılığı \(p(y \mid \mathbf{x})\) şeklindedir. Örneğimizde \(y=0, \ldots, 9\) için \(p(y \mid \mathbf{x})\) olan bu olasılıkları hesaplayabilirsek, sınıflandırıcı aşağıda verilen ifade ile tahminini, \(\hat{y}\), yapacaktır:
Maalesef bu, her \(\mathbf{x} = x_1, ..., x_d\) değeri için \(p(y \mid \mathbf{x})\)’yi tahmin etmemizi gerektirir. Her özniteliğin \(2\) değerden birini alabileceğini düşünün. Örneğin, \(x_1 = 1\) özniteliği, elma kelimesinin belirli bir belgede göründüğünü ve \(x_1 = 0\) görünmediğini belirtebilir. Eğer \(30\) tane bu tür ikili özniteliğe sahip olsaydık, bu \(\mathbf{x}\) girdi vektörünün \(2^{30}\) (1 milyardan fazla!) olası değerlerinden herhangi birini sınıflandırmaya hazırlıklı olmamız gerektiği anlamına gelirdi.
Dahası, öğrenme nerede? İlgili etiketi tahmin etmek için her bir olası örneği görmemiz gerekiyorsa, o zaman gerçekten bir model öğrenmiyoruz, sadece veri kümesini ezberliyoruz.
18.9.3. Naif Bayes Sınıflandırıcı¶
Neyse ki, koşullu bağımsızlık hakkında bazı varsayımlar yaparak, bazı tümevarımsal önyargılar sunabilir ve nispeten mütevazı bir eğitim örnekleri seçiminden genelleme yapabilen bir model oluşturabiliriz. Başlamak için, sınıflandırıcıyı şu şekilde ifade etmede Bayes teoremini kullanalım:
Paydanın normalleştirme teriminin \(p(\mathbf{x})\) olduğunu ve \(y\) etiketinin değerine bağlı olmadığını unutmayın. Sonuç olarak, sadece payı farklı \(y\) değerlerinde karşılaştırken endişelenmemiz gerekiyor. Paydanın hesaplanmasının zorlu olduğu ortaya çıksa bile, payı değerlendirebildiğimiz sürece onu görmezden gelerek kurtulabilirdik. Neyse ki, normalleştirme sabitini kurtarmak istesek, bunu da yapabilirdik. Normalleştirme terimini \(\sum_y p(y \mid \mathbf{x}) = 1\) olduğundan her zaman kurtarabiliriz.
Şimdi \(p( \mathbf{x} \mid y)\) üzerine odaklanalım. Zincir olasılık kuralını kullanarak \(p( \mathbf{x} \mid y)\) terimini şu şekilde ifade edebiliriz:
Tek başına bu ifade bizi daha ileriye götürmez. Yine de kabaca \(2^d\) tane parametreyi tahmin etmeliyiz. Bununla birlikte, etiketi verildiğinde özniteliklerin koşullu olarak birbirinden bağımsız olduğunu varsayarsak, aniden çok daha iyi durumda oluruz, çünkü bu terim \(\prod_i p(x_i \mid y)\)’a sadeleşerek bize şu tahminciyi verir:
Her \(i\) ve \(y\) için \(p(x_i=1 \mid y)\) tahmin edebilir ve değerini \(P_{xy}[i, y]\) olarak kaydedebilirsek, burada \(P_{xy}\) \(n\) sınıf sayısı ve \(y\in\{1, \ldots, n\}\) olan bir \(d\times n\) matrisidir, o zaman bunu \(p(x_i = 0 \mid y)\)’i tahmin etmek için de kullanabiliriz, yani
Ayrıca, her \(y\) için \(p(y)\) tahmininde bulunur ve \(n\) uzunluğunda bir \(P_y\) vektörü ile, \(P_y[y]\)’a kaydederiz. Ardından, herhangi bir yeni örnek \(\mathbf t = (t_1, t_2, \ldots, t_d)\) için şunu hesaplayabiliriz;
üstelik herhangi bir \(y\) için. Dolayısıyla, koşullu bağımsızlık varsayımımız, modelimizin karmaşıklığını öznitelik sayısına bağlı \(\mathcal{O}(2^dn)\) üstel bir bağımlılıktan \(\mathcal{O}(dn)\) olan doğrusal bir bağımlılığa almıştır.
18.9.4. Eğitim¶
Şimdi sorun, \(P_{xy}\) ve \(P_y\)’yi bilmiyor olmamızdır. Bu nedenle, önce bazı eğitim verileri verildiğinde bu değerleri tahmin etmemiz gerekiyor. Bu, modeli eğitmektir. \(P_y\)’yi tahmin etmek çok zor değil. Sadece \(10\) sınıfla uğraştığımız için, her rakam için görülme sayısını, \(n_y\), sayabilir ve bunu toplam veri miktarına \(n\) bölebiliriz. Örneğin, 8 rakamı \(n_8 = 5.800\) kez ortaya çıkarsa ve toplam \(n = 60.000\) imgemiz varsa, olasılık tahminimiz \(p(y=8) = 0.0967\) olur.
X, Y = mnist_train[:] # Tüm eğitim örnekleri
n_y = np.zeros((10))
for y in range(10):
n_y[y] = (Y == y).sum()
P_y = n_y / n_y.sum()
P_y
array([0.09871667, 0.11236667, 0.0993 , 0.10218333, 0.09736667,
0.09035 , 0.09863333, 0.10441667, 0.09751666, 0.09915 ])
X = torch.stack([mnist_train[i][0] for i in range(len(mnist_train))], dim=0)
Y = torch.tensor([mnist_train[i][1] for i in range(len(mnist_train))])
n_y = torch.zeros(10)
for y in range(10):
n_y[y] = (Y == y).sum()
P_y = n_y / n_y.sum()
P_y
tensor([0.0987, 0.1124, 0.0993, 0.1022, 0.0974, 0.0904, 0.0986, 0.1044, 0.0975,
0.0992])
X = train_images
Y = train_labels
n_y = tf.Variable(tf.zeros(10))
for y in range(10):
n_y[y].assign(tf.reduce_sum(tf.cast(Y == y, tf.float32)))
P_y = n_y / tf.reduce_sum(n_y)
P_y
<tf.Tensor: shape=(10,), dtype=float32, numpy=
array([0.09871667, 0.11236667, 0.0993 , 0.10218333, 0.09736667,
0.09035 , 0.09863333, 0.10441667, 0.09751666, 0.09915 ],
dtype=float32)>
Şimdi biraz daha zor şeylere, \(P_{xy}\)’ye, geçelim. Siyah beyaz imgeler seçtiğimiz için, \(p(x_i \mid y)\), \(i\) pikselinin \(y\) sınıfı için açık olma olasılığını gösterir. Tıpkı daha önce olduğu gibi, bir olayın meydana geldiği \(n_{iy}\) sayısını sayabilmemiz ve bunu \(y\)’nin toplam oluş sayısına bölebilmemiz gibi, yani \(n_y\). Ancak biraz rahatsız edici bir şey var: Belirli pikseller asla siyah olmayabilir (örneğin, iyi kırpılmış imgelerde köşe pikselleri her zaman beyaz olabilir). İstatistikçilerin bu sorunla baş etmeleri için uygun bir yol, tüm oluşumlara sözde sayımlar eklemektir. Bu nedenle, \(n_{iy}\) yerine \(n_{iy} + 1\) ve \(n_y\) yerine \(n_{y} + 1\) kullanıyoruz. Bu aynı zamanda Laplace Düzleştirme (Smoothing) olarak da adlandırılır. Geçici görünebilir, ancak Bayesci bir bakış açısından iyi motive edilmiş olabilir.
n_x = np.zeros((10, 28, 28))
for y in range(10):
n_x[y] = np.array(X.asnumpy()[Y.asnumpy() == y].sum(axis=0))
P_xy = (n_x + 1) / (n_y + 1).reshape(10, 1, 1)
d2l.show_images(P_xy, 2, 5);
n_x = torch.zeros((10, 28, 28))
for y in range(10):
n_x[y] = torch.tensor(X.numpy()[Y.numpy() == y].sum(axis=0))
P_xy = (n_x + 1) / (n_y + 1).reshape(10, 1, 1)
d2l.show_images(P_xy, 2, 5);
n_x = tf.Variable(tf.zeros((10, 28, 28)))
for y in range(10):
n_x[y].assign(tf.cast(tf.reduce_sum(
X.numpy()[Y.numpy() == y], axis=0), tf.float32))
P_xy = (n_x + 1) / tf.reshape((n_y + 1), (10, 1, 1))
d2l.show_images(P_xy, 2, 5);
Bu \(10 \times 28 \times 28\) olasılıkları görselleştirerek (her sınıf için her piksel için) ortalama görünümlü rakamlar elde edebiliriz.
Şimdi yeni bir imgeyi tahmin etmek için (18.9.6) denklemini kullanabiliriz. \(\mathbf x\) verildiğinde, aşağıdaki işlevler her \(y\) için \(p(\mathbf x \mid y)p(y)\)’yi hesaplar.
def bayes_pred(x):
x = np.expand_dims(x, axis=0) # (28, 28) -> (1, 28, 28)
p_xy = P_xy * x + (1 - P_xy)*(1 - x)
p_xy = p_xy.reshape(10, -1).prod(axis=1) # p(x|y)
return np.array(p_xy) * P_y
image, label = mnist_test[0]
bayes_pred(image)
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
def bayes_pred(x):
x = x.unsqueeze(0) # (28, 28) -> (1, 28, 28)
p_xy = P_xy * x + (1 - P_xy)*(1 - x)
p_xy = p_xy.reshape(10, -1).prod(dim=1) # p(x|y)
return p_xy * P_y
image, label = mnist_test[0]
bayes_pred(image)
tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
def bayes_pred(x):
x = tf.expand_dims(x, axis=0) # (28, 28) -> (1, 28, 28)
p_xy = P_xy * x + (1 - P_xy)*(1 - x)
p_xy = tf.math.reduce_prod(tf.reshape(p_xy, (10, -1)), axis=1) # p(x|y)
return p_xy * P_y
image, label = train_images[0], train_labels[0]
bayes_pred(image)
<tf.Tensor: shape=(10,), dtype=float32, numpy=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>
Bu korkunç bir şekilde yanlış gitti! Nedenini bulmak için piksel başına olasılıklara bakalım. Bunlar tipik \(0.001\) ile \(1\) arasındaki sayılardır. \(784\) tanesini çarpıyoruz. Bu noktada, bu sayıları bir bilgisayarda sabit bir aralıkla hesapladığımızı belirtmekte fayda var, dolayısıyla bu kuvvet için de geçerli. Olan şu ki, sayısal küçümenlik (underflow) yaşıyoruz, yani tüm küçük sayıları çarpmak, sıfıra yuvarlanana kadar daha da küçük değerlere yol açar. Bunu teorik bir mesele olarak :numref:`sec_maximum_likelihood içinde tartıştık, ancak burada pratikteki bir vaka olarak açıkça görüyoruz.
O bölümde tartışıldığı gibi, bunu \(\log a b = \log a + \log b\) gerçeğini kullanarak, yani logaritma toplamaya geçerek düzeltiriz. Hem \(a\) hem de \(b\) küçük sayılar olsa bile, logaritma değerleri uygun bir aralıkta olacaktır.
a = 0.1
print('underflow:', a**784)
print('logarithm is normal:', 784*math.log(a))
underflow: 0.0
logarithm is normal: -1805.2267129073316
a = 0.1
print('underflow:', a**784)
print('logarithm is normal:', 784*math.log(a))
underflow: 0.0
logarithm is normal: -1805.2267129073316
a = 0.1
print('underflow:', a**784)
print('logarithm is normal:', 784*tf.math.log(a).numpy())
underflow: 0.0
logarithm is normal: -1805.2267379760742
Logaritma artan bir fonksiyon olduğundan, (18.9.6) denklemini şu şekilde yeniden yazabiliriz:
Aşağıdaki kararlı sürümü uygulayabiliriz:
log_P_xy = np.log(P_xy)
log_P_xy_neg = np.log(1 - P_xy)
log_P_y = np.log(P_y)
def bayes_pred_stable(x):
x = np.expand_dims(x, axis=0) # (28, 28) -> (1, 28, 28)
p_xy = log_P_xy * x + log_P_xy_neg * (1 - x)
p_xy = p_xy.reshape(10, -1).sum(axis=1) # p(x|y)
return p_xy + log_P_y
py = bayes_pred_stable(image)
py
array([-269.0042 , -301.73447, -245.21458, -218.8941 , -193.46907,
-206.10315, -292.54315, -114.62834, -220.35619, -163.18881])
log_P_xy = torch.log(P_xy)
log_P_xy_neg = torch.log(1 - P_xy)
log_P_y = torch.log(P_y)
def bayes_pred_stable(x):
x = x.unsqueeze(0) # (28, 28) -> (1, 28, 28)
p_xy = log_P_xy * x + log_P_xy_neg * (1 - x)
p_xy = p_xy.reshape(10, -1).sum(axis=1) # p(x|y)
return p_xy + log_P_y
py = bayes_pred_stable(image)
py
tensor([-269.0042, -301.7345, -245.2146, -218.8941, -193.4691, -206.1031,
-292.5432, -114.6283, -220.3562, -163.1888])
log_P_xy = tf.math.log(P_xy)
log_P_xy_neg = tf.math.log(1 - P_xy)
log_P_y = tf.math.log(P_y)
def bayes_pred_stable(x):
x = tf.expand_dims(x, axis=0) # (28, 28) -> (1, 28, 28)
p_xy = log_P_xy * x + log_P_xy_neg * (1 - x)
p_xy = tf.math.reduce_sum(tf.reshape(p_xy, (10, -1)), axis=1) # p(x|y)
return p_xy + log_P_y
py = bayes_pred_stable(image)
py
<tf.Tensor: shape=(10,), dtype=float32, numpy=
array([-266.66373, -320.79816, -261.50876, -202.63194, -295.5783 ,
-199.49413, -318.6671 , -266.0148 , -224.60349, -271.93506],
dtype=float32)>
Şimdi tahminin doğru olup olmadığını kontrol edebiliriz.
# Karşılaştırma için int32 dtype skaler tensörü olan etiketi
# Python skaler tamsayısına dönüştürün
py.argmax(axis=0) == int(label)
array(True)
py.argmax(dim=0) == label
tensor(True)
tf.argmax(py, axis=0, output_type = tf.int32) == label
<tf.Tensor: shape=(), dtype=bool, numpy=True>
Şimdi birkaç geçerleme örneği tahmin edersek, Bayes sınıflandırıcısının oldukça iyi çalıştığını görebiliriz.
def predict(X):
return [bayes_pred_stable(x).argmax(axis=0).astype(np.int32) for x in X]
X, y = mnist_test[:18]
preds = predict(X)
d2l.show_images(X, 2, 9, titles=[str(d) for d in preds]);
def predict(X):
return [bayes_pred_stable(x).argmax(dim=0).type(torch.int32).item()
for x in X]
X = torch.stack([mnist_test[i][0] for i in range(18)], dim=0)
y = torch.tensor([mnist_test[i][1] for i in range(18)])
preds = predict(X)
d2l.show_images(X, 2, 9, titles=[str(d) for d in preds]);
def predict(X):
return [tf.argmax(
bayes_pred_stable(x), axis=0, output_type = tf.int32).numpy()
for x in X]
X = tf.stack([train_images[i] for i in range(10, 38)], axis=0)
y = tf.constant([train_labels[i].numpy() for i in range(10, 38)])
preds = predict(X)
d2l.show_images(X, 2, 9, titles=[str(d) for d in preds]);
Son olarak, sınıflandırıcının genel doğruluğunu hesaplayalım.
X, y = mnist_test[:]
preds = np.array(predict(X), dtype=np.int32)
float((preds == y).sum()) / len(y) # Validation accuracy
0.8426
X = torch.stack([mnist_test[i][0] for i in range(len(mnist_test))], dim=0)
y = torch.tensor([mnist_test[i][1] for i in range(len(mnist_test))])
preds = torch.tensor(predict(X), dtype=torch.int32)
float((preds == y).sum()) / len(y) # Validation accuracy
0.8426
X = test_images
y = test_labels
preds = tf.constant(predict(X), dtype=tf.int32)
# Validation accuracy
tf.reduce_sum(tf.cast(preds == y, tf.float32)).numpy() / len(y)
0.8426
Modern derin ağlar \(0.01\)’den daha düşük hata oranlarına ulaşır. Nispeten düşük performans, modelimizde yaptığımız yanlış istatistiksel varsayımlardan kaynaklanmaktadır: Her pikselin yalnızca etikete bağlı olarak bağımsızca oluşturulduğunu varsaydık. İnsanların rakamları böyle yazmadığı açıktır ve bu yanlış varsayım, aşırı naif (Bayes) sınıflandırıcımızın çökmesine yol açtı.
18.9.5. Özet¶
Bayes kuralı kullanılarak, gözlenen tüm özniteliklerin bağımsız olduğu varsayılarak bir sınıflandırıcı yapılabilir.
Bu sınıflandırıcı, etiket ve piksel değerlerinin kombinasyonlarının olma sayısını sayarak bir veri kümesi üzerinde eğitilebilir.
Bu sınıflandırıcı, istenmeyen elektronik posta (spam) tespiti gibi görevler için onlarca yıldır altın standarttı.
18.9.6. Alıştırmalar¶
\([[0,0], [0,1], [1,0], [1,1]]\) veri kümesini iki öğenin XOR tarafından verilen etiketleri ile, \([0,1,1,0]\), düşünün. Bu veri kümesine dayanan bir naif Bayes sınıflandırıcısının olasılıkları nelerdir? Noktalarımızı başarıyla sınıflandırıyor mu? Değilse, hangi varsayımlar ihlal edilir?
Olasılıkları tahmin ederken Laplace düzleştirmeyi kullanmadığımızı ve eğitimde asla gözlenmeyen bir değer içeren bir veri örneğinin test zamanında geldiğini varsayalım. Model ne çıkarır?
Naif Bayes sınıflandırıcısı, rastgele değişkenlerin bağımlılığının bir grafik yapısıyla kodlandığı belirli bir Bayes ağı örneğidir. Tam teorisi bu bölümün kapsamı dışında olsa da (tüm ayrıntılar için (Koller and Friedman, 2009) çalışmasına bakınız), XOR modelinde iki girdi değişkeni arasında açık bağımlılığa izin vermenin neden başarılı bir sınıflandırıcı oluşturmaya izin verdiğini açıklayıniz.