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:
İ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ı!
Ayrıca bkz. [Keras ile özel bir etkinleştirme işlevi nasıl oluşturulur?] (Http://stackoverflow.com/q/43915482/562769) –
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