【问题标题】:Lambda layer to perform if then in keras/tensorflow如果然后在 keras/tensorflow 中执行的 Lambda 层
【发布时间】:2020-03-06 14:24:20
【问题描述】:

我用这个把头发扯掉了。

我在这里问了一个问题If then inside custom non-trainable keras layer,但我仍然遇到困难。

我尝试了他的解决方案,但它没有用 - 我想我会用他的解决方案发布我的完整代码

我有一个自定义 Keras 层,我想从特定输入返回特定输出。我不希望它是可训练的。

图层应该做以下事情

if input = [1,0] then output = 1
if input = [0,1] then output = 0

这是执行此操作的 lambda 层代码:

input_tensor = Input(shape=(n_hots,))


def custom_layer_1(tensor):
    if tensor == [1,0]:
        resp_1 = np.array([1,],dtype=np.int32)
        k_resp_1 = backend.variable(value=resp_1)
        return k_resp_1
    elif tensor == [0,1]:
        resp_0 = np.array([0,],dtype=np.int32)
        k_resp_0 = backend.variable(value=resp_0)
        return k_resp_0
    else:
        resp_e = np.array([-1,])
        k_resp_e = backend.variable(value=resp_e)
        return k_resp_e
    print(tensor.shape)

layer_one = keras.layers.Lambda(custom_layer_1,output_shape = (None,))(input_tensor)


_model = Model(inputs=input_tensor, outputs = layer_one)

当我拟合我的模型时,尽管有输入,它总是计算 -1。

这是模型的样子:

Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 2)                 0         
_________________________________________________________________
lambda_1 (Lambda)            (None, None)              0         
=================================================================
Total params: 0
Trainable params: 0
Non-trainable params: 0

这是模型的完整代码:

import numpy as np
from keras.models import Model
from keras import layers
from keras import Input
from keras import backend
import keras
from keras import models
import tensorflow as tf


# Generate the datasets:
n_obs = 1000

n_hots = 2

obs_mat = np.zeros((n_obs,n_hots),dtype=np.int32)

resp_mat = np.zeros((n_obs,1),dtype=np.int32)

# which position in the array should be "hot" ?
hot_locs = np.random.randint(n_hots, size=n_obs)

# set the bits:
for row,loc in zip(np.arange(n_obs),hot_locs):
    obs_mat[row,loc] = 1

for idx in np.arange(n_obs):
    if( (obs_mat[idx,:]==[1,0]).all() == True ):
        resp_mat[idx] = 1
    if( (obs_mat[idx,:]==[0,1]).all() == True ):
        resp_mat[idx] = 0

# test data:
test_suite = np.identity(n_hots)

# Build the network
input_tensor = Input(shape=(n_hots,))


def custom_layer_1(tensor):
    if tensor == [1,0]:
        resp_1 = np.array([1,],dtype=np.int32)
        k_resp_1 = backend.variable(value=resp_1)
        return k_resp_1
    elif tensor == [0,1]:
        resp_0 = np.array([0,],dtype=np.int32)
        k_resp_0 = backend.variable(value=resp_0)
        return k_resp_0
    else:
        resp_e = np.array([-1,])
        k_resp_e = backend.variable(value=resp_e)
        return k_resp_e
    print(tensor.shape)

layer_one = keras.layers.Lambda(custom_layer_1,output_shape = (None,))(input_tensor)


_model = Model(inputs=input_tensor, outputs = layer_one)

# compile
_model.compile(optimizer="adam",loss='mse')

#train (even thought there's nothing to train)
history_mdl = _model.fit(obs_mat,resp_mat,verbose=True,batch_size = 100,epochs = 10)

# test
_model.predict(test_suite)
# outputs: array([-1., -1.], dtype=float32)

test = np.array([1,0])
test = test.reshape(1,2)
_model.predict(test,verbose=True)
# outputs: -1

这看起来很简单,为什么它不起作用?谢谢

【问题讨论】:

    标签: python tensorflow keras


    【解决方案1】:

    有几个原因:

    • 您将二维张量 (samples, hots) 与一维张量 (hots) 进行比较。
    • 您没有在任何结果中考虑批量大小。
    • 如果tf 是一个张量框架,使用普通的if 可能不会获得好的结果。

    所以,建议是:

    from keras import backend as K
    
    def custom_layer(tensor):
        #comparison tensors with compatible shape 2D: (dummy_batch, hots)
        t10 = K.reshape(K.constant([1,0]), (1,2))
        t01 = K.reshape(K.constant([0,1]), (1,2))
    
        #comparison results - elementwise - shape (batch_size, 2)
        is_t10 = K.equal(tensor, t10)
        is_t01 = K.equal(tensor, t01)
    
        #comparison results - per sample - shape (batch_size,)
        is_t10 = K.all(is_t10, axis=-1)
        is_t01 = K.all(is_t01, axis=-1)
    
        #result options
        zeros = K.zeros_like(is_t10, dtype='float32') #shape (batch_size,)
        ones = K.ones_like(is_t10, dtype='float32')   #shape (batch_size,)
        negatives = -ones                             #shape (batch_size,)
    
        #selecting options
        result_01_or_else = K.switch(is_t01, zeros, negatives)
        result = K.switch(is_t10, ones, result_01_or_else)
    
        return result
    

    警告

    • 此层不可微分(它返回常量) - 您将无法训练该层之前的任何内容,如果您尝试,您将收到“一个操作具有 None 梯度”错误。
    • 输入tensor 不能是其他层的输出,因为您要求它是精确的1 或0。

    【讨论】:

    • 谢谢,不幸的是,负数 = -ones 线上的错误。 TypeError:传递给参数“x”的值的 DataType bool 不在允许值列表中:bfloat16、float16、float32、float64、int32、int64、complex64、complex128
    • 什么???听起来太奇怪了...... --- 无论如何,如果这行确实有错误,请在K.zeros_likeK.ones_like 中添加dtype='float32'。 (根据您的型号选择 32 或 64)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2018-04-30
    • 2017-12-12
    • 2017-12-06
    • 2020-06-16
    • 2018-08-24
    相关资源
    最近更新 更多