【新闻】:机器学习炼丹术的粉丝的人工智能交流群已经建立,目前有目标检测、医学图像、时间序列等多个目标为技术学习的分群和水群唠嗑答疑解惑的总群,欢迎大家加炼丹兄为好友,加入炼丹协会。微信:cyx645016617.

参考目录:

我们对Keras应该已经有了一个直观、宏观的认识了。现在,我们来系统的学习一下Keras的一些关于网络层的API,本文的主要内容是围绕卷积展开的,包含以下的内容:

  • 不同类型的卷积层;
  • 不同的参数初始化方式;
  • 不同的激活函数;
  • 增加L1/L2正则;
  • 不同的池化层;
  • 多个Normalization层;
  • 其他的常用层。

本文内容较多,对于API的学习了解即可。

1 Keras卷积层

Keras的卷积层和PyTorch的卷积层,都包括1D、2D和3D的版本,1D就是一维的,2D是图像,3D是立体图像。这里就用最常见的2D图像来做讲解,1D和3D和2D基本相同,不多赘述。

1.1 Conv2D

先看Conv2D的所有参数:

tf.keras.layers.Conv2D(
filters,
kernel_size,
strides=(1, 1),
padding="valid",
data_format=None,
dilation_rate=(1, 1),
groups=1,
activation=None,
use_bias=True,
kernel_initializer="glorot_uniform",
bias_initializer="zeros",
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
**kwargs
)

先看一个简单的例子:

import tensorflow as tf
input_shape = (4, 28, 28, 3)
x = tf.random.normal(input_shape)
y = tf.keras.layers.Conv2D(
filters=2,kernel_size=3,
activation='relu',padding='same'
)
print(y(x).shape)
>>> (4, 28, 28, 2)

现在来看参数含义

  • filter: 一个int整数,输出特征图的通道数;
  • kernel_size:一个int整数,卷积核大小;
  • strides:一个整数或者是(a,b)这样的list,表示卷积核是否跳步;
  • padding'valid'表示没有padding,'same'表示输出和输入特征图的尺寸相同;只有这两种选择
  • data_format'channels_last'或者是'channels_first'。默认是'channels_last',表示特征图的最后一个维度是通道,(batch_size, height, width, channels) ;如果选择了'channels_first'表示每一个样本的第一个维度是通道,所以特征图的格式和PyTorch的格式相同,(batch_size, channels, height, width)。
  • dilation_rate:碰撞卷积的设置,默认是1,1就是一般的卷积。需要注意的是dilation_rate和stride目前不支持同时不为1,换句话说,如果要膨胀卷积的话,那么stride必须是1;
  • groups;分组卷积;
  • activation:这个表示,可以直接在卷积层后面设置一个激活层,比方说'relu',这个在后面的章节会详细讲解目前Keras支持的所有激活层,如果什么都不填入,则不使用激活层
  • use_bias:一个bool参数,True表示使用bias,默认是True;
  • kernel_initializer:卷积核的初始化的方法,这个会在后面的章节详细讲解;
  • bias_initializer:偏置的初始化的方法,这个会在后面的章节详细讲解;
  • kernel_regularizer:卷积核的正则化的方法,在后面的章节会详细讲解;
  • bias_regularizer:偏置的正则化的方法,在后面的章节会详细讲解;

1.2 SeparableConv2D

Keras直接提供了深度可分离卷积层,这个层其实包含两个卷积层(了解深度可分离卷积的应该都知道这个吧),一层是depthwise,一层是pointwise。

这个SeparableConv2D的参数也很多,与Conv2D有很多重复的参数,就不多加赘述了:

tf.keras.layers.SeparableConv2D(
filters,
kernel_size,
strides=(1, 1),
padding="valid",
data_format=None,
dilation_rate=(1, 1),
depth_multiplier=1,
activation=None,
use_bias=True,
depthwise_initializer="glorot_uniform",
pointwise_initializer="glorot_uniform",
bias_initializer="zeros",
depthwise_regularizer=None,
pointwise_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
depthwise_constraint=None,
pointwise_constraint=None,
bias_constraint=None,
**kwargs
)

参数详解:

  • depth_multiplier:depthwise卷积之后,一般会增多通道数。比方说输入通道是16个,那么输出通道数64个,然后再输入到pointwise卷积层。这个depth_multiplier就是depthwise卷积层的通道数的扩增系数,在上面的例子中这个扩增系数是4;
  • depthwise_initializerpointwise_initializer不用多说,就是两个卷积层的卷积核的初始化的方法。

但是这个深度可分离卷积完全可以用一般的Conv2D来构建,所以其实在用到深度可分离卷积的时候,自己会重新构建一个这样的网络层

1.3 Conv2DTranspose

对于上采样,这种方法应该并不陌生。Transposed convolution有的时候也被称为Deconvolution去卷积

tf.keras.layers.Conv2DTranspose(
filters,
kernel_size,
strides=(1, 1),
padding="valid",
output_padding=None,
data_format=None,
dilation_rate=(1, 1),
activation=None,
use_bias=True,
kernel_initializer="glorot_uniform",
bias_initializer="zeros",
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
**kwargs
)

参数详解:

  • output_padding:一个整数或者list,用来给输出的特征图增加一个padding的效果,默认是None,不添加padding;

对于去卷积,可能会比较生疏,这里多讲几个例子

1.3.1 去卷积的例子1

import tensorflow as tf
from tensorflow import keras input_shape = (4, 28, 28, 3)
x = tf.random.normal(input_shape)
y = keras.layers.Conv2DTranspose(
filters=10,kernel_size=3,strides=1,padding='same')
print(y(x).shape)
>>> (4, 28, 28, 10)

但是假如我们去掉了padding=‘same’

input_shape = (4, 28, 28, 3)
x = tf.random.normal(input_shape)
y = keras.layers.Conv2DTranspose(
filters=10,kernel_size=3,strides=1)
print(y(x).shape)
>>> (4, 30, 30, 10)

这是因为去卷积的卷积核的中心是从原特征图的边界之外开始计算的。一个3乘3的卷积核,那么当卷积核的右下角与原特征图的左上角重合的时候,去卷积的就已经进行了一次运算,而一般的卷积是只有当卷积核的全部都与原特征图重合的时候,才进行计算的。(这里的讲解不太细致,因为之前在其他的文章中已经讲过去卷积的详细过程了)。

1.3.2 去卷积的例子2

现在把stride改成2

input_shape = (4, 28, 28, 3)
x = tf.random.normal(input_shape)
y = keras.layers.Conv2DTranspose(
filters=10,kernel_size=3,strides=2)
print(y(x).shape)
>>> (4, 57, 57, 10)

假如加上padding='same'

input_shape = (4, 28, 28, 3)
x = tf.random.normal(input_shape)
y = keras.layers.Conv2DTranspose(
filters=10,kernel_size=3,strides=2,padding='same')
print(y(x).shape)
>>> (4, 56, 56, 10)

所以一般情况下,使用的参数是strides=2,padding='same',这样特征图的尺寸就刚好放大一倍。

2 Keras参数初始化

把之前提到的简单的例子,增加卷积核和偏置的初始化:

import tensorflow as tf
input_shape = (4, 28, 28, 3)
initializer = tf.keras.initializers.RandomNormal(mean=0., stddev=1.)
x = tf.random.normal(input_shape)
y = tf.keras.layers.Conv2D(
filters=2,kernel_size=3,
activation='relu',padding='same',
kernel_initializer=initializer,
bias_initializer=initializer
)
print(y(x).shape)
>>> (4, 28, 28, 2)

简单的说,就是先定义一个初始化器initializer,然后把这个初始化器作为参数传给Keras.Layers就行了。

2.1 正态分布

tf.keras.initializers.RandomNormal(mean=0.0, stddev=0.05, seed=None)

2.2 均匀分布

tf.keras.initializers.RandomUniform(minval=-0.05, maxval=0.05, seed=None)

2.3 截尾正态分布

tf.keras.initializers.TruncatedNormal(mean=0.0, stddev=0.05, seed=None)

基本和正态分布一样,但是如果随机的取值是在距离均值两个标准差的这个范围之外的,那么会重新取值。

换句话说,初始化的数值会被限制在均值正负两个标准差的范围内

2.4 常数

tf.keras.initializers.Zeros()
tf.keras.initializers.Ones()

2.5 Xavier/Glorot

tf.keras.initializers.GlorotNormal(seed=None)

这个本质是一个截尾正态分布,但是GlorotNormal(又称Xavier),是一个以0为均值,标准差计算公式是:$$std = \sqrt{\frac{2}{in+out}}$$

是in和out表示输入和输出神经元数目的数目。如果是之前已经学习过或者看过我写的关于Xavier初始化的论文笔记的朋友,可能会发现论文中使用的是一个均匀分布而不是正态分布。

均匀分布的初始化如下:

tf.keras.initializers.GlorotUniform(seed=None)

这个均匀分布是我们讲的:

\[[-\sqrt{\frac{6}{in+out}},\sqrt{\frac{6}{in+out}}]
\]

这个Xavier方法,也是Keras默认的初始化的方法

2.6 自定义初始化

当然,Keras也是支持自定义初始化的方法的。

import tensorflow as tf

class ExampleRandomNormal(tf.keras.initializers.Initializer):

def __init__(self, mean, stddev):
self.mean = mean
self.stddev = stddev def __call__(self, shape, dtype=None)`:
return tf.random.normal(
shape, mean=self.mean, stddev=self.stddev, dtype=dtype) def get_config(self): # To support serialization
return {'mean': self.mean, 'stddev': self.stddev}

关键就是在__call__中返回一个和输入参数shape大小相同的一个tf张量就行了。

3 Keras激活函数

基本支持了所有的常见激活函数。在卷积层的参数activation中,可以输入relu,sigmoid,softmax等下面的字符串的形式,全部小写。

3.1 relu

tf.keras.activations.relu(x, alpha=0.0, max_value=None, threshold=0)

  • alpha就是斜率,如果是0.1,则变成leakyReLU;
  • max_value是ReLU的上界,如果是None则没有上界;
  • threshold是ReLU的下界,小于下界的都会被置0,一般默认是0.

3.2 sigmoid

tf.keras.activations.sigmoid(x)

函数方程:

\[sigmoid(x)=\frac{1}{1+e^{-x}}
\]

3.3 softmax

tf.keras.activations.softmax(x, axis=-1)

3.4 softplus

tf.keras.activations.softplus(x)

计算公式:

\[softplus(x)=log(e^x+1)
\]

3.5 softsign

tf.keras.activations.softsign(x)

计算公式:

\[softsign(x)=\frac{x}{|x|+1}
\]

3.6 tanh

tf.keras.activations.tanh(x)

计算公式:

\[tanh(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}}
\]

3.7 selu

tf.keras.activations.selu(x)

  • 如果\(x>0\),返回\(scale \times x\);
  • 如果\(x<0\),返回\(scale \times \alpha \times (e^x-1)\);
  • scale和\(\alpha\)是事先设置的数值,alpha=1.67216214,scale=1.05070098
  • 与elu激活函数类似,但是多了有个scale系数,\(selu=scale\times elu\)
  • 2017年的一篇论文提出selu,elu是2016年提出的

4 Keras的L1/L2正则

正则化就比较简单,不是L1就是L2,再或者两者都有。

4.1 L1/L2正则

from tensorflow.keras import layers
from tensorflow.keras import regularizers layer = layers.Dense(
units=64,
kernel_regularizer=regularizers.l1_l2(l1=1e-5, l2=1e-4),
)

这里的正则化,可以使用:

  • tf.keras.regularizers.l1_l2(l1=1e-5, l2=1e-4)
  • tf.keras.regularizers.l2(1e-4)
  • tf.keras.regularizers.l1(1e-5)

关于L1和L2的计算细节:

  • L1:L1正则就是$$loss=L1\times sum(abs(x))$$
  • L2:L1正则就是$$loss=L1\times sum(x^2)$$

4.2 自定义正则化

class MyRegularizer(tf.keras.regularizers.Regularizer):

    def __init__(self, strength):
self.strength = strength def __call__(self, x):
return self.strength * tf.reduce_sum(tf.square(x)) def get_config(self):
return {'strength': self.strength}

这个实现的是L2正则的。其中的get_config是用来保存模型数据的,不要的话也没事,只是不能序列化的保存模型(不用使用config或者json来存储模型)。

【小白学PyTorch】21 Keras的API详解(上)卷积、激活、初始化、正则的更多相关文章

  1. 【小白学PyTorch】21 Keras的API详解(下)池化、Normalization层

    文章来自微信公众号:[机器学习炼丹术].作者WX:cyx645016617. 参考目录: 目录 1 池化层 1.1 最大池化层 1.2 平均池化层 1.3 全局最大池化层 1.4 全局平均池化层 2 ...

  2. 小白如何学习PyTorch】25 Keras的API详解(下)缓存激活,内存输出,并发解决

    [新闻]:机器学习炼丹术的粉丝的人工智能交流群已经建立,目前有目标检测.医学图像.时间序列等多个目标为技术学习的分群和水群唠嗑答疑解惑的总群,欢迎大家加炼丹兄为好友,加入炼丹协会.微信:cyx6450 ...

  3. 【小白学AI】GBDT梯度提升详解

    文章来自微信公众号:[机器学习炼丹术] 文章目录: 目录 0 前言 1 基本概念 2 梯度 or 残差 ? 3 残差过于敏感 4 两个基模型的问题 0 前言 先缕一缕几个关系: GBDT是gradie ...

  4. 【小白学PyTorch】20 TF2的eager模式与求导

    [新闻]:机器学习炼丹术的粉丝的人工智能交流群已经建立,目前有目标检测.医学图像.时间序列等多个目标为技术学习的分群和水群唠嗑的总群,欢迎大家加炼丹兄为好友,加入炼丹协会.微信:cyx64501661 ...

  5. Java 8 Stream API详解--转

    原文地址:http://blog.csdn.net/chszs/article/details/47038607 Java 8 Stream API详解 一.Stream API介绍 Java8引入了 ...

  6. hibernate学习(2)——api详解对象

    1   Configuration 配置对象 /详解Configuration对象 public class Configuration_test { @Test //Configuration 用户 ...

  7. 转】Mahout推荐算法API详解

    原博文出自于: http://blog.fens.me/mahout-recommendation-api/ 感谢! Posted: Oct 21, 2013 Tags: itemCFknnMahou ...

  8. Java8学习笔记(五)--Stream API详解[转]

    为什么需要 Stream Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念.它也不同于 StAX 对 ...

  9. Android Developer -- Bluetooth篇 开发实例之四 API详解

    http://www.open-open.com/lib/view/open1390879771695.html 这篇文章将会详细解析BluetoothAdapter的详细api, 包括隐藏方法, 每 ...

随机推荐

  1. Codeforece E. Anton and Permutation

    主席树算贡献l,r中交换位置,算出>=rank(h) 和 <=rank(h) a[l],a[r] 先不统计 a[l]比a[r]大的话交换后ans-1,a[l]比a[r]小的话交换后ans- ...

  2. WebStorm下ReactNative代码提示设置

    ReactNative 代码智能提醒  (Webstrom live template) https://github.com/virtoolswebplayer/ReactNative-LiveTe ...

  3. 利用递归方法实现链表反转、前N个节点反转以及中间部分节点反转

    一.反转整个链表 问题:定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点. 示例: 输入: 1->2->3->4->5->NULL 输出: 5-&g ...

  4. Java进阶专题(十三) 从电商系统角度研究多线程(上)

    前言 ​ 本章节主要分享下,多线程并发在电商系统下的应用.主要从以下几个方面深入:线程相关的基础理论和工具.多线程程序下的性能调优和电商场景下多线程的使用. 多线程J·U·C 线程池 概念 回顾线程创 ...

  5. Hive 高阶应用开发示例(一)

    Hive的一些常用的高阶开发 内容    1.开窗函数   2.行转列,列转行,多行转一行,一行转多行   3.分组: 增强型group   4.排序  5.关联 本次的内容: 内容1 和内容2,采用 ...

  6. 会话技术之 Session

    会话技术之 Session 不多废话,先来一个 HelloWorld. Session 有 get 肯定要先有 set . @Override protected void service(HttpS ...

  7. MySQL通过实体经纬度字段插入数据库point类型的经纬度字段

    说明:数据库:表中没有经度跟纬度字段,只有location字段(point类型) POINT(经度 纬度)实体类:只有经度 lng 字段.纬度 lat 字段 没有location字段 <!--添 ...

  8. jQuery的那些事儿

    jQuery概述 j-JavaScript+Query就是查询js的库,把js中的DOM操作做了封装,实现快速查询使用其中的功能. 优化了DOM操作.事件处理.动画设计和Ajax交互 学习jQuery ...

  9. ssm框架spring-mvc.xml和spring-mybatis.xml报错项目无法正常启动问题

    报错信息 Multiple annotations found at this line: - Referenced file contains errors (http://www.springfr ...

  10. django之models字段参数

    字段内部参数: null 数据库中字段是否可以为空 db_column 数据库中字段的列名 db_tablespace default 数据库中字段的默认值 primary_key 数据库中字段是否为 ...