Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 多输出的张量流自记多项式模型_Python_Tensorflow_Machine Learning_Keras_Tensor - Fatal编程技术网

Python 多输出的张量流自记多项式模型

Python 多输出的张量流自记多项式模型,python,tensorflow,machine-learning,keras,tensor,Python,Tensorflow,Machine Learning,Keras,Tensor,我有一个tensorflow模型,它的输出对应于多个多项式的系数。请注意,我的模型实际上有另一组输出(多输出),但下面我只是通过返回多项式系数之外的输入来模拟这一点 在训练模型的过程中,我遇到了很多麻烦,与张量形状有关。我已经验证了该模型能够预测样本输入,并且损失函数对样本输出有效。但是,在训练期间,它会立即抛出一个错误(见下文) 对于每个输入,该模型接受固定嵌入大小的输入,并输出次数2多项式的系数。例如,单个输入上的输出可以如下所示: [array([[[1, 2, 3],

我有一个tensorflow模型,它的输出对应于多个多项式的系数。请注意,我的模型实际上有另一组输出(多输出),但下面我只是通过返回多项式系数之外的输入来模拟这一点

在训练模型的过程中,我遇到了很多麻烦,与张量形状有关。我已经验证了该模型能够预测样本输入,并且损失函数对样本输出有效。但是,在训练期间,它会立即抛出一个错误(见下文)

对于每个输入,该模型接受固定嵌入大小的输入,并输出次数
2
多项式的系数。例如,单个输入上的输出可以如下所示:

[array([[[1, 2,  3],
        [ 4,  5,  6]]]),
[...]]
对应于多项式
[1*x^2+2*x+3,4*x^2+5*x+6]
。注意,我已经隐藏了第二个输出

我注意到
tf.math.polyval
需要一个系数列表,这使得AutoGrad不可靠。所以,我用纯张量实现了我自己版本的Horner算法

import numpy as np
import tensorflow as tf
import logging
import tensorflow.keras as K

@tf.function
def tensor_polyval(coeffs, x):
    """
    Calculates polynomial scalars from tensor of polynomial coefficients
    Tensorflow tf.math.polyval requires a list coeff, which isn't compatible with autograd

    # Inputs:
      - coeffs (NxD Tensor): each row of coeffs corresponds to r[0]*x^(D-1)+r[1]*x^(D-2)...+r[D]
      - x: Scalar!

    # Output:
      - r[0]*x^(D-1)+r[1]*x^(D-2)...+r[D] for row in coeffs
    """
    p = coeffs[:, 0]
    for i in range(1,coeffs.shape[1]):
      tf.autograph.experimental.set_loop_options(
        shape_invariants=[(p, tf.TensorShape([None]))])
      c = coeffs[:, i]
      p = tf.add(c, tf.multiply(x, p))
    return p

@tf.function
def coeffs_to_poly(coeffs, n):
    # Converts a NxD array of coefficients to N evaluated polynomials at x=n
    return tensor_polyval(coeffs, tf.convert_to_tensor(n))
下面是我的模型、损失函数和训练程序的超级简化示例:

def model_init(embedDim=8, polyDim=2,terms=2):
  input = K.Input(shape=(embedDim,))
  x = K.layers.Reshape((embedDim,))(input)
  aCoeffs = K.layers.Dense((polyDim+1)*terms, activation='tanh')(x)
  aCoeffs = K.layers.Reshape((terms, polyDim+1))(aCoeffs)

  model = K.Model(inputs=input, outputs=[aCoeffs, input])
  return model

def get_random_batch(batch, embedDim, dtype='float64'):
  x = np.random.randn(batch, embedDim).astype(dtype)
  y = np.array([1. for i in range(batch)]).astype(dtype)
  return [x, 
          y]

@tf.function
def test_loss(y_true, y_pred, dtype=dataType):
  an = tf.vectorized_map(lambda y_p: coeffs_to_poly(y_p[0],
                                                    tf.constant(5,dtype=dataType)),
                         y_pred)
  
  return tf.reduce_mean(tf.reduce_mean(an,axis=-1))

embedDim=8
polyDim=2
terms=2
dataType = 'float64'
tf.keras.backend.set_floatx(dataType)

model = model_init(embedDim, polyDim, terms)

XTrain, yTrain  = get_random_batch(batch=128,
                                  embedDim=embedDim)

# Init Model
LR = 0.001
loss = test_loss
epochs = 5
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=LR), loss=loss)

hist = model.fit(XTrain,
        yTrain,
        batch_size=4,
        epochs=epochs,
        max_queue_size=10, workers=2, use_multiprocessing=True)
我得到的错误与
tensor\u polyval
函数有关:

    <ipython-input-15-f96bd099fe08>:3 test_loss  *
        an = tf.vectorized_map(lambda y_p: coeffs_to_poly(y_p[0],
    <ipython-input-5-7205207d12fd>:23 coeffs_to_poly  *
        return tensor_polyval(coeffs, tf.convert_to_tensor(n))
    <ipython-input-5-7205207d12fd>:13 tensor_polyval  *
        p = coeffs[:, 0]
    ...
    ValueError: Index out of range using input dim 1; input has only 1 dims for '{{node strided_slice}} = StridedSlice[Index=DT_INT32, T=DT_DOUBLE, begin_mask=1, ellipsis_mask=0, end_mask=1, new_axis_mask=0, shrink_axis_mask=2](coeffs, strided_slice/stack, strided_slice/stack_1, strided_slice/stack_2)' with input shapes: [3], [2], [2], [2] and with computed input tensors: input[3] = <1 1>.
它运行得很好

test\u loss
函数中,具体地说,我只是指第一个输出,通过
y\u p[0]
。它尝试在
n=5时计算多项式的值,然后输出所有值的平均值(同样,这只是模拟代码)。据我所知,
y\u p[1]
将引用第二个输出(在本例中,是输入的副本)。我认为
tf.vectoriazed_map
应该在模型批处理的所有输出中运行,但它似乎在切割一个额外的维度


我注意到,如果我删除输出
,在模型中输入
(使其成为单个输出),并在
测试中将
y\u p[0]
更改为
y\u p
,代码就会训练。我不知道为什么在添加额外的输出时它会被破坏,因为我对tf.vectoriazed_map的理解意味着它分别作用于列表的每个元素
y_pred
如果我们需要单个损失函数来接收多个输出,也许我们可以将它们连接在一起形成一个输出

在这种情况下:

  • 对模型结构的更改,我们在此打包输出:
  • def model_init(embeddedim=8,polyDim=2,terms=2):
    输入=K.输入(形状=(嵌入尺寸,))
    x=K.layers.重塑((嵌入尺寸,))(输入)
    aCoeffs=K.layers.density((polyDim+1)*项,活化=tanh')(x)
    #打包两个输出,如果它们的形状不是batch*K,则添加展平层
    输出=K.layers.Concatenate()([aCoeffs,input])
    模型=K.模型(输入=输入,输出=输出)
    model.summary()
    回归模型
    
  • 对损失函数的更改,我们在这里解包输出:
  • #损失函数需要知道这些
    polyDim=2
    术语=2
    @功能
    def测试丢失(y_true,y_pred,dtype=数据类型):
    “”“平坦输出的损失函数。”“”
    #解包多个输出
    偏移量=(多边形尺寸+1)*术语
    aCoeffs=tf.重塑(y_pred[:,:offset],-1,terms,polyDim+1])
    输入=y_pred[:,偏移量:]
    打印(aCoeffs,输入)
    #对两个未打包的输出执行一些操作,如下所示
    an=tf.vectoriated\u映射(
    lambda y_p:coefs_to_poly(y_p,tf.constant(5,dtype=dataType)),
    ACOEFS)
    返回tf.reduce_平均值(tf.reduce_平均值(an,轴=-1))
    
    请注意,损失函数依赖于输出的原始形状的知识来恢复它们。考虑子类<代码> tf.kas。丢失。丢失<代码> < /p> 对任何人来说,只需对多重损失进行不同的损失:

  • 定义两个输出的损耗函数
  • @tf.function
    def测试丢失(y_true,y_pred,dtype=数据类型):
    “”“输出1的丢失函数”
    (仅将y_p[0]更改为y_p)”
    an=tf.vectoriated\u映射(
    lambda y_p:coefs_to_poly(y_p,tf.constant(5,dtype=dataType)),
    y_pred)
    返回tf.reduce_平均值(tf.reduce_平均值(an,轴=-1))
    @功能
    def伪丢失(y_真,y_pred,dtype=数据类型):
    “”“输出2(即输入)的丢失功能,用于调试
    最好使用1.2345英寸的0英寸
    返回tf.常量(1.2345,数据类型)
    
  • 更改为
    模型。编译
  • model.compile(optimizer=tf.keras.optimizers.Adam(learning\u rate=LR),loss=[test\u loss,dummy\u loss])
    
    使用多个输出会增加复杂性。也许值得尝试删除第二个输出(即输入)并对其进行测试。对于多个输出和一个损失函数,Keras计算每个输出的损失并将其相加。这与使用预测结果手动调用损失函数不同,因此预期会有不同的结果(错误与成功)。@MeowCat2012:谢谢您的建议。因此,真正令人沮丧的是,当我从模型中删除输出
    ,输入
    ,并将
    y\u p[0]
    更改为
    y\u p
    时,它就起作用了。我将把这个添加到我的帖子中。我不知道为什么在添加额外输出时它会断开如果您仍然需要第二个输出,请参考新添加的答案~感谢您的快速响应!但在我的例子中,我的(实际)损失函数将取决于每个输出。在这种情况下,这当然是可能的?啊,但似乎凯拉斯不支持我想要的。所以我可能需要将输出连接成一个平坦张量,然后在损耗计算过程中对其进行重塑。这个答案似乎是说一个损耗中的多个输出是不可能的:这意味着你需要一个损耗函数来处理多个输出(而不是单独处理)?我会对输出进行展平和压缩,所以只有一个输出。我可以在损失函数中拆分和重塑它们。丑陋但有效的方法
    test_loss(yTrain[0:5],
              model.predict(XTrain[0:5]),
              dtype=dataType)