2017-10-10 61 views
3

我想在TF/Keras中生成自定義丟失函數,如果在會話中運行並傳遞常量,則丟失函數將工作,但編譯時會停止工作進入凱拉斯。Keras中的自定義丟失函數,如何處理佔位符

成本函數(感謝利奧爾用於將其轉換爲TF)

def ginicTF(actual,pred): 

    n = int(actual.get_shape()[-1]) 

    inds = K.reverse(tf.nn.top_k(pred,n)[1],axes=[0]) 
    a_s = K.gather(actual,inds) 
    a_c = K.cumsum(a_s) 
    giniSum = K.sum(a_c)/K.sum(a_s) - (n+1)/2.0 

    return giniSum/n 

def gini_normalizedTF(a,p): 
    return -ginicTF(a, p)/ginicTF(a, a) 

#Test the cost function 

sess = tf.InteractiveSession() 

p = [0.9, 0.3, 0.8, 0.75, 0.65, 0.6, 0.78, 0.7, 0.05, 0.4, 0.4, 0.05, 0.5, 0.1, 0.1] 
a = [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]  

ac = tf.placeholder(shape=(len(a),),dtype=K.floatx()) 
pr = tf.placeholder(shape=(len(p),),dtype=K.floatx()) 

print(gini_normalizedTF(ac,pr).eval(feed_dict={ac:a,pr:p})) 

此打印-0.62962962963,這是正確的值。

現在,讓我們把這個變成Keras MLP

def makeModel(n_feat): 

    model = Sequential() 

    #hidden layer #1 
    model.add(layers.Dense(12, input_shape=(n_feat,))) 
    model.add(layers.Activation('selu')) 
    model.add(layers.Dropout(0.2)) 

    #output layer 
    model.add(layers.Dense(1)) 
    model.add(layers.Activation('softmax')) 

    model.compile(loss=gini_normalizedTF, optimizer='sgd', metrics=['binary_accuracy']) 

    return model 

model=makeModel(n_feats) 
model.fit(x=Mout,y=targets,epochs=n_epochs,validation_split=0.2,batch_size=batch_size) 

這會產生錯誤

<ipython-input-62-6ade7307336f> in ginicTF(actual, pred) 
     9 def ginicTF(actual,pred): 
    10 
---> 11  n = int(actual.get_shape()[-1]) 
    12 
    13  inds = K.reverse(tf.nn.top_k(pred,n)[1],axes=[0]) 

TypeError: __int__ returned non-int (type NoneType) 

我試着去圍繞它通過給N /等的默認值,但這似乎並沒有被去任何地方。

有人可以解釋這個問題的性質和我可以如何補救嗎?

謝謝!

編輯:

更新的東西,以保持它作爲張量,然後抹上

def ginicTF(actual,pred): 


    nT = K.shape(actual)[-1] 
    n = K.cast(nT,dtype='int32') 
    inds = K.reverse(tf.nn.top_k(pred,n)[1],axes=[0]) 
    a_s = K.gather(actual,inds) 
    a_c = K.cumsum(a_s) 
    n = K.cast(nT,dtype=K.floatx()) 
    giniSum = K.cast(K.sum(a_c)/K.sum(a_s),dtype=K.floatx()) - (n+1)/2.0 

    return giniSum/n 

def gini_normalizedTF(a,p): 
    return ginicTF(a, p)/ginicTF(a, a) 

仍然得到「沒有」的問題作爲一個成本函數使用時

+0

我試圖解決這個問題,但我最終陷入死衚衕。 Keras根本找不到這個基尼係數的導數,因爲y_pred的值丟失了。剩下的就是指數,這是不可區分的。這可能是一個很好的指標,但不會作爲損失函數傳遞。 –

+0

DanielMöller:這個功能至少在原則上是可區分的。正如在一個numpy版本適用於xgboost/sklearn自定義成本函數。在大多數地方(與l1-norm相似),函數的分析定義是可區分的也很簡單,因爲它曾經是tf.nn.top_k不可微分(評估op),但它現在是在梯度計算中: https://github.com/tensorflow/tensorflow/blob/43346a1c81d503f0f764e09bb2f12e31a793a168/tensorflow/python/ops/nn_grad.py#L525 – Ilya

+0

要添加,它也不僅僅是它不可區分,我得到如果我嘗試將我的自定義函數用作精確度度量,則會出現相同的錯誤。 – Ilya

回答

0

嗯,我得到了與你同樣的問題,後來我意識到基尼是不可區分的,因此你不能將它用作成本函數。

+0

問題是tf.nn.top_k是可區分的(儘管它最初是一個eval函數),所以應該有一種方法可以使這個工作,我只是不知道如何。 – Ilya

+0

那麼我仍然不知道關於tf.nn.top_k,但從我在其他論壇上詢問的研究中得到的所有答案都是基尼不是可區分的功能。 –