【问题标题】:Dictionary of tensors input for Keras Functional API TensorFlow 2.0Keras Functional API TensorFlow 2.0 的张量输入字典
【发布时间】:2019-10-02 21:34:30
【问题描述】:

我有一个张量字典数据集,以及使用子类化 API 定义的以下模型:

class Model(tf.keras.Model):

  def __init__(self):
    super().__init__()
    self._movie_full_dense = tf.keras.layers.Dense(
        units=40, activation=tf.keras.layers.Activation("relu"))
    self._user_full_dense = tf.keras.layers.Dense(
        units=40, activation=tf.keras.layers.Activation("relu"))
    self._full_dense = tf.keras.layers.Dense(
        units=1, activation=tf.keras.layers.Activation("sigmoid"))

  def call(self, features):
    movie_embedding = self._movie_full_dense(features['movie'])
    user_embedding = self._user_full_dense(features['user'])
    combined = tf.concat([movie_embedding, user_embedding], 1)
    output = self._full_dense(combined)
    return output

我想使用函数式 API 来实现它。但我不知道如何定义输入?即,以下的功能等价物是什么?

self._movie_full_dense(features['movie'])

【问题讨论】:

    标签: tensorflow keras tensorflow2.0 tf.keras


    【解决方案1】:
    import tensorflow as tf
    
    print(tf.version.VERSION)
    
    toy_data = {'movie': [[0], [1], [0], [1]], 'user': [[10], [12], [12], [10]]}
    dataset = tf.data.Dataset.from_tensor_slices(toy_data).batch(2)
    
    for x in dataset:
        print(x)
    
    def make_model():
        inp_movie = tf.keras.Input(shape=(1,))
        inp_user = tf.keras.Input(shape=(1,))
        movie_embedding = tf.keras.layers.Dense(
                units=40, activation=tf.keras.layers.Activation("relu"))(inp_movie)
        user_embedding = tf.keras.layers.Dense(
                units=40, activation=tf.keras.layers.Activation("relu"))(inp_user)
        combined = tf.concat([movie_embedding, user_embedding], 1)
        output = tf.keras.layers.Dense(
                units=1, activation=tf.keras.layers.Activation("sigmoid"))(combined)
        model = tf.keras.Model(inputs=[inp_movie, inp_user], outputs=output)
        return model
    
    model = make_model()
    
    for x in dataset:
        print(model(x))
    

    这行得通。请注意,您传递给tf.keras.Model 调用的inputs 参数的可迭代对象必须按照与您将使用的字典相同的顺序进行排序,字典按其键排序,movie 然后user。所以使用inputs={'a': inp_movie, 'b': inp_user}inputs={'movie': inp_movie, 'user': inp_user} 也可以,而inputs=[inp_user, inp_movie] 则不行。

    您可以使用此代码来测试这种交互:

    def make_test_model():
        inp_movie = tf.keras.Input(shape=(1,))
        inp_user = tf.keras.Input(shape=(1,))
        model = tf.keras.Model(inputs={'a': inp_movie, 'b': inp_user}, outputs=inp_movie)
        return model
    
    def make_test_model_2():
        inp_movie = tf.keras.Input(shape=(1,))
        inp_user = tf.keras.Input(shape=(1,))
        model = tf.keras.Model(inputs=[inp_user, inp_movie], outputs=inp_movie)
        return model
    
    model_test = make_test_model()
    model_test_2 = make_test_model_2()
    
    for x in dataset:
        print(model_test(x))
    for x in dataset:
        print(model_test_2(x))
    

    您还可以使用字典的键命名Input 层,并作为inputs 参数提供按层名称排序的Input 层列表。这允许您在模型中添加或删除输入,而不必担心每次都重写您的 inputs 参数。所以这就是我要做的:

    def make_model_2():
        input_list = []
        inp_movie = tf.keras.Input(shape=(1,), name='movie')
        input_list.append(inp_movie)
        inp_user = tf.keras.Input(shape=(1,), name='user')
        input_list.append(inp_user)
        movie_embedding = tf.keras.layers.Dense(
                units=40, activation=tf.keras.layers.Activation("relu"))(inp_movie)
        user_embedding = tf.keras.layers.Dense(
                units=40, activation=tf.keras.layers.Activation("relu"))(inp_user)
        combined = tf.concat([movie_embedding, user_embedding], 1)
        output = tf.keras.layers.Dense(
                units=1, activation=tf.keras.layers.Activation("sigmoid"))(combined)
        input_list.sort(key=lambda inp: inp._keras_history.layer.name)
        model = tf.keras.Model(inputs=input_list, outputs=output)
        return model
    

    这是一种测试它是否有效的方法:

    def make_test_model_3(boolean):
        input_list = []
        inp_movie = tf.keras.Input(shape=(1,), name='movie')
        inp_user = tf.keras.Input(shape=(1,), name='user')
        if boolean:
            input_list.append(inp_movie)
            input_list.append(inp_user)
        else:
            input_list.append(inp_user)
            input_list.append(inp_movie)
        input_list.sort(key=lambda inp: inp._keras_history.layer.name)
        model = tf.keras.Model(inputs=input_list, outputs=inp_movie)
        return model
    
    model_test_3_0= make_test_model_3(True)
    model_test_3_1= make_test_model_3(False)
    
    for x in dataset:
        print(model_test_3_0(x))
    for x in dataset:
        print(model_test_3_1(x))
    

    编辑 2020-02-20:

    make_model 不适用于 tf2.1.0,但 make_model_2 仍然可以。我在 GitHub 上提出了一个关于这种向后不兼容的问题。 Here 是链接,如果您有兴趣。回想一下,如果您打算继续使用 tf2.0.0,这两个函数都可以工作。

    【讨论】:

      猜你喜欢
      • 2020-03-17
      • 2016-11-29
      • 1970-01-01
      • 1970-01-01
      • 2017-07-15
      • 2020-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多