2017-08-24 39 views
1

我試圖在使用keras訓練我的LSTM時添加自定義指標。請參見下面的代碼:張量數學後張量數學運算

from keras.models import Sequential 
from keras.layers import Dense, LSTM, Masking, Dropout 
from keras.optimizers import SGD, Adam, RMSprop 
import keras.backend as K 
import numpy as np 

_Xtrain = np.random.rand(1000,21,47) 
_ytrain = np.random.randint(2, size=1000) 

_Xtest = np.random.rand(200,21,47) 
_ytest = np.random.randint(1, size=200) 

def t1(y_pred, y_true): 
    return K.tf.count_nonzero((1 - y_true)) 

def t2(y_pred, y_true): 
    return K.tf.count_nonzero(y_true) 

def build_model(): 
    model = Sequential() 
    model.add(Masking(mask_value=0, input_shape=(21, _Xtrain[0].shape[1]))) 
    model.add(LSTM(32, return_sequences=True)) 
    model.add(LSTM(64, return_sequences=False)) 
    model.add(Dense(1, activation='sigmoid')) 
    rms = RMSprop(lr=.001, decay=.001) 
    model.compile(loss='binary_crossentropy', optimizer=rms, metrics=[t1, t2]) 
    return model 

model = build_model() 

hist = model.fit(_Xtrain, _ytrain, epochs=1, batch_size=5, validation_data=(_Xtest, _ytest), shuffle=True) 

上述代碼的輸出如下所示:

上1000個樣本列車,驗證對200個樣本 曆元1/1 1000/1000 [====== ========================] - 5s - loss:0.6958 - t1:5.0000 - t2:5.0000 - val_loss:0.6975 - val_t1:5.0000 - val_t2: 5.0000

所以看來,方法t1和t2都產生完全相同的輸出,這讓我很困惑。有什麼可能會出錯,我怎麼能得到補充張量y_true?

背景故事:我試圖爲自己的模型編寫自定義指標(F1分數)。凱拉斯似乎沒有那些容易獲得的。如果有人知道更好的方法,請幫助我指出正確的方向。

回答

1

解決此問題的一個簡單方法是使用回調代替。按照此issue的邏輯,您可以指定一個度量回調,它使用sci-kit learn來計算任何度量。例如,如果您想計算f1,則可以執行以下操作:

from keras.models import Sequential 
from keras.layers import Dense, LSTM, Masking, Dropout 
from keras.optimizers import SGD, Adam, RMSprop 
import keras.backend as K 
from keras.callbacks import Callback 
import numpy as np 

from sklearn.metrics import f1_score 

_Xtrain = np.random.rand(1000,21,47) 
_ytrain = np.random.randint(2, size=1000) 

_Xtest = np.random.rand(200,21,47) 
_ytest = np.random.randint(2, size=200) 

class MetricsCallback(Callback): 
    def __init__(self, train_data, validation_data): 
     super().__init__() 
     self.validation_data = validation_data 
     self.train_data = train_data 
     self.f1_scores = [] 
     self.cutoff = .5 

    def on_epoch_end(self, epoch, logs={}): 
     X_val = self.validation_data[0] 
     y_val = self.validation_data[1] 

     preds = self.model.predict(X_val) 

     f1 = f1_score(y_val, (preds > self.cutoff).astype(int)) 
     self.f1_scores.append(f1) 


def build_model(): 
    model = Sequential() 
    model.add(Masking(mask_value=0, input_shape=(21, _Xtrain[0].shape[1]))) 
    model.add(LSTM(32, return_sequences=True)) 
    model.add(LSTM(64, return_sequences=False)) 
    model.add(Dense(1, activation='sigmoid')) 
    rms = RMSprop(lr=.001, decay=.001) 
    model.compile(loss='binary_crossentropy', optimizer=rms, metrics=['acc']) 
    return model 

model = build_model() 

hist = model.fit(_Xtrain, _ytrain, epochs=2, batch_size=5, validation_data=(_Xtest, _ytest), shuffle=True, 
       callbacks=[MetricsCallback((_Xtrain, _ytrain), (_Xtest, _ytest))])