TensorFlow'da Gradient Descent'in Birçok Uygulaması
Yayınlanan: 2022-03-11Google'ın TensorFlow'u, derin öğrenme modellerini eğitmek ve dağıtmak için önde gelen araçlardan biridir. Yüz milyonlarca parametreyle son derece karmaşık sinir ağı mimarilerini optimize edebilir ve donanım hızlandırma, dağıtılmış eğitim ve üretim iş akışları için çok çeşitli araçlarla birlikte gelir. Bu güçlü özellikler, derin öğrenme alanının dışında korkutucu ve gereksiz görünmesini sağlayabilir.
Ancak TensorFlow, derin öğrenme modellerinin eğitimi ile doğrudan ilgili olmayan daha basit problemler için hem erişilebilir hem de kullanılabilir olabilir. Özünde, TensorFlow, tensör işlemleri (vektörler, matrisler vb.) ve rastgele hesaplama dizileri üzerinde gradyan inişi gerçekleştirmek için kullanılan kalkülüs işlemleri için optimize edilmiş bir kitaplıktır. Deneyimli veri bilimcileri, "gradyan inişinin" hesaplamalı matematik için temel bir araç olduğunu kabul edeceklerdir, ancak genellikle uygulamaya özel kod ve denklemlerin uygulanmasını gerektirir. Göreceğimiz gibi, TensorFlow'un modern “otomatik farklılaşma” mimarisi burada devreye giriyor.
TensorFlow Kullanım Örnekleri
- Örnek 1: TensorFlow 2.0'da Gradient Descent ile Lineer Regresyon
- Gradyan İniş Nedir?
- Örnek 2: Maksimal Yayılmış Birim Vektörleri
- Örnek 3: Karşıt Yapay Zeka Girdileri Oluşturma
- Son Düşünceler: Gradient Descent Optimizasyonu
- TensorFlow'da Gradient Descent: Minimumları Bulmaktan Yapay Zeka Sistemlerine Saldırmaya
Örnek 1: TensorFlow 2.0'da Gradient Descent ile Lineer Regresyon
Örnek 1 Defter
TensorFlow koduna geçmeden önce gradyan inişi ve lineer regresyon hakkında bilgi sahibi olmak önemlidir.
Gradyan İniş Nedir?
En basit ifadeyle, çıktısını en aza indiren bir denklem sisteminin girdilerini bulmak için sayısal bir tekniktir. Makine öğrenimi bağlamında, bu denklem sistemi bizim modelimizdir , girdiler modelin bilinmeyen parametreleridir ve çıktı, model ile verilerimiz arasında ne kadar hata olduğunu temsil eden, minimize edilecek bir kayıp fonksiyonudur . Bazı problemler için (doğrusal regresyon gibi), hatamızı en aza indiren parametreleri doğrudan hesaplamak için denklemler vardır, ancak çoğu pratik uygulamada, tatmin edici bir çözüme ulaşmak için gradyan inişi gibi sayısal tekniklere ihtiyaç duyarız.
Bu makalenin en önemli noktası, gradyan inişinin genellikle denklemlerimizi oluşturmayı ve kayıp fonksiyonumuz ile parametrelerimiz arasındaki ilişkiyi türetmek için hesabı kullanmayı gerektirmesidir. TensorFlow (ve herhangi bir modern otomatik farklılaştırma aracı) ile hesap bizim için halledilir, böylece çözümü tasarlamaya odaklanabiliriz ve çözümün uygulanması için zaman harcamak zorunda kalmazız.
İşte basit bir lineer regresyon probleminde nasıl göründüğü. 150 yetişkin erkeğin boylarının (h) ve ağırlıklarının (w) bir örneğine sahibiz ve bu çizginin eğimi ve standart sapması konusunda kusurlu bir tahminle başlıyoruz. Yaklaşık 15 gradyan iniş yinelemesinden sonra, optimuma yakın bir çözüme ulaşırız.
TensorFlow 2.0 kullanarak yukarıdaki çözümü nasıl ürettiğimizi görelim.
Doğrusal regresyon için, ağırlıkların doğrusal bir yükseklik denklemi ile tahmin edilebileceğini söylüyoruz.
Tahminler ve gerçek değerler arasındaki ortalama karesel hatayı (kayıp) en aza indiren α ve β (eğim ve kesişim) parametrelerini bulmak istiyoruz. Dolayısıyla kayıp fonksiyonumuz (bu durumda “ortalama kare hatası” veya MSE) şöyle görünür:
Ortalama kare hatasının birkaç kusurlu çizgiyi nasıl aradığını ve ardından tam çözümle (α=6.04, β=-230.5) görebiliriz.
Bu fikri TensorFlow ile hayata geçirelim. Yapılacak ilk şey, tensörleri ve tf.*
işlevlerini kullanarak kayıp işlevini kodlamaktır.
def calc_mean_sq_error(heights, weights, slope, intercept): predicted_wgts = slope * heights + intercept errors = predicted_wgts - weights mse = tf.reduce_mean(errors**2) return mse
Bu oldukça basit görünüyor. Tüm standart cebirsel operatörler tensörler için aşırı yüklenmiştir, bu nedenle yalnızca optimize ettiğimiz değişkenlerin tensör olduğundan emin olmamız gerekir ve diğer her şey için tf.*
yöntemlerini kullanırız.
O zaman tek yapmamız gereken bunu bir gradyan iniş döngüsüne koymak:
def run_gradient_descent(heights, weights, init_slope, init_icept, learning_rate): # Any values to be part of gradient calcs need to be vars/tensors tf_slope = tf.Variable(init_slope, dtype='float32') tf_icept = tf.Variable(init_icept, dtype='float32') # Hardcoding 25 iterations of gradient descent for i in range(25): # Do all calculations under a "GradientTape" which tracks all gradients with tf.GradientTape() as tape: tape.watch((tf_slope, tf_icept)) # This is the same mean-squared-error calculation as before predictions = tf_slope * heights + tf_icept errors = predictions - weights loss = tf.reduce_mean(errors**2) # Auto-diff magic! Calcs gradients between loss calc and params dloss_dparams = tape.gradient(loss, [tf_slope, tf_icept]) # Gradients point towards +loss, so subtract to "descend" tf_slope = tf_slope - learning_rate * dloss_dparams[0] tf_icept = tf_icept - learning_rate * dloss_dparams[1]
Bunun ne kadar temiz olduğunu anlamak için bir dakikanızı ayıralım. Gradyan inişi, optimize etmeye çalıştığımız tüm değişkenlere göre kayıp fonksiyonunun türevlerinin hesaplanmasını gerektirir. Calculus'un dahil olması gerekiyordu, ama aslında hiçbirini yapmadık. Sihir aslında şudur:
- TensorFlow, bir
tf.GradientTape()
altında yapılan her hesaplamanın bir hesaplama grafiğini oluşturur. - TensorFlow, hesaplama grafiğindeki herhangi bir değişkenin diğer değişkenleri nasıl etkilediğini belirleyebilmesi için her işlemin türevlerini (gradyanlarını) nasıl hesaplayacağını bilir.
Süreç farklı başlangıç noktalarından nasıl görünüyor?
Gradyan inişi, optimal MSE'ye dikkat çekici bir şekilde yaklaşır, ancak aslında her iki örnekte de optimumdan önemli ölçüde farklı bir eğim ve kesişme noktasına yakınsar. Bazı durumlarda, bu, gradyan iniş algoritmalarının doğasında bulunan bir zorluk olan yerel minimuma yakınsayan gradyan inişidir. Ancak lineer regresyon kanıtlanabilir bir şekilde yalnızca bir küresel minimuma sahiptir. Peki nasıl yanlış eğime ve kesişme noktasına geldik?
Bu durumda sorun, gösteri için kodu aşırı basitleştirmemizdir. Verilerimizi normalleştirmedik ve eğim parametresi, kesişme parametresinden farklı bir özelliğe sahip. Eğimdeki küçük değişiklikler kayıpta büyük değişiklikler üretebilirken, kesişme noktasındaki küçük değişikliklerin çok az etkisi vardır. Eğitilebilir parametrelerin ölçeğindeki bu büyük fark, kesişme parametresi neredeyse göz ardı edilerek eğim hesaplamalarına hakim olan eğime yol açar.
Böylece gradyan inişi, ilk kesişim tahminine çok yakın olan en iyi eğimi etkili bir şekilde bulur. Ve hata optimuma çok yakın olduğu için etrafındaki gradyanlar küçüktür, bu nedenle her ardışık yineleme sadece küçük bir parça hareket eder. Önce verilerimizi normalleştirmek, bu fenomeni önemli ölçüde iyileştirebilirdi, ancak onu ortadan kaldırmazdı.
Bu nispeten basit bir örnekti, ancak sonraki bölümlerde bu “otomatik farklılaşma” yeteneğinin oldukça karmaşık şeylerle başa çıkabileceğini göreceğiz.
Örnek 2: Maksimal Yayılmış Birim Vektörleri
Örnek 2 Defter
Bu sonraki örnek, geçen yıl aldığım bir derin öğrenme kursundaki eğlenceli bir derin öğrenme alıştırmasına dayanmaktadır.
Sorunun özü, normal olarak dağıtılmış 32 sayıdan gerçekçi yüzler üretebilen bir "varyasyonlu otomatik kodlayıcıya" (VAE) sahip olmamızdır. Şüpheli tanımlaması için, bir tanığın seçebileceği çeşitli (teorik) yüzler oluşturmak için VAE'yi kullanmak, ardından seçilenlere benzer daha fazla yüz üreterek aramayı daraltmak istiyoruz. Bu alıştırma için, ilk vektör setinin rastgele seçilmesi önerildi, ancak ben optimal bir başlangıç durumu bulmak istedim.
Problemi şu şekilde ifade edebiliriz: 32 boyutlu bir uzay verildiğinde, maksimum olarak dağılmış bir dizi X birim vektörü bulun. İki boyutta, bunu tam olarak hesaplamak kolaydır. Ancak üç boyut (veya 32 boyut!) için doğrudan bir cevap yoktur. Ancak, hedef durumumuza ulaştığımızda minimumda olan uygun bir kayıp fonksiyonu tanımlayabilirsek, belki gradyan inişi oraya ulaşmamıza yardımcı olabilir.
Yukarıda gösterildiği gibi rastgele 20 vektörden oluşan bir setle başlayacağız ve TensorFlow'un yeteneklerini göstermek için her biri artan karmaşıklığa sahip üç farklı kayıp işlevi deneyeceğiz.
Önce eğitim döngümüzü tanımlayalım. Tüm TensorFlow mantığını self.calc_loss()
yönteminin altına koyacağız ve ardından bu döngüyü geri dönüştürerek her teknik için bu yöntemi basitçe geçersiz kılabiliriz.
# Define the framework for trying different loss functions # Base class implements loop, sub classes override self.calc_loss() class VectorSpreadAlgorithm: # ... def calc_loss(self, tensor2d): raise NotImplementedError("Define this in your derived class") def one_iter(self, i, learning_rate): # self.vecs is an 20x2 tensor, representing twenty 2D vectors tfvecs = tf.convert_to_tensor(self.vecs, dtype=tf.float32) with tf.GradientTape() as tape: tape.watch(tfvecs) loss = self.calc_loss(tfvecs) # Here's the magic again. Derivative of spread with respect to # input vectors gradients = tape.gradient(loss, tfvecs) self.vecs = self.vecs - learning_rate * gradients
Denenecek ilk teknik en basit olanıdır. Birbirine en yakın vektörlerin açısı olan bir yayılma metriği tanımlarız. Yayılmayı en üst düzeye çıkarmak istiyoruz, ancak bunu bir minimizasyon sorunu haline getirmek gelenekseldir. Yani yayılma metriğinin negatifini alıyoruz:
class VectorSpread_Maximize_Min_Angle(VectorSpreadAlgorithm): def calc_loss(self, tensor2d): angle_pairs = tf.acos(tensor2d @ tf.transpose(tensor2d)) disable_diag = tf.eye(tensor2d.numpy().shape[0]) * 2 * np.pi spread_metric = tf.reduce_min(angle_pairs + disable_diag) # Convention is to return a quantity to be minimized, but we want # to maximize spread. So return negative spread return -spread_metric
Bazı Matplotlib büyüsü bir görselleştirme sağlayacaktır.
Bu hantal (tam anlamıyla!) ama işe yarıyor. Bir seferde 20 vektörden sadece ikisi güncellenir, aralarındaki boşluk artık en yakın olana kadar büyütülür, ardından en yakın iki vektör arasındaki açıyı artırmaya geçilir. Dikkat edilmesi gereken önemli şey, işe yaramasıdır . TensorFlow'un doğru olanı yapmak için tf.reduce_min()
yöntemi ve tf.acos()
() yöntemi aracılığıyla degradeleri geçirebildiğini görüyoruz.
Biraz daha ayrıntılı bir şey deneyelim. Optimal çözümde tüm vektörlerin en yakın komşularıyla aynı açıya sahip olması gerektiğini biliyoruz. Öyleyse kayıp fonksiyonuna “minimum açıların varyansını” ekleyelim.
class VectorSpread_MaxMinAngle_w_Variance(VectorSpreadAlgorithm): def spread_metric(self, tensor2d): """ Assumes all rows already normalized """ angle_pairs = tf.acos(tensor2d @ tf.transpose(tensor2d)) disable_diag = tf.eye(tensor2d.numpy().shape[0]) * 2 * np.pi all_mins = tf.reduce_min(angle_pairs + disable_diag, axis=1) # Same calculation as before: find the min-min angle min_min = tf.reduce_min(all_mins) # But now also calculate the variance of the min angles vector avg_min = tf.reduce_mean(all_mins) var_min = tf.reduce_sum(tf.square(all_mins - avg_min)) # Our spread metric now includes a term to minimize variance spread_metric = min_min - 0.4 * var_min # As before, want negative spread to keep it a minimization problem return -spread_metric
Bu yalnız kuzeye doğru vektör şimdi hızla emsallerine katılıyor, çünkü en yakın komşusuna olan açı çok büyük ve şimdi en aza indirilen varyans terimini artırıyor. Ama yine de sonuçta, yavaşlayan küresel minimum açı tarafından yönlendiriliyor. Bunu geliştirmem gereken fikirler genellikle bu 2B durumda işe yarar, ancak daha yüksek boyutlarda değil.
Ancak bu matematiksel girişimin kalitesine çok fazla odaklanmak asıl noktayı kaçırıyor. Ortalama ve varyans hesaplamalarında kaç tane tensör işleminin yer aldığına ve TensorFlow'un giriş matrisindeki her bileşen için her hesaplamayı nasıl başarılı bir şekilde izlediğine ve farklılaştırdığına bakın. Ve herhangi bir manuel hesap yapmak zorunda değildik. Biraz basit bir matematiği bir araya getirdik ve TensorFlow bizim için hesabı yaptı.
Son olarak, bir şey daha deneyelim: kuvvete dayalı bir çözüm. Her vektörün, merkezi bir noktaya bağlı küçük bir gezegen olduğunu hayal edin. Her gezegen, onu diğer gezegenlerden iten bir kuvvet yayar. Bu modelin bir fizik simülasyonunu çalıştıracak olsaydık, istediğimiz çözüme ulaşmalıyız.
Benim hipotezim, gradyan inişinin de çalışması gerektiğidir. Optimal çözümde, diğer gezegenlerden her gezegene uygulanan teğet kuvvet, net sıfır kuvvete eşit olmalıdır (sıfır olmasaydı, gezegenler hareket ediyor olurdu). O halde, her vektör üzerindeki kuvvetin büyüklüğünü hesaplayalım ve onu sıfıra doğru itmek için gradyan inişini kullanalım.
Öncelikle tf.*
yöntemlerini kullanarak kuvveti hesaplayan yöntemi tanımlamamız gerekiyor:
class VectorSpread_Force(VectorSpreadAlgorithm): def force_a_onto_b(self, vec_a, vec_b): # Calc force assuming vec_b is constrained to the unit sphere diff = vec_b - vec_a norm = tf.sqrt(tf.reduce_sum(diff**2)) unit_force_dir = diff / norm force_magnitude = 1 / norm**2 force_vec = unit_force_dir * force_magnitude # Project force onto this vec, calculate how much is radial b_dot_f = tf.tensordot(vec_b, force_vec, axes=1) b_dot_b = tf.tensordot(vec_b, vec_b, axes=1) radial_component = (b_dot_f / b_dot_b) * vec_b # Subtract radial component and return result return force_vec - radial_component
Daha sonra yukarıdaki force fonksiyonunu kullanarak kayıp fonksiyonumuzu tanımlıyoruz. Her vektör üzerindeki net kuvveti biriktirir ve büyüklüğünü hesaplarız. Optimal çözümümüzde, tüm kuvvetler birbirini götürmeli ve sıfır kuvvete sahip olmalıyız.

def calc_loss(self, tensor2d): n_vec = tensor2d.numpy().shape[0] all_force_list = [] for this_idx in range(n_vec): # Accumulate force of all other vecs onto this one this_force_list = [] for other_idx in range(n_vec): if this_idx == other_idx: continue this_vec = tensor2d[this_idx, :] other_vec = tensor2d[other_idx, :] tangent_force_vec = self.force_a_onto_b(other_vec, this_vec) this_force_list.append(tangent_force_vec) # Use list of all N-dimensional force vecs. Stack and sum. sum_tangent_forces = tf.reduce_sum(tf.stack(this_force_list)) this_force_mag = tf.sqrt(tf.reduce_sum(sum_tangent_forces**2)) # Accumulate all magnitudes, should all be zero at optimal solution all_force_list.append(this_force_mag) # We want to minimize total force sum, so simply stack, sum, return return tf.reduce_sum(tf.stack(all_force_list))
Çözüm sadece güzel bir şekilde çalışmakla kalmıyor (ilk birkaç karedeki bazı kaosların yanı sıra), aynı zamanda gerçek kredi TensorFlow'a gidiyor. Bu çözüm birden çok for
döngüsü, bir if
ifadesi ve devasa bir hesaplama ağı içeriyordu ve TensorFlow bizim için hepsinde degradeleri başarıyla izledi.
Örnek 3: Karşıt Yapay Zeka Girdileri Oluşturma
Örnek 3 Defter
Bu noktada okuyucular, "Hey! Bu yazının derin öğrenme ile ilgili olmaması gerekiyordu!" diye düşünüyor olabilir. Ancak teknik olarak giriş, "derin öğrenme modellerinin eğitimi "nin ötesine geçmeyi ifade eder. Bu durumda, eğitim yapmıyoruz, bunun yerine önceden eğitilmiş bir derin sinir ağının bazı matematiksel özelliklerinden yararlanarak onu yanlış sonuçlar vermesi için kandırıyoruz. Bunun hayal edilenden çok daha kolay ve etkili olduğu ortaya çıktı. Ve tüm gereken, TensorFlow 2.0 kodunun bir başka kısa bloğuydu.
Saldırmak için bir görüntü sınıflandırıcı bularak başlıyoruz. Köpekler ve Kediler Kaggle Yarışması için en iyi çözümlerden birini kullanacağız; özellikle, Kaggler “uysimty” tarafından sunulan çözüm. Etkili bir kedi-köpek modeli sağladıkları ve harika belgeler sağladıkları için tüm kredi onlara aittir. Bu, 18 sinir ağı katmanında 13 milyon parametreden oluşan güçlü bir modeldir. (Okuyucular, ilgili not defterinde bununla ilgili daha fazla bilgi alabilirler.)
Lütfen buradaki amacın bu belirli ağdaki herhangi bir eksikliği vurgulamak değil , çok sayıda girdiye sahip herhangi bir standart sinir ağının nasıl savunmasız olduğunu göstermek olduğunu unutmayın.
Biraz kurcalayarak, modelin nasıl yükleneceğini ve sınıflandırılacak görüntülerin ön işleme tabi tutulacağını anlayabildim.
Bu gerçekten sağlam bir sınıflandırıcıya benziyor! Tüm numune sınıflandırmaları doğrudur ve %95 güvenin üzerindedir. Saldıralım!
Açıkça bir kedi olan bir görüntü üretmek istiyoruz, ancak sınıflandırıcının yüksek güven ile bir köpek olduğuna karar vermesini istiyoruz. Bunu nasıl yapabiliriz?
Doğru şekilde sınıflandırdığı bir kedi resmiyle başlayalım, ardından belirli bir giriş pikselinin her bir renk kanalındaki (0-255 değerleri) küçük değişikliklerin son sınıflandırıcı çıktısını ne kadar etkilediğini anlayalım. Bir pikseli değiştirmek muhtemelen pek bir işe yaramaz, ancak belki de 128x128x3 = 49,152 piksel değerlerinin tümünün toplu ince ayarları hedefimize ulaşacaktır.
Her pikseli hangi yöne iteceğimizi nasıl bileceğiz? Normal sinir ağı eğitimi sırasında, 13 milyon serbest parametrenin tümünü eşzamanlı olarak güncellemek için TensorFlow'da gradyan inişini kullanarak hedef etiket ile tahmin edilen etiket arasındaki kaybı en aza indirmeye çalışıyoruz. Bu durumda, bunun yerine 13 milyon parametreyi sabit bırakacağız ve girdinin piksel değerlerini ayarlayacağız.
Kayıp fonksiyonumuz nedir? Eh, görüntünün bir kediye ne kadar benzediği! Her bir girdi pikseline göre cat değerinin türevini hesaplarsak, cat sınıflandırma olasılığını en aza indirmek için her birini hangi yöne iteceğimizi biliriz.
def adversarial_modify(victim_img, to_dog=False, to_cat=False): # We only need four gradient descent steps for i in range(4): tf_victim_img = tf.convert_to_tensor(victim_img, dtype='float32') with tf.GradientTape() as tape: tape.watch(tf_victim_img) # Run the image through the model model_output = model(tf_victim_img) # Minimize cat confidence and maximize dog confidence loss = (model_output[0] - model_output[1]) dloss_dimg = tape.gradient(loss, tf_victim_img) # Ignore gradient magnitudes, only care about sign, +1/255 or -1/255 pixels_w_pos_grad = tf.cast(dloss_dimg > 0.0, 'float32') / 255. pixels_w_neg_grad = tf.cast(dloss_dimg < 0.0, 'float32') / 255. victim_img = victim_img - pixels_w_pos_grad + pixels_w_neg_grad
Matplotlib büyüsü yine sonuçları görselleştirmeye yardımcı olur.
Vay! İnsan gözü için bu resimlerin her biri aynıdır. Yine de dört yinelemeden sonra, sınıflandırıcıyı yüzde 99,4 güvenle bunun bir köpek olduğuna ikna ettik!
Bunun bir tesadüf olmadığından ve diğer yönde de çalıştığından emin olalım.
Başarı! Sınıflandırıcı başlangıçta bunu yüzde 98,4 güvenle bir köpek olarak doğru tahmin etti ve şimdi yüzde 99,8 güvenle bir kedi olduğuna inanıyor.
Son olarak örnek bir resim yamasına bakalım ve nasıl değiştiğini görelim.
Beklendiği gibi, son yama orijinale çok benziyor, her piksel kırmızı kanalın yoğunluk değerinde yalnızca -4 ila +4 arasında değişiyor. Bu kayma, bir insanın farkı ayırt etmesi için yeterli değildir, ancak sınıflandırıcının çıktısını tamamen değiştirir.
Son Düşünceler: Gradient Descent Optimizasyonu
Bu makale boyunca, basitlik ve şeffaflık adına eğitilebilir parametrelerimize degradeleri manuel olarak uygulamayı inceledik. Bununla birlikte, gerçek dünyada, veri bilimcileri, herhangi bir kod şişkinliği eklemeden çok daha etkili olma eğiliminde olduklarından, optimize edicileri kullanmaya başlamalıdır.
RMSprop, Adagrad ve Adadelta dahil olmak üzere birçok popüler optimize edici vardır, ancak en yaygın olanı muhtemelen Adam'dır . Bazen, her parametre için dinamik olarak farklı bir öğrenme oranını korudukları için "uyarlanabilir öğrenme hızı yöntemleri" olarak adlandırılırlar. Birçoğu, yerel minimumlardan kaçmak ve daha hızlı yakınsama elde etmek amacıyla momentum terimlerini ve yaklaşık yüksek dereceli türevleri kullanır.
Sebastian Ruder'dan ödünç alınan bir animasyonda, kayıp bir yüzeye inen çeşitli optimize edicilerin yolunu görebiliriz. Gösterdiğimiz manuel teknikler en çok “SGD” ile karşılaştırılabilir. En iyi performans gösteren optimize edici, her kayıp yüzeyi için aynı olmayacaktır; ancak, daha gelişmiş optimize ediciler tipik olarak daha basit olanlardan daha iyi performans gösterir.
Bununla birlikte, yapay zeka geliştirme hizmetleri sağlamaya hevesli olanlar için bile, optimize ediciler konusunda uzman olmak nadiren yararlıdır. TensorFlow'da gradyan inişini nasıl iyileştirdiklerini anlamak için geliştiricilerin bir çiftle tanışmaları için zamanını daha iyi kullanmaktır. Bundan sonra, varsayılan olarak Adam'ı kullanabilir ve yalnızca modelleri yakınsamıyorsa farklı olanları deneyebilirler.
Bu optimize edicilerin nasıl ve neden çalıştığıyla gerçekten ilgilenen okuyucular için, animasyonun göründüğü Ruder'ın genel bakışı, konuyla ilgili en iyi ve en kapsamlı kaynaklardan biridir.
Optimize edicileri kullanmak için ilk bölümden lineer regresyon çözümümüzü güncelleyelim. Aşağıdaki, manuel degradeleri kullanan orijinal degrade iniş kodudur.
# Manual gradient descent operations def run_gradient_descent(heights, weights, init_slope, init_icept, learning_rate): tf_slope = tf.Variable(init_slope, dtype='float32') tf_icept = tf.Variable(init_icept, dtype='float32') for i in range(25): with tf.GradientTape() as tape: tape.watch((tf_slope, tf_icept)) predictions = tf_slope * heights + tf_icept errors = predictions - weights loss = tf.reduce_mean(errors**2) gradients = tape.gradient(loss, [tf_slope, tf_icept]) tf_slope = tf_slope - learning_rate * gradients[0] tf_icept = tf_icept - learning_rate * gradients[1]
Şimdi, bunun yerine bir optimize edici kullanan aynı kod. Fazladan kod olmadığını göreceksiniz (değişen satırlar mavi renkle vurgulanmıştır):
# Gradient descent with Optimizer (RMSprop) def run_gradient_descent (heights, weights, init_slope, init_icept, learning_rate) : tf_slope = tf.Variable(init_slope, dtype= 'float32' ) tf_icept = tf.Variable(init_icept, dtype= 'float32' ) # Group trainable parameters into a list trainable_params = [tf_slope, tf_icept] # Define your optimizer (RMSprop) outside of the training loop optimizer = keras.optimizers.RMSprop(learning_rate) for i in range( 25 ): # GradientTape loop is the same with tf.GradientTape() as tape: tape.watch( trainable_params ) predictions = tf_slope * heights + tf_icept errors = predictions - weights loss = tf.reduce_mean(errors** 2 ) # We can use the trainable parameters list directly in gradient calcs gradients = tape.gradient(loss, trainable_params ) # Optimizers always aim to *minimize* the loss function optimizer.apply_gradients(zip(gradients, trainable_params))
Bu kadar! Gradyan iniş döngüsünün dışında bir RMSprop
optimize edici tanımladık ve ardından eğitilebilir parametreleri güncellemek için her gradyan hesaplamasından sonra optimizer.apply_gradients()
yöntemini kullandık. Optimize edici, momentum ve yüksek dereceli türevler gibi ekstra terimleri hesaplamak için tarihsel gradyanları takip edeceğinden döngünün dışında tanımlanır.
Bakalım RMSprop optimizer ile nasıl görünüyor.
Harika görünüyor! Şimdi Adam optimizer ile deneyelim.
Vay, ne oldu burada? Görünüşe göre Adam'daki momentum mekaniği, optimal çözümü aşmasına ve rotayı birçok kez tersine çevirmesine neden oluyor. Normalde, bu momentum mekaniği karmaşık kayıp yüzeylerde yardımcı olur, ancak bu basit durumda bize zarar verir. Bu, modelinizi eğitirken optimize edici seçimini ayarlanacak hiperparametrelerden biri yapma tavsiyesini vurgular.
Derin öğrenmeyi keşfetmek isteyen herkes, standart iş akışına kolayca sığdırılamayan karmaşık kayıp mekaniğine ihtiyaç duyulan özel TensorFlow mimarilerinde yaygın olarak kullanıldığı için bu modele aşina olmak isteyecektir. Bu basit TensorFlow gradyan inişi örneğinde, eğitilebilir yalnızca iki parametre vardı, ancak optimize etmek için yüz milyonlarca parametre içeren mimarilerle çalışırken bu gereklidir.
TensorFlow'da Gradient Descent: Minimumları Bulmaktan Yapay Zeka Sistemlerine Saldırmaya
Tüm kod parçacıkları ve görüntüler, ilgili GitHub deposundaki not defterlerinden üretildi. Ayrıca, kodun tamamını görmek isteyen okuyucular için, tek tek not defterlerine bağlantılar içeren tüm bölümlerin bir özetini içerir. İletiyi basitleştirmek adına, kapsamlı satır içi belgelerde bulunabilecek birçok ayrıntı atlandı.
Umarım bu makale bilgilendirici olmuştur ve sizi TensorFlow'da gradyan inişini kullanmanın yollarını düşünmeye sevk etmiştir. Kendiniz kullanmasanız bile, umarım tüm modern sinir ağı mimarilerinin nasıl çalıştığını daha net hale getirir - bir model oluşturun, bir kayıp işlevi tanımlayın ve modeli veri kümenize uydurmak için gradyan inişi kullanın.
Bir Google Cloud İş Ortağı olarak, Toptal'ın Google sertifikalı uzmanları, en önemli projeleri için şirketlere talep üzerine hizmet vermektedir.