.. _sec_softmax_scratch:
Sıfırdan Softmaks Regresyon Uygulaması Yaratma
==============================================
Sıfırdan lineer regresyon uyguladığımız gibi, softmax regresyonunun da
benzer şekilde temel olduğuna ve kanlı ayrıntılarını ve nasıl kendinizin
uygulanacağını bilmeniz gerektiğine inanıyoruz.
:numref:`sec_fashion_mnist` içinde yeni eklenen Fashion-MNIST veri
kümesiyle çalışacağız, grup boyutu 256 olan bir veri yineleyicisi
kuracağız.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
X.sum(0, keepdims=True), X.sum(1, keepdims=True)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(array([[5., 7., 9.]]),
array([[ 6.],
[15.]]))
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
X.sum(0, keepdim=True), X.sum(1, keepdim=True)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(tensor([[5., 7., 9.]]),
tensor([[ 6.],
[15.]]))
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
tf.reduce_sum(X, 0, keepdims=True), tf.reduce_sum(X, 1, keepdims=True)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(,
)
.. raw:: html
.. raw:: html
Artık softmaks işlemini uygulamaya hazırız. Softmaks'ın üç adımdan
oluştuğunu hatırlayın: (i) Her terimin üssünü alıyoruz (``exp``
kullanarak); (ii) her bir örnek için normalleştirme sabitini elde etmek
için her satırı topluyoruz (toplu işte (batch) örnek başına bir
satırımız vardır); (iii) her satırı normalleştirme sabitine bölerek
sonucun toplamının 1 olmasını sağlıyoruz. Koda bakmadan önce, bunun bir
denklem olarak nasıl ifade edildiğini hatırlayalım:
.. math:: \mathrm{softmax}(\mathbf{X})_{ij} = \frac{\exp(\mathbf{X}_{ij})}{\sum_k \exp(\mathbf{X}_{ik})}.
Payda veya normalleştirme sabiti bazen *bölmeleme fonksiyonu* olarak da
adlandırılır (ve logaritmasına log-bölmeleme fonksiyonu denir). Bu ismin
kökenleri, ilgili bir denklemin bir parçacıklar topluluğu üzerindeki
dağılımı modellediği `istatistiksel
fizik `__'tedir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def softmax(X):
X_exp = np.exp(X)
partition = X_exp.sum(1, keepdims=True)
return X_exp / partition # Burada yayin mekanizmasi uygulanir
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def softmax(X):
X_exp = torch.exp(X)
partition = X_exp.sum(1, keepdim=True)
return X_exp / partition # Burada yayin mekanizmasi uygulanir
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def softmax(X):
X_exp = tf.exp(X)
partition = tf.reduce_sum(X_exp, 1, keepdims=True)
return X_exp / partition # Burada yayin mekanizmasi uygulanir
.. raw:: html
.. raw:: html
Gördüğünüz gibi, herhangi bir rastgele girdi için, her bir öğeyi negatif
olmayan bir sayıya dönüştürüyoruz. Ayrıca, olasılık belirtmek için
gerektiği gibi, her satırın toplamı 1'dir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = np.random.normal(0, 1, (2, 5))
X_prob = softmax(X)
X_prob, X_prob.sum(1)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(array([[0.22376052, 0.06659239, 0.06583703, 0.29964197, 0.3441681 ],
[0.63209665, 0.03179282, 0.194987 , 0.09209415, 0.04902935]]),
array([1. , 0.99999994]))
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = torch.normal(0, 1, (2, 5))
X_prob = softmax(X)
X_prob, X_prob.sum(1)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(tensor([[0.0155, 0.2640, 0.5381, 0.1014, 0.0810],
[0.7024, 0.0739, 0.0257, 0.0696, 0.1284]]),
tensor([1.0000, 1.0000]))
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = tf.random.normal((2, 5), 0, 1)
X_prob = softmax(X)
X_prob, tf.reduce_sum(X_prob, 1)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(,
)
.. raw:: html
.. raw:: html
Bu matematiksel olarak doğru görünse de, uygulamamızda biraz özensiz
davrandık çünkü matrisin büyük veya çok küçük öğeleri nedeniyle sayısal
taşma (overflow) veya küçümenliğe (underflow) karşı önlem alamadık.
Modeli Tanımlama
----------------
Artık softmaks işlemini tanımladığımıza göre, softmaks regresyon
modelini uygulayabiliriz. Aşağıdaki kod, girdinin ağ üzerinden çıktıya
nasıl eşlendiğini tanımlar. Verileri modelimizden geçirmeden önce,
``reshape`` işlevini kullanarak toplu işteki (batch) her esas görseli
bir vektör halinde düzleştirdiğimize dikkat edin.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def net(X):
return softmax(np.dot(X.reshape((-1, W.shape[0])), W) + b)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def net(X):
return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def net(X):
return softmax(tf.matmul(tf.reshape(X, (-1, W.shape[0])), W) + b)
.. raw:: html
.. raw:: html
Kayıp Fonksiyonunu Tanımlama
----------------------------
Daha sonra, :numref:`sec_softmax` içinde tanıtıldığı gibi, çapraz
entropi kaybı işlevini uygulamamız gerekir. Bu, tüm derin öğrenmede en
yaygın kayıp işlevi olabilir, çünkü şu anda sınıflandırma sorunları
regresyon sorunlarından çok daha fazladır.
Çapraz entropinin, gerçek etikete atanan tahmin edilen olasılığın
negatif log-olabilirliğini aldığını hatırlayın. Bir Python for-döngüsü
(verimsiz olma eğilimindedir) ile tahminler üzerinde yinelemek yerine,
tüm öğeleri tek bir operatörle seçebiliriz. Aşağıda, 3 sınıf üzerinde
tahmin edilen olasılıkların 2 örneğini ve bunlara karşılık gelen ``y``
etiketleriyle ``y_hat`` örnek verilerini oluşturuyoruz. ``y`` ile, ilk
örnekte birinci sınıfın doğru tahmin olduğunu biliyoruz ve ikinci
örnekte üçüncü sınıf temel referans değerdir. ``y``'yi ``y_hat``
içindeki olasılıkların indeksleri olarak kullanarak, ilk örnekte birinci
sınıfın olasılığını ve ikinci örnekte üçüncü sınıfın olasılığını
seçiyoruz.
Aşağıda, 3 sınıf üzerinden tahmin edilen olasılıkların 2 örneğini içeren
bir oyuncak verisi ``y_hat``'i oluşturuyoruz. Ardından birinci örnekte
birinci sınıfın olasılığını ve ikinci örnekte üçüncü sınıfın olasılığını
seçiyoruz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
y = np.array([0, 2])
y_hat = np.array([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])
y_hat[[0, 1], y]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([0.1, 0.5])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
y = torch.tensor([0, 2])
y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])
y_hat[[0, 1], y]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([0.1000, 0.5000])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
y_hat = tf.constant([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])
y = tf.constant([0, 2])
tf.boolean_mask(y_hat, tf.one_hot(y, depth=y_hat.shape[-1]))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Artık, çapraz entropi kaybı işlevini tek bir kod satırı ile verimli bir
şekilde uygulayabiliriz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def cross_entropy(y_hat, y):
return - np.log(y_hat[range(len(y_hat)), y])
cross_entropy(y_hat, y)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([2.3025851, 0.6931472])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def cross_entropy(y_hat, y):
return - torch.log(y_hat[range(len(y_hat)), y])
cross_entropy(y_hat, y)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([2.3026, 0.6931])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def cross_entropy(y_hat, y):
return -tf.math.log(tf.boolean_mask(
y_hat, tf.one_hot(y, depth=y_hat.shape[-1])))
cross_entropy(y_hat, y)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Sınıflandırma Doğruluğu
-----------------------
Tahmin edilen olasılık dağılımı ``y_hat`` göz önüne alındığında,
genellikle kesin bir tahmin vermemiz gerektiğinde tahmin edilen en
yüksek olasılığa sahip sınıfı seçeriz. Aslında, birçok uygulama bir
seçim yapmamızı gerektirir. Gmail, bir e-postayı "Birincil", "Sosyal",
"Güncellemeler" veya "Forumlar" olarak sınıflandırmalıdır. Olasılıkları
dahili olarak tahmin edebilir, ancak günün sonunda sınıflar arasından
birini seçmesi gerekir.
Tahminler ``y`` etiket sınıfıyla tutarlı olduğunda doğrudur.
Sınıflandırma doğruluğu, doğru olan tüm tahminlerin oranıdır. Doğruluğu
doğrudan optimize etmek zor olabilse de (türevleri alınamaz), genellikle
en çok önemsediğimiz performans ölçütüdür ve sınıflandırıcıları
eğitirken neredeyse her zaman onu rapor edeceğiz.
Doğruluğu hesaplamak için aşağıdakileri yapıyoruz. İlk olarak, ``y_hat``
bir matris ise, ikinci boyutun her sınıf için tahmin puanlarını
sakladığını varsayıyoruz. Her satırdaki en büyük girdi için dizine göre
tahmin edilen sınıfı elde ederken ``argmax`` kullanırız. Ardından,
tahmin edilen sınıfı gerçek referans değer ``y`` ile karşılaştırırız.
Eşitlik operatörü ``==`` veri türlerine duyarlı olduğundan, ``y_hat``
veri türünü ``y`` ile eşleşecek şekilde dönüştürürüz. Sonuç, 0 (yanlış)
ve 1 (doğru) girişlerini içeren bir tensördür. Toplamlarını almak doğru
tahminlerin sayısını verir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def accuracy(y_hat, y): #@save
"""Doğru tahminlerin sayısını hesaplayın."""
if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
y_hat = y_hat.argmax(axis=1)
cmp = y_hat.astype(y.dtype) == y
return float(cmp.astype(y.dtype).sum())
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def accuracy(y_hat, y): #@save
"""Doğru tahminlerin sayısını hesaplayın."""
if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
y_hat = y_hat.argmax(axis=1)
cmp = y_hat.type(y.dtype) == y
return float(cmp.type(y.dtype).sum())
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def accuracy(y_hat, y): #@save
"""Doğru tahminlerin sayısını hesaplayın."""
if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
y_hat = tf.argmax(y_hat, axis=1)
cmp = tf.cast(y_hat, y.dtype) == y
return float(tf.reduce_sum(tf.cast(cmp, y.dtype)))
.. raw:: html
.. raw:: html
Önceden tanımlanan ``y_hat`` ve ``y`` değişkenlerini sırasıyla tahmin
edilen olasılık dağılımları ve etiketler olarak kullanmaya devam
edeceğiz. İlk örneğin tahmin sınıfının 2 olduğunu görebiliriz (satırın
en büyük öğesi dizin 2 ile 0.6'dır), bu gerçek etiket, 0 ile
tutarsızdır. İkinci örneğin tahmin sınıfı 2'dir (satırın en büyük öğesi
2 endeksi ile 0.5'tir) ve bu gerçek etiket 2 ile tutarlıdır. Bu nedenle,
bu iki örnek için sınıflandırma doğruluk oranı 0.5'tir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
accuracy(y_hat, y) / len(y)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
0.5
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
accuracy(y_hat, y) / len(y)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
0.5
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
accuracy(y_hat, y) / len(y)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
0.5
.. raw:: html
.. raw:: html
Benzer şekilde, veri yineleyici ``data_iter`` aracılığıyla erişilen bir
veri kümesindeki herhangi bir ``net`` modelinin doğruluğunu
hesaplayabiliriz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def evaluate_accuracy(net, data_iter): #@save
"""Bir veri kümesinde bir modelin doğruluğunu hesaplayın."""
metric = Accumulator(2) # Doğru tahmin sayısı, tahmin sayısı
for X, y in data_iter:
metric.add(accuracy(net(X), y), d2l.size(y))
return metric[0] / metric[1]
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def evaluate_accuracy(net, data_iter): #@save
"""Bir veri kumesinde bir modelin doğruluğunu hesaplayın."""
if isinstance(net, torch.nn.Module):
net.eval() # Modeli değerlendirme moduna kurun
metric = Accumulator(2) # Doğru tahmin sayısı, tahmin sayısı
with torch.no_grad():
for X, y in data_iter:
metric.add(accuracy(net(X), y), y.numel())
return metric[0] / metric[1]
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def evaluate_accuracy(net, data_iter): #@save
"""Bir veri kümesinde bir modelin doğruluğunu hesaplayın."""
metric = Accumulator(2) # Doğru tahmin sayısı, tahmin sayısı
for X, y in data_iter:
metric.add(accuracy(net(X), y), d2l.size(y))
return metric[0] / metric[1]
.. raw:: html
.. raw:: html
Burada, ``Accumulator``, birden çok değişken üzerindeki toplamları
biriktirmek için bir yardımcı sınıftır. Yukarıdaki ``evaluate_accuracy``
işlevinde, ``Accumulator`` örneğinde sırasıyla hem doğru tahminlerin
sayısını hem de tahminlerin sayısını depolamak için 2 değişken
oluştururuz. Veri kümesini yineledikçe her ikisi de zaman içinde
birikecektir.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
class Accumulator: #@save
"""`n` değişken üzerinden toplamları biriktirmek için"""
def __init__(self, n):
self.data = [0.0] * n
def add(self, *args):
self.data = [a + float(b) for a, b in zip(self.data, args)]
def reset(self):
self.data = [0.0] * len(self.data)
def __getitem__(self, idx):
return self.data[idx]
``net`` modelini rastgele ağırlıklarla başlattığımız için, bu modelin
doğruluğu rastgele tahmin etmeye yakın olmalıdır, yani 10 sınıf için 0.1
gibi.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
evaluate_accuracy(net, test_iter)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
0.0811
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
evaluate_accuracy(net, test_iter)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
0.0979
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
evaluate_accuracy(net, test_iter)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
0.0797
.. raw:: html
.. raw:: html
Eğitim
------
Softmaks regresyonu için eğitim döngüsü, :numref:`sec_linear_scratch`
içindeki doğrusal regresyon uygulamamızı okursanız, çarpıcı bir şekilde
tanıdık gelebilir. Burada uygulamayı yeniden kullanılabilir hale
getirmek için yeniden düzenliyoruz. İlk olarak, bir dönemi (epoch)
eğitmek için bir işlev tanımlıyoruz. ``updater``'in, grup boyutunu
bağımsız değişken olarak kabul eden, model parametrelerini güncellemek
için genel bir işlev olduğuna dikkat edin. ``d2l.sgd`` işlevinin bir
sarmalayıcısı (wrapper) veya bir çerçevenin yerleşik optimizasyon işlevi
olabilir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def train_epoch_ch3(net, train_iter, loss, updater): #@save
"""Bir modeli bir dönem içinde eğitme (Bölüm 3'te tanımlanmıştır)."""
# Eğitim kaybı toplamı, eğitim doğruluğu toplamı, örnek sayısı
metric = Accumulator(3)
if isinstance(updater, gluon.Trainer):
updater = updater.step
for X, y in train_iter:
# Gradyanları hesaplayın ve parametreleri güncelleyin
with autograd.record():
y_hat = net(X)
l = loss(y_hat, y)
l.backward()
updater(X.shape[0])
metric.add(float(l.sum()), accuracy(y_hat, y), y.size)
# Eğitim kaybını ve doğruluğunu döndür
return metric[0] / metric[2], metric[1] / metric[2]
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def train_epoch_ch3(net, train_iter, loss, updater): #@save
"""Bölüm 3'te tanımlanan eğitim döngüsü."""
# Modeli eğitim moduna kurun
if isinstance(net, torch.nn.Module):
net.train()
# Eğitim kaybı toplamı, eğitim doğruluğu toplamı, örnek sayısı
metric = Accumulator(3)
for X, y in train_iter:
# Gradyanları hesaplayın ve parametreleri güncelleyin
y_hat = net(X)
l = loss(y_hat, y)
if isinstance(updater, torch.optim.Optimizer):
# PyTorch yerleşik optimize edicisini ve kayıp kriterini kullanma
updater.zero_grad()
l.mean().backward()
updater.step()
else:
# Özel olarak oluşturulmuş optimize edicisini ve kayıp ölçütünü kullanma
l.sum().backward()
updater(X.shape[0])
metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())
# Eğitim kaybını ve doğruluğunu döndür
return metric[0] / metric[2], metric[1] / metric[2]
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def train_epoch_ch3(net, train_iter, loss, updater): #@save
"""Bölüm 3'te tanımlanan eğitim döngüsü."""
# Eğitim kaybı toplamı, eğitim doğruluğu toplamı, örnek sayısı
metric = Accumulator(3)
for X, y in train_iter:
# Gradyanları hesaplayın ve parametreleri güncelleyin
with tf.GradientTape() as tape:
y_hat = net(X)
# Kullanıcıların bu kitapta uygulayabilecekleri (tahminler, etiketler)
# yerine kayıp alımları (etiketler, tahminler) için Keras uygulamaları
# ör. yukarıda uyguladığımız `cross_entropy`
if isinstance(loss, tf.keras.losses.Loss):
l = loss(y, y_hat)
else:
l = loss(y_hat, y)
if isinstance(updater, tf.keras.optimizers.Optimizer):
params = net.trainable_variables
grads = tape.gradient(l, params)
updater.apply_gradients(zip(grads, params))
else:
updater(X.shape[0], tape.gradient(l, updater.params))
# Varsayılan olarak Keras kaybı, bir toplu iş içindeki ortalama kaybı döndürür
l_sum = l * float(tf.size(y)) if isinstance(
loss, tf.keras.losses.Loss) else tf.reduce_sum(l)
metric.add(l_sum, accuracy(y_hat, y), tf.size(y))
# Eğitim kaybını ve doğruluğunu döndür
return metric[0] / metric[2], metric[1] / metric[2]
.. raw:: html
.. raw:: html
Eğitim işlevinin uygulamasını göstermeden önce, verileri animasyonda
(canlandırma) çizen bir yardımcı program sınıfı tanımlıyoruz. Yine
kitabın geri kalanında kodu basitleştirmeyi amaçlamaktadır.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
class Animator: #@save
"""Animasyonda veri çizdirme"""
def __init__(self, xlabel=None, ylabel=None, legend=None, xlim=None,
ylim=None, xscale='linear', yscale='linear',
fmts=('-', 'm--', 'g-.', 'r:'), nrows=1, ncols=1,
figsize=(3.5, 2.5)):
# Çoklu çizgileri artarak çizdir
if legend is None:
legend = []
d2l.use_svg_display()
self.fig, self.axes = d2l.plt.subplots(nrows, ncols, figsize=figsize)
if nrows * ncols == 1:
self.axes = [self.axes, ]
# Argumanları elde tutmak için bir lambda işlevi kullan
self.config_axes = lambda: d2l.set_axes(
self.axes[0], xlabel, ylabel, xlim, ylim, xscale, yscale, legend)
self.X, self.Y, self.fmts = None, None, fmts
def add(self, x, y):
# Çoklu veri noktalarını şekile ekleyin
if not hasattr(y, "__len__"):
y = [y]
n = len(y)
if not hasattr(x, "__len__"):
x = [x] * n
if not self.X:
self.X = [[] for _ in range(n)]
if not self.Y:
self.Y = [[] for _ in range(n)]
for i, (a, b) in enumerate(zip(x, y)):
if a is not None and b is not None:
self.X[i].append(a)
self.Y[i].append(b)
self.axes[0].cla()
for x, y, fmt in zip(self.X, self.Y, self.fmts):
self.axes[0].plot(x, y, fmt)
self.config_axes()
display.display(self.fig)
display.clear_output(wait=True)
Aşağıdaki eğitim işlevi daha sonra, ``num_epochs`` ile belirtilen birden
çok dönem için ``train_iter`` aracılığıyla erişilen bir eğitim veri
kümesinde bir ``net`` modeli eğitir. Her dönemin sonunda model,
``test_iter`` aracılığıyla erişilen bir test veri kümesinde
değerlendirilir. Eğitimin ilerlemesini görselleştirmek için ``Animator``
sınıfından yararlanacağız.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def train_ch3(net, train_iter, test_iter, loss, num_epochs, updater): #@save
"""Bir modeli eğitin (Bölüm 3'te tanımlanmıştır)."""
animator = Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9],
legend=['egitim kaybi', 'egitim dogr', 'test dogr'])
for epoch in range(num_epochs):
train_metrics = train_epoch_ch3(net, train_iter, loss, updater)
test_acc = evaluate_accuracy(net, test_iter)
animator.add(epoch + 1, train_metrics + (test_acc,))
train_loss, train_acc = train_metrics
assert train_loss < 0.5, train_loss
assert train_acc <= 1 and train_acc > 0.7, train_acc
assert test_acc <= 1 and test_acc > 0.7, test_acc
Sıfırdan bir uygulama olarak, modelin kayıp fonksiyonunu 0.1 öğrenme
oranıyla optimize ederek :numref:`sec_linear_scratch` içinde
tanımlanan minigrup rasgele gradyan inişini kullanıyoruz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
lr = 0.1
def updater(batch_size):
return d2l.sgd([W, b], lr, batch_size)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
lr = 0.1
def updater(batch_size):
return d2l.sgd([W, b], lr, batch_size)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
class Updater(): #@save
"""Minigrup rasgele gradyan inişini kullanarak parametreleri güncellemek için."""
def __init__(self, params, lr):
self.params = params
self.lr = lr
def __call__(self, batch_size, grads):
d2l.sgd(self.params, grads, self.lr, batch_size)
updater = Updater([W, b], lr=0.1)
.. raw:: html
.. raw:: html
Şimdi modeli 10 dönem ile eğitiyoruz. Hem dönem sayısının
(``num_epochs``) hem de öğrenme oranının (``lr``) ayarlanabilir hiper
parametreler olduğuna dikkat edin. Değerlerini değiştirerek modelin
sınıflandırma doğruluğunu artırabiliriz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
num_epochs = 10
train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater)
.. figure:: output_softmax-regression-scratch_a48321_177_0.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
num_epochs = 10
train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater)
.. figure:: output_softmax-regression-scratch_a48321_180_0.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
num_epochs = 10
train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater)
.. figure:: output_softmax-regression-scratch_a48321_183_0.svg
.. raw:: html
.. raw:: html
Tahminleme
----------
Artık eğitim tamamlandı, modelimiz bazı imgeleri sınıflandırmaya hazır.
Bir dizi resim verildiğinde, bunların gerçek etiketlerini (metin
çıktısının ilk satırı) ve modelden gelen tahminleri (metin çıktısının
ikinci satırı) karşılaştıracağız.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def predict_ch3(net, test_iter, n=6): #@save
"""Etiketleri tahmin etme (Bölüm 3'te tanımlanmıştır)."""
for X, y in test_iter:
break
trues = d2l.get_fashion_mnist_labels(y)
preds = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1))
titles = [true +'\n' + pred for true, pred in zip(trues, preds)]
d2l.show_images(
X[0:n].reshape((n, 28, 28)), 1, n, titles=titles[0:n])
predict_ch3(net, test_iter)
.. figure:: output_softmax-regression-scratch_a48321_189_0.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def predict_ch3(net, test_iter, n=6): #@save
"""Etiketleri tahmin etme (Bölüm 3'te tanımlanmıştır)."""
for X, y in test_iter:
break
trues = d2l.get_fashion_mnist_labels(y)
preds = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1))
titles = [true +'\n' + pred for true, pred in zip(trues, preds)]
d2l.show_images(
X[0:n].reshape((n, 28, 28)), 1, n, titles=titles[0:n])
predict_ch3(net, test_iter)
.. figure:: output_softmax-regression-scratch_a48321_192_0.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def predict_ch3(net, test_iter, n=6): #@save
"""Etiketleri tahmin etme (Bölüm 3'te tanımlanmıştır)."""
for X, y in test_iter:
break
trues = d2l.get_fashion_mnist_labels(y)
preds = d2l.get_fashion_mnist_labels(tf.argmax(net(X), axis=1))
titles = [true +'\n' + pred for true, pred in zip(trues, preds)]
d2l.show_images(
tf.reshape(X[0:n], (n, 28, 28)), 1, n, titles=titles[0:n])
predict_ch3(net, test_iter)
.. figure:: output_softmax-regression-scratch_a48321_195_0.svg
.. raw:: html
.. raw:: html
Özet
----
- Softmaks regresyonu ile çok sınıflı sınıflandırma için modeller
eğitebiliriz.
- Softmaks regresyonunun eğitim döngüsü doğrusal regresyondakine çok
benzer: Verileri alın ve okuyun, modelleri ve kayıp fonksiyonlarını
tanımlayın, ardından optimizasyon algoritmalarını kullanarak
modelleri eğitin. Yakında öğreneceğiniz gibi, en yaygın derin öğrenme
modellerinin benzer eğitim yordamları vardır.
Alıştırmalar
------------
1. Bu bölümde, softmaks işlemini matematiksel tanımına dayalı olarak
doğrudan uyguladık. Bu hangi sorunlara neden olabilir? İpucu:
:math:`\exp(50)`'nin boyutunu hesaplamaya çalışın.
2. Bu bölümdeki ``cross_entropy`` işlevi, çapraz entropi kaybı işlevinin
tanımına göre uygulandı. Bu uygulamadaki sorun ne olabilir? İpucu:
Logaritmanın etki alanını düşünün.
3. Yukarıdaki iki sorunu çözmek için düşünebileceğiniz çözümler
nelerdir?
4. En olası etiketi iade etmek her zaman iyi bir fikir midir? Örneğin,
bunu tıbbi teşhis için yapar mıydınız?
5. Bazı özniteliklere dayanarak sonraki kelimeyi tahmin etmek için
softmaks regresyonunu kullanmak istediğimizi varsayalım. Geniş bir
kelime dağarcığı kullanımından ortaya çıkabilecek problemler
nelerdir?
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html