目录
TensorFlow 2.9的零零碎碎(二)-TensorFlow 2.9的零零碎碎(六)都是围绕使用TensorFlow 2.9在MNIST数据集上训练和评价模型来展开。
Python环境3.8。
代码调试都用的PyCharm。
模型的输入一般在第一层指定,有两种方法:使用tf.keras.layers.Input函数或者使用input_shape参数
tf.keras.layers.Input是一个函数,定义在keras.engine.input_layer.Input
其中有一个常用参数叫shape,也就是输入的尺寸,比如MNIST数据集的数据是28*28
在用Sequential实例化处模型对象之后,第一层应该添加Input层,也就是输入层
- import tensorflow as tf
-
- model = tf.keras.models.Sequential()
- model.add(tf.keras.layers.Input(shape=(28, 28)))
源码里注释比代码还多,基本都解释清楚了
- @keras_export('keras.Input', 'keras.layers.Input')
- @traceback_utils.filter_traceback
- def Input( # pylint: disable=invalid-name
- shape=None,
- batch_size=None,
- name=None,
- dtype=None,
- sparse=None,
- tensor=None,
- ragged=None,
- type_spec=None,
- **kwargs):
- """`Input()` is used to instantiate a Keras tensor.
- A Keras tensor is a symbolic tensor-like object,
- which we augment with certain attributes that allow us to build a Keras model
- just by knowing the inputs and outputs of the model.
- For instance, if `a`, `b` and `c` are Keras tensors,
- it becomes possible to do:
- `model = Model(input=[a, b], output=c)`
- Args:
- shape: A shape tuple (integers), not including the batch size.
- For instance, `shape=(32,)` indicates that the expected input
- will be batches of 32-dimensional vectors. Elements of this tuple
- can be None; 'None' elements represent dimensions where the shape is
- not known.
- batch_size: optional static batch size (integer).
- name: An optional name string for the layer.
- Should be unique in a model (do not reuse the same name twice).
- It will be autogenerated if it isn't provided.
- dtype: The data type expected by the input, as a string
- (`float32`, `float64`, `int32`...)
- sparse: A boolean specifying whether the placeholder to be created is
- sparse. Only one of 'ragged' and 'sparse' can be True. Note that,
- if `sparse` is False, sparse tensors can still be passed into the
- input - they will be densified with a default value of 0.
- tensor: Optional existing tensor to wrap into the `Input` layer.
- If set, the layer will use the `tf.TypeSpec` of this tensor rather
- than creating a new placeholder tensor.
- ragged: A boolean specifying whether the placeholder to be created is
- ragged. Only one of 'ragged' and 'sparse' can be True. In this case,
- values of 'None' in the 'shape' argument represent ragged dimensions.
- For more information about RaggedTensors, see
- [this guide](https://www.tensorflow.org/guide/ragged_tensors).
- type_spec: A `tf.TypeSpec` object to create the input placeholder from.
- When provided, all other args except name must be None.
- **kwargs: deprecated arguments support. Supports `batch_shape` and
- `batch_input_shape`.
- Returns:
- A `tensor`.
- Example:
- ```python
- # this is a logistic regression in Keras
- x = Input(shape=(32,))
- y = Dense(16, activation='softmax')(x)
- model = Model(x, y)
- ```
- Note that even if eager execution is enabled,
- `Input` produces a symbolic tensor-like object (i.e. a placeholder).
- This symbolic tensor-like object can be used with lower-level
- TensorFlow ops that take tensors as inputs, as such:
- ```python
- x = Input(shape=(32,))
- y = tf.square(x) # This op will be treated like a layer
- model = Model(x, y)
- ```
- (This behavior does not work for higher-order TensorFlow APIs such as
- control flow and being directly watched by a `tf.GradientTape`).
- However, the resulting model will not track any variables that were
- used as inputs to TensorFlow ops. All variable usages must happen within
- Keras layers to make sure they will be tracked by the model's weights.
- The Keras Input can also create a placeholder from an arbitrary `tf.TypeSpec`,
- e.g:
- ```python
- x = Input(type_spec=tf.RaggedTensorSpec(shape=[None, None],
- dtype=tf.float32, ragged_rank=1))
- y = x.values
- model = Model(x, y)
- ```
- When passing an arbitrary `tf.TypeSpec`, it must represent the signature of an
- entire batch instead of just one example.
- Raises:
- ValueError: If both `sparse` and `ragged` are provided.
- ValueError: If both `shape` and (`batch_input_shape` or `batch_shape`) are
- provided.
- ValueError: If `shape`, `tensor` and `type_spec` are None.
- ValueError: If arguments besides `type_spec` are non-None while `type_spec`
- is passed.
- ValueError: if any unrecognized parameters are provided.
- """
- if sparse and ragged:
- raise ValueError(
- 'Cannot set both `sparse` and `ragged` to `True` in a Keras `Input`.')
-
- input_layer_config = {'name': name, 'dtype': dtype, 'sparse': sparse,
- 'ragged': ragged, 'input_tensor': tensor,
- 'type_spec': type_spec}
-
- batch_input_shape = kwargs.pop('batch_input_shape',
- kwargs.pop('batch_shape', None))
- if shape is not None and batch_input_shape is not None:
- raise ValueError('Only provide the `shape` OR `batch_input_shape` argument '
- 'to Input, not both at the same time.')
- if (batch_input_shape is None and shape is None and tensor is None
- and type_spec is None):
- raise ValueError('Please provide to Input a `shape` '
- 'or a `tensor` or a `type_spec` argument. Note that '
- '`shape` does not include the batch '
- 'dimension.')
- if kwargs:
- raise ValueError(f'Unrecognized keyword arguments: {list(kwargs.keys())}')
-
- if batch_input_shape:
- shape = batch_input_shape[1:]
- input_layer_config.update({'batch_input_shape': batch_input_shape})
- else:
- input_layer_config.update(
- {'batch_size': batch_size, 'input_shape': shape})
- input_layer = InputLayer(**input_layer_config)
-
- # Return tensor including `_keras_history`.
- # Note that in this case train_output and test_output are the same pointer.
- outputs = input_layer._inbound_nodes[0].outputs
- if isinstance(outputs, list) and len(outputs) == 1:
- return outputs[0]
- else:
- return outputs
一个模型由若干层构成,在keras.api._v2.keras.layers.__init__.py中可以看到Keras封装好的层的名字,不同层的定义所在位置不同,比如keras.engine.base_layer、keras.engine.input_layer、keras.layers.activation.relu、keras.layers.convolutional.conv2d、keras.layers.core.dense
如果不用tf.keras.layers.Input函数,则可以直接在其他层中构建输入层,比如Dense层、Flatten层
- import tensorflow as tf
-
- model = tf.keras.models.Sequential()
- model.add(tf.keras.layers.Flatten(input_shape=(28, 28)))
- model.add(tf.keras.layers.Dense(128, activation='relu'))
- model.add(tf.keras.layers.Dropout(0.2))
- model.add(tf.keras.layers.Dense(10, activation='softmax'))
在keras.layers.core.dense模块的Dense类中,有以下注释
- When a popular kwarg `input_shape` is passed, then keras will create
- an input layer to insert before the current layer. This can be treated
- equivalent to explicitly defining an `InputLayer`.
可以看出,给这些层传参input_shape的时候,Keras会在当前层之前构建一个输入层,效果和使用tf.keras.layers.Input函数相同。
一个模型由若干层构成,每一层作为一个模块,接受一个输入,并产生一个输出,这种逻辑在代码中很常见。
就像我们搭积木一样,无非是小积木组成大积木,大积木再组成更大的积木,最后模型也就出来了。
用户需要负责的就是第一层的输入,也就是模型的输入
只要这个总输入定义好,层间的输入和输出TensorFlow、Keras已经封装好了,会自动计算,不用用户去管