[机器学习炼丹术] 的炼丹总群已经快满了, 要加入的快联系炼丹兄 WX:cyx645016617
参考目录:
目录
1 创建自定义网络层
2 创建一个完整的 CNN
2.1 keras.Model vs keras.layers.Layer
之前讲过了如何用 tensorflow 构建数据集, 然后这一节课讲解如何用 Tensorflow2.0 来创建模型.
TF2.0 中创建模型的 API 基本上都放到了它的 Keras 中了, Keras 可以理解为 TF 的高级 API, 里面封装了很多的常见网络层, 常见损失函数等. 后续会详细介绍 keras 的全面功能, 本篇文章讲解如何构建模型.
1 创建自定义网络层
- import tensorflow as tf
- import tensorflow.keras as keras
- class MyLayer(keras.layers.Layer):
- def __init__(self, input_dim=32, output_dim=32):
- super(MyLayer, self).__init__()
- w_init = tf.random_normal_initializer()
- self.weight = tf.Variable(
- initial_value=w_init(shape=(input_dim, output_dim), dtype=tf.float32),
- trainable=True) # 如果是 false 则是不参与梯度下降的变量
- b_init = tf.zeros_initializer()
- self.bias = tf.Variable(initial_value=b_init(
- shape=(output_dim), 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(input_dim=5,
- output_dim=10)
- out = my_layer(x)
- print(out.shape)
- >>> (3, 10)
这个就是定义了一个 TF 的网络层, 其实可以看出来和 PyTorch 定义的方式非常的类似:
这个类要继承
tf.keras.layers.Layer
, 这个 pytorch 中要继承 torch.nn.Module 类似;
网络层的组件在__def__中定义, 和 pytorch 的模型类相同;
call()和 pytorch 中的 forward()的类似.
上面代码中实现的是一个全连接层的定义, 其中可以看到使用 tf.random_normal_initializer()来作为参数的初始化器, 然后用 tf.Variable 来产生网络层中的权重变量, 通过 trainable=True 这个参数说明这个权重变量是一个参与梯度下降的可以训练的变量.
我通过 tf.ones((3,5))产生一个 shape 为 [3,5] 的一个全是 1 的张量, 这里面第一维度的 3 表示有 3 个样本, 第二维度的 5 就是表示要放入全连接层的数据(全连接层的输入是 5 个神经元); 然后设置的全连接层的输出神经元数量是 10, 所以最后的输出是(3,10).
2 创建一个完整的 CNN
- import tensorflow as tf
- import tensorflow.keras as keras
- class CBR(keras.layers.Layer):
- def __init__(self,output_dim):
- super(CBR,self).__init__()
- self.conv = keras.layers.Conv2D(filters=output_dim, kernel_size=4, padding='same', strides=1)
- self.bn = keras.layers.BatchNormalization(axis=3)
- self.ReLU = keras.layers.ReLU()
- def call(self, inputs):
- inputs = self.conv(inputs)
- inputs = self.ReLU(self.bn(inputs))
- return inputs
- class MyNet(keras.Model):
- def __init__ (self,input_dim=3):
- super(MyNet,self).__init__()
- self.cbr1 = CBR(16)
- self.maxpool1 = keras.layers.MaxPool2D(pool_size=(2,2))
- self.cbr2 = CBR(32)
- self.maxpool2 = keras.layers.MaxPool2D(pool_size=(2,2))
- def call(self, inputs):
- inputs = self.maxpool1(self.cbr1(inputs))
- inputs = self.maxpool2(self.cbr2(inputs))
- return inputs
- model = MyNet(3)
- data = tf.random.normal((16,224,224,3))
- output = model(data)
- print(output.shape)
- >>> (16, 56, 56, 32)
这个是构建了一个非常简单的卷积网络, 结构是常见的: 卷积层 + BN 层 + ReLU 层. 可以发现这里继承的一个 tf.keras.Model 这个类.
2.1 keras.Model vs keras.layers.Layer
Model 比 Layer 的功能更多, 反过来说, Layer 的功能更精简专一.
Layer: 仅仅用作张量的操作, 输入一个张量, 输出也要求是一个张量, 对张量的操作都可以用 Layer 来封装;
Model: 一个更加复杂的结构, 由多个 Layer 组成. Model 的话, 可以使用. fit(),.evaluate(),.predict()等方法来快速训练. 保存和加载模型也是在 Model 这个级别进行的.
现在说一说上面的代码和 pytorch 中的区别, 作为一个对比学习, 也作为一个对 pytorch 的回顾:
卷积层 Conv2D 中, Keras 中不用输入输入的通道数, filters 就是卷积后的输出特征图的通道数; 而 PyTorch 的卷积层是需要输入两个通道数的参数, 一个是输入特征图的通道数, 一个是输出特征图的通道数;
keras.layers.BatchNormalization(axis=3)
是 BN 层, 这里的 axis=3 说明第三个维度 (从 0 开始计数) 是通道数, 是需要作为批归一化的维度(这个了解 BN 算法的朋友应该可以理解吧, 不了解的话去重新看我之前剖析 BN 层算法的那个文章吧, 在文章末尾有相关链接).pytorch 的图像的四个维度是:
\[[样本数量, 通道数, width,height] \]
而 tensorflow 是:
\[[样本数量, width,height, 通道数] \]
总之, 学了 pytorch 之后, 再看 keras 的话, 对照的 keras 的 API, 很多东西都直接就会了, 两者的 API 越来越相似了.
上面最后输出是 (16, 56, 56, 32), 输入的是 \(224\times 224\) 的维度, 然后经过两个最大池化层, 就变成了 \(56\times 56\)了.
到此为止, 我们现在应该是可以用 keras 来构建模型了.
来源: https://www.cnblogs.com/PythonLearner/p/13767150.html