【问题标题】:Writing this exotic NN architecture with keras, tensorflow and python用 keras、tensorflow 和 python 编写这种奇特的 NN 架构
【发布时间】:2019-06-09 23:09:20
【问题描述】:

我正在尝试让 Keras 训练一个多类分类模型,该模型可以写在这样的网络中:

唯一可训练的参数集是,其余的都给出。函数 fi 是常用数学函数的组合(例如 .Sigma 代表对前面的项求和,softmax 是常用函数。 (x1,x2,...xn) 是训练集或测试集的元素,@ 987654330@ 是已选择的原始数据的特定子集。

更深入的模型:

具体来说,给定 (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 函数只能将输入层作为变量):

def f_fixedRow(x):
   #picking a particular row (as a vector) to evaluate f in (f works element-wise)
   y=tf.constant(value=x[0,:],dtype=tf.float32) 
   return f(x,y)

我设法用 tensorflow 编写了 f 函数(按元素连续工作),尽管这可能是我的代码中出现问题的原因(并且上述解决方法似乎不自然)。

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

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

无论如何,我不确定在 keras 中使用此模型的好方法是什么,也许由于参数的编写方式不标准或缺乏 tensorflow 经验,我错过了重要的一点。欢迎提出任何建议。

【问题讨论】:

  • 请帮我解决这些问题:1 - 你打算如何选择特定的x_pk 集合? 2 - a_pk 每行x_pk 的权重真的不同吗? (在这种情况下,您必须始终选择具有相同大小的子集)。
  • @DanielMöller 1- x_pk 的集合已在此阶段定义(运行特定算法)。 2- 是的,每一行都有一组不同的权重(大小都相同),因此在这个公式中,我们有一个参数矩阵 a_pk。
  • f 函数在答案的最后一部分:)

标签: python tensorflow keras neural-network


【解决方案1】:

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

假设:

  • x_pk 集是常量,否则必须审查此解决方案。
  • 函数f 是元素级的(如果不是,请显示f 以获得更好的代码)

您的模型需要x_pk 作为张量输入。您应该在 功能 API 模型中做到这一点。

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

首先让我们处理将xx_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)

现在,与Dense 层不同,此公式使用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 将接受形状为(batch, 1, n)x,而calculate_f 函数中没有使用stack
  • 或者可以接受形状为(1, m, n)x_pk,允许可变批量大小。

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

【讨论】:

  • 我无法让 calculate_f 函数工作。假设我们想要 f(x_i,x_i^p_k)=exp((x_i-x_i^p_k)/c_i),其中 c_i 是一个常数,取决于 x_1,...,x_n 的索引 i。我应该如何编写 f 以便在 calculate_f 实现中返回 f(x, x_pk) ?谢谢
  • 请在您的问题中添加f 的确切公式,就像您对其余公式所做的那样。我承认我不明白你所说的 f(x_i,x_i^p_k) 是什么意思。
  • 我在问题中添加了 f 的公式并编辑了网络图像以允许 f 函数对于每个 i 都不同(以便使示例适合)
猜你喜欢
  • 2018-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-13
  • 2017-12-24
  • 2011-06-20
  • 2016-10-21
相关资源
最近更新 更多