Yapay Zeka Destekli Görüntü Tanıyan iOS Uygulama Nasıl Geliştirilir?

Özgür Şahin
NSIstanbul
Published in
8 min readJul 23, 2018

Makine öğrenmesi giderek daha popüler hale geliyor. Bu alanda her gün yeni bir gelişme görüyoruz. Gün geçtikçe daha iyi derin öğrenme modelleri ortaya çıkıyor. Akademi son sürat yol alıp bazı büyük firmalar hızlı bir şekilde adapte olarak derin öğrenme tabanlı ürünler geliştirirken, bireysel geliştirici bu alanda geride kalabiliyor. Bu yazımda bireysel geliştirici olarak geliştirebileceğiniz bir uygulama üzerinden güncel pratiklere bir bakış açısı sunmak istiyorum.

Bu yazı biraz ileri seviye için derinlemesine olacak daha yumuşak bir giriş için şu yazı dizimi (iOS Geliştiriciler için Makine Öğrenmesi) tavsiye ederim.

Rehber niteliğinde olmasını umduğum yazımda aşağıdaki konuları işleyeceğim :

  1. Makine öğrenmesinde kullanım için resim veri kümesi hazırlama
  2. Veri setini çeşitlendirmek için veri sentezi
  3. Öğrenme aktarımı (transfer learning) ve ince ayar (fine-tuning) yöntemlerinden faydalanarak daha önceden eğitilmiş bir modeli kendi veri setimiz için tekrar eğitme
  4. Keras’ta eğitilen modeli CoreML’e çevirerek iOS uygulamada kullanma

Bu rehber sonunda görme engelliler için Türk Lirası (yazının ilerleyen bölümlerinde ‘TL’ olarak anılacaktır) banknotlarını tanıyan bir uygulama hazırlamış olacağız.

Gelin ilk önce kullanacağımız araçlara bir göz gezdirelim.

Keras

Keras kütüphanesi Tensorflow ve Theano’ya üst katman olarak yazılmış, daha kolay model geliştirmeyi sağlayan bir Python kütüphanesidir. Sizi detaylardan kurtararak modelinizi geliştirmeye odaklar. Hazır metotlarla hızlı bir şekilde prototip ortaya çıkartmanıza olanak sağlar.

Resnet50

Resnet, artık değerli nöral ağların (residual neural network) bir kısaltmasıdır. Bu model evrişimli sinir ağlarının (convolutional neural network:CNN) geliştirilmiş bir versiyonudur. Evrişimli sinir ağlarını hatırlamıyorsanız Ayyüce Kızrak’ın DERİNE DAHA DERİNE: Evrişimli Sinir Ağları yazısına göz atmanızı tavsiye ederim. Resnet modeli CNN ağlarının performans düşümü (degradation) problemini çözmeyi hedeflemektedir. Performans düşümü problemi Resnet’in makalesinde şu şekilde açıklanmaktadır: ¨Derin ağlar yakınsamaya başladığı zaman, bozulma problemi ortaya çıkar. Ağ derinliği arttıkça, verimliliği (accuracy) doygunluğa (beklendiği şekilde) ulaşır ama daha sonra hızlı bir düşüş eğilimi gösterir.¨

Resnet bu problemi çözmek için katmanlar arasına kısayollar ekler. Bu basit fikir, ağ derinleştikçe oluşan bozulmayı önler. Ayrıca Resnet modelinde daha hızlı eğitim yapabilmek için darboğaz (bottleneck) blokları kullanılır. Resnet50, ImageNet veri kümesi üzerinde eğitilmiş 50 katmanlı bir ağdır. ImageNet, görüntü tanıma yarışmaları için oluşturulmuş 20 binden fazla kategoriye ait 14 milyondan fazla resmin bulunduğu bir görüntü veritabanıdır. Resnet modeli 2 adet (3x3) evrişim kullanmak yerine (1x1), (3x3), (1x1) şeklinde evrişim katmanları kullanır.

https://arxiv.org/pdf/1512.03385.pdf

Veri Kümesi ve Veri Sentezi

TL banknotlarını resimlerinden tanımak istediğim için hali hazırda bir veri kümesi bulamadım. Bu sebeple kendim basit bir veri kümesi oluşturdum. Farklı arka planlarda ve farklı ortam ışığı altında 900 fotoğraf çektim ve bunları Resnet modelinin girdisine uygun olması için 224x224 olarak boyutlandırdım. Veri kümesi çok profesyonel bir küme olmadı ve tüm fotolarda yalnız benim elim göründüğü için benim elime karşı ön yargılı bir küme olduğunu söyleyebiliriz :).

Prototip bir uygulama olacağı için bu şekilde bir veri kümesi de iş görecektir. Son kullanıcı için hazırlanacak uygulamalarda, farklı koşulları olabildiğince göz önüne alan büyük veri kümeleri kullanılması tavsiye edilir. TL banknotları için 6 sınıfımız bulunuyor. Veri kümesini %80 eğitim, %20 test veri kümesi olacak şekilde rastgele ayırdım.

https://github.com/ozgurshn/TurkishBanknoteDataset

Veri çeşitliliğini artırmak için veri sentezi (data augmentation) yönteminden yararlandım. Bu yöntem ile bir resmin farklı varyasyonlarını (döndürülmüş, yaklaştırılmış, eğilmiş gibi) üretebiliyoruz. Aşağıdaki kolajda örnek bir veri sentezi görebilirsiniz. Sol taraftaki orjinal resim sağ taraftakiler üretilmiş resimler.

Görüntü sentezi

Öğrenme Transferi

Öğrenme transferi, belirli bir problemi çözmek için öğrenilen bilgiyi benzer ama başka bir alanda kullanmaktır.

Öğrenme transferi, makine öğreniminde kullanılmasına rağmen asıl mantığı psikolojiye dayanıyor. Bu bağlamda öğrenme transferi; bireylerin bir alanda öğrendiklerini, benzer özelliklerdeki başka bir alana aktarma işlemidir ve bilişsel psikolojinin temel araştırma alanlarından biridir. Psikoloji tarihinde ilk olarak Thorndike ve Woodworth tarafından 1901 yılında tanımlanmıştır. Uluslararası Eğitim Ansiklopedisinde Perkins ve Salomon tarafından 1992 yılında şu şekilde açıklanmıştır: “Öğrenme transferi bir konuyu öğrenirken başka bir konudaki performansın artması veya azalması şeklinde ortaya çıkar. Transfer, yakın transfer (yakın ilişkili konular arası) veya uzak transfer de (farklı konular arası) olabilir. Transferin gerçekleşmesi; öğrenen kişinin yeteneklerine bağlı olarak, benzerlik değerlendirmesine dayalı olan subjektif bir konudur. Benzerlik yargımızın bazı alanları hayat boyu gelişse de temel mekanizmaları doğa tarafından beynimize kodlanmıştır.” (Aytar, 2014)

¨Örneğin bir insanın araba sürmeyi öğrenmesi daha sonra kamyon sürmeyi öğrenmesini kolaylaştırır, matematik öğrenmesi fizik çalışmasını kolaylaştırır, kardeşiyle geçinmeyi öğrenmesi başkalarıyla geçinmeyi öğrenmesini kolaylaştırır, satranç oynamayı öğrenmesi onu politikada veya iş hayatında daha stratejik bir düşünür haline getirebilir. Transfer, eğitimde ve öğrenme teorisinde anahtar bir kavramdır. Çünkü çoğu örgün eğitim bu şekilde bir transferi amaçlamaktadır.¨ (Parkins ve Sololons, Transfer Learning, 1992)

Makine öğreniminde ise öğrenme transferi, belirli bir alanda eğitilmiş modelin başka bir işlemde kullanılmak için tekrar eğitilmesi anlamına geliyor. Model daha önceden öğrenilen bilginin üzerine inşa edildiği için öğrenme süresi daha kısa sürüyor.

Yapay sinir ağlarını eğitmek için genellikle büyük veri kümeleri gerekmektedir. Eğer veri kümeniz küçük olursa, ezberleme (overfitting) sorunuyla karşı karşıya kalabilirsiniz. Ezberleme sorununda modeliniz eğittiğiniz resimleri çok iyi öğrenirken, daha önceden hiç görmediği resimlerde kötü sonuçlar verir. Burada, test verisi olarak modelin eğitimde görmediği resimleri kullanmak çok önemlidir. Eğer modelinizi eğitmek için haftalarca bekleyecek zamanınız yoksa, donanımınız yetersizse ve de veri kümeniz küçükse öğrenme transferi (transfer learning) yöntemi sizin kurtarıcınız olacaktır. Bu yöntem sayesinde daha önceden benzer bir işlem için (görüntü tanıma vb.) eğitilmiş modelin ağırlıklarından faydalanarak hızlı bir şekilde kendi işlemimize adapte olmasını sağlayabiliriz. ResNet50 modeli ImageNet resimleri üzerinde eğitilmiştir. Bu model köpek türleri, kedi türleri, ev araçları vb. gibi gündelik görüntülerden oluşan ImageNet kategorilerini sınıflandırmayı öğrenmiştir. Biz de bu görüntü sınıflandırmayı öğrenmiş modeli alarak kendi veri kümemiz için eğiteceğiz. Evrişimli ağlarda ara katmanlar genellikle üst seviye özellikleri (kenar, şekil, şeklin bir bölümü vb.) sınıflandırmayı öğrenirken son katmanlar veri kümesinin daha spesifik özelliklerini öğrenir. Bundan dolayı ağın son katmanını çıkartarak kendi sınıflandırıcı katmanımızı ekleyeceğiz ve tüm ağ katmanlarını değil sadece son katmanı eğiterek hızlı bir şekilde yeni bir model elde edeceğiz.

Resnet50 Modeline İnce Ayar Yapma

İnce ayar yapmak ve modelimi hızlı bir şekilde eğitmek için Google Colab servisini kullanacağım. Colab servisini daha önce kullanmadıysanız Fuat Beşer’in Google Colab ile Ücretsiz GPU Kullanımı yazısı faydalı olacaktır. Bu servis sayesinde iPython defterleri oluşturup paylaşabiliyoruz ve başkalarının araştırmalarını ve kod örneklerini çalıştırarak geliştirmelerini teyit edebiliyoruz. Bu şekilde bilim tekrar edilebilir hale geliyor ve hayat bir dakikalığına güzelleşiyor :).

Konumuza geri dönersek, Keras kütüphanesinde ResNet50 modeli hazır olarak sunuluyor. Bu sayede modeli sıfırdan oluşturmakla uğraşmıyor, direkt metodunu çağırarak kullanabiliyoruz. Aşağıdaki kod bölümünde model girdisi olarak resmin boyutunu belirliyorum. Bu eğitim için ResNet’in hali hazırda öğrenmiş olduğu ağırlıkları kullanacağım. Bu katmanlarını tekrar eğitmeyeceğimden dolayı donduruyorum. Çıktı katmanı ImageNet sınıflandırmasına göre özelleştirildiği için bu katmanı dahil etmiyorum (includetop=false). Modelin sonuna ortalama ortaklama (average-pooling) katmanı ve softmax katmanı ekliyorum.

Ortalama ortaklama aşağıdaki gibi piksel matrisindeki ortaklama alanındaki değerlerin ortalamasını alarak matris boyutunu küçültür ve hesaplama karmaşıklığını azaltır.

https://pythonmachinelearning.pro/introduction-to-convolutional-neural-networks-for-vision-tasks/

Tüm model yerine en son eklediğim katmanı eğiteceğim için, modeli daha hızlı bir şekilde eğitebileceğim.

Tüm eğitim kodunu bu Colab linkinde bulabilirsiniz. Modelde optimizasyon için Adadelta’yı kullanacağım ve modeli bu şekilde derleyeceğim.

Sentezlenmiş (döndürülmüş, ters çevrilmiş, yakınlaştırılmış vb.) resimler üretmek için ImageDataGenerator kullanıyorum.

Keras’ta eğittiğim modeli Apple’ın formatı olan CoreML formatına dönüştürmek için Coremltools Python kütüphanesini kullanıyorum. Bu model sayesinde .mlmodel modelleri oluşturma, inceleme ve test etme gibi işlemleri yapabiliyoruz. Burada Keras’ta oluşturduğum modeli CoreML formatına dönüştürmek için kütüphanenin convert metodunu kullanıyorum.

Bu modeli 16’lık görüntü paketleriyle 50 devirde eğitiyorum. Eğitim sonucunda eğitim verisi için 0.98 tahminleme doğruluğuna (accuracy), test verisi için ise 0.77 doğruluğa ulaşıyorum. Modeli daha çok devirde eğiterek model doğruluğunu artırabilirim, ama ben burada kısıtlı bir zamanda adeta bir hackathonda yarışırcasına bu modeli hızlı bir şekilde eğiterek prototip oluşturmak istiyorum. Sonuçta ortaya çıkan verimlilik mükemmel değil ama prototip bir uygulama için iş görecektir.

Doğruluk ve kayıp

iOS Uygulama Oluşturma

Örnek projeyi tüm kodlarıyla Github’ta paylaştım. Burada geliştirme sürecinde oluşturduğunuz CoreML modelini aşağıdaki gibi model klasörüne sürükleyip bıraktım. viewDidLoad metodunda oluşturduğum modeli kullanmak üzere bir değişkene atadım.

XCode’da mlmodel dosyasına tıklayarak modelinizi inceleyebilirsiniz. Aşağıdaki gibi, XCode model boyutunu, girdisini ve çıktısını gösterir. Model girdisi 224x244 boyutunda bir resim olduğu için modeli işaretlendiği şekilde bir resimle beslemeliyiz.

Modelin disk boyutu uygulamanız için çok büyükse, MobileNet gibi daha küçük modeller tercih edebilirsiniz veya modelinizi half-precision modele çevirebilirsiniz. Core ML Tools kullanarak modelinizin ağırlık değerlerinin ondalıklı kısmını tam kesinlikten (full-precision:32 bit) yarı kesinliğe (half-precision:16 bit) çevirebilirsiniz.

Kameradan elde edilen görüntüyü ResNet modelinin girdisine uygun şekilde 224x224 olarak boyutlandırıyoruz.

Aslında Apple’ın Vision kütüphanesi bu işi de hallediyor. Resmi sizin modelinizin alacağı formata otomatik çevirebiliyor.

VNCoreMLModel, Vision requestleriyle kullanılan Core ML modeli için bir konteynerdir. Burada kendi modelimiz için bir konteyner oluşturuyoruz. VNCoreMLRequest görüntüyü işlemek için CoreML modelini kullanan bir görüntü analizi isteği (request) oluşturuyor.

Görüntü sınıflandırma isteği için VNImageRequestHandler kullanılıyor. Bu işleyici (handler) kameradan gelen görüntü ara belleğini (buffer) girdi olarak alıyor.

Bu istek tamamlandığında, geriye her bir sınıfımız için bir güven katsayısı (confidence level) dönüyor. Bu değerler telefon kamerasıyla çektiğimiz görüntünün her bir banknot sınıfına olan benzerlik değeri aslında. Dönülen liste güven katsayısına göre sıralanmış durumda. Yani modelin en emin olduğu sınıf en üstte yer alıyor. Bu aşamada artık uygulamayı derleyip görüntü tanıma işlemimizi gerçekleştirebiliriz.

Gördüğünüz gibi uygulamamız hazır artık siz de bu adımları uygulayarak görüntü tanıyan uygulamalar geliştirebilirsiniz! Uygulamanın daha fazla veriyle eğitilmiş son halini AppStore’dan indirebilirsiniz.

Konu ilginizi çektiyse iOS geliştiriciler için Makine Öğrenmesi yazı dizimi de tavsiye ederim. Bu yazılarda yazı sınıflandırma ve görüntü sınıflandırmanın detaylarına iniyoruz.

Bu alanda uzmanlaşmak isterseniz mail bültenime kayıt olabilirsiniz.

Bu yazıdan keyif aldıysanız Medium ve Twitter üzerinden beni takip edebilirsiniz.

Kaynaklar

Perkins and Salamon (1992), Transfer Learning

https://pdfs.semanticscholar.org/fb86/245e6623502017940c796c01ed508c3d8208.pdf

Aytar, Y. (2014). Transfer Learning for Object Category Detection. University of Oxford.

How to Retrain Inception’s Final Layer for New Categories (2016, April 26). TensorFlow. Retrieved from https://www.tensorflow.org/tutorials/image_retraining

Kaiming He ve ark. (2015), Deep Residual Learning for Image Recognition

--

--

Özgür Şahin
NSIstanbul

Articles about Deep Learning, iOS App Development, Entrepreneurship and Psychology