首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Tensorflow或Keras如何处理模型权重初始化以及何时发生?

Tensorflow或Keras如何处理模型权重初始化以及何时发生?
EN

Stack Overflow用户
提问于 2020-12-25 21:28:29
回答 2查看 547关注 0票数 1

在阅读了对这个问题的回答之后,我有点困惑于TensorFlow究竟是什么时候初始化了权重和偏差变量。根据答案,编译定义了损失函数优化器度量。就这样。

因为compile()方法没有初始化它,所以这意味着它发生在fit()方法运行期间。

然而,在加载模型或加载权重的情况下,fit()如何知道它所提供的权重实际上是有用的,不应该丢弃,然后分配随机值来代替这些权重。

在声明该层时,我们在参数kernel_initializer中传递不整化器的类型。例如:

代码语言:javascript
运行
复制
dense02 = tf.keras.layers.Dense(units=10, 
                kernel_initializer='glorot_uniform',
                bias_initializer='zeros')

因此,一个很明显的问题是,在第一次划线过程中,权重是逐层初始化,还是在第一次划线之前,对所有层都进行初始化。

(我想说的是,如果模型中有5层稠密层,那么初始化是否一次表示一层,即第一稠密层被初始化,然后该层发生前传,然后第二层初始化,第二稠密层发生前传,等等)

另一个方面是关于传输学习,当在经过训练的模型之上堆叠自定义层时,经过训练的模型层具有权重,而我添加的层不会有任何有用的层。那么,TensorFlow如何知道只初始化我添加的层的变量,而不是将传输模型的层搞乱(前提是,我没有trainable=False)

TensorFlow或Keras如何处理权值初始化?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-12-26 03:32:03

在创建模型时(当模型中的每个层被初始化时),即在compile()fit()之前初始化权重

代码语言:javascript
运行
复制
import tensorflow as tf
from tensorflow.keras import models, layers

inputs = layers.Input((3, ))
outputs = layers.Dense(units=10, 
                kernel_initializer='glorot_uniform',
                bias_initializer='zeros')(inputs)

model = models.Model(inputs=inputs, outputs=outputs)

for layer in model.layers: 
    print("Config:\n{}\nWeights:\n{}\n".format(layer.get_config(), layer.get_weights()))

产出:

代码语言:javascript
运行
复制
Config:
{'batch_input_shape': (None, 3), 'dtype': 'float32', 'sparse': False, 'ragged': False, 'name': 'input_1'}
Weights:
[]

Config:
{'name': 'dense', 'trainable': True, 'dtype': 'float32', 'units': 10, 'activation': 'linear', 'use_bias': True, 'kernel_initializer': {'class_name': 'GlorotUniform', 'config': {'seed': None}}, 'bias_initializer': {'class_name': 'Zeros', 'config': {}}, 'kernel_regularizer': None, 'bias_regularizer': None, 'activity_regularizer': None, 'kernel_constraint': None, 'bias_constraint': None}
Weights:
[array([[-0.60352975,  0.08275259, -0.6521113 , -0.5860774 , -0.42276743,
        -0.3142944 , -0.28118378,  0.07770532, -0.5644444 , -0.47069687],
       [ 0.4611913 ,  0.35170448, -0.62191975,  0.5837332 , -0.3390234 ,
        -0.4033073 ,  0.03493106, -0.06078851, -0.53159714,  0.49872506],
       [ 0.43685734,  0.6160207 ,  0.01610583, -0.3673877 , -0.14144647,
        -0.3792309 ,  0.05478126,  0.602067  , -0.47438127,  0.36463356]],
      dtype=float32), array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)]
票数 3
EN

Stack Overflow用户

发布于 2021-01-05 06:55:34

在做了更多的研究之后,即使例如,先生的回答是正确的,让我们更深入地了解TensorFlow Keras中的初始化工作方式。

根据tf.keras.layers.Layer医生,我们可以在以下两个方法中创建变量:

  • __init__(self, ...):定义自定义层属性,并使用add_weight()创建不依赖于输入形状的层状态变量。
  • build(self, input_shape):此方法可用于使用add_weight() kb创建依赖于输入的形状的权重。

下面的代码显示了一个基本层的示例,其中包含两个计算变量:y = w . x + b

代码语言:javascript
运行
复制
class SimpleDense(Layer):

  def __init__(self, units=32):
      super(SimpleDense, self).__init__()
      self.units = units

  def build(self, input_shape):  # Create the state of the layer (weights)
    w_init = tf.random_normal_initializer()
    self.w = tf.Variable(
        initial_value=w_init(shape=(input_shape[-1], self.units),
                             dtype='float32'),
        trainable=True)
    b_init = tf.zeros_initializer()
    self.b = tf.Variable(
        initial_value=b_init(shape=(self.units,), dtype='float32'),
        trainable=True)

  def call(self, inputs):  # Defines the computation from inputs to outputs
      return tf.matmul(inputs, self.w) + self.b

# Instantiates the layer.
linear_layer = SimpleDense(4)

# This will also call `build(input_shape)` and create the weights.
y = linear_layer(tf.ones((2, 2)))
assert len(linear_layer.weights) == 2

# These weights are trainable, so they're listed in `trainable_weights`:
assert len(linear_layer.trainable_weights) == 2

在上面的代码中需要注意的最有趣的事情是何时调用构建方法。

当层(在初始化之后)被分配某种类型的输入时调用 build() ,无论它是实际值还是仅为 TensorFlow占位符

当使用Keras序列模型时,我们在模型中添加一个层,它通过同时初始化输入占位符来自动分配输入占位符。

因此,我们看到调用compile()或Keras的fit()方法之前的权重。(请注意,__call__()将通过调用build()自动构建该层(如果尚未构建))

关于传输学习,当我们加载传输模型时,我们是加载已经构建的层,所以当您将这些层添加到自己的模型时,构建方法是而不是再次调用

换句话说,传输模型的层已经为其分配了输入占位符,并且在训练传输模型时已经调用了build()方法。

有用的参考资料:

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65451939

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档