用keras、tensorflow和python编写这种奇特的NN体系结构

用keras、tensorflow和python编写这种奇特的NN体系结构,python,tensorflow,keras,neural-network,Python,Tensorflow,Keras,Neural Network,我试图让Keras训练一个多类分类模型,该模型可以在如下网络中编写: #create the n coefficients: coefficients = np.array([c0, c1, .... , cn]) coefficients = coefficients.reshape((1,1,n)) def f(x, x_pk): c = K.variable(coefficients) #shape (1, 1, n) out = (x - x_pk) / c

我试图让Keras训练一个多类分类模型,该模型可以在如下网络中编写:

#create the n coefficients:
coefficients = np.array([c0, c1, .... , cn])
coefficients = coefficients.reshape((1,1,n))

def f(x, x_pk):

    c = K.variable(coefficients) #shape (1, 1, n)
    out = (x - x_pk) / c
    return K.exp(out)
唯一一组可训练的参数是那些,其余的都给出了。函数fi是常用数学函数的组合(例如,Sigma表示对前面的项求和,softmax表示常用函数)(x1,x2,…xn)是序列或测试集的元素,是已选择的原始数据的特定子集

模型更深入:

具体地说,给定(x_1,x_2,…,x_n)列车或测试集中的输入,网络将评估

其中fi是给定的数学函数,是原始数据特定子集的行,系数是我想要训练的参数。 当我使用keras时,我希望它在每一行中添加一个偏差项

在上述评估之后,我将应用softmax层(上面的m行中的每一行都是将作为softmax功能输入的数字)

最后,我想编译模型并像往常一样运行model.fit

问题是我无法将表达式转换为keras sintax

我的尝试:

在上面的网络划痕之后,我首先尝试在顺序模型中考虑窗体的每一个表达式作为lambda层,但是我能得到的最好的结果是一个稠密层与线性激活的组合(这将起到一个行参数的作用):后跟一个Lambda层,输出一个不需要求和的向量,如下所示:

model = Sequential()
#single row considered:
model.add(Lambda(lambda x:  f_fixedRow(x), input_shape=(nFeatures,))) 
#parameters set after lambda layer to get (a1*f(x1,y1),...,an*f(xn,yn)) and not (f(a1*x1,y1),...,f(an*xn,yn))
model.add(Dense(nFeatures, activation='linear')) 

#missing summation: sum(x)
#missing evaluation of f in all other rows

model.add(Dense(classes,activation='softmax',trainable=False)) #should get all rows
model.compile(optimizer='sgd',
              loss='categorical_crossentropy',
              metrics=['accuracy'])
此外,我还必须在lambda函数调用中定义参数已经固定的函数(因为lambda函数只能将输入层作为变量):

我设法用tensorflow(一行中的工作元素)编写了f函数,尽管这可能是代码中出现问题的根源(而且上面的解决方法似乎不自然)

我还认为,如果我能在上述尝试中正确地编写向量的元素和,我可以用keras函数API以并行方式重复相同的过程,然后根据需要将每个并行模型的输出插入到softmax函数中

我考虑的另一种方法是训练参数,使它们的自然矩阵结构在中保持可见,也许写一个矩阵Lambda层,但我找不到与此想法相关的任何东西


无论如何,我不确定在keras中使用该模型的好方法是什么,可能我遗漏了一个要点,因为参数的编写方式不标准,或者缺乏tensorflow的经验。欢迎提供任何建议。

对于这个答案,
f
是一个元素操作的张量函数,这一点很重要(没有迭代)。这相当容易,只需检查

假设:

  • x_pk
    设置为常量,否则必须检查此解决方案
  • 函数
    f
    是元素式的(如果不是,请显示
    f
    以获得更好的代码)
您的模型需要
x_pk
作为张量输入

import keras.backend as K
from keras.layers import Input, Lambda, Activation
from keras.models import Model

#x_pk data
x_pk_numpy = select_X_pk_samples(x_train)
x_pk_tensor = K.variable(x_pk_numpy)

#number of rows in x_pk
m = len(x_pk_numpy)

#I suggest a fixed batch size for simplicity
batch = some_batch_size
首先,让我们研究一下将调用
x
x_pk
调用
f
的函数

def calculate_f(inputs): #inputs will be a list with x and x_pk
    x, x_pk = inputs

    #since f will work elementwise, let's replicate x and x_pk so they have equal shapes 
    #please explain f for better optimization

    # x from (batch, n) to (batch, m, n)
    x = K.stack([x]*m, axis=1)

    # x_pk from (m, n) to (batch, m, n)
    x_pk = K.stack([x_pk]*batch, axis=0)
        #a batch size of 1 could make this even simpler    
        #a variable batch size would make this more complicated
        #certain f functions could make this process unnecessary    

    return f(x, x_pk)
现在,与
密集
层不同,此公式使用的是
a_pk
元素相乘的权重。因此,我们需要一个自定义层:

class ElementwiseWeights(Layer):
    def __init__(self, **kwargs):
        super(ElementwiseWeights, self).__init__(**kwargs)

    def build(self, input_shape):
        weight_shape = (1,) + input_shape[1:] #shape (1, m, n)

        self.kernel = self.add_weight(name='kernel', 
                                  shape=weight_shape,
                                  initializer='uniform',
                                  trainable=True)

        super(ElementwiseWeights, self).build(input_shape)  

    def compute_output_shape(self,input_shape):
        return input_shape

    def call(self, inputs):
        return self.kernel * inputs
现在,让我们构建我们的函数式API模型:

#x_pk model tensor input
x_pk = Input(tensor=x_pk_tensor) #shape (m, n)

#x usual input with fixed batch size
x = Input(batch_shape=(batch,n))  #shape (batch, n)

#calculate F
out = Lambda(calculate_f)([x, xp_k]) #shape (batch, m, n)

#multiply a_pk
out = ElementwiseWeights()(out) #shape (batch, m, n)

#sum n elements, keep m rows:
out = Lambda(lambda x: K.sum(x, axis=-1))(out) #shape (batch, m)

#softmax
out = Activation('softmax')(out) #shape (batch,m)
继续此模型并完成所需操作:

model = Model([x, x_pk], out)
model.compile(.....)
model.fit(x_train, y_train, ....) #perhaps you might need .fit([x_train], ytrain,...)

编辑功能
f
建议的
f
如下:

#create the n coefficients:
coefficients = np.array([c0, c1, .... , cn])
coefficients = coefficients.reshape((1,1,n))

def f(x, x_pk):

    c = K.variable(coefficients) #shape (1, 1, n)
    out = (x - x_pk) / c
    return K.exp(out)
  • f
    将接受形状
    (批次,1,n)
    x
    ,而不使用
    计算函数中使用的
    堆栈
  • 或者可以接受形状为(1,m,n)
    x_pk
    ,允许不同的批量大小

但我不确定这两种形状是否可能同时存在。测试这可能很有趣。

请帮助我了解这些:
1-
您打算如何选择特定的
x\u pk
2-
每行
x\u pk的权重是否真的不同?(在这种情况下,您必须始终选择具有相同大小的子集)。@DanielMöller 1-在此阶段已经定义了x_pk集(运行特定算法)。2-是的,每行都有一组不同的权重(所有权重大小相同)因此,在这个公式中,我们有一个参数a_pk的矩阵。
f
函数在答案的最后一部分:)我无法使计算函数工作。假设我们想要f(x_I,x_I^p_k)=exp((x_I-x_I^p_k)/c_I),其中c_I是一个常数,取决于x_1的指数I,…,x_n。为了返回f,我应该如何写f(x,x_pk)在计算f实现中?谢谢你,请在你的问题中添加
f
的精确公式,就像你对其余公式所做的那样。我承认我不理解你所说的
f(x_I,x_I^p_k)是什么意思
。我在问题中添加了f的公式,并对网络映像进行了编辑,以允许每个I的f函数不同(从而使示例更合适)