在阅读了对这个问题的回答之后,我有点困惑于TensorFlow究竟是什么时候初始化了权重和偏差变量。根据答案,编译定义了损失函数、优化器和度量。就这样。
因为compile()
方法没有初始化它,所以这意味着它发生在fit()
方法运行期间。
然而,在加载模型或加载权重的情况下,fit()
如何知道它所提供的权重实际上是有用的,不应该丢弃,然后分配随机值来代替这些权重。
在声明该层时,我们在参数kernel_initializer
中传递不整化器的类型。例如:
dense02 = tf.keras.layers.Dense(units=10,
kernel_initializer='glorot_uniform',
bias_initializer='zeros')
因此,一个很明显的问题是,在第一次划线过程中,权重是逐层初始化,还是在第一次划线之前,对所有层都进行初始化。
(我想说的是,如果模型中有5层稠密层,那么初始化是否一次表示一层,即第一稠密层被初始化,然后该层发生前传,然后第二层初始化,第二稠密层发生前传,等等)
另一个方面是关于传输学习,当在经过训练的模型之上堆叠自定义层时,经过训练的模型层具有权重,而我添加的层不会有任何有用的层。那么,TensorFlow如何知道只初始化我添加的层的变量,而不是将传输模型的层搞乱(前提是,我没有trainable=False
)
TensorFlow或Keras如何处理权值初始化?
发布于 2020-12-26 03:32:03
在创建模型时(当模型中的每个层被初始化时),即在compile()
和fit()
之前初始化权重
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()))
产出:
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)]
发布于 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
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()
方法。
有用的参考资料:
https://stackoverflow.com/questions/65451939
复制相似问题