TensorFlow学习(5)数据结构 & 自定义组件(损失函数,激活函数,初始化,正则化和约束,层)

神经网络架构进一步学习:TensorFlow模型花园

1.数据结构

在使用之前先要导入tensorflow

import tensorflow as tf

1.1 张量

1.1.1 通过直接传入创建

使用tf.constant()创建张量

print(tf.constant([[1,2,3],[4,5,6]]))

输出
tf.Tensor(
[[1 2 3]
 [4 5 6]], shape=(2, 3), dtype=int32)
  • 具有形状和数据类型
  • 工作方式类似于Numpy’
  • 包含所有基本上的数学运算

1.1.2 和numpy配合使用

1.1.2.1 使用numpy创建tensor

a=np.array([2.,4.,5.])
b=tf.constant(a)

1.1.2.2 使用tensor创建numpy

print("--------------------------")
c=t.numpy()
print(c)

输出
--------------------------
[[1 4]
 [2 5]
 [3 6]]

1.2 类型转换

tensorflow不会自动执行任何类型转换,使用tf.cast进行类型转换

tf.cast(
    x, dtype, name=None
)
  1. x :需要转换的参数
  2. dtype:需要转换的参数类型

1.3 变量

使用tf.Variable()创建可以调整的Variable变量

v=tf.Variable([[1.,2.,3.],[4.,5.,6.]])
print(v)

输出:
<tf.Variable 'Variable:0' shape=(2, 3) dtype=float32, numpy=
array([[1., 2., 3.],
       [4., 5., 6.]], dtype=float32)>

1.3.1 修改变量

1.3.1.1 assign

使用assign进行i修改

v1=v[:,2].assign([0.,1.])
print(v1)

输出:
<tf.Variable 'UnreadVariable' shape=(2, 3) dtype=float32, numpy=
array([[1., 2., 0.],
       [4., 5., 1.]], dtype=float32)>

或者是使用assign_add()或assign_sub()直接对变量增加减少

1.3.1.2 scatter_nd_update

v3=v.scatter_nd_update(indices=[[0,0],[1,2]],updates=[100.,200.])
print(v3)

1.3.2 变量创建

除了上面提到的手动创建,实际上更加使用的是add_weight()方法自动创建

 def add_weight(self,
                   name,
                   shape,
                   dtype=None,
                   initializer=None,
                   regularizer=None,
                   trainable=True,
                   constraint=None):

我在网上找到的源代码如下,但是在keras官网中

def __init__(self, name='binary_true_positives', **kwargs):
    super(BinaryTruePositives, self).__init__(name=name, **kwargs)
    self.true_positives = self.add_weight(name='tp', initializer='zeros')

并没有直接传入shape参数,应该是使用父类的参数初始化(我注释之后没有影响)?或者是代码小改了?

2. 定制模型

2.1 保存和加载自定义组件的模型

当加载包含自定义对象的模型时,需要将名称映射到对象

model=keras.models.load_model(...,custom_objects={"函数名称":实际函数})

2.1.1 自定义损失函数 参数传入

  1. 解决办法1:创建一个函数,该函数创建已配置的损失函数
  2. 解决办法2:创建keras.losses.loss类的子类,然后实现器get_config()方法

需要调用父类get_config()方法

base_config=super().get_config()
return{**base_config,"参数名":self.参数名}

2.2 自定义激活函数,初始化,正则化和约束

定义后,在相应的层中赋值就可以使用了

2.2.1 保存自定义函数

需要继承适当的类:
①keras.regularizers.Regularizer
②keras.constraints.Constraints
③keras.initializers.Initializer
④keras.layers.layer(适用于任何层,包括激活函数)

类同于上面的get_config操作但是不再需要调用父类

2.3 自定义指标

损失 指标
微分性 必须是可微的 ,梯度不应为0 可以是不可微的
解释性 不容易解释 易于解释

在大多数情况下,定义一个自定义的指标函数与定义一个自定义的损失函数完全相同

2.3.1 keras.metrics.Precision类

  • 定义:一个可以跟踪真正的数量和假正的数量,并且可以在请求时计算其比率
  • 得到的是到目前为止的总体精度,属于流式指标,即逐批次更新
precision=keras.metrics.Precision()
precision([0,1,1,0],[1,0,1,0])
print(precision)

输出:
<keras.metrics.Precision object at 0x0000016F4B757520>

在我的版本中并不会输出相应的numpy值

2.3.1.1 api

  1. result():获得指标的当前值
print(precision.result())

输出:
tf.Tensor(0.5, shape=(), dtype=float32)
  1. variables属性查看变量
print(precision.variables) 

输出:
[<tf.Variable 'true_positives:0' shape=(1,) dtype=float32, numpy=array([1.], dtype=float32)>, <tf.Variable 'false_positives:0' shape=(1,) dtype=float32, numpy=array([1.], dtype=float32)>]

查看变量以便于跟踪真正和假正的数量

  1. 使用reset_states重置变量
print(precision.reset_states())

输出:
None

2.3.2 小结

使用自定义的指标需要构建对应的类,包含以下几个部分:

  1. __ init __
    初始化函数,使用add_weight函数构建变量
  2. update_state
    使用assign_add等操作对__init__构造的变量进行复制
    def update_state(self,y_true,y_pred,sample_weight=None):
        metric=self.huber_fn(y_true,y_pred)
        metric.total.assign_add(tf.reduce_sum(metric))
        metric.count.assign_add(tf.cast(tf.cast(tf.size(y_true)),tf.float32))

加法运算可能需要数据类型变化
3. result
4. get_config
确保threshold可以与模型一起被保存

2.4 自定义层

用于创建一个自定义层或者构建一个重复结构

2.4.1 没有权重的某些层

exponential_layer=keras.layers.Lambda(lambda x: tf.exp(x))

调用可以通过以下三种方式:

第一种方式:activation=tf.exp
keras.layers.Dense(300,activation=tf.exp),

第二种方式:activation=keras.activations.exponential
keras.layers.Dense(300,activation=keras.activations.exponential),

第三种方式:activation="exponential"
keras.layers.Dense(300,activation="exponential"),

后面两种方式似乎是比较通用的,第一种方式换用其他自定义激活函数可能会报ValueError: Input has undefined rank.

2.4.2 构建自定义的有状态(权重)层

  1. __ init __
    调用父类的构造函数传递给kwargs
    使用keras.activation.get()将激活函数参数(接受字符串,函数等)转换为适当的激活函数

  2. build()
    通过对每个权重调用add_weight方法来创建层的变量,需要传入层的形状
    在build() 方法的最后需要调用父类的build()方法

  3. call()
    执行所需的操作

  4. get_config(self)
    返回包含用于初始化此层的配置的字典。如果键与 中的参数不同,则也重写。

2.4.2.1 多个输入(出)

只能使用函数式子类api

2.4.2.2 训练测试不同行为

在call中使用training参数进行控制

你可能感兴趣的:(#,tensorflow,tensorflow,学习,数据结构)