如何在NeuPy或Theano中实现一个自定义的激活函数(通过梯度下降调整均值和方差的RBF核),以便在NeuPy中使用?
{简要背景:梯度下降适用于网络中的所有参数。我希望创建一个包含优化特征参数的专用特征空间,以便NeuPy}
我认为我的问题在于参数的创建、它们的尺寸以及它们如何相互连接。
主要关注的函数。
激活函数类
class RBF(layers.ActivationLayer): def initialize(self): super(RBF, self).initialize() self.add_parameter(name='mean', shape=(1,), value=init.Normal(), trainable=True) self.add_parameter(name='std_dev', shape=(1,), value=init.Normal(), trainable=True) def output(self, input_value): return rbf(input_value, self.parameters)
RBF函数
def rbf(input_value, parameters): K = _outer_substract(input_value, parameters['mean']) return np.exp(- np.linalg.norm(K)/parameters['std_dev'])
用于调整形状的函数?
def _outer_substract(x, y): return (x - y.T).T
非常感谢您的帮助,这将为如何定制NeuPy网络提供很好的见解。至少可以说,文档在某些方面需要改进…
回答:
当层改变输入变量的形状时,它必须通知后续层关于此变化的情况。为此,它必须具有自定义的output_shape
属性。例如:
from neupy import layersfrom neupy.utils import as_tupleimport theano.tensor as Tclass Flatten(layers.BaseLayer): """ 对neupy库中的Reshape层的轻微修改: https://github.com/itdxer/neupy/blob/master/neupy/layers/reshape.py """ @property def output_shape(self): # 输出特征的数量取决于输入形状 # 当层接收到形状为(10, 3, 4)的输入时 # 输出将为(10, 12)。第一个数字10定义了 # 样本数量,通常在传播过程中不需要更改 n_output_features = np.prod(self.input_shape) return (n_output_features,) def output(self, input_value): n_samples = input_value.shape[0] return T.reshape(input_value, as_tuple(n_samples, self.output_shape))
如果您在终端中运行它,您会看到它是有效的
>>> network = layers.Input((3, 4)) > Flatten()>>> predict = network.compile()>>> predict(np.random.random((10, 3, 4))).shape(10, 12)
在您的示例中,我可以看到几个问题:
rbf
函数没有返回theano表达式。在函数编译期间应该会失败- 像
np.linalg.norm
这样的函数如果不指定要计算范数的轴,将返回标量。
以下解决方案应该对您有用
import numpy as npfrom neupy import layers, initimport theano.tensor as Tdef norm(value, axis=None): return T.sqrt(T.sum(T.square(value), axis=axis))class RBF(layers.BaseLayer): def initialize(self): super(RBF, self).initialize() # 当参数的形状依赖于输入形状时,更加灵活 self.add_parameter( name='mean', shape=self.input_shape, value=init.Constant(0.), trainable=True) self.add_parameter( name='std_dev', shape=self.input_shape, value=init.Constant(1.), trainable=True) def output(self, input_value): K = input_value - self.mean return T.exp(-norm(K, axis=0) / self.std_dev)network = layers.Input(1) > RBF()predict = network.compile()print(predict(np.random.random((10, 1))))network = layers.Input(4) > RBF()predict = network.compile()print(predict(np.random.random((10, 4))))