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

参考目录:

目录

1 Keras卷积层

1.1 Conv2D

1.2 SeparableConv2D

1.3 Conv2DTranspose

1.3.1 去卷积的例子1

1.3.2 去卷积的例子2

2 Keras参数初始化

2.1 正态分布

2.2 均匀分布

2.3 截尾正态分布

2.4 常数

2.5 Xavier/Glorot

2.6 自定义初始化

3 Keras激活函数

3.1 relu

3.2 sigmoid

3.3 softmax

3.4 softplus

3.5 softsign

3.6 tanh

3.7 selu

4 Keras的L1/L2正则

4.1 L1/L2正则

4.2 自定义正则化

我们对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_initializer和pointwise_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=2in+out−−−−−−−−√

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

均匀分布的初始化如下:

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

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

[−6in+out−−−−−−−−√,6in+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)=11+e−x

3.3 softmax

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

3.4 softplus

tf.keras.activations.softplus(x)

计算公式:

softplus(x)=log(ex+1)

3.5 softsign

tf.keras.activations.softsign(x)

计算公式:

softsign(x)=x|x|+1

3.6 tanh

tf.keras.activations.tanh(x)

计算公式:

tanh(x)=ex−e−xex+e−x

3.7 selu

tf.keras.activations.selu(x)

如果x>0,返回scale×x;

如果x<0,返回scale×α×(ex−1);

scale和α是事先设置的数值,alpha=1.67216214,scale=1.05070098

与elu激活函数类似,但是多了有个scale系数,selu=scale×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×sum(abs(x))

L2:L1正则就是

loss=L1×sum(x2)

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】25 Keras的API详解(下)缓存激活,内存输出,并发解决的更多相关文章

  1. 百度地图API详解之事件机制,function“闭包”解决for循环和监听器冲突的问题:

    原文:百度地图API详解之事件机制,function"闭包"解决for循环和监听器冲突的问题: 百度地图API详解之事件机制 2011年07月26日 星期二 下午 04:06 和D ...

  2. 【小白学PyTorch】21 Keras的API详解(上)卷积、激活、初始化、正则

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

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

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

  4. linux命令学习笔记(25):linux文件属性详解

    Linux 文件或目录的属性主要包括:文件或目录的节点.种类.权限模式.链接数量.所归属的用户和用户组. 最近访问或修改的时间等内容.具体情况如下: 命令: ls -lih 输出: [root@loc ...

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

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

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

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

  7. 大数据学习笔记——Spark工作机制以及API详解

    Spark工作机制以及API详解 本篇文章将会承接上篇关于如何部署Spark分布式集群的博客,会先对RDD编程中常见的API进行一个整理,接着再结合源代码以及注释详细地解读spark的作业提交流程,调 ...

  8. jqGrid APi 详解

    jqGrid APi 详解 jqGrid皮肤 从3.5版本开始,jqGrid完全支持jquery UI的theme.我们可以从http://jqueryui.com/themeroller/下载我们所 ...

  9. Java 8 Stream API详解--转

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

随机推荐

  1. Android Handler MessageQueue Looper 消息机制原理

    提到Android里的消息机制,便会提到Message.Handler.Looper.MessageQueue这四个类,我先简单介绍以下这4个类 之间的爱恨情仇. Message 消息的封装类,里边存 ...

  2. 078 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 03 创建类

    078 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 03 创建类 本文知识点:创建类 说明:因为时间紧张,本人写博客过程中只是对知识点的关 ...

  3. 018 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 12 数据类型转换的基本概念

    018 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 12 数据类型转换的基本概念 本文知识点:Java中的数据类型转换 类型转换 类型转换分类 2类,分别是: ...

  4. 《流畅的Python》第三部分 把函数视作对象 【一等函数】【使用一等函数实现设计模式】【函数装饰器和闭包】

    第三部分 第5章 一等函数 一等对象 在运行时创建 能赋值给变量或数据结构中的元素 能作为参数传递给函数 能作为函数的返回结果 在Python中,所有函数都是一等对象 函数是对象 函数本身是 func ...

  5. springboot2.2.2企业级项目整合redis与redis 工具类大全

    1.springboot2.2.2整合redis教程很多,为此编写了比较完整的redis工具类,符合企业级开发使用的工具类 2.springboot与redis maven相关的依赖 <depe ...

  6. C和C++区别——前置自增与后置自增

    一.先看下面两段完全一样的代码块 /* test.cpp */ int main() { int a = 5; ++a = 7; printf("%d\n", a); return ...

  7. hugo官方相关文档地址

    +++ date="2020-10-17" title="hugo官方相关文档地址" tags=["hugo"] categories=[& ...

  8. C++ Primer第5版 第三章课后练习

    练习3.1 #include <iostream> using namespace std; int main() { int sum = 0, val = 50; while (val ...

  9. 全文检索Solr集成HanLP中文分词【转】

    以前发布过HanLP的Lucene插件,后来很多人跟我说其实Solr更流行(反正我是觉得既然Solr是Lucene的子项目,那么稍微改改配置就能支持Solr),于是就抽空做了个Solr插件出来,开源在 ...

  10. C# 将dataset数据导出到excel中

    //添加引用 NPOI.dll //添加 using NPOI.HSSF.UserModel; /// <summary> /// 导出数据到Excel /// </summary& ...