用keras构建自己的网络层

用keras构建自己的网络层

weixin_42813521 2020-04-14 22:25:29 45 收藏
分类专栏: tensorflow2.0
版权
tensorflow 2.0 学习记录
用keras构建自己的网络层

1.构建一个简单的网络层
from __future__ import absolute_import, division, print_function
import tensorflow as tf
tf.keras.backend.clear_session()
import tensorflow.keras as keras
import tensorflow.keras.layers as layers

class MyLayer(layers.Layer):
def __init__(self, input_dim=32, unit=32):
super(MyLayer, self).__init__()
#自定义权重
w_init = tf.random_normal_initializer()
self.weight = tf.Variable(initial_value=w_init(
shape=(input_dim, unit), dtype=tf.float32), trainable=True)

b_init = tf.zeros_initializer()
self.bias = tf.Variable(initial_value=b_init(
shape=(unit,), dtype=tf.float32), trainable=True)

def call(self, inputs):
return tf.matmul(inputs, self.weight) + self.bias

x = tf.ones((3,5))
my_layer = MyLayer(5, 4)
out = my_layer(x)
print(out)
'''
结果
tf.Tensor(
[[0.06709253 0.06818779 0.09926171 0.0179923 ]
[0.06709253 0.06818779 0.09926171 0.0179923 ]
[0.06709253 0.06818779 0.09926171 0.0179923 ]], shape=(3, 4), dtype=float32)
'''
按上面构建网络层,图层会自动跟踪权重w和b,当然我们也可以直接用add_weight的方法构建权重
#使用add_weight方法添加权重
class MyLayer(layers.Layer):
def __init__(self, input_dim=32, unit=32):
super(MyLayer, self).__init__()
self.weight = self.add_weight(shape=(input_dim, unit),
initializer=keras.initializers.RandomNormal(),
trainable=True)
self.bias = self.add_weight(shape=(unit,),
initializer=keras.initializers.Zeros(),
trainable=True)

def call(self, inputs):
return tf.matmul(inputs, self.weight) + self.bias

x = tf.ones((3,5))
my_layer = MyLayer(5, 4)
out = my_layer(x)
print(out)
'''
结果
tf.Tensor(
[[-0.10401802 -0.05459599 -0.08195674 0.13151655]
[-0.10401802 -0.05459599 -0.08195674 0.13151655]
[-0.10401802 -0.05459599 -0.08195674 0.13151655]], shape=(3, 4), dtype=float32)
'''
**当定义网络时不知道网络的维度是可以重写build()函数,用获得的shape构建网络**
class MyLayer(layers.Layer):
def __init__(self, unit=32):
super(MyLayer, self).__init__()
self.unit = unit

def build(self, input_shape):
self.weight = self.add_weight(shape=(input_shape[-1], self.unit),
initializer=keras.initializers.RandomNormal(),
trainable=True)
self.bias = self.add_weight(shape=(self.unit,),
initializer=keras.initializers.Zeros(),
trainable=True)
**#build函数根据inputs的维度确定weight的维度**
def call(self, inputs):
return tf.matmul(inputs, self.weight) + self.bias
my_layer = MyLayer(3)
x = tf.ones((3,5))
out = my_layer(x)
print(out)
my_layer = MyLayer(3)
x = tf.ones((2,2))
out = my_layer(x)
print(out)
'''
结果
tf.Tensor(
[[ 0.00949192 -0.02009935 -0.11726624]
[ 0.00949192 -0.02009935 -0.11726624]
[ 0.00949192 -0.02009935 -0.11726624]], shape=(3, 3), dtype=float32)
tf.Tensor(
[[-0.00516411 -0.04891593 -0.0181773 ]
[-0.00516411 -0.04891593 -0.0181773 ]], shape=(2, 3), dtype=float32)
'''
2.使用子层递归构建网络层
class MyBlock(layers.Layer):
def __init__(self):
super(MyBlock, self).__init__()
self.layer1 = MyLayer(32)
self.layer2 = MyLayer(16)
self.layer3 = MyLayer(2)
def call(self, inputs):
h1 = self.layer1(inputs)
h1 = tf.nn.relu(h1)
h2 = self.layer2(h1)
h2 = tf.nn.relu(h2)
return self.layer3(h2)
my_block = MyBlock()
print('trainable weights:', len(my_block.trainable_weights))
y = my_block(tf.ones(shape=(3, 64)))
# 构建网络在build()里面,所以执行了才有网络
print('trainable weights:', len(my_block.trainable_weights))
'''
结果
trainable weights: 0
trainable weights: 6
'''
可以通过构建网络层的方法来收集loss
class LossLayer(layers.Layer):

def __init__(self, rate=1e-2):
super(LossLayer, self).__init__()
self.rate = rate

def call(self, inputs):
self.add_loss(self.rate * tf.reduce_sum(inputs))
return inputs

class OutLayer(layers.Layer):
def __init__(self):
super(OutLayer, self).__init__()
self.loss_fun=LossLayer(1e-2)
def call(self, inputs):
return self.loss_fun(inputs)

my_layer = OutLayer()
print(len(my_layer.losses)) # 还未call
y = my_layer(tf.zeros(1,1))
print(len(my_layer.losses)) # 执行call之后
y = my_layer(tf.zeros(1,1))
print(len(my_layer.losses)) # call之前会重新置0
'''
结果
0
1
1
'''
3.其他网络层配置
使自己的网络层可以序列化
class Linear(layers.Layer):

def __init__(self, units=32, **kwargs):
super(Linear, self).__init__(**kwargs)
self.units = units

def build(self, input_shape):
self.w = self.add_weight(shape=(input_shape[-1], self.units),
initializer='random_normal',
trainable=True)
self.b = self.add_weight(shape=(self.units,),
initializer='random_normal',
trainable=True)
def call(self, inputs):
return tf.matmul(inputs, self.w) + self.b

def get_config(self):
config = super(Linear, self).get_config()
config.update({'units':self.units})
return config
layer = Linear(125)
config = layer.get_config()
print(config)
'''
结果
{'name': 'linear_1', 'trainable': True, 'dtype': None, 'units': 125}
'''
————————————————
版权声明:本文为CSDN博主「weixin_42813521」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42813521/java/article/details/105522972

posted on 2020-06-22 11:43  曹明  阅读(210)  评论(0编辑  收藏  举报