Python Keras Conv2D自定义内核初始化
我需要使用权重初始化自定义Conv2D内核 W=a1b1+a2b2+…+anbn 其中W=要初始化的Conv2D层的自定义权重 a=随机权重张量,如Python Keras Conv2D自定义内核初始化,python,keras,conv-neural-network,Python,Keras,Conv Neural Network,我需要使用权重初始化自定义Conv2D内核 W=a1b1+a2b2+…+anbn 其中W=要初始化的Conv2D层的自定义权重 a=随机权重张量,如keras.backend.variable(np.random.uniform()),shape=(64,1,10) b=定义为keras.backend.constant(…),shape=(10,11,11)的固定基过滤器 W=K.sum(a[:,:,:,无,无]*b[无,无,无,:,:,:],轴=2)#形状=(64,1,11,11) 我希望我
keras.backend.variable(np.random.uniform())
,shape=(64,1,10)
b=定义为keras.backend.constant(…)
,shape=(10,11,11)的固定基过滤器
W=K.sum(a[:,:,:,无,无]*b[无,无,无,:,:,:],轴=2)#形状=(64,1,11,11)
我希望我的模型更新“W”值,只更改“a”,同时保持“b”不变
我通过海关的“W”为
Conv2D(64,kernel\u size=(11,11),activation='relu',kernel\u初始值设定项=kernel\u init\u L1)(img)
其中kernel\u init\u L1
返回keras.backend.variable(K.reformate(w\u L1,(11,11,1,64))
问题:
我不确定这样做是否正确。是否可以在KERA中指定哪些是可培训的,哪些不是。我知道可以设置层trainable=True
,但我不确定权重
我认为实现是不正确的,因为无论是否使用自定义初始化,我的模型都会得到类似的结果
如果有人能指出我的方法中的任何错误或提供一种方法来验证它,那将是非常有帮助的 关于形状的警告:如果内核大小为
(11,11)
,并且假设有64个输入通道和1个输出通道,那么最终的内核形状必须是(11,11,64,1)
您可能应该选择a[None,None]
和b[:,:,:,None,None]
class CustomConv2D(Conv2D):
def __init__(self, filters, kernel_size, kernelB = None, **kwargs):
super(CustomConv2D, self).__init__(filters, kernel_size,**kwargs)
self.kernelB = kernelB
def build(self, input_shape):
#use the input_shape to calculate the shapes of A and B
#if needed, pay attention to the "data_format" used.
#this is an actual weight, because it uses `self.add_weight`
self.kernelA = self.add_weight(
shape=shape_of_kernel_A + (1,1), #or (1,1) + shape_of_A
initializer='glorot_uniform', #or select another
name='kernelA',
regularizer=self.kernel_regularizer,
constraint=self.kernel_constraint)
#this is an ordinary var that will participate in the calculation
#not a weight, not updated
if self.kernelB is None:
self.kernelB = K.constant(....)
#use the shape already containing the new axes
#in the original conv layer, this property would be the actual kernel,
#now it's just a var that will be used in the original's "call" method
self.kernel = K.sum(self.kernelA * self.kernelB, axis=2)
#important: the resulting shape should be:
#(kernelSizeX, kernelSizeY, input_channels, output_channels)
#the following are remains of the original code for "build" in Conv2D
#use_bias is True by default
if self.use_bias:
self.bias = self.add_weight(shape=(self.filters,),
initializer=self.bias_initializer,
name='bias',
regularizer=self.bias_regularizer,
constraint=self.bias_constraint)
else:
self.bias = None
# Set input spec.
self.input_spec = InputSpec(ndim=self.rank + 2,
axes={channel_axis: input_dim})
self.built = True
自定义图层提示 当您从零开始创建自定义图层(源自
图层
)时,您应该具有以下方法:
-这是创建者,在创建层的新实例时调用它。在这里,存储用户作为参数传递的值。(在Conv2D中,init将具有“过滤器”、“内核大小”等)\uuuuu init\uuuuuu(self,…parameters…)
-这是您应该创建权重的地方(所有可学习的变量都在这里创建,基于输入形状)build(self,input\u shape)
-在这里,您根据输入形状返回输出形状compute\u output\u shape(self,input\u shape)
-在这里您可以执行实际的图层计算调用(self,inputs)
Conv2D
派生出来的,所以一切都准备好了,我们所做的只是“更改”构建方法并替换Conv2D层的内核
有关自定义图层的详细信息:
conv层的
调用方法是。关于形状的警告:如果内核大小是(11,11)
,并且假设您有64个输入通道和1个输出通道,那么最终的内核形状必须是(11,11,64,1)
您可能应该选择a[None,None]
和b[:,:,:,None,None]
class CustomConv2D(Conv2D):
def __init__(self, filters, kernel_size, kernelB = None, **kwargs):
super(CustomConv2D, self).__init__(filters, kernel_size,**kwargs)
self.kernelB = kernelB
def build(self, input_shape):
#use the input_shape to calculate the shapes of A and B
#if needed, pay attention to the "data_format" used.
#this is an actual weight, because it uses `self.add_weight`
self.kernelA = self.add_weight(
shape=shape_of_kernel_A + (1,1), #or (1,1) + shape_of_A
initializer='glorot_uniform', #or select another
name='kernelA',
regularizer=self.kernel_regularizer,
constraint=self.kernel_constraint)
#this is an ordinary var that will participate in the calculation
#not a weight, not updated
if self.kernelB is None:
self.kernelB = K.constant(....)
#use the shape already containing the new axes
#in the original conv layer, this property would be the actual kernel,
#now it's just a var that will be used in the original's "call" method
self.kernel = K.sum(self.kernelA * self.kernelB, axis=2)
#important: the resulting shape should be:
#(kernelSizeX, kernelSizeY, input_channels, output_channels)
#the following are remains of the original code for "build" in Conv2D
#use_bias is True by default
if self.use_bias:
self.bias = self.add_weight(shape=(self.filters,),
initializer=self.bias_initializer,
name='bias',
regularizer=self.bias_regularizer,
constraint=self.bias_constraint)
else:
self.bias = None
# Set input spec.
self.input_spec = InputSpec(ndim=self.rank + 2,
axes={channel_axis: input_dim})
self.built = True
自定义图层提示
当您从零开始创建自定义图层(源自图层
)时,您应该具有以下方法:
\uuuuu init\uuuuuu(self,…parameters…)
-这是创建者,在创建层的新实例时调用它。在这里,存储用户作为参数传递的值。(在Conv2D中,init将具有“过滤器”、“内核大小”等)
build(self,input\u shape)
-这是您应该创建权重的地方(所有可学习的变量都在这里创建,基于输入形状)
compute\u output\u shape(self,input\u shape)
-在这里,您根据输入形状返回输出形状
调用(self,inputs)
-在这里您可以执行实际的图层计算
因为我们不是从零开始创建这个层,而是从Conv2D
派生出来的,所以一切都准备好了,我们所做的只是“更改”构建方法并替换Conv2D层的内核
有关自定义图层的详细信息:
conv层的调用方法是。但是,我的方法是否意味着只更新“a”值?我如何验证这一点?那么我如何控制在Keras中更新哪些参数?我怎样才能阻止“b”值的变化,从而使“W”中的变化只是由于“a”中的变化。据我所知,只能设置层trainable=False
我再次考虑了这一点,并删除了以前的注释。你说得对,只有“层”可以训练/不训练。要控制权重,必须创建自定义层并实现自定义“构建”方法。但是,我的方法是否意味着只更新“a”值?我如何验证这一点?那么我如何控制在Keras中更新哪些参数?我怎样才能阻止“b”值的变化,从而使“W”中的变化只是由于“a”中的变化。据我所知,只能设置层trainable=False
我再次考虑了这一点,并删除了以前的注释。你说得对,只有“层”可以训练/不训练。要控制权重,必须创建自定义层并实现自定义“构建”方法。非常感谢。我会试试这个。:)您还可以给我一些关于call()
函数的建议吗?这是我第一次实现自定义Keras层。我需要实现Conv2D功能还是调用Conv2D层功能?不,您只需要这些。查看答案中的更新。感谢更新;真的帮了大忙。还有两个问题:1。我使用层作为l1=CustConv2D(filters=64,kernel\u size=(11,11),kernelA=None,kernelB=basic\u l1,activation='relu')(img)
\img\u shape=(28,28,1),但我得到的输出是(None,28,28,1)
,而不是(None,18,18,1)
2。我得到ValueError:一个操作有