主要内容

定义嵌套深度学习层

如果深度学习工具箱™没有为您的分类或回归问题提供所需的层,那么您可以使用此示例作为指导定义自己的自定义层。有关内置层的列表,请参见深度学习层列表

要创建一个自定义层来定义一个层图,你可以声明一个dlnetwork对象中的可学习参数属性(可学的)部分的层定义。这种方法被称为网络的作文.你可以使用网络组合:

  • 创建一个单独的自定义层,表示可学习层的块,例如,残留块。

  • 创建具有控制流的网络,例如,具有可以根据输入数据动态更改的部分的网络。

  • 创建一个具有循环的网络,例如,一个具有将输出反馈回自身的部分的网络。

对于同时具有可学习参数和状态参数的嵌套网络,例如具有批处理归一化或LSTM层的网络,在属性(可学习的,状态)部分的层定义。

有关更多信息,请参见深度学习网络构成

这个例子展示了如何创建一个表示残留块的自定义层。自定义层residualBlockLayer包含可学习的层块,由卷积、组归一化、ReLU和添加层组成,还包括跳过连接和在跳过连接中的可选卷积层和组归一化层。该层有一个单独的输入,作为每个分支的输入使用两次。此图突出显示了剩余块结构。

残块结构。它包含一个卷积、一个组归一化、一个ReLU、一个第二个卷积、一个第二个组归一化、一个加法和一个串联的ReLU层。从块输入到添加层有一个跳过连接。还有另一个串行连接的卷积和组归一化层出现在跳过连接上。出现在跳过连接上的层被高亮显示为可选的。

要定义自定义深度学习层,您可以使用本例中提供的模板,该模板将带您完成以下步骤:

  1. 给图层命名——给图层命名以便在MATLAB中使用®

  2. 声明层属性——指定层的属性,包括可学习参数和状态参数。

  3. 创建一个构造函数(可选)——指定如何构造这个层并初始化它的属性。如果没有指定构造函数,则在创建时,软件将初始化的名字描述,类型属性与[]并设置层输入和输出的数量为1。

  4. 创建前向函数——指定数据在预测时和训练时如何通过层(前向传播)向前传递。

  5. 创建reset state功能(可选)-指定重置状态参数的方式。

  6. 创建反向函数(可选)——指定损失对输入数据和可学习参数的导数(反向传播)。如果没有指定向后函数,则向前函数必须支持万博1manbetxdlarray对象。

中间层模板

在MATLAB中将中间层模板复制到一个新文件中。该模板概述了中间层类定义的结构。概述:

  • 可选属性块的层属性,可学习参数,和状态参数。

  • 层构造函数。

  • 预测函数和可选的向前函数。

  • 可选resetState函数用于具有状态属性的层。

  • 可选落后的函数。

classdefmyLayer < nnet.layer.Layer可格式化的(可选)属性%(可选)图层属性。在这里声明图层属性。结束属性(可学的)%(可选)层可学习参数。在这里声明可学习的参数。结束属性(状态)%(可选)层状态参数。在这里声明状态参数。结束属性(可学的,状态)%(可选)嵌套的dlnetwork对象,两者都可学习参数和状态。在这里使用可学习和状态参数声明嵌套网络。结束方法函数图层= myLayer()%(可选)创建myLayer。此函数必须与类同名。在这里定义层构造函数。结束函数[Z,state] = predict(层,X)%在预测时间和转发输入数据通过层%输出结果和更新状态。%的输入:% layer -向前传播的层% X -输入数据%输出:% Z -层正向函数的输出% state -(可选)更新的层状态。% -对于有多个输入的层,将X替换为X1,…,XN,%,其中N是输入的数量。% -对于有多个输出的层,将Z替换为% Z1,…,Z米,在那里米is the number of outputs.% -对于有多个状态参数的层,替换state% with state1,…,状态K,在那里Kis the number of state%的参数。在这里定义层预测函数。结束函数[Z,状态,内存]=前进(层,X)%(可选)通过训练层转发输入数据%的时间,并输出结果,更新状态,和一个内存%值。%的输入:% layer -向前传播的层% X -层输入数据%输出:% Z -层正向函数的输出% state -(可选)更新的层状态%内存-(可选)自定义向后的内存值%的功能% -对于有多个输入的层,将X替换为X1,…,XN,%,其中N是输入的数量。% -对于有多个输出的层,将Z替换为% Z1,…,Z米,在那里米is the number of outputs.% -对于有多个状态参数的层,替换state% with state1,…,状态K,在那里Kis the number of state%的参数。在这里定义层转发函数。结束函数图层= resetState(图层)%(可选)重置层状态。在这里定义重置状态函数。结束函数[dLdX,dLdW,dLdSin] =向后(层,X,Z,dLdZ,dLdSout,内存)%(可选)反向传播损失的导数%函数通过层。%的输入:% layer -向后传播的层% X -层输入数据% Z -层输出数据-损失对层的导数%输出% dLdSout -(可选)关于损失的导数%到状态输出% memory -转发功能的内存值%输出:% dLdX -损失对层输入的导数% dLdW -(可选)损失对的导数%可学习参数% dLdSin -(可选)损失对的导数%状态输入% -对于有状态参数的层,必须使用向后语法%包含dLdSout和dLdSin,或两者都不包含。% -对于有多个输入的层,将X和dLdX替换为% X1,…,XN而且dLdX1,...,dLdXN, respectively, where N is%输入的数量。% -对于有多个输出的层,将Z和dlZ替换为% Z1,…,Z米而且dLdZ,...,dLdZM, respectively, where M is the输出的百分比。% -对于有多个可学习参数的层,替换% dLdW with dLdW1,…,dLdWP, where P is the number of%可学习参数。% -对于有多个状态参数的层,替换dLdSin% and dLdSout with dLdSin1,…、dLdSinK和% dLdSout1,…dldSoutK, respectively, where K is the number%的状态参数。在这里定义层向后函数。结束结束结束

名字层

首先,给图层起一个名字。在类文件的第一行中,替换现有的名称myLayerresidualBlockLayer

classdefresidualBlockLayer < nnet.layer.Layer...结束

接下来,将myLayer构造函数的第一个函数方法Section),这样它就有了与图层相同的名称。

方法函数layer = residualBlockLayer()…结束...结束

保存层

将图层类文件保存在一个名为residualBlockLayer.m.文件名必须与层名匹配。要使用该层,必须将文件保存在当前文件夹或MATLAB路径上的文件夹中。

声明属性和可学习参数

中声明层属性属性类中列出可学习参数,并声明这些参数属性(可学的)部分。

默认情况下,自定义中间层具有这些属性。中不要声明这些属性属性部分。

财产 描述
的名字 层名,指定为字符向量或字符串标量。为数组输入时,trainNetworkassembleNetworklayerGraph,dlnetwork函数自动为层分配名称的名字设置为
描述

层的一行描述,指定为字符串标量或字符向量。当该层显示在数组中。

如果不指定层描述,则软件显示层类名称。

类型

层的类型,指定为字符向量或字符串标量。的价值类型控件中显示该层时显示数组中。

如果不指定层类型,则软件显示层类名称。

NumInputs 层的输入数,指定为正整数。如果您不指定此值,那么软件将自动设置NumInputs的名字的数量InputNames.缺省值为1。
InputNames 输入层的名称,指定为字符向量的单元格数组。如果不指定此值和NumInputs大于1,那么软件自动设置InputNames{“三机”,…,“客栈”},在那里N等于NumInputs.默认值为{'在'}
NumOutputs 层的输出数,指定为正整数。如果您不指定此值,那么软件将自动设置NumOutputs的名字的数量OutputNames.缺省值为1。
OutputNames 输出层的名称,指定为字符向量的单元格数组。如果不指定此值和NumOutputs大于1,那么软件自动设置OutputNames{着干活,…,“outM”},在那里等于NumOutputs.默认值为{“出”}

如果该层没有其他属性,则可以省略属性部分。

提示

如果要创建具有多个输入的层,则必须设置NumInputsInputNames层构造函数中的属性。如果要创建具有多个输出的层,则必须设置NumOutputsOutputNames层构造函数中的属性。示例请参见定义具有多重输入的自定义深度学习层

剩余块层不需要任何附加属性,因此可以删除属性部分。

这个自定义层只有一个可学习的参数,剩余块本身指定为dlnetwork对象。中声明此可学习参数属性(可学的)节并调用参数网络

属性(可学的)%层可学习参数%残留块。网络结束

Create Constructor命令功能

创建构造层并初始化层属性的函数。指定创建层所需的任何变量,作为构造函数的输入。

残差块层构造函数需要四个输入参数:

  • 卷积滤波器的个数

  • 跨步(可选,默认跨步1)

  • 标志在跳过连接中包含卷积(可选,带有默认标志

  • 层名(可选,默认名称。

在构造函数中residualBlockLayer,指定所需的输入参数numFilters和可选参数作为名称-值对与名称NameValueArgs.在函数的顶部添加注释,解释函数的语法。

函数层= residualBlockLayer(numFilters,NameValueArgs)% layer = residualBlockLayer(numFilters)创建一个残差%块层与指定数量的过滤器。% layer = residualBlockLayer(numFilters,名称,值)指定%使用一个或多个名称-值对的附加选项%参数:'Stride' -卷积运算的步幅%(默认1)% ' incleskipvolution ' -包含卷积的标志%跳过连接%(默认为false)% 'Name' -层名称%(默认值")...结束

解析输入参数

类解析输入参数参数块。按照与函数语法相同的顺序列出参数,并指定默认值。然后,从NameValueArgs输入。

解析输入参数。参数numFilters NameValueArgs。Stride = 1 NameValueArgs。incleskipconvolution = false NameValueArgs。Name =结束stride = NameValueArgs.Stride;incleskipconvolution = namevalueargs . incleskipconvolution;name = NameValueArgs.Name;

初始化图层属性

在构造函数中,初始化层属性,包括dlnetwork对象。替换注释%层构造函数在这里使用初始化层属性的代码。

设置的名字属性设置为输入参数的名字

设置图层名称。层。的名字= name;

给图层一个单行描述描述层的属性。设置描述来描述图层和任何可选属性。

设置层描述。描述=“残块带”+ numFilters +“滤镜,大步走”+步伐;如果incleskipconvolution description = description +,跳过卷积运算结束层。Description =描述;

指定层的类型类型财产。的价值类型控件中显示该层时显示数组中。

设置图层类型。层。类型=“剩余块”

定义剩余块。您可以将剩余块层创建为未初始化的嵌套dlnetwork对象,并允许软件在训练时自动初始化可学习参数和状态参数。有关更多信息,请参见自动初始化可学习的dlnetwork对象进行训练

首先,创建一个包含块的主要层的层数组,并将其转换为层图。

定义嵌套层图。layers = [convolution2dLayer(3,numFilters,“填充”“相同”“步”步,“名字”“conv1”) groupNormalizationLayer (所有渠道的“名字”“gn1”) reluLayer (“名字”“relu1”) convolution2dLayer (3 numFilters“填充”“相同”“名字”“conv2”) groupNormalizationLayer (“channel-wise”“名字”“gn2”) additionLayer (2“名字”“添加”) reluLayer (“名字”“relu2”));lgraph = layerGraph(图层);

接下来,添加跳过连接。如果includeSkipConvolution国旗是真正的,则在跳过连接中还包括卷积层和组归一化层。

添加跳过连接。如果incleskipconvolution layers = [convolution2dLayer(1,numFilters,“步”步,“名字”“convSkip”) groupNormalizationLayer (所有渠道的“名字”“gnSkip”));lgraph = addLayers(lgraph,layers);lgraph = connectLayers(lgraph,“gnSkip”“添加/ in2”);结束

由于没有输入层,这个网络有两个不连接的输入。如果网络没有跳转连接,则输入到“conv2”层和一个输入“添加”层之间没有连接。如果网络确实有跳过连接,则未连接的输入是“conv1”而且“convSkip”层。

最后,将图层图转换为adlnetwork对象并设置图层网络财产。创建一个未初始化的dlnetwork对象。的权重和可学习参数dlnetwork对象在装配完整的网络进行训练时自动初始化。

%转换为dlnetwork。Dlnet = dlnetwork(lgraph,“初始化”、假);设置网络属性。层。Network = dlnet;

查看已完成的构造函数。

函数层= residualBlockLayer(numFilters,NameValueArgs)% layer = residualBlockLayer(numFilters)创建一个残差%块层与指定数量的过滤器。% layer = residualBlockLayer(numFilters,名称,值)指定%使用一个或多个名称-值对的附加选项%参数:'Stride' -卷积运算的步幅%(默认1)% ' incleskipvolution ' -包含卷积的标志%跳过连接%(默认为false)% 'Name' -层名称%(默认值")解析输入参数。参数numFilters NameValueArgs。Stride = 1 NameValueArgs。incleskipconvolution = false NameValueArgs。Name =结束stride = NameValueArgs.Stride;incleskipconvolution = namevalueargs . incleskipconvolution;name = NameValueArgs.Name;设置图层名称。层。的名字= name;设置层描述。描述=“残块带”+ numFilters +“滤镜,大步走”+步伐;如果incleskipconvolution description = description +,跳过卷积运算结束层。Description =描述;设置图层类型。层。类型=“剩余块”定义嵌套层图。layers = [convolution2dLayer(3,numFilters,“填充”“相同”“步”步,“名字”“conv1”) groupNormalizationLayer (所有渠道的“名字”“gn1”) reluLayer (“名字”“relu1”) convolution2dLayer (3 numFilters“填充”“相同”“名字”“conv2”) groupNormalizationLayer (“channel-wise”“名字”“gn2”) additionLayer (2“名字”“添加”) reluLayer (“名字”“relu2”));lgraph = layerGraph(图层);添加跳过连接。如果incleskipconvolution layers = [convolution2dLayer(1,numFilters,“步”步,“名字”“convSkip”) groupNormalizationLayer (所有渠道的“名字”“gnSkip”));lgraph = addLayers(lgraph,layers);lgraph = connectLayers(lgraph,“gnSkip”“添加/ in2”);结束%转换为dlnetwork。dlnet = dlnetwork(lgraph,'Initialize',false);设置网络属性。层。Network = dlnet;结束

对于这个构造函数,命令residualBlockLayer(64年,“大步”2“IncludeSkipConvolution”,的确,“名字”,“res5”)创建一个带有64个过滤器、步幅为2、跳过连接中的卷积和名称的残留块层“res5”.所需的权重和参数的大小是在完成的网络进行训练时确定的。

创建前向函数

创建在预测时和训练时使用的层转发函数。

创建一个名为预测的层转发数据预测的时间并输出结果。

预测函数语法取决于层的类型。

  • Z = predict(layer,X)转发输入数据X通过层并输出结果Z,在那里只有一个输入,一个输出。

  • [Z,state] = predict(层,X)还输出更新后的状态参数状态,在那里只有一个状态参数。

您可以调整具有多个输入、多个输出或多个状态参数的层的语法:

  • 对于有多个输入的层,替换XX1,…,XN,在那里N是输入的数量。的NumInputs属性必须匹配N

  • 对于有多个输出的层,替换ZZ1,…,ZM评选,在那里是输出的数量。的NumOutputs属性必须匹配

  • 对于有多个状态参数的层,替换状态state1,…,stateK,在那里K状态参数的个数。

提示

如果对层的输入数量可以变化,那么使用变长度输入宗量而不是X1,…,XN.在这种情况下,变长度输入宗量单元格数组的输入在哪里变长度输入宗量{我}对应于西

如果输出的数量可以变化,那么使用varargout而不是Z1,…,锌.在这种情况下,varargout是单元格数组的输出,在哪里varargout {j}对应于Zj

提示

如果自定义层有dlnetwork对象获取可学习参数,然后在预测函数的自定义层,使用预测的函数dlnetwork.使用dlnetwork对象预测功能确保软件使用正确的层操作进行预测。

因为剩余块只有一个输入和一个输出,所以自定义层的预测语法为Z = predict(layer,X)

默认情况下,该层使用预测作为训练时的正向函数。要在训练时使用不同的前向函数,或保留自定义后向函数所需的值,还必须创建名为向前

输入的维度取决于数据的类型和连接层的输出。

层的输入 输入的大小 观察维度
特征向量 c——- - - - - -N,在那里c对应于通道和的数量N是观察数。 2
二维图像 h——- - - - - -w——- - - - - -c——- - - - - -N,在那里hw,c分别对应于图像的高度、宽度和通道数,和N是观察数。 4
三维图像 h——- - - - - -w——- - - - - -d——- - - - - -c——- - - - - -N,在那里hwd,c分别为三维图像的高度、宽度、深度和通道数,和N是观察数。 5
向量序列 c——- - - - - -N——- - - - - -年代,在那里c是序列特征的数量,N是观察的次数,和年代为序列长度。 2
二维图像序列 h——- - - - - -w——- - - - - -c——- - - - - -N——- - - - - -年代,在那里hw,c分别对应于图像的高度、宽度和通道数,N是观察的次数,和年代为序列长度。 4
三维图像序列 h——- - - - - -w——- - - - - -d——- - - - - -c——- - - - - -N——- - - - - -年代,在那里hwd,c分别对应三维图像的高度、宽度、深度和通道数,N是观察的次数,和年代为序列长度。 5

对于输出序列的层,该层可以输出任意长度的序列或输出无时间维的数据。方法输出序列时请注意trainNetwork函数中,输入和输出序列的长度必须匹配。

对于剩余块层,层的前向传递仅仅是层的前向传递dlnetwork对象。将输入数据传递给dlnetwork对象,则必须首先将其转换为格式化的dlarray对象。

在自定义层函数中实现此操作预测.的向前传递dlnetwork对于预测,使用预测函数dlnetwork对象。在这种情况下,对剩余块层的输入被用作对两个未连接的输入的输入dlnetwork对象,所以语法预测dlnetwork对象是Z = predict(dlnet,X,X)

因为这些层dlnetwork对象在训练过程中没有不同的行为,并且剩余块层不需要内存或不同的前向函数进行训练,则可以删除向前函数从类文件中获取。

创建预测函数,并在函数的顶部添加注释,解释函数的语法。

函数Z = predict(layer, X)%在预测时间和转发输入数据通过层%输出结果。%的输入:% layer -向前传播的层% X -输入数据%输出:% Z -层正向函数的输出将输入数据转换为格式化的dlarray。X = dlarray(X,“SSCB”);%利用网络进行预测。dlnet = layer.Network;Z = predict(dlnet,X,X);条尺寸标签。Z = stripdims(Z);结束

因为预测函数只使用支持的函数万博1manbetxdlarray对象,定义落后的函数可选。获取支持的函数的列表万博1manbetxdlarray对象,看到dlarray支持的函数列表万博1manbetx

完成一层

查看完成的层类文件。

classdefresidualBlockLayer < nnet.layer.Layer示例自定义残留块层。属性(可学的)%层可学习参数%残留块。网络结束方法函数层= residualBlockLayer(numFilters,NameValueArgs)% layer = residualBlockLayer(numFilters)创建一个残差%块层与指定数量的过滤器。% layer = residualBlockLayer(numFilters,名称,值)指定%使用一个或多个名称-值对的附加选项%参数:'Stride' -卷积运算的步幅%(默认1)% ' incleskipvolution ' -包含卷积的标志%跳过连接%(默认为false)% 'Name' -层名称%(默认值")解析输入参数。参数numFilters NameValueArgs。Stride = 1 NameValueArgs。incleskipconvolution = false NameValueArgs。Name =结束stride = NameValueArgs.Stride;incleskipconvolution = namevalueargs . incleskipconvolution;name = NameValueArgs.Name;设置图层名称。层。的名字= name;设置层描述。描述=“残块带”+ numFilters +“滤镜,大步走”+步伐;如果incleskipconvolution description = description +,跳过卷积运算结束层。Description =描述;设置图层类型。层。类型=“剩余块”定义嵌套层图。layers = [convolution2dLayer(3,numFilters,“填充”“相同”“步”步,“名字”“conv1”) groupNormalizationLayer (所有渠道的“名字”“gn1”) reluLayer (“名字”“relu1”) convolution2dLayer (3 numFilters“填充”“相同”“名字”“conv2”) groupNormalizationLayer (“channel-wise”“名字”“gn2”) additionLayer (2“名字”“添加”) reluLayer (“名字”“relu2”));lgraph = layerGraph(图层);添加跳过连接。如果incleskipconvolution layers = [convolution2dLayer(1,numFilters,“步”步,“名字”“convSkip”) groupNormalizationLayer (所有渠道的“名字”“gnSkip”));lgraph = addLayers(lgraph,layers);lgraph = connectLayers(lgraph,“gnSkip”“添加/ in2”);结束%转换为dlnetwork。dlnet = dlnetwork(lgraph,'Initialize',false);设置网络属性。层。Network = dlnet;结束函数Z = predict(layer, X)%在预测时间和转发输入数据通过层%输出结果。%的输入:% layer -向前传播的层% X -输入数据%输出:% Z -层正向函数的输出将输入数据转换为格式化的dlarray。X = dlarray(X,“SSCB”);%利用网络进行预测。dlnet = layer.Network;Z = predict(dlnet,X,X);条尺寸标签。Z = stripdims(Z);结束结束结束

GPU的兼容性

如果转发层功能完全支持万博1manbetxdlarray对象,那么该层是GPU兼容的。否则,为了与GPU兼容,层函数必须支持类型的输入和返回输出万博1manbetxgpuArray(并行计算工具箱)

许多MATLAB内置函数支持万博1manbetxgpuArray(并行计算工具箱)而且dlarray输入参数。获取支持的函数的列表万博1manbetxdlarray对象,看到dlarray支持的函数列表万博1manbetx.有关在GPU上执行的函数列表,请参见在图形处理器上运行MATLAB函数(并行计算工具箱)要使用GPU进行深度学习,还必须有支持的GPU设备。万博1manbetx有关支持的设备的信息,请参见万博1manbetxGPU支万博1manbetx持按版本划分(并行计算工具箱)有关在MATLAB中使用gpu的更多信息,请参见MATLAB中的GPU计算(并行计算工具箱)

在本例中,所用的MATLAB函数预测所有的支万博1manbetx持dlarray对象,所以该层是GPU兼容的。

检查层使用的有效性checkLayer

检查自定义层的层有效性residualBlockLayer使用checkLayer函数。

创建一个剩余块层的实例。要访问此层,请将此示例作为实时脚本打开。

numFilters = 64;图层= residualBlockLayer(numFilters)
Name: " Learnable Parameters Network: [1x1 dlnetwork] State Parameters没有属性。显示所有属性

检查层的有效性使用checkLayer函数。该层期望4-D数组输入,其中前三个维度对应于前一层输出的高度、宽度和通道数量,第四个维度对应于观测结果。指定典型的输入大小并设置“ObservationDimension”选项为4。

validInputSize = [56 56 64];validInputSize checkLayer(层,“ObservationDimension”4)
跳过GPU测试。没有找到兼容的GPU设备。跳过代码生成兼容性测试。要检查代码生成层的有效性,请指定“CheckCodegenCompatibility”和“ObservationDimension”选项。运行nnet.checklayer.TestLayerWithoutBackward .......... ........testlayerwithoutbackward __________测试总结:18通过,0失败,0不完整,10跳过。时间:8.1321秒。

该函数不会检测到该层的任何问题。

另请参阅

|||||

相关的话题