24

Sadece önceden tanımlanmış tensorflow yapı bloklarını kullanarak mümkün olmayan bir aktivasyon fonksiyonu yapmanız gerektiğini varsayalım, ne yapabilirsiniz?Tensorflow'da yalnızca Python ile özel bir aktivasyon işlevi nasıl oluşturulur?

Tensorflow'da kendi aktivasyon işlevinizi yapmak mümkündür. Ama oldukça karmaşık, C++ 'da yazmalı ve tensorflow [1][2]'un tamamını yeniden derlemelisiniz.

Daha basit bir yolu var mı?

+1

Ayrıca bkz. [Keras ile özel bir etkinleştirme işlevi nasıl oluşturulur?] (Http://stackoverflow.com/q/43915482/562769) –

+0

Herhangi bir yazılımla mutlak özgürlüğe sahip olmak zordur, ancak bize verirseniz Bir aktivasyon (işlev ailesi) oluşturmaya çalıştığınız bir fikir, birileri size yardımcı olabilir. – user1700890

cevap

41

Evet Var!

Kredi: Bu bilgi bulabilir ve bu çalışma için zordu ama burada ilkelerinden bir örnek kopyalama ve kod here ve here bulundu.

Koşullar: Başlamadan önce, bunun başarılı olabilmesi için iki gereksinim vardır. İlk önce aktivasyonunuzu numpy dizilerinde bir işlev olarak yazabilmeniz gerekir. İkincisi, bu fonksiyonun türevini Tensorflow'daki (daha kolay) bir fonksiyon olarak veya en kötü durum senaryosunda numpy dizilerinde bir fonksiyon olarak yazabilmeniz gerekir.

Yazma Aktivasyon fonksiyonu: Yani

en Örneğin biz bir aktivasyon fonksiyonu kullanmak isteyeyim bu işlevi alalım:

def spiky(x): 
    r = x % 1 
    if r <= 0.5: 
     return r 
    else: 
     return 0 

olarak bakmak aşağıdaki gibidir: Spiky Activation

İlk adım, bir numpy işlevine yapıyor, bu kolay:

Şimdi türevini yazmalıyız. Aktivasyonu

Gradyan: kolaydır eden durumda , bu 1 aksi x mod 1 < 0.5 ve 0 ise. Bu nedenle, bir TensorFlow işlevi gerçekleştirmenin zor kısmı için şimdi. Bir tensorflow fct bir numpy FCT yapma

: Biz tensorflow fonksiyonu haline np_d_spiky yaparak başlayacak. , Biz neden

import tensorflow as tf 
from tensorflow.python.framework import ops 

np_d_spiky_32 = lambda x: np_d_spiky(x).astype(np.float32) 


def tf_d_spiky(x,name=None): 
    with ops.op_scope([x], name, "d_spiky") as name: 
     y = tf.py_func(np_d_spiky_32, 
         [x], 
         [tf.float32], 
         name=name, 
         stateful=False) 
     return y[0] 

tf.py_func eylemleri tensörlerinin listelerinde (ve tensörlerle listesini döndürür): Orada bir tensorflow işlevine herhangi numpy fonksiyonunu dönüştüren tf.py_func(func, inp, Tout, stateful=stateful, name=name)[doc] tensorflow bir fonksiyonudur, bu yüzden bunu kullanabilirsiniz [x] var (ve y[0] döndürün). stateful seçeneği, tensorflow'un tensorflow'un tensorflow grafiğinde olduğu durumda aynı çıktı için her zaman aynı çıktıyı vermesinin tensorflow olduğunu söylemektir, bu bizim durumumuzdur ve muhtemelen birçok durumda geçerli olacaktır.Bu noktada dikkatli olmak için bir şey float64 ama tensorflow float32 kullanır, bu yüzden bir tensorflow işlevi dönüştürebilirsiniz önce işlevinizi float32 kullanmak için dönüştürmeniz gerekir tensorflow şikayet edecektir. Bu yüzden önce np_d_spiky_32 yapmamız gerekiyor.

Degradeler hakkında ne düşünüyorsunuz? Sadece yukarıdaki ile sorun şu ki biz np_d_spiky tensorflow sürümü olan tf_d_spiky şimdi sahip olsak bile, biz bir aktivasyon fonksiyonu olarak kullanamadık çünkü tensorflow gradyanların nasıl hesaplanacağını bilmiyor çünkü Bu işlev.

kesmek Degradeleri almak için: Yukarıda belirtilen kaynaklarda açıklanan, tf.RegisterGradient[doc] ve tf.Graph.gradient_override_map[doc] kullanılarak bir fonksiyonun gradyanlar tanımlamak için bir kesmek vardır. harpone kodunu kopyalama biz aynı anda degrade tanımlamak yapmak tf.py_func işlevini değiştirebilirsiniz:

def py_func(func, inp, Tout, stateful=True, name=None, grad=None): 

    # Need to generate a unique name to avoid duplicates: 
    rnd_name = 'PyFuncGrad' + str(np.random.randint(0, 1E+8)) 

    tf.RegisterGradient(rnd_name)(grad) # see _MySquareGrad for grad example 
    g = tf.get_default_graph() 
    with g.gradient_override_map({"PyFunc": rnd_name}): 
     return tf.py_func(func, inp, Tout, stateful=stateful, name=name) 

Şimdi neredeyse bitti, tek şey grad işlevi yukarıda geçmek gerektiğidir py_func işlevi özel bir form almalıdır. Operasyondan önce ve operasyondan önceki önceki gradyanları almalı ve operasyondan sonra gradyanları geriye doğru yaymalıdır.

Gradyan Fonksiyon: Yani bizim dikenli aktivasyon fonksiyonu için biz bunu görecektir:

def spikygrad(op, grad): 
    x = op.inputs[0] 

    n_gr = tf_d_spiky(x) 
    return grad * n_gr 

aktivasyon fonksiyonu sadece bir girişi vardır, işte bu yüzden x = op.inputs[0] olduğunu. Operasyonda birçok girdi varsa, her giriş için bir degrade, bir degrade döndürmeliyiz. Örneğin, işlem a-b ise, a'a göre gradyan +1 ve b'a göre -1 olup return +1*grad,-1*grad olacaktır. Girişin tensorflow işlevlerini döndürmemiz gerektiğine dikkat edin, bu nedenle tf_d_spiky, np_d_spiky'a ihtiyaç duyulmamıştır çünkü tensorflow tensörler üzerinde hareket edemez. Hepsini bir araya birleştiren

def spikygrad2(op, grad): 
    x = op.inputs[0] 
    r = tf.mod(x,1) 
    n_gr = tf.to_float(tf.less_equal(r, 0.5)) 
    return grad * n_gr 

: Alternatif biz türev kullanarak tensorflow fonksiyonlarını yazmış olabilirdi şimdi

np_spiky_32 = lambda x: np_spiky(x).astype(np.float32) 

def tf_spiky(x, name=None): 

    with ops.op_scope([x], name, "spiky") as name: 
     y = py_func(np_spiky_32, 
         [x], 
         [tf.float32], 
         name=name, 
         grad=spikygrad) # <-- here's the call to the gradient 
     return y[0] 

Ve: Biz tüm bölümlerine sahip olduğunu Şimdi, birlikte hepsini birleştirebilirsiniz yapılır. Ve biz de deneyebiliriz.

Testi:

with tf.Session() as sess: 

    x = tf.constant([0.2,0.7,1.2,1.7]) 
    y = tf_spiky(x) 
    tf.initialize_all_variables().run() 

    print(x.eval(), y.eval(), tf.gradients(y, [x])[0].eval()) 

[0,2 0,69999999 1,20000005 1,70000005] [0,2 0. 0,20000005 0.] [1. 0. 1. 0.]

Başarı!

+0

Ne kadar iyi öğrendin? – lahwran

+2

@lahwran bu gerçekten gerçek hayatta kullanmak isteyeceğiniz bir aktivasyon işlevi değildir. Bunu yapmak için özel aktivasyon işlevinin nasıl uygulanacağıyla ilgili bir örnek. –

+0

tamamen, bu yüzden işe yaramış olup olmadığınızı merak ettim: p – lahwran

5

Neden yeni işlevinizi oluşturmak için tensorflow'da bulunan işlevleri kullanmıyorsunuz?

def spiky(x): 
    r = tf.floormod(x, tf.constant(1)) 
    cond = tf.less_equal(r, tf.constant(0.5)) 
    return tf.where(cond, r, tf.constant(0)) 

şöyle

your answer yılında spiky fonksiyonu için, bu ben bu dikkate alacağını görünebilir ölçüde çok daha kolay (hatta herhangi geçişlerini hesaplamak gerekmez) ve gerçekten egzotik şeyler yapmak istemedikçe, ben tensorflow'un son derece karmaşık aktivasyon fonksiyonları oluşturmak için yapı taşları sağlamadığını düşünebilir.

+1

Evet, gerçekten, spiky, tf ilkelleriyle yapılabilir, ancak diken dikmek, gerçekten uygulamak istediğim fonksiyonun karmaşıklığı ile aşırı derecede karışmamak için basit bir örnektir. Gerçekte uygulamak istediğim işlev maalesef ilkellerle uygulanamayabilir. –

+1

Sorunun tüm noktası şudur: aktivasyon işlevini tf ilkelleriyle formüle edemediğinizde ne yaparsınız? –

+1

@patapouf_ai Bunu zaten bekledim, ama sorunuzdan belli değil. Bu sorunun popülerliğinden dolayı, bu çözüme de işaret etmenin iyi bir fikir olduğunu düşündüm (tensorflow ile çok az deneyime sahip insanlar için kendi aktivasyon fonksiyonlarını yaratmaya çalışıyorlar). –

İlgili konular