首先Model类是在training.py文件下的Model。继承了Network

Model groups layers into an object with training and inference features.
意思是说Model将网络层集成为具有训练推理功能的对象

所以Model就是将神经网络打包了,加了一个漂亮的外包装,可以让你一只手提起来的那种。。。

实例化

两种实例化方式:

  1. 使用functionAPI接口, 从Input开始,将所有网络层链接好并得到Output,然后创建Model。 意思就是说,你创建好了Input,然后依次创建网络层,每一层的输入要么是Input,要么是上一层网络(为啥呢?因为Dense除了第一次,可以自动计算当前层的输入–其实就是上一层的输出,所以其实就是每一层都是根据输Input创建。)一次创建。最后根据调用Model的API接口将input和output作为参数就可以创建Model了。
import tensorflow as tfinputs = tf.keras.Input(shape=(3,))
x = tf.keras.layers.Dense(4, activation=tf.nn.relu)(inputs)
outputs = tf.keras.layers.Dense(5, activation=tf.nn.softmax)(x)
model = tf.keras.Model(inputs=inputs, outputs=outputs)

所以,其实tf.keras.models.Sequential也是这种实例化方式?(因为Sequential也就是个定义好的神经网络啊)。

2.创建Model的子类。 在这里呢, 你需要创建自己的Model类(MyModel),在__init__方法中定义你的网络层(也就是说,你要在init里面将你的网络构建好。), 继承tf.keras.Model并实现前向传播方法call

import tensorflow as tfclass MyModel(tf.keras.Model):def __init__(self):super(MyModel, self).__init__()self.dense1 = tf.keras.layers.Dense(4, activation=tf.nn.relu)self.dense2 = tf.keras.layers.Dense(5, activation=tf.nn.softmax)self.dropout = tf.keras.layers.Dropout(0.5)def call(self, inputs, training=False):x = self.dense1(inputs)if training:x = self.dropout(x, training=training)return self.dense2(x)model = MyModel()

Model.compile()

这玩意看起来好吓人。。。(这是一个500行的python方法!!)

一步步来吧。


参数
optimizer : 传入的是优化器的名字(String类型)或者是优化器实例

loss : 目标函数的名字或者目标函数。(如果模型有多个output, 可以使用不同的loss, 传入一个loss字典或者list, 模型的目标值是所有独立的loss的总和,而模型的优化目标变成了这个总和。)

metrics : 衡量标准。在测试和训练过程中使用什么衡量标准来评估模型,通常是准确度-- metrics=['accuracy']. 你也可以为不同的output指定不同的衡量标准,只要使用字典将其对应好就可以。metrics={'output_a': 'accuracy'}.

loss_weights : 损失权重。嗯···(还不太熟悉,以后再补充。)这是一个针对多输出的参数,不同输出的loss需要有不同的权重(不设置,当然就是1:1了。)。目前理解就是对损失进行加权。

sample_weight_mode : 样本加权方式。如果需要按时间步长进行样本加权(2D),请将其设置为“时间”。没有默认的采样权值(1D)。如果模型有多个输出,则可以通过传递字典或模式列表对每个输出使用不同的sample_weight_mode。

weighted_metrics : 衡量标准权重。(这个好理解,就是对不同的标准进行加权。)

target_tensors : 目标张量。默认情况下,Keras将为模型的目标创建占位符,这些占位符将在培训期间与目标数据一起提供。相反,如果您想使用自己的目标张量(反过来,Keras在训练时不会期望这些目标的外部Numpy数据),您可以通过target_tensors参数指定它们。它可以是一个单张量(对于单输出模型),一个张量列表,或者一个字典把输出名映射到目标张量。

distribute : 在TF 2.0中不支持,请在分发策略范围下创建和编译模型,而不是将其传递给compile。

所以看起来,后面两个参数不用管,真要用这两个参数,那已经是大神了。


下面开始看代码。。

 loss = loss or {}if context.executing_eagerly() and not isinstance(optimizer, (tf_optimizer_module.Optimizer, optimizers.TFOptimizer)):raise ValueError('Only TF native optimizers are supported in Eager mode.')self.optimizer = optimizers.get(optimizer)

在这里进行了优化器的检测,如果不是tf本地的优化器都会被拒绝。嗯,就是这么厉害啊。

    if isinstance(self.optimizer, checkpointable.CheckpointableBase):self._track_checkpointable(self.optimizer, name='optimizer', overwrite=True)self.loss = lossself.metrics = metrics or []self.loss_weights = loss_weightsif context.executing_eagerly() and sample_weight_mode is not None:raise ValueError('sample_weight_mode is not supported in Eager mode.')self.sample_weight_mode = sample_weight_modeif context.executing_eagerly() and weighted_metrics is not None:raise ValueError('weighted_metrics is not supported in Eager mode.')self.weighted_metrics = weighted_metricsif context.executing_eagerly() and target_tensors is not None:raise ValueError('target_tensors is not supported in Eager mode.')self.target_tensors = target_tensors

在当前优化器是可检测的情况下,添加checkpoint dependency…(就是加了name属性和将overwrite赋值为True)。
然后进行了一系列的参数检测。

    if not self.built:returnself._is_compiled = True

built属性在model init 的时候会赋值为true,如果初始化失败,当然为false,就不知道它的input和output,包括他们的名字和shape。所以当需要训练时,必须要进行编译。将编译标志赋值为true。

 # Prepare loss functions.if isinstance(loss, dict):for name in loss:if name not in self.output_names:raise ValueError('Unknown entry in loss ''dictionary: "' + name + '". ''Only expected the following keys: ' + str(self.output_names))loss_functions = []for name in self.output_names:if name not in loss:logging.warning('Output "' + name + '" missing from loss dictionary. ''We assume this was done on purpose, ''and we will not be expecting ''any data to be passed to "' + name + '" during training.')loss_functions.append(losses.get(loss.get(name)))elif isinstance(loss, list):if len(loss) != len(self.outputs):raise ValueError('When passing a list as loss, ''it should have one entry per model outputs. ''The model has ' + str(len(self.outputs)) +' outputs, but you passed loss=' + str(loss))loss_functions = [losses.get(l) for l in loss]else:loss_function = losses.get(loss)loss_functions = [loss_function for _ in range(len(self.outputs))]self.loss_functions = loss_functionsweighted_losses = [training_utils.weighted_masked_objective(fn)for fn in loss_functions]skip_target_indices = []skip_target_weighing_indices = []self._feed_outputs = []self._feed_output_names = []self._feed_output_shapes = []self._feed_loss_fns = []for i in range(len(weighted_losses)):if weighted_losses[i] is None:skip_target_indices.append(i)skip_target_weighing_indices.append(i)

嗯,目标函数。
如果给定的是字典,巴拉巴拉,如果给的是list,巴拉巴拉,如果就是个目标函数,巴拉巴拉。。。
weighted_losses = [training_utils.weighted_masked_objective(fn)
for fn in loss_functions]
这是干嘛呢?? 为每个目标函数返回一个weight_loss的计算函数(output_loss = weighted_loss(y_true, y_pred, sample_weight, mask)), 用来计算得到output_loss。 (这里面水有点深, 简单说就是计算真实值与预测值之间的某个值,这个某个值就是目标函数给定的计算方式,可以是平方,可以是交叉熵等。如果样本还有权重–第三个参数,那这个权重也要加入到loss的计算中。),先走着,理解深入了再回来看这里。

这里面有个mask,要咋翻译呢?马赛克?-- 其实就是一个赋值0的操作。理解dropout的作用,dropout就是将节点mask

 # Prepare output masks.if not context.executing_eagerly():masks = self.compute_mask(self.inputs, mask=None)if masks is None:masks = [None for _ in self.outputs]if not isinstance(masks, list):masks = [masks]

context.executing_eagerly() , 这个判断当前线程是否需要立即执行。
这段得到新输入的输出张量。

 # Prepare loss weights.if loss_weights is None:loss_weights_list = [1. for _ in range(len(self.outputs))]elif isinstance(loss_weights, dict):for name in loss_weights:if name not in self.output_names:raise ValueError('Unknown entry in loss_weights ''dictionary: "' + name + '". ''Only expected the following keys: ' + str(self.output_names))loss_weights_list = []for name in self.output_names:loss_weights_list.append(loss_weights.get(name, 1.))elif isinstance(loss_weights, list):if len(loss_weights) != len(self.outputs):raise ValueError('When passing a list as loss_weights, ''it should have one entry per model output. ''The model has ' + str(len(self.outputs)) +' outputs, but you passed loss_weights=' + str(loss_weights))loss_weights_list = loss_weightselse:raise TypeError('Could not interpret loss_weights argument: ' +str(loss_weights) + ' - expected a list of dicts.')self.loss_weights_list = loss_weights_list

这段是进行loss_weights的处理。(将字典啊、list啊什么的都变为统一的东东。)

 # initialization for Eager mode executionif context.executing_eagerly():if target_tensors is not None:raise ValueError('target_tensors are not currently supported in Eager ''mode.')self.total_loss = Noneself.metrics_tensors = []self.metrics_names = ['loss']for i in range(len(self.outputs)):if len(self.outputs) > 1:self.metrics_names.append(self.output_names[i] + '_loss')self.nested_metrics = training_utils.collect_metrics(metrics,self.output_names)# TODO(fchollet): support stateful metrics in eager execution.self.stateful_metric_functions = []self.stateful_metric_names = []with K.name_scope('metrics'):training_utils.populate_metric_names(self)self._feed_sample_weight_modes = []for i in range(len(self.outputs)):self._feed_sample_weight_modes.append(None)self.sample_weights = []self.targets = []for i in range(len(self.outputs)):self._feed_output_names.append(self.output_names[i])self._collected_trainable_weights = self.trainable_weightsreturn
 # Prepare targets of model.self.targets = []self._feed_targets = []if target_tensors not in (None, []):if isinstance(target_tensors, list):if len(target_tensors) != len(self.outputs):raise ValueError('When passing a list as `target_tensors`, ''it should have one entry per model output. ''The model has ' + str(len(self.outputs)) +' outputs, but you passed target_tensors=' + str(target_tensors))elif isinstance(target_tensors, dict):for name in target_tensors:if name not in self.output_names:raise ValueError('Unknown entry in `target_tensors` ''dictionary: "' + name + '". ''Only expected the following keys: ' + str(self.output_names))tmp_target_tensors = []for name in self.output_names:tmp_target_tensors.append(target_tensors.get(name, None))target_tensors = tmp_target_tensorselse:raise TypeError('Expected `target_tensors` to be ''a list or dict, but got:', target_tensors)for i in range(len(self.outputs)):if i in skip_target_indices:self.targets.append(None)else:shape = K.int_shape(self.outputs[i])name = self.output_names[i]if target_tensors not in (None, []):target = target_tensors[i]else:target = Noneif target is None or K.is_placeholder(target):if target is None:target = K.placeholder(ndim=len(shape),name=name + '_target',sparse=K.is_sparse(self.outputs[i]),dtype=K.dtype(self.outputs[i]))self._feed_targets.append(target)self._feed_outputs.append(self.outputs[i])self._feed_output_names.append(name)self._feed_output_shapes.append(shape)self._feed_loss_fns.append(self.loss_functions[i])else:skip_target_weighing_indices.append(i)self.targets.append(target)

准备target, 如果target_tensors参数没有设置,这里就是[], 空的。

    # Prepare sample weights.sample_weights = []sample_weight_modes = []if isinstance(sample_weight_mode, dict):for name in sample_weight_mode:if name not in self.output_names:raise ValueError('Unknown entry in ''sample_weight_mode dictionary: "' + name + '". ''Only expected the following keys: ' + str(self.output_names))for i, name in enumerate(self.output_names):if i in skip_target_weighing_indices:weight = Nonesample_weight_modes.append(None)else:if name not in sample_weight_mode:raise ValueError('Output "' + name + '" missing from sample_weight_modes ''dictionary')if sample_weight_mode.get(name) == 'temporal':weight = K.placeholder(ndim=2, name=name + '_sample_weights')sample_weight_modes.append('temporal')else:weight = K.placeholder(ndim=1, name=name + 'sample_weights')sample_weight_modes.append(None)sample_weights.append(weight)elif isinstance(sample_weight_mode, list):if len(sample_weight_mode) != len(self.outputs):raise ValueError('When passing a list as sample_weight_mode, ''it should have one entry per model output. ''The model has ' + str(len(self.outputs)) +' outputs, but you passed ''sample_weight_mode=' + str(sample_weight_mode))for i in range(len(self.output_names)):if i in skip_target_weighing_indices:weight = Nonesample_weight_modes.append(None)else:mode = sample_weight_mode[i]name = self.output_names[i]if mode == 'temporal':weight = K.placeholder(ndim=2, name=name + '_sample_weights')sample_weight_modes.append('temporal')else:weight = K.placeholder(ndim=1, name=name + '_sample_weights')sample_weight_modes.append(None)sample_weights.append(weight)else:for i, name in enumerate(self.output_names):if i in skip_target_weighing_indices:sample_weight_modes.append(None)sample_weights.append(None)else:if sample_weight_mode == 'temporal':sample_weights.append(array_ops.placeholder_with_default(constant_op.constant([[1.]], dtype=K.floatx()),shape=[None, None], name=name + '_sample_weights'))sample_weight_modes.append('temporal')else:sample_weights.append(array_ops.placeholder_with_default(constant_op.constant([1.], dtype=K.floatx()),shape=[None], name=name + '_sample_weights'))sample_weight_modes.append(None)self.sample_weight_modes = sample_weight_modesself._feed_sample_weight_modes = []for i in range(len(self.outputs)):if i not in skip_target_weighing_indices:self._feed_sample_weight_modes.append(self.sample_weight_modes[i])

一波操作后,样本权重准备就绪。。。

 # Prepare metrics.self.weighted_metrics = weighted_metricsself.metrics_names = ['loss']self.metrics_tensors = []

没啥好说的。。

 # Compute total loss.total_loss = None# K是什么?? from tensorflow.python.keras import backend as K# 一个张量在指定轴附近的平均值。with K.name_scope('loss'):for i in range(len(self.outputs)):if i in skip_target_indices:continuey_true = self.targets[i]y_pred = self.outputs[i]weighted_loss = weighted_losses[i]sample_weight = sample_weights[i]mask = masks[i]loss_weight = loss_weights_list[i]with K.name_scope(self.output_names[i] + '_loss'):output_loss = weighted_loss(y_true, y_pred, sample_weight, mask)if len(self.outputs) > 1:self.metrics_tensors.append(output_loss)self.metrics_names.append(self.output_names[i] + '_loss')if total_loss is None:total_loss = loss_weight * output_losselse:total_loss += loss_weight * output_lossif total_loss is None:if not self.losses:raise ValueError('The model cannot be compiled ''because it has no loss to optimize.')else:total_loss = 0.# Add regularization penalties# and other layer-specific losses.for loss_tensor in self.losses:total_loss += loss_tensor

总损失计算。
K是什么?? from tensorflow.python.keras import backend as K,

这里拿到所有的值, 真实值,预测是,样本权重,损失权重,损失计算方法(损失计算方法是在前面就得到了,还记得吗?),进行了一波计算,然后得到了总的损失值。

接下来就是metric的处理和梯度更新状态更新等。。。

Model.fit()

按照给定的epoch数目训练模型。

参数
x : input data。
y : target data。

batch_size : 每次梯度更新的样本数。如果未指定,batch_size将默认为32。如果您的数据采用符号张量、数据集、生成器或keras.utils.Sequence 实例的形式,则不要指定batch_size,因为它们会生成batch。
epochs : 训练模型的迭代次数(针对所有数据)。请注意,与initial_epoch一起,epoch将被理解为“最终代”。模型不是针对epoch给出的多次迭代进行训练,而是仅仅在到达索引epoch之前进行训练。(等待理解)

verbose :
callbacks : 在训练期间应用的回调列表。

validation_split : 将训练数据的一部分用作验证数据。模型将把这部分训练数据分开,不进行训练,并将在每个epoch结束时评估损失和对这些数据的任何模型度量。验证数据从提供的x和y数据中的最后一个样本中选择,然后进行变换。如果您的数据采用符号张量、数据集、生成器或keras.utils.Sequence 实例的形式,改参数不起作用。(也就是说将训练数据的一部分划分为验证数据。参数值在0-1之间。)
validation_data : 用于在每个epoch结束时评估损失的数据和模型度量(metric)。模型不会根据这些数据进行训练。validation_data将覆盖validation_split。
shuffle : 布尔值(在每个epoch之前对训练数据进行洗牌)或str(用于“batch”)。“批处理”是处理HDF5数据限制的特殊选项;它以批量大小的块进行重组。当steps_per_epoch不是空时,没有任何效果。

class_weight : 可选的字典将类索引(整数)映射到一个权值(浮点数),用于加权损失函数(仅在训练期间)。用于告诉模型“需要更多地关注”来自代表性不足的类的样本。类似不平衡数据等等。

sample_weight : 可选的用于训练样本的Numpy权重数组,用于加权损失函数(仅在训练期间)。您可以传递一个与输入示例长度相同的平面(1D) Numpy数组(1:1重量和样品之间的映射), 或在时态数据的情况下,您可以传递一个shape(samples, sequence_length)的2D数组,以便对每个样本的每个时间步长应用不同的权重。

initial_epoch : 训练的时间(对于恢复之前的训练很有用怎么有用了?)。

steps_per_epoch : 每个epoch的步数(最大的那种),一个epoch最多这么多步数了。当使用输入张量(如TensorFlow数据张量)进行训练时,默认的None等于数据集中的样本数量除以批处理大小,如果无法确定,就设置为1。如果数据集是tf.data并且该参数设置为None,那么epoch将一直运行,直到输入数据集耗尽为止。

validation_steps : 只有设置了validata参数且数据集是tf.data, 该参数才起作用。每个epoch结束之前的验证步数,如该参数设置为Node,则验证完说有验证数据。

validation_freq : 验证频率,多少个epoch验证一次。

max_queue_size : 整数。用于Sequence的输入和生成器,生成器队列的最大大小。当没有指定时,默认为10。。

workers : 线程数,用于Sequence的输入和生成器。默认值为1, 设置0则表示使用主线程。

use_multiprocessing : 是否多进程?

**kwargs : 向后兼容参数。忽略。

整个fit这部分,主要完成了参数的校验与赋值,真正的训练过程在training_arrays.fit_loop()函数中进行。

Model.evaluate()

在测试模式下返回模型的损失值和度量值。 (度量值:假如给定的metrics是accuracy, 那么返回的度量值就是准确度。)

参数与fit中的类似。

最后的测试过程在training_arrays.predict_loop() 函数中进行。

所以重要的部分在这里–training_arrays.fit_loop()和这里training_arrays.predict_loop()。

先吃饭,待续。。。

tf 2.0 -- Model -- 模型相关推荐

  1. gpxclear寄存器写0和写1_画图,搭积木,写对象 [TF 笔记 0]

    前言 从2019年9月底到现在,TF 2.0 已经正式发布三个多月了.但其实很多和 2.0 相关的特性,比如说 eager 模式,@tf.function 装饰器和 AutoGraph, 以及 ker ...

  2. 啥是符号式API,命令式API:TF 2.0两种搭建都支持,该怎么选?

    原作 Josh Gordon  栗子 编译  量子位 出品 | 公众号 QbitAI TensorFlow 2.0有一个很友好的地方,就是提供了多种不同的抽象方式,可以根据自己的需求来选择.这些API ...

  3. keras系列︱Sequential与Model模型、keras基本结构功能(一)

    不得不说,这深度学习框架更新太快了尤其到了Keras2.0版本,快到Keras中文版好多都是错的,快到官方文档也有旧的没更新,前路坑太多. 到发文为止,已经有theano/tensorflow/CNT ...

  4. Tensorflow学习之tf.keras(一) tf.keras.layers.Model(另附compile,fit)

    模型将层分组为具有训练和推理特征的对象. 继承自:Layer, Module tf.keras.Model(*args, **kwargs ) 参数 inputs 模型的输入:keras.Input ...

  5. TensorFlow2.0保存模型

    介绍 模型保存有5种:1.整体保存:2.网络架构保存:3.权重保存:4.回调保存:5.自定义训练模型的保存 1.整体保存:权重值,模型配置(架构),优化器配置 整个模型可以保存到一个文件中,其中包含权 ...

  6. Keras的Model模型使用

    本主题主要阐述下Keras框架中的模型Model的使用,主要包含的内容:   1.模型的两种使用方式:   2.经典模型的实现(定制模型):   3.模型的定制训练: 一. 模型使用的两种方式 Ker ...

  7. Keras Model模型方法

    Model模型方法 compile compile(self, optimizer, loss, metrics=None, loss_weights=None, sample_weight_mode ...

  8. 深度学习框架 TensorFlow:张量、自动求导机制、tf.keras模块(Model、layers、losses、optimizer、metrics)、多层感知机(即多层全连接神经网络 MLP)

    日萌社 人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新) 安装 TensorFlow2.CUDA10.cuDNN7.6. ...

  9. 争论不休的TF 2.0与PyTorch,到底现在战局如何了? | 技术头条

    点击上方↑↑↑蓝字关注我们~ 「2019 Python开发者日」全日程揭晓,请扫码咨询 ↑↑↑ 作者 | Jeff Hale 译者 | Jackey 编辑 | Jane 出品 | AI科技大本营(id ...

最新文章

  1. 国内人脸识别第一案,我们来谈谈国外法规和隐私保护技术
  2. linux下oracle启动关闭
  3. Lua和C++交互总结(很详细)
  4. MySQL—02—MySQL的操作
  5. Linux通常把设备对象抽象为,linux 设备模型(1)
  6. Set精讲(Java)·算法常用集合处理方法
  7. 几种流行的AJAX框架:jQuery,Mootools,Dojo,Ext JS的对比
  8. Unknown column '' in 'field list'
  9. 苹果自己设计芯片,但是还是绕不过高通
  10. 阿里沈询:分布式事务原理与实践
  11. jenkins手把手教你从入门到放弃03-安装Jenkins时web界面出现该jenkins实例似乎已离线
  12. 微pe装linux系统教程,微PE工具箱增加安装Linux系统菜单
  13. WEB前端助手FeHelper|前端人员的神器
  14. Oracle-数据库的备份与恢复
  15. leecode.1758. 生成交替二进制字符串的最少操作数
  16. itunes登录时显示服务器失败怎么办,苹果手机itunes验证失败怎么办
  17. 湖北师范大学计信计科2018届期末实训EduCoder习题 (参考答案)
  18. 有什么好用的在线图表制作网站吗?试试这个吧
  19. 随机事件和概率及概率的性质
  20. 二叉搜索树的创建、插入、遍历、删除

热门文章

  1. 递归回溯生成和解决数独问题c/c++
  2. linux awk 区别,linux awk 中 RS,ORS,FS,OFS 区别与联系
  3. 中高级运维工程师所需要掌握的技能
  4. 计算机深度睡眠状态啥意思,什么是计算机的“深度睡眠”模式?
  5. CTO和技术副总裁应该如何分工?谁才是技术领导者?
  6. Eclipse ADT插件和Android SDK使用离线包升级笔记
  7. 水印相机定位不准确怎么办_第一台胶卷相机入门品鉴
  8. 接着,运营基础知识(福利篇)
  9. 纯前端导出excel文件(包含设置样式)
  10. TApplicaiton.ProcessMessages不能在非主线程使用