How To

[TR] Kotlin İle Derin Öğrenmeye Giriş

Reklam

[TR] Kotlin İle Derin Öğrenmeye Giriş

Herkese merhaba, bugün yakın zamanlarda yayınlanmış olan Kotlin ile Derin Öğrenmeye giriş yapıyoruz.

Derin Öğrenme Nedir?

Derin öğrenme makine öğrenme yöntemlerinden biridir. Temelde beynin sinir ağlarından ilham alınarak tasarlanmıştır (yapay sinir ağları).

Derin öğrenme algoritmaları, girilen veri veya veri setleri üzerinden yapay sinir ağları üzerinde analiz eder. Derin öğrenme, makine öğrenmesi yöntemleri arasında insan beynine en çok benzeyendir.

Yapay Sinir Ağı Örneği
Yapay Sinir Ağı Örneği

Gördüğünüz gibi aynı insan beynindeki gibi aldığı veriler arasında bağlantılar kurarak öğrenir.

Hiç düşündünüz mü? Bir e-ticaret sitesinde size önerilen ürünler karşınıza nasıl çıkıyor diye. Ya da YouTube ve Netflix gibi platformlarda “size önerilen” kısımlar neye göre belirleniyor. Makine öğrenmesi algoritmaları sayesinde! Siz bir videoyu veya bir filmi izlediğinizde; izleme süreniz, verdiğiniz geri dönüş v.s. veriler toplanarak işlenir, bu sayede sizin için en uygun içerikler karşınıza çıkar.

Bütün bu öğrenme ve çıkarım yapma kısmında yazdığımız kodların arkasında bayağı bir matematik var, şu anlık o kısma girmeyeceğim. Ancak incelemek isteyenler olursa diye link bırakıyorum. https://towardsdatascience.com/what-is-deep-learning-and-how-does-it-work-2ce44bb692ac

Derin Öğrenme hakkında temel bir fikre sahip olduğumuza göre başlayabiliriz.

KotlinDL

KotlinDL, Keras’tan (https://keras.io/) ilham alınarak oluşturulmuş, yüksek seviye derin öğrenme API’ıdır. Bu API ile sıfırdan derin öğrenme modülleri yazabilirsiniz. KotlinDL projesinin temel amacı ise Derin Öğrenme’yi JVM (Java Virtual Machine) kullanıcıları için daha kolay hale getirmek.

Başlayalım!

Öncelikle yeni bir Kotlin projesi oluşturalım. Ben kotlin-dl koyuyorum ismini.

Proje Ayarlaması
Proje Ayarlaması

Projemizi oluşturduktan sonra build.gradle.kts dosyasının içine

repositories {
   jcenter()
   maven(url = "https://kotlin.bintray.com/kotlin-datascience")
}

dependencies {
   implementation ("org.jetbrains.kotlin-deeplearning:api:[KOTLIN-DL-VERSION]")
}

bunları ekleyelim. Bu Kotlin DL’i projemize import edecektir. Güncel Kotlin-DL versiyonuna https://github.com/JetBrains/KotlinDL üzerinden ulaşabilirsiniz.

Nöral Ağ Oluşturmak

Nöral ağlar oluşturmak için dataset(verisetleri) kullanılır. Resim sınıflandırma için oluşturacağımız bu örneğimizde Fashion-MNIST Dataset bu dataset’i kullanacağız. Bu dataset’te yaklaşık 70.000 tane resim var. Sayı büyük gibi gelebilir ama aslında bu gibi rakamları resim sınıflandırmanın “Hello World!”u olarak düşünebiliriz (:

Bizim kullanacağımız datasetteki sınıflandırmaları şimdiden yapalım.

val stringLabels = mapOf(0 to "T-shirt/top",
   1 to "Trouser",
   2 to "Pullover",
   3 to "Dress",
   4 to "Coat",
   5 to "Sandal",
   6 to "Shirt",
   7 to "Sneaker",
   8 to "Bag",
   9 to "Ankle boot"
)

Dataset’ten bazı resimler

Fashion-MNIST Data Örneği
Fashion-MNIST Data Örneği

İlk olarak nöral ağımızın yapısını tanımlayarak başlayalım. Nöral ağlarının temel yapı taşı layerlardır (katman). Bir nöral ağ oluşturmak için hangi layerlardan oluşacağını belirtmemiz gerekir. * Yeterli data, layer ve training (öğrenim) ile nöral ağlar, karışık sonuçları bile harika performanslarla vermeye başlar.

Burada tanımlayacağımız nöral ağ Multilayer Perceptron (MLP) olarak adlandırılır. Bu nöral ağ, multiple fully-connected layers(çoklu tamamen-bağlanmış katmanlar)‘dan oluşan basit bir nöral ağdır. MLP’nin içinde bulunan her bir layer’daki nöron (neuron), kendisinden önceki tüm layer’lardan output alır ve kendi output’unu bir sonraki katmanda bulunan tüm nöronlara gönderir.

Şimdi birkaç sıralı layer’dan oluşan bir nöral ağ tanımlayalım.

val model = Sequential.of(
   Input(28,28,1),
   Flatten(),
   Dense(300),
   Dense(100),
   Dense(10)
)

Bu kadar anlatımın üstüne yazılan kod basit geldi değil mi? 🙂 Şimdi burada neler tanımladığımıza bakalım.

İlk olarak, nöral ağa nasıl bir input (girdi) vereceğimizi belirttik. Kullanacağımız dataset’teki resimler 28 x 28 piksel, ve sadece bir renk kanalına (monochrome) sahip. Bu şekilde input 28 x 28 x 1 olacak.

Burada oluşturduğumuz ilk katman Flatten. Bu katman basitçe üç-boyutlu girdiyi tek-boyutlu’ya dönüştürür. Bizim örneğimizde 28 * 28 * 1 = 784.

Flatten’dan sonra, sıralı şekilde 3 tane Dense katmanı var. Dense katmanları, “tamamen bağlanmış katmanlar” olarak da anılır, bütün nöral ağ mimarilerinde en çok yaygın olan katmanlardır. Her bir Dense katmanı için bir boyut belirledik. Birincinin 300, ikincinin 100 ve sonuncunun 10 nöronu var.

Nöral Ağı Derleyelim

model.use {
   it.compile(
   optimizer = Adam(),
   loss = Losses.SOFT_MAX_CROSS_ENTROPY_WITH_LOGITS,
   metric = Metrics.ACCURACY
   )
}

it.compile() fonksiyonu ile nöral ağımızı derleyebiliyoruz.

optimizer için atadığımız Adam bir optimizasyon algoritması, giriş seviyesinde olduğundan bunu seçtik.
loss fonksiyonu, accuracy’i (doğruluğu) ayarlamak için kullanılır.
metric ise model’i eğitme ve değerlendirme sırasında durumları izlemek için kullanılır.

Artık summary() fonksiyonunu çağırıp nöral ağımızın yapısını yazdırabiliriz.

it.summary()
INFO api.core.Sequential - =================================================================
INFO api.core.Sequential - Model: Sequential
INFO api.core.Sequential - _________________________________________________________________
INFO api.core.Sequential - Layer (type) Output Shape Param # 
INFO api.core.Sequential - =================================================================
INFO api.core.Sequential - flatten_1(Flatten) [784] 0
INFO api.core.Sequential - _________________________________________________________________
INFO api.core.Sequential - dense_2(Dense) [300] 235500
INFO api.core.Sequential - _________________________________________________________________
INFO api.core.Sequential - dense_3(Dense) [100] 30100
INFO api.core.Sequential - _________________________________________________________________
INFO api.core.Sequential - dense_4(Dense) [10] 1010
INFO api.core.Sequential - _________________________________________________________________
INFO api.core.Sequential - =================================================================
INFO api.core.Sequential - Total trainable params: 266610
INFO api.core.Sequential - Total frozen params: 0
INFO api.core.Sequential - Total params: 266610
INFO api.core.Sequential - =================================================================

Bu şekilde bir çıktı alıyoruz.

Bir nöral ağ tanımladık. Şimdi asıl veriyi eğitmeye başlayalım.

Nöral Ağı Eğitmek (Training)

Herhangi bir veriyi kullanmadan önce, genel olarak birtakım önişlemlerle (preprocessing) gereklidir. Bizim örneğimizde bu önişlem küçük – bütün işlemler zaten aynı boyutta, gri tonlarında. Şimdi Fashion MNIST resim arşivlerini modelimizi eğitmek üzere dataset objelerine (object) çevireceğiz.

Dataset’i verdiğim linkten indirip proje içinde dataset adlı bir klasör oluşturup içine attıktan sonra önişleme başlayabiliriz.

val (train, test) = Dataset.createTrainAndTestDatasets(
   trainFeaturesPath = "datasets/mnist/train-images-idx3-ubyte.gz",
   trainLabelsPath = "datasets/mnist/train-labels-idx1-ubyte.gz",
   testFeaturesPath = "datasets/mnist/t10k-images-idx3-ubyte.gz",
   testLabelsPath = "datasets/mnist/t10k-labels-idx1-ubyte.gz",
   numClasses = 10,
   ::extractImages,
   ::extractLabels
)

val (newTrain, validation) = train.split(splitRatio = 0.95)

Farketmiş olabileceğiniz üzere, datayı 3 sete ayrdık. İlk olarak, test setlerini eğitmemiz gerekiyor. Modelden memnun kalana kadar test setlerine dokunmayacağız. Ayrıca train setini de newTrain ve valdiation’a ayırdık. Bunları eğitme (training) ve validation (doğrulama) işlemlerinde kullanacağız.

Şimdi modeli eğitmek için her şey hazır. Bunun için fit metodunu kullanacağız.

model.use {
   it.compile(
   optimizer = Adam(),
   loss = Losses.SOFT_MAX_CROSS_ENTROPY_WITH_LOGITS,
   metric = Metrics.ACCURACY
)

   it.summary()

   it.fit(
      dataset = newTrain,
      epochs = 10,
      batchSize = 100
   )

   val accuracy = it.evaluate(dataset = validation, batchSize = 100).metrics[Metrics.ACCURACY]

   println("Accuracy: $accuracy")
   it.save(File("src/model/my_model"))
}

fit metodundaki parametreleri açıklayalım.

Epochs: Yineleme sayısıdır. Eğitim sırasında verinin kaç kere işleneceğini belirtir.
Batch Size: Bu ise modelin parametreleri için kaç tane örnek kullanıldığını belirtir. Bizim örneğimizde bu sayı 100.

Model bir kez eğitildikten sonra, doğruluk değerini görmek yeni veriyi analiz etmek için oldukça önemlidir.

Accuracy: 0.9806665182113647

Accuracy (doğrulama) değeri ortalama bu civarlarda olmalıdır, değişkenlik gösterebilir.

Şu ana kadar derin öğrenme modelimizi oluşturduk, eğittik ve kaydettik. Şimdi modelimize daha önceden gösterilmemiş yeni bir görseli verip tahminler yapmasını sağlayalım.

Çanta
Çanta

Kullanacağımız görsel bu olacak. Bahsettiğim gibi bu görsel daha önceden datasette bulunmayan bir görsel, yani tam anlamıyla bir tahmin yaptıracağız.

Eğer modelinizde işlediğiniz veriyle tahminde bulunduracağınız verinin boyutu ve formatı aynıysa bir önişlem gerektirmeden tahmini yapabilirsiniz. Bizim örneğimizde bu şekilde o yüzden bir şey yapmayacağız.

fun reshapeInput(inputData: FloatArray): Array<Array<FloatArray>> {
   val reshaped = Array(
      1
   ) { Array(28) { FloatArray(28) } }
   for (i in inputData.indices) reshaped[0][i / 28][i % 28] = inputData[i]
   return reshaped
}

fun main() {
   InferenceModel.load(File(MODELIN_PATHI)).use {
      it.reshape(::reshapeInput)
      val prediction = it.predict(test.getX(0))

      println("Tahmin edilen katman: $prediction. Sınıfı da aha bu: ${stringLabels[prediction]}.")
   }
}

Kodu çalıştırdıktan sonra aşağıdaki logu görmeliyiz.

Tahmin edilen katman: 8. Sınıfı da aha bu: Bag.
Gerçek katman: 8.

Gördüğünüz gibi modelimiz daha öncesinde kendine hiç verilmemiş olan bir resmi, başarılı bir şekilde tahmin etti. Tebrikler! (:

Reklam
Reklam

İlgili Makaleler

Bir Yorum

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Başa dön tuşu