代码之家  ›  专栏  ›  技术社区  ›  I. A Ziang Yan

了解Keras和TensorFlow中的对象创建

  •  0
  • I. A Ziang Yan  · 技术社区  · 5 年前

    在处理Keras和TensorFlow时,我发现以下代码行令人困惑。

    w_init = tf.random_normal_initializer()
    self.w = tf.Variable(initial_value=w_init(shape=(input_dim, units),
                                              dtype='float32'),trainable=True)
    

    此外,我还看到了如下情况:

     Dense(64, activation='relu')(x)
    

    因此,如果 Dense(...) 将为我创建对象,那么我如何使用 (x) 是吗?

    同样适用于 w_init 上面。我怎么能这样说:

    tf.random_normal_initializer()(shape=(input_dim, units), dtype='float32'),trainable=True)
    

    我们在蟒蛇里有这样的东西吗 "ClassName()" followed by "()" 创建对象(如图层)时?

    当我调查的时候 Closures 在Python中,我发现一个函数可以返回另一个函数。因此,这是喀拉什真正发生的事情吗?

    非常感谢您的帮助!你看!

    0 回复  |  直到 5 年前
        1
  •  2
  •   Djib2011 Benoit Steiner    5 年前

    这是定义模型的两种完全不同的方法。

    Keras使用层的概念。每一行定义网络的完整层。具体来说,您所指的是Keras的功能API。其概念是将这样的层组合在一起:

    
    inp = Input(shape=(28, 28, 1))
    x = Conv2D((6,6), strides=(1,1), activation='relu')(inp)
    # ... etc ...
    x = Flatten()(x)
    x = Dense(10, activation='softmax')(x)
    
    
    model = Model(inputs=[inp], outputs=[x])
    

    从未

    现在,这只需要 model.compile(...) 然后你可以训练它通过 model.fit(...)

    另一方面,张量流则稍微低一点。这意味着您已经手工定义了变量和操作。因此,要编写一个完全连接的层,您必须执行以下操作:

    # Input placeholders
    x = tf.placeholder(tf.float32, shape=(None, 28, 28, 1))
    y = tf.placeholder(tf.float32, shape=(None, 10))
    
    # Convolution layer
    W1 = tf.Variable(tf.truncated_normal([6, 6, 1, 32], stddev=0.1)) 
    b1 = tf.Variable(tf.constant(0.1, tf.float32, [32]))
    z1 = tf.nn.conv2d(x_2d, W1, strides=[1, 1, 1, 1], padding='SAME') + b1 
    c1 = tf.nn.relu(z1)
    
    # ... etc ...
    
    # Flatten
    flat = tf.reshape(p2, [-1, ...]) # need to calculate the ... by ourselves
    
    # Dense
    W3 = tf.Variable(tf.truncated_normal([..., 10], stddev=0.1))  # same size as before
    b3 = tf.Variable(tf.constant(0.1, tf.float32, [10]))
    fc1 = tf.nn.relu(tf.matmul(flat, W3) + b3)
    

    model 这里必须通过 tf.Session feed_dict 将数据提供给占位符。如果你感兴趣,你可以在网上找到几本指南。

    TensorFlow有一种更友好、更容易的方法来定义和训练模型 老路


    没有一层是 __call__ 方法,也使其可调用。他们这样做是为了包装 call

    您可以查看实现 here

    class MyClass:
        def __init__(self, param):
            self.p = param
        def call(self, x):
            print(x)
    

    如果你想写 c = MyClass(1)(3)

    class MyClass:
        def __init__(self, param):
            self.p = param
        def __call__(self, x):
            print(x)
    

    现在可以工作了。基本上,Keras是这样做的:

    class MyClass:
        def __init__(self, param):
            self.p = param
        def call(self, x):
            print(x)
        def __call__(self, x):
            self.call(x)
    

    方法和 包装您的方法将从Keras的基类继承。

        2
  •  0
  •   Code-Apprentice    5 年前

    Dense() 返回函数(或更准确地说 w_init 也是可调用的。