MXNet ile Derin Öğrenme 1.2: Doğrusal (Linear) Regresyon (Uygulama)
Herkese merhabalar, MXNet ile derin öğrenme serisine devam ediyoruz. İlk bölümde doğrusal regresyon konusunda teorik bilgiler paylaşmıştık. Bu bölümde doğrusal regresyon konusunda MXNet kütüphanesini kullanarak uygulama yapacağız.
İlk bölümü incelemeyenler buradan erişebilirsiniz.
Uygulama kısmında hazır verisetlerini kullanmak yerine kendi verisetimizi hazırlayacağız.
Uygulama
- Kütüphane ekleme,
- Veriseti oluşturma,
- Verisetini okuma,
- Model parametrelerini belirleme,
- Sinir ağ modeli oluşturma,
- Kayıp fonksiyonunu tanımlama,
- Optimizasyon algoritmasını tanımlama,
- Eğitim,
kısımlarından oluşacaktır.
1.1 Kütüphaneleri Ekleme
İlk aşamada gerekli olan kütüphaneleri ekleyeceğiz.
from d2l import mxnet as d2l from mxnet import autograd, np, npx import random npx.set_np()
1.2 Verisetini Oluşturma
Ek gürültülü doğrusal bir modele göre yapay bir veri kümesi oluşturulacaktır. Veri setinizde yer alan sonlu örnekler kümesini kullanarak bu modelin parametreleri oluşturulacaktır . Veriler düşük boyutlu tutulacak, böylece kolayca görselleştirebiliriz. Aşağıdaki kod parçacığında, her biri standart bir normal dağılımdan örneklenmiş 2 özellikten oluşan 1000 örnek içeren bir veri kümesi oluşturulacaktır. Bu nedenle sentetik veri setimiz bir X ∈ R 1000 × 2 matrisi olacaktır.
def synthetic_data(w, b, num_examples): 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)
Özelliklerdeki her satırın 2 boyutlu bir veri örneğinden oluştuğunu ve etiketlerdeki her satırın 1 boyutlu bir etiket değerinden oluşmaktadır.
İkincil özelliklerini [:, 1] ve etiketleri kullanarak bir dağılım grafiği oluşturarak, ikisi arasındaki doğrusal korelasyonu açıkça gözlemleyebiliriz.
d2l.set_figsize() d2l.plt.scatter(d2l.numpy(features[:, 1]), d2l.numpy(labels), 1);
Şekil 1: Verisetinin görselleştirilmesi
1.3 Verisetini Okuma
Eğitim modellerinin, veri kümesi üzerinde birden çok geçiş yapmaktan, bir seferde bir mini grup örnek almaktan ve bunları modelimizi güncellemek için kullanmaktan oluşmaktadır. Bu süreç, makine öğrenimi algoritmalarını eğitmek için çok temel olduğundan, veri kümesini karıştırmak ve ona mini gruplar halinde erişmek için bir yardımcı program işlevi 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. İşlev bir parti boyutunu, bir özellik matrisini ve bir etiket vektörünü alarak batch_size boyutundaki mini grupları verir. Her mini parti, bir dizi özellik ve etiketten oluşur.
def data_iter(batch_size, features, labels): num_examples = len(features) indices = list(range(num_examples)) 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]
Genel olarak, paralelleştirme işlemlerinde verimli olan GPU donanımından yararlanmak için makul boyutta mini gruplar kullanmak istemekteyiz.
batch_size = 10 for X, y in data_iter(batch_size, features, labels): print(X, '\n', y) break
işlemi ile mini parti boyutunu 10 olarak belirliyoruz. Her mini partideki özelliklerin şekli bize hem minibatch boyutunu hem de girdi özelliklerinin sayısını söyler. Aşağıda kod çıktısı bulunmaktadır.
[[-0.10548475 2.1780314 ] [-0.9567186 -1.6827176 ] [-0.40910295 0.93317765] [ 1.5418535 -1.7995142 ] [ 0.7882709 -2.0847268 ] [-0.23282665 -0.8926184 ] [ 0.08035068 0.80551594] [-0.9711102 0.05383795] [ 0.5524162 0.21463515] [ 1.1116904 0.10874183]] [[-3.419401 ] [ 8.01163 ] [ 0.22510855] [13.404824 ] [12.8573065 ] [ 6.751007 ] [ 1.6076912 ] [ 2.0689626 ] [ 4.603484 ] [ 6.066374 ]]
Yinelemeyi çalıştırırken, tüm veri kümesi tükenene kadar art arda farklı mini gruplar elde ederiz. Yukarıda uygulanan yineleme, didaktik amaçlar için iyi olsa da, bizi gerçek problemlerde başımızı belaya sokacak şekillerde verimsizdir. Derin öğrenme çerçevesinde uygulanan yerleşik yineleyiciler önemli ölçüde daha verimlidir ve hem dosyalarda depolanan verilerle hem de veri akışlarıyla beslenen verilerle ilgilenebilirler.
1.4 Model Parametrelerini Belirleme
Modelimizin parametrelerini minibatch stokastik gradyan inişiyle optimize etmeye başlamadan önce, ilk olarak bazı parametrelere ihtiyacımız var. Aşağıdaki kodda, ortalama 0 ve standart sapma 0.01 olan normal bir dağılımdan rastgele sayıları örnekleyerek ve sapmayı 0 olarak ayarlayarak ağırlıklar başlatılacaktır.
w = np.random.normal(0, 0.01, (2, 1)) b = np.zeros(1) w.attach_grad() b.attach_grad()
Parametreleri başlattıktan sonra, bir sonraki aşamada, verileri yeterince iyi uyana kadar onları güncellemektir. Her güncelleme, parametrelere göre kayıp fonksiyonun gradyanını almayı gerektirir. Bu gradyan göz önüne alındığında, her bir parametreyi kaybı azaltabilecek yönde güncelleyebiliriz.
1.5 Sinir Ağ Modeli Oluşturma
Modeli, girdi ve parametrelerini çıktılarıyla ilişkilendirerek tanımlamalıyız. Doğrusal modelin çıktısını hesaplamak için, X girdi özelliklerinin ve model ağırlıklarının W matris vektör iç çarpımını aldığımızı ve her bir örneğe ofset b‘yi eklediğimizi hatırlayın. Xw‘nin altında bir vektör ve b‘nin bir skaler olduğuna dikkat edin.
Şekil 2: Doğrusal regresyon formülü
def linreg(X, w, b): return np.dot(X, w) + b
1.6 Kayıp Fonksiyonunu Tanımlama
Modeli güncellemek, kayıp fonksiyonun gradyanını almayı gerektirdiğinden, önce kayıp fonksiyonunu tanımlamalıyız. Burada, kayıp karesi (squared loss) işlevini kullanacağız. Uygulamada, gerçek y değerini tahmin edilen değer şekli y_hat‘a dönüştürülmesi gerekir. Aşağıdaki işlev tarafından döndürülen sonuç da y_hat ile aynı şekle sahip olacaktır.
def squared_loss(y_hat, y): return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
1.7 Optimizasyon Algoritmasını Tanımlama
Her adımda, veri setinden rastgele alınan bir mini parti kullanarak, parametrelere göre kaybın gradyanı tahmin edilecektir. Daha sonra kayıpları azaltabilecek yönde parametreler güncellenecektir. Aşağıdaki kod, bir dizi parametre, bir öğrenme hızı ve bir parti boyutu verilen minibatch stokastik gradyan iniş güncellemesini uygular. Güncelleme adımının boyutu öğrenme oranı lr tarafından belirlenir. Kayıp, örneklerin mini partisi üzerinden bir toplam olarak hesaplandığından, adım boyutunu parti boyutuna (batch_size) göre normalleştirilir, böylece tipik bir adım boyutunun büyüklüğü, parti boyutu seçimine büyük ölçüde bağlı olmaz.
def sgd(params, lr, batch_size): for param in params: param[:] = param - lr * param.grad / batch_size
1.8 Eğitim
Her yinelemede, bir mini grup eğitim örneği alınacak ve bir dizi tahmin elde etmek için bunları modelden geçirilecektir. Kaybı hesapladıktan sonra, her parametreye göre gradyanları depolayarak ağ üzerinden geriye doğru geçişi başlatılır. Son olarak, model parametrelerini güncellemek için optimizasyon algoritmasına sgd adı verilecektir.
Her dönemde, eğitim veri kümesindeki her örnekten geçtikten sonra tüm veri kümesini (data_iter işlevini kullanarak) yinelenecek. Epoch sayısı num_epochs ve öğrenme hızı lr, burada sırasıyla 3 ve 0,03 olarak belirlediğimiz hiperparametrelerdir.
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) # Minibatch loss in `X` and `y` l.backward() sgd([w, b], lr, batch_size) train_l = loss(net(features, w, b), labels) print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')
Çıktılardan birkaçı:
epoch 1, loss 0.024854 epoch 2, loss 0.000092 epoch 3, loss 0.000051
Son olarak, Tahmin edilen değerler ile gerçek değerler karşılaştırılacaktır.
print(f'error in estimating w: {true_w - w.reshape(true_w.shape)}') print(f'error in estimating b: {true_b - b}')
Çıktı:
error in estimating w: [ 0.00078118 -0.00038838] error in estimating b: [0.00023365]
Verisetini 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 öğrenilen ile karşılaştırarak değerlendirdik. Gerçekten de birbirlerine çok yakın oldukları ortaya çıktı.
Doğrusal Regresyon bölümünün uygulama kısmını bitirmiş olduk. Bu bölümde kendi olşuturduğumuz küçük verisetini kullanarak doğrusal regresyon kullanarak modeli eğittik ve test ettik. Bu bölüm öğretici olduğundan dolayı küçük ve anlaşılır veriseti kullanıldı. Sonraki bölümlerde çok kullanılan hazır verisetleri kullanılacaktır.
Kodların tamamına buradan ulaşabilirsiniz.
Serinin sonraki bölümlerinde görüşmek dileğiyle.
Kaynakça