如果深度学习工具箱™没有为您的分类或回归问题提供所需的层,那么您可以使用此示例作为指导定义自己的自定义层。有关内置层的列表,请参见深度学习层列表.
要创建一个自定义层来定义一个层图,你可以声明一个dlnetwork
对象中的可学习参数属性(可学的)
部分的层定义。这种方法被称为网络的作文.你可以使用网络组合:
创建一个单独的自定义层,表示可学习层的块,例如,残留块。
创建具有控制流的网络,例如,具有可以根据输入数据动态更改的部分的网络。
创建一个具有循环的网络,例如,一个具有将输出反馈回自身的部分的网络。
对于同时具有可学习参数和状态参数的嵌套网络,例如具有批处理归一化或LSTM层的网络,在属性(可学习的,状态)
部分的层定义。
有关更多信息,请参见深度学习网络构成.
这个例子展示了如何创建一个表示残留块的自定义层。自定义层residualBlockLayer
包含可学习的层块,由卷积、组归一化、ReLU和添加层组成,还包括跳过连接和在跳过连接中的可选卷积层和组归一化层。该层有一个单独的输入,作为每个分支的输入使用两次。此图突出显示了剩余块结构。
要定义自定义深度学习层,您可以使用本例中提供的模板,该模板将带您完成以下步骤:
给图层命名——给图层命名以便在MATLAB中使用®.
声明层属性——指定层的属性,包括可学习参数和状态参数。
创建一个构造函数(可选)——指定如何构造这个层并初始化它的属性。如果没有指定构造函数,则在创建时,软件将初始化的名字
,描述
,类型
属性与[]
并设置层输入和输出的数量为1。
创建前向函数——指定数据在预测时和训练时如何通过层(前向传播)向前传递。
创建reset state功能(可选)-指定重置状态参数的方式。
创建反向函数(可选)——指定损失对输入数据和可学习参数的导数(反向传播)。如果没有指定向后函数,则向前函数必须支持万博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%的状态参数。在这里定义层向后函数。结束结束结束
首先,给图层起一个名字。在类文件的第一行中,替换现有的名称myLayer
与residualBlockLayer
.
classdefresidualBlockLayer < nnet.layer.Layer...结束
接下来,将myLayer
构造函数的第一个函数方法
Section),这样它就有了与图层相同的名称。
方法函数layer = residualBlockLayer()…结束...结束
将图层类文件保存在一个名为residualBlockLayer.m
.文件名必须与层名匹配。要使用该层,必须将文件保存在当前文件夹或MATLAB路径上的文件夹中。
中声明层属性属性
类中列出可学习参数,并声明这些参数属性(可学的)
部分。
默认情况下,自定义中间层具有这些属性。中不要声明这些属性属性
部分。
财产 | 描述 |
---|---|
的名字 |
层名,指定为字符向量或字符串标量。为层 数组输入时,trainNetwork ,assembleNetwork ,layerGraph ,dlnetwork 函数自动为层分配名称的名字 设置为” . |
描述 |
层的一行描述,指定为字符串标量或字符向量。当该层显示在 如果不指定层描述,则软件显示层类名称。 |
类型 |
层的类型,指定为字符向量或字符串标量。的价值 如果不指定层类型,则软件显示层类名称。 |
NumInputs |
层的输入数,指定为正整数。如果您不指定此值,那么软件将自动设置NumInputs 的名字的数量InputNames .缺省值为1。 |
InputNames |
输入层的名称,指定为字符向量的单元格数组。如果不指定此值和NumInputs 大于1,那么软件自动设置InputNames 来{“三机”,…,“客栈”} ,在那里N 等于NumInputs .默认值为{'在'} . |
NumOutputs |
层的输出数,指定为正整数。如果您不指定此值,那么软件将自动设置NumOutputs 的名字的数量OutputNames .缺省值为1。 |
OutputNames |
输出层的名称,指定为字符向量的单元格数组。如果不指定此值和NumOutputs 大于1,那么软件自动设置OutputNames 来{着干活,…,“outM”} ,在那里米 等于NumOutputs .默认值为{“出”} . |
如果该层没有其他属性,则可以省略属性
部分。
提示
如果要创建具有多个输入的层,则必须设置NumInputs
或InputNames
层构造函数中的属性。如果要创建具有多个输出的层,则必须设置NumOutputs
或OutputNames
层构造函数中的属性。示例请参见定义具有多重输入的自定义深度学习层.
剩余块层不需要任何附加属性,因此可以删除属性
部分。
这个自定义层只有一个可学习的参数,剩余块本身指定为dlnetwork
对象。中声明此可学习参数属性(可学的)
节并调用参数网络
.
属性(可学的)%层可学习参数%残留块。网络结束
创建构造层并初始化层属性的函数。指定创建层所需的任何变量,作为构造函数的输入。
残差块层构造函数需要四个输入参数:
卷积滤波器的个数
跨步(可选,默认跨步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)
还输出更新后的状态参数状态
,在那里层
只有一个状态参数。
您可以调整具有多个输入、多个输出或多个状态参数的层的语法:
对于有多个输入的层,替换X
与X1,…,XN
,在那里N
是输入的数量。的NumInputs
属性必须匹配N
.
对于有多个输出的层,替换Z
与Z1,…,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,在那里h,w,c分别对应于图像的高度、宽度和通道数,和N是观察数。 | 4 |
三维图像 | h——- - - - - -w——- - - - - -d——- - - - - -c——- - - - - -N,在那里h,w,d,c分别为三维图像的高度、宽度、深度和通道数,和N是观察数。 | 5 |
向量序列 | c——- - - - - -N——- - - - - -年代,在那里c是序列特征的数量,N是观察的次数,和年代为序列长度。 | 2 |
二维图像序列 | h——- - - - - -w——- - - - - -c——- - - - - -N——- - - - - -年代,在那里h,w,c分别对应于图像的高度、宽度和通道数,N是观察的次数,和年代为序列长度。 | 4 |
三维图像序列 | h——- - - - - -w——- - - - - -d——- - - - - -c——- - - - - -N——- - - - - -年代,在那里h,w,d,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);结束结束结束
如果转发层功能完全支持万博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秒。
该函数不会检测到该层的任何问题。
setLearnRateFactor
|checkLayer
|setL2Factor
|getLearnRateFactor
|getL2Factor
|assembleNetwork