.. _sec_linear_scratch:
Sıfırdan Doğrusal Regresyon Uygulaması Yaratma
==============================================
Artık doğrusal regresyonun arkasındaki temel fikirleri anladığınıza
göre, işe ellerimizi daldırarak kodda uygulamaya başlayabiliriz. Bu
bölümde, veri komut işleme hattı (pipeline), model, kayıp fonksiyonu ve
minigrup rasgele gradyan iniş eniyileyici dahil olmak üzere tüm yöntemi
sıfırdan uygulayacağız. Modern derin öğrenme çerçeveleri neredeyse tüm
bu çalışmayı otomatikleştirebilirken, bir şeyleri sıfırdan uygulamak, ne
yaptığınızı gerçekten bildiğinizden emin olmanın tek yoludur. Dahası,
modelleri ihtiyacımıza göre özelleştirken, kendi katmanlarımızı veya
kayıp işlevlerimizi tanımlama zamanı geldiğinde, kaputun altında işlerin
nasıl ilerlediğini anlamak kullanışlı olacaktır. Bu bölümde, sadece
tensörlere ve otomatik türev almaya güveneceğiz. Daha sonra, derin
öğrenme çerçevelerinin çekici ek özelliklerden yararlanarak daha kısa
bir uygulama sunacağız.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
%matplotlib inline
import random
from d2l import mxnet as d2l
from mxnet import autograd, np, npx
npx.set_np()
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
%matplotlib inline
import random
import torch
from d2l import torch as d2l
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
%matplotlib inline
import random
import tensorflow as tf
from d2l import tensorflow as d2l
.. raw:: html
.. raw:: html
Veri Kümesini Oluşturma
-----------------------
İşleri basitleştirmek için, gürültülü doğrusal bir model için yapay bir
veri kümesi oluşturacağız. Görevimiz, veri kümemizde bulunan sonlu örnek
kümesini kullanarak bu modelin parametrelerini elde etmek olacaktır.
Verileri düşük boyutlu tutacağız, böylece kolayca görselleştirebiliriz.
Aşağıdaki kod parçacığında, her biri standart bir normal dağılımdan
örneklenmiş 2 öznitelikten oluşan 1000 örnekli bir veri kümesi
oluşturuyoruz. Böylece, sentetik veri kümemiz matris
:math:`\mathbf{X}\in \mathbb{R}^{1000 \times 2}` olacaktır.
Veri kümemizi oluşturan gerçek parametreler
:math:`\mathbf{w} = [2, -3.4]^\top` ve :math:`b = 4.2` olacaktır ve
sentetik etiketlerimiz aşağıdaki :math:`\epsilon` gürültü terimli
doğrusal modele göre atanacaktır:
.. math:: \mathbf{y}= \mathbf{X} \mathbf{w} + b + \mathbf\epsilon.
:math:`\epsilon`'u öznitelikler ve etiketlerdeki olası ölçüm hatalarını
yakalıyor diye düşünebilirsiniz. Standart varsayımların geçerli olduğunu
ve böylece :math:`\epsilon` değerinin ortalaması 0 olan normal bir
dağılıma uyduğunu varsayacağız. Problemimizi kolaylaştırmak için,
standart sapmasını 0.01 olarak ayarlayacağız. Aşağıdaki kod, sentetik
veri kümemizi üretir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def synthetic_data(w, b, num_examples): #@save
"""Veri yaratma, y = Xw + b + gürültü."""
X = np.random.normal(0, 1, (num_examples, len(w)))
y = np.dot(X, w) + b
y += np.random.normal(0, 0.01, y.shape)
return X, y.reshape((-1, 1))
true_w = np.array([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def synthetic_data(w, b, num_examples): #@save
"""Veri yaratma, y = Xw + b + gürültü."""
X = torch.normal(0, 1, (num_examples, len(w)))
y = torch.matmul(X, w) + b
y += torch.normal(0, 0.01, y.shape)
return X, y.reshape((-1, 1))
true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def synthetic_data(w, b, num_examples): #@save
"""Veri yaratma, y = Xw + b + gürültü."""
X = tf.zeros((num_examples, w.shape[0]))
X += tf.random.normal(shape=X.shape)
y = tf.matmul(X, tf.reshape(w, (-1, 1))) + b
y += tf.random.normal(shape=y.shape, stddev=0.01)
y = tf.reshape(y, (-1, 1))
return X, y
true_w = tf.constant([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)
.. raw:: html
.. raw:: html
``features``'deki (öznitelikleri tutan değişken) her satırın 2 boyutlu
bir veri örneğinden oluştuğuna ve ``labels``'deki (etiketleri tutan
değişken) her satırın 1 boyutlu bir etiket değerinden (bir skaler)
oluştuğuna dikkat edin.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print('oznitelikler:', features[0],'\netiket:', labels[0])
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
oznitelikler: [2.2122064 1.1630787]
etiket: [4.662078]
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print('oznitelikler:', features[0],'\netiket:', labels[0])
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
oznitelikler: tensor([0.1546, 2.3925])
etiket: tensor([-3.6205])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print('oznitelikler:', features[0],'\netiket:', labels[0])
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
oznitelikler: tf.Tensor([ 1.0085982 -0.9955097], shape=(2,), dtype=float32)
etiket: tf.Tensor([9.597065], shape=(1,), dtype=float32)
.. raw:: html
.. raw:: html
İkinci öznitelik ``features[:, 1]`` ve ``labels`` kullanılarak bir
dağılım grafiği oluşturup ikisi arasındaki doğrusal korelasyonu net bir
şekilde gözlemleyebiliriz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
d2l.set_figsize()
# İki nokta üstüste sadece gösterim amaçlıdır
d2l.plt.scatter(features[:, 1].asnumpy(), labels.asnumpy(), 1);
.. figure:: output_linear-regression-scratch_58de05_39_0.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
d2l.set_figsize()
# İki nokta üstüste sadece gösterim amaçlıdır
d2l.plt.scatter(features[:, 1].detach().numpy(), labels.detach().numpy(), 1);
.. figure:: output_linear-regression-scratch_58de05_42_0.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
d2l.set_figsize()
# İki nokta üstüste sadece gösterim amaçlıdır
d2l.plt.scatter(features[:, 1].numpy(), labels.numpy(), 1);
.. figure:: output_linear-regression-scratch_58de05_45_0.svg
.. raw:: html
.. raw:: html
Veri Kümesini Okuma
-------------------
Model eğitimlerinin, veri kümesi üzerinde birden çok geçiş yapmaktan,
her seferde bir minigrup örnek almaktan ve bunları modelimizi
güncellemek için kullanmaktan oluştuğunu hatırlayın. Bu süreç, makine
öğrenmesi algoritmalarını eğitmek için çok temel olduğundan, veri
kümesini karıştırmak ve ona minigruplar halinde erişmek için bir
yardımcı işlev tanımlamaya değer.
Aşağıdaki kodda, bu işlevselliğin olası bir uygulamasını göstermek için
``data_iter`` işlevini tanımlıyoruz. Fonksiyon, bir grup boyutunu, bir
öznitelik matrisini ve bir etiket vektörünü alarak ``batch_size``
boyutundaki minigrupları verir. Her bir minigrup, bir dizi öznitelik ve
etiketten oluşur.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def data_iter(batch_size, features, labels):
num_examples = len(features)
indices = list(range(num_examples))
# Örnekler belirli bir sıra gözetmeksizin rastgele okunur
random.shuffle(indices)
for i in range(0, num_examples, batch_size):
batch_indices = np.array(
indices[i: min(i + batch_size, num_examples)])
yield features[batch_indices], labels[batch_indices]
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def data_iter(batch_size, features, labels):
num_examples = len(features)
indices = list(range(num_examples))
# Örnekler belirli bir sıra gözetmeksizin rastgele okunur
random.shuffle(indices)
for i in range(0, num_examples, batch_size):
batch_indices = torch.tensor(
indices[i: min(i + batch_size, num_examples)])
yield features[batch_indices], labels[batch_indices]
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def data_iter(batch_size, features, labels):
num_examples = len(features)
indices = list(range(num_examples))
# Örnekler belirli bir sıra gözetmeksizin rastgele okunur
random.shuffle(indices)
for i in range(0, num_examples, batch_size):
j = tf.constant(indices[i: min(i + batch_size, num_examples)])
yield tf.gather(features, j), tf.gather(labels, j)
.. raw:: html
.. raw:: html
Genel olarak, paralelleştirme işlemlerinde mükemmel olan GPU
donanımından yararlanmak için makul boyutta minigruplar kullanmak
istediğimizi unutmayın. Her örnek, modellerimiz üzerinden paralel olarak
beslenebildiği ve her örnek için kayıp fonksiyonunun gradyanı da paralel
olarak alınabildiğinden, GPU'lar, yüzlerce örneği yalnızca tek bir
örneği işlemek için gerekebileceğinden çok daha az kısa sürede
işlememize izin verir.
Biraz sezgi oluşturmak için, ilk olarak küçük bir grup veri örneği
okuyup yazdıralım. Her minigruptaki özniteliklerin şekli bize hem
minigrup boyutunu hem de girdi özniteliklerinin sayısını söyler. Aynı
şekilde, minigrubumuzun etiketleri de ``batch_size`` ile verilen şekle
sahip olacaktır.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
batch_size = 10
for X, y in data_iter(batch_size, features, labels):
print(X, '\n', y)
break
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
[[-1.6242899 -3.2149546 ]
[ 1.5702168 1.11278 ]
[-0.36137256 0.98650014]
[ 1.317333 0.63940585]
[-2.1471155 -0.6573725 ]
[-1.4225755 -1.1081946 ]
[-1.5367762 1.0635569 ]
[-1.48432 1.0816108 ]
[-0.1742568 1.9691626 ]
[-0.38354877 1.6984322 ]]
[[11.875465 ]
[ 3.5531938 ]
[ 0.11717813]
[ 4.6646976 ]
[ 2.157684 ]
[ 5.1158175 ]
[-2.4930956 ]
[-2.441576 ]
[-2.8460252 ]
[-2.335064 ]]
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
batch_size = 10
for X, y in data_iter(batch_size, features, labels):
print(X, '\n', y)
break
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[ 1.4869, 1.5494],
[-0.8690, -0.0986],
[ 1.5624, 0.0090],
[-0.4172, 0.9719],
[ 0.3500, -0.1156],
[-0.3433, 2.4511],
[-1.1783, -1.2873],
[-1.1068, -0.5236],
[ 0.8041, 0.2262],
[-2.2314, 0.0541]])
tensor([[ 1.9146],
[ 2.7896],
[ 7.2889],
[ 0.0441],
[ 5.3029],
[-4.8102],
[ 6.2084],
[ 3.7547],
[ 5.0364],
[-0.4410]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
batch_size = 10
for X, y in data_iter(batch_size, features, labels):
print(X, '\n', y)
break
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tf.Tensor(
[[ 1.8249083 0.43419597]
[ 0.7772833 0.6235751 ]
[-0.7631955 0.08624952]
[ 0.5574609 1.3876617 ]
[ 0.17594892 1.5851324 ]
[ 0.21412234 -1.7341554 ]
[ 0.06975526 0.54019475]
[-2.0243845 0.78842735]
[-1.2418027 0.4114364 ]
[ 0.39266726 -1.0444765 ]], shape=(10, 2), dtype=float32)
tf.Tensor(
[[ 6.3809032 ]
[ 3.630106 ]
[ 2.377214 ]
[ 0.59058595]
[-0.8450924 ]
[10.518543 ]
[ 2.5056705 ]
[-2.541665 ]
[ 0.30798355]
[ 8.541502 ]], shape=(10, 1), dtype=float32)
.. raw:: html
.. raw:: html
Yinelemeyi çalıştırırken, tüm veri kümesi tükenene kadar art arda farklı
minigruplar elde ederiz (bunu deneyin). Yukarıda uygulanan yineleme,
eğitici amaçlar için iyi olsa da, gerçek problemlerde bizim başımızı
belaya sokacak şekilde verimsizdir. Örneğin, tüm verileri belleğe
yüklememizi ve çok sayıda rastgele bellek erişimi gerçekleştirmemizi
gerektirir. Derin öğrenme çerçevesinde uygulanan yerleşik yineleyiciler
önemli ölçüde daha verimlidir ve hem dosyalarda depolanan verilerle hem
de veri akışları aracılığıyla beslenen verilerle ilgilenebilirler.
Model Parametrelerini İlkleme
-----------------------------
Modelimizin parametrelerini minigrup rasgele gradyan inişiyle optimize
etmeye başlamadan önce, ilk olarak bazı parametrelere ihtiyacımız var.
Aşağıdaki kodda, ağırlıkları, ortalaması 0 ve standart sapması 0.01 olan
normal bir dağılımdan rasgele sayılar örnekleyerek ve ek girdiyi 0
olarak ayarlayarak ilkliyoruz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
w = np.random.normal(0, 0.01, (2, 1))
b = np.zeros(1)
w.attach_grad()
b.attach_grad()
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
w = torch.normal(0, 0.01, size=(2,1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
w = tf.Variable(tf.random.normal(shape=(2, 1), mean=0, stddev=0.01),
trainable=True)
b = tf.Variable(tf.zeros(1), trainable=True)
.. raw:: html
.. raw:: html
Parametrelerimizi ilkledikten sonra, bir sonraki görevimiz, verilerimize
yeterince iyi uyum sağlayana kadar onları güncellemektir. Her
güncelleme, parametrelere göre kayıp fonksiyonumuzun gradyanını almayı
gerektirir. Gradyan verildiğinde, her parametreyi kaybı azaltabilecek
yönde güncelleyebiliriz.
Hiç kimse gradyanları açıkça hesaplamak istemediğinden (bu sıkıcı ve
hataya açıktır), gradyanı hesaplamak için :numref:`sec_autograd`
içinde tanıtıldığı gibi otomatik türev almayı kullanırız.
Modeli Tanımlama
----------------
Daha sonra, modelimizi, onun girdileri ve parametreleri çıktıları ile
ilişkilendirerek tanımlamalıyız. Doğrusal modelin çıktısını hesaplamak
için, :math:`\mathbf{X}` girdi özniteliklerinin ve :math:`\mathbf{w}`
model ağırlıklarının matris vektör nokta çarpımını alıp her bir örneğe
:math:`b` ek girdisini eklediğimizi hatırlayın. Aşağıda
:math:`\mathbf{Xw}` bir vektör ve :math:`b` bir skalerdir. Yayma
mekanizmasının şurada açıklandığı anımsayalım
:numref:`subsec_broadcasting`. Bir vektör ve bir skaleri
topladığımızda, skaler vektörün her bileşenine eklenir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def linreg(X, w, b): #@save
"""Doğrusal regresyon modeli."""
return np.dot(X, w) + b
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def linreg(X, w, b): #@save
"""Doğrusal regresyon modeli."""
return torch.matmul(X, w) + b
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def linreg(X, w, b): #@save
"""Doğrusal regresyon modeli."""
return tf.matmul(X, w) + b
.. raw:: html
.. raw:: html
Kayıp Fonksiyonunu Tanımlama
----------------------------
Modelimizi güncellemek, kayıp fonksiyonumuzun gradyanını almayı
gerektirdiğinden, önce kayıp fonksiyonunu tanımlamalıyız. Burada kare
kayıp fonksiyonunu şurada açıklandığı,
:numref:`sec_linear_regression`, gibi kullanacağız . Uygulamada, ``y``
gerçek değerini tahmin edilen değer ``y_hat`` şekline dönüştürmemiz
gerekir. Aşağıdaki işlev tarafından döndürülen sonuç da ``y_hat`` ile
aynı şekle sahip olacaktır.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def squared_loss(y_hat, y): #@save
"""Kare kayıp."""
return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def squared_loss(y_hat, y): #@save
"""Kare kayıp."""
return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def squared_loss(y_hat, y): #@save
"""Kare kayıp."""
return (y_hat - tf.reshape(y, y_hat.shape)) ** 2 / 2
.. raw:: html
.. raw:: html
Optimizasyon Algoritmasını Tanımlama
------------------------------------
:numref:`sec_linear_regression` içinde tartıştığımız gibi, doğrusal
regresyon kapalı biçim bir çözüme sahiptir. Ancak, bu doğrusal regresyon
hakkında bir kitap değil: Derin öğrenme hakkında bir kitap. Bu kitabın
tanıttığı diğer modellerin hiçbiri analitik olarak çözülemediğinden, bu
fırsatı minigrup rasgele gradyan inişinin ilk çalışan örneğini tanıtmak
için kullanacağız.
Her adımda, veri kümemizden rastgele alınan bir minigrup kullanarak,
parametrelerimize göre kaybın gradyanını tahmin edeceğiz. Daha sonra
kayıpları azaltabilecek yönde parametrelerimizi güncelleyeceğiz.
Aşağıdaki kod, bir küme parametre, bir öğrenme oranı ve bir grup boyutu
verildiğinde minigrup rasgele gradyan iniş güncellemesini uygular.
Güncelleme adımının boyutu, öğrenme oranı ``lr`` tarafından belirlenir.
Kaybımız, örneklerin minigrubu üzerinden bir toplam olarak
hesaplandığından, adım boyutumuzu grup boyutuna (``batch_size``) göre
normalleştiririz, böylece tipik bir adım boyutunun büyüklüğü, grup
boyutu seçimimize büyük ölçüde bağlı olmaz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def sgd(params, lr, batch_size): #@save
"""Minigrup rasgele gradyan inişi."""
for param in params:
param[:] = param - lr * param.grad / batch_size
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def sgd(params, lr, batch_size): #@save
"""Minigrup rasgele gradyan inişi."""
with torch.no_grad():
for param in params:
param -= lr * param.grad / batch_size
param.grad.zero_()
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def sgd(params, grads, lr, batch_size): #@save
"""Minigrup rasgele gradyan inişi."""
for param, grad in zip(params, grads):
param.assign_sub(lr*grad/batch_size)
.. raw:: html
.. raw:: html
Eğitim
------
Artık tüm parçaları yerine koyduğumuza göre, ana eğitim döngüsünü
uygulamaya hazırız. Bu kodu anlamanız çok önemlidir çünkü derin
öğrenmede kariyeriniz boyunca neredeyse aynı eğitim döngülerini tekrar
tekrar göreceksiniz.
Her yinelemede, bir minigrup eğitim örneği alacağız ve bir dizi tahmin
elde etmek için bunları modelimizden geçireceğiz. Kaybı hesapladıktan
sonra, her parametreye göre gradyanları depolayarak ağ üzerinden geriye
doğru geçişi başlatırız. Son olarak, model parametrelerini güncellemek
için optimizasyon algoritması ``sgd``'yi çağıracağız.
Özetle, aşağıdaki döngüyü uygulayacağız:
- :math:`(\mathbf {w}, b)` parametrelerini ilkletin.
- Tamamlanana kadar tekrarlayın
- Gradyanı hesaplayın:
:math:`\mathbf{g} \leftarrow \partial_{(\mathbf{w},b)} \frac{1}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} l(\mathbf{x}^{(i)}, y^{(i)}, \mathbf{w}, b)`
- Parametreleri güncelleyin:
:math:`(\mathbf{w}, b) \leftarrow (\mathbf{w}, b) - \eta \mathbf{g}`
Her bir *dönemde (epoch)*, eğitim veri kümesindeki her örnekten
geçtikten sonra (örneklerin sayısının grup boyutuna bölünebildiği
varsayılarak) tüm veri kümesini (``data_iter`` işlevini kullanarak)
yineleyeceğiz. Dönemlerin sayısı, ``num_epochs``, ve öğrenme hızı,
``lr``, burada sırasıyla 3 ve 0.03 olarak belirlediğimiz hiper
parametrelerdir. Ne yazık ki, hiper parametrelerin belirlenmesi zordur
ve deneme yanılma yoluyla bazı ayarlamalar gerektirir. Bu ayrıntıları
şimdilik atlıyoruz, ancak daha sonra :numref:`chap_optimization`
içinde tekrarlayacağız.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
lr = 0.03
num_epochs = 3
net = linreg
loss = squared_loss
for epoch in range(num_epochs):
for X, y in data_iter(batch_size, features, labels):
with autograd.record():
l = loss(net(X, w, b), y) # `X` ve `y`'deki minigrup kaybı
# `l`'nin şekli (`batch_size`, 1) olduğu ve skaler bir değişken olmadığı için,
# `l`'deki öğeler,[`w`, `b`]'ye göre gradyanların olduğu yeni bir değişken
# elde etmek için birbirine eklenir.
l.backward()
sgd([w, b], lr, batch_size) # Parametreleri gradyanlarına göre güncelle
train_l = loss(net(features, w, b), labels)
print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
[21:55:08] src/base.cc:49: GPU context requested, but no GPUs found.
epoch 1, loss 0.025044
epoch 2, loss 0.000090
epoch 3, loss 0.000051
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
lr = 0.03
num_epochs = 3
net = linreg
loss = squared_loss
for epoch in range(num_epochs):
for X, y in data_iter(batch_size, features, labels):
l = loss(net(X, w, b), y) # `X` ve `y`'deki minigrup kaybı
# [`w`, `b`]'e göre `l` üzerindeki gradyanı hesaplayın
l.sum().backward()
sgd([w, b], lr, batch_size) # Parametreleri gradyanlarına göre güncelle
with torch.no_grad():
train_l = loss(net(features, w, b), labels)
print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
epoch 1, loss 0.035539
epoch 2, loss 0.000133
epoch 3, loss 0.000050
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
lr = 0.03
num_epochs = 3
net = linreg
loss = squared_loss
for epoch in range(num_epochs):
for X, y in data_iter(batch_size, features, labels):
with tf.GradientTape() as g:
l = loss(net(X, w, b), y) # `X` ve `y`'deki minigrup kaybı
# [`w`, `b`]'e göre `l` üzerindeki gradyanı hesaplayın
dw, db = g.gradient(l, [w, b])
# Parametreleri gradyanlarına göre güncelle
sgd([w, b], [dw, db], lr, batch_size)
train_l = loss(net(features, w, b), labels)
print(f'donem {epoch + 1}, kayip {float(tf.reduce_mean(train_l)):f}')
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
donem 1, kayip 0.051920
donem 2, kayip 0.000222
donem 3, kayip 0.000052
.. raw:: html
.. raw:: html
Bu durumda, veri kümemizi kendimiz sentezlediğimiz için, gerçek
parametrelerin ne olduğunu tam olarak biliyoruz. Böylece eğitimdeki
başarımızı, gerçek parametreleri eğitim döngümüz aracılığıyla
öğrendiklerimizle karşılaştırarak değerlendirebiliriz. Gerçekten de
birbirlerine çok yakın oldukları ortaya çıkıyor.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print(f'w tahminindeki hata: {true_w - w.reshape(true_w.shape)}')
print(f'b tahminindeki hata: {true_b - b}')
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
w tahminindeki hata: [0.00038254 0.00028729]
b tahminindeki hata: [-4.6253204e-05]
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print(f'w tahminindeki hata: {true_w - w.reshape(true_w.shape)}')
print(f'b tahminindeki hata: {true_b - b}')
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
w tahminindeki hata: tensor([0.0002, 0.0002], grad_fn=)
b tahminindeki hata: tensor([-4.7684e-07], grad_fn=)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print(f'w tahminindeki hata: {true_w - tf.reshape(w, true_w.shape)}')
print(f'b tahminindeki hata: {true_b - b}')
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
w tahminindeki hata: [-0.0001471 -0.00130081]
b tahminindeki hata: [0.00119877]
.. raw:: html
.. raw:: html
Parametreleri mükemmel bir şekilde elde ettiğimizi kabullenmememiz
gerektiğini unutmayın. Bununla birlikte, makine öğrenmesinde, genellikle
temeldeki gerçek parametreleri elde etmek ile daha az ilgileniriz ve
yüksek derecede doğru tahminlere yol açan parametrelerle daha çok
ilgileniriz. Neyse ki, zorlu optimizasyon problemlerinde bile, rasgele
gradyan inişi, kısmen derin ağlar için, oldukça doğru tahmine götüren
parametrelerin birçok konfigürasyonunun mevcut olmasından dolayı,
genellikle dikkate değer ölçüde iyi çözümler bulabilir.
Özet
----
- Derin bir ağın, katmanları veya süslü optimize edicileri tanımlamaya
gerek kalmadan sadece tensörler ve otomatik türev alma kullanarak
nasıl sıfırdan uygulanabileceğini ve optimize edilebileceğini gördük.
- Bu bölüm sadece mümkün olanın yüzeyine ışık tutar. İlerideki
bölümlerde, yeni tanıttığımız kavramlara dayalı yeni modelleri
açıklayacak ve bunları daha kısaca nasıl uygulayacağımızı
öğreneceğiz.
Alıştırmalar
------------
1. Ağırlıkları sıfıra ilkleseydik ne olurdu? Algoritma yine de çalışır
mıydı?
2. Voltaj ve akım arasında bir model bulmaya çalışan `Georg Simon
Ohm `__ olduğunuzu varsayın.
Modelinizin parametrelerini öğrenmek için otomatik türev almayı
kullanabilir misiniz?
3. Spektral enerji yoğunluğunu kullanarak bir nesnenin sıcaklığını
belirlemek için `Planck
Yasası `__'nı
kullanabilir misiniz?
4. İkinci türevleri hesaplamak isterseniz karşılaşabileceğiniz sorunlar
nelerdir? Onları nasıl düzeltirsiniz?
5. ``squared_loss`` işlevinde ``reshape`` işlevi neden gereklidir?
6. Kayıp işlevi değerinin ne kadar hızlı düştüğünü bulmak için farklı
öğrenme oranları kullanarak deney yapın.
7. Örneklerin sayısı parti boyutuna bölünemezse, ``data_iter`` işlevinin
davranışına ne olur?
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html