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 向keras模型添加预处理层并设置张量值 如何最好地将预处理层(例如,减去平均值和除以STD)添加到一个KARAS(V2.0.5)模型中,这样模型就可以完全独立地包含在部署中(可能在C++环境中)。我试过: def getmodel(): model = Sequential() mean_tensor = K.placeholder(shape=(1,1,3), name="mean_tensor") std_tensor = K.placeholder(shape=(1,1,3), name="std_tensor") preproc_layer = Lambda(lambda x: (x - mean_tensor) / (std_tensor + K.epsilon()), input_shape=im_shape) model.add(preproc_layer) # Build the remaining model, perhaps set weights, ... return model_Python_Tensorflow_Deep Learning_Keras_Keras Layer - Fatal编程技术网

Python 向keras模型添加预处理层并设置张量值 如何最好地将预处理层(例如,减去平均值和除以STD)添加到一个KARAS(V2.0.5)模型中,这样模型就可以完全独立地包含在部署中(可能在C++环境中)。我试过: def getmodel(): model = Sequential() mean_tensor = K.placeholder(shape=(1,1,3), name="mean_tensor") std_tensor = K.placeholder(shape=(1,1,3), name="std_tensor") preproc_layer = Lambda(lambda x: (x - mean_tensor) / (std_tensor + K.epsilon()), input_shape=im_shape) model.add(preproc_layer) # Build the remaining model, perhaps set weights, ... return model

Python 向keras模型添加预处理层并设置张量值 如何最好地将预处理层(例如,减去平均值和除以STD)添加到一个KARAS(V2.0.5)模型中,这样模型就可以完全独立地包含在部署中(可能在C++环境中)。我试过: def getmodel(): model = Sequential() mean_tensor = K.placeholder(shape=(1,1,3), name="mean_tensor") std_tensor = K.placeholder(shape=(1,1,3), name="std_tensor") preproc_layer = Lambda(lambda x: (x - mean_tensor) / (std_tensor + K.epsilon()), input_shape=im_shape) model.add(preproc_layer) # Build the remaining model, perhaps set weights, ... return model,python,tensorflow,deep-learning,keras,keras-layer,Python,Tensorflow,Deep Learning,Keras,Keras Layer,然后,在其他地方设置模型的平均值/标准。我发现该函数,因此尝试了以下操作: m = getmodel() mean, std = get_mean_std(..) graph = K.get_session().graph mean_tensor = graph.get_tensor_by_name("mean_tensor:0") std_tensor = graph.get_tensor_by_name("std_tensor:0") K.set_value(mean_tensor, m

然后,在其他地方设置模型的平均值/标准。我发现该函数,因此尝试了以下操作:

m = getmodel()
mean, std = get_mean_std(..)

graph = K.get_session().graph
mean_tensor = graph.get_tensor_by_name("mean_tensor:0")
std_tensor = graph.get_tensor_by_name("std_tensor:0")

K.set_value(mean_tensor, mean)
K.set_value(std_tensor, std)
但是,
设置_值
在以下情况下失败:

AttributeError: 'Tensor' object has no attribute 'assign'
因此,
set_value
不能像(有限的)文档所建议的那样工作。正确的方法是什么?获取TF会话,用(会话)将所有培训代码包装在一个
中,然后使用feed\u dict?我本以为会有一种本地的keras方法来设置张量值

我没有使用占位符,而是尝试使用
K.variable
K.constant
设置模型构造的平均值/std:

mean_tensor = K.variable(mean, name="mean_tensor")
std_tensor = K.variable(std, name="std_tensor")
这避免了任何
设置值
问题。虽然我注意到,如果我尝试训练该模型(我知道这不是特别有效,因为您正在对每个图像进行归一化),它可以工作,但在第一个历元结束时,处理程序失败,出现了非常深的堆栈跟踪:

...
File "/Users/dgorissen/Library/Python/2.7/lib/python/site-packages/keras/models.py", line 102, in save_model
  'config': model.get_config()
File "/Users/dgorissen/Library/Python/2.7/lib/python/site-packages/keras/models.py", line 1193, in get_config
  return copy.deepcopy(config)
File "/usr/local/Cellar/python/2.7.12_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 163, in deepcopy
  y = copier(x, memo)
...
File "/usr/local/Cellar/python/2.7.12_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 190, in deepcopy
  y = _reconstruct(x, rv, 1, memo)
File "/usr/local/Cellar/python/2.7.12_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 343, in _reconstruct
  y.__dict__.update(state)
AttributeError: 'NoneType' object has no attribute 'update'
更新1:

我也尝试了不同的方法。按照正常方式训练一个模型,然后只需预先准备第二个进行预处理的模型:

# Regular model, trained as usual
model = ...

# Preprocessing model
preproc_model = Sequential()
mean_tensor = K.constant(mean, name="mean_tensor")
std_tensor = K.constant(std, name="std_tensor")
preproc_layer = Lambda(lambda x: (x - mean_tensor) / (std_tensor + K.epsilon()),
                       input_shape=im_shape, name="normalisation")
preproc_model.add(preproc_layer)

# Prepend the preprocessing model to the regular model    
full_model = Model(inputs=[preproc_model.input],
              outputs=[model(preproc_model.output)])

# Save the complete model to disk
full_model.save('full_model.hdf5')
在调用
save()
之前,这似乎都是有效的,调用失败时会出现与上面相同的深堆栈跟踪。 也许问题出在
Lambda
层上,但从另一个角度来看,它似乎应该正确地序列化

因此,总体而言,我如何在不影响序列化(并导出到pb)能力的情况下将归一化层附加到keras模型

我相信你可以通过直接下载到TF(例如,或使用)来让它工作,但你会认为直接在keras中是可能的

更新2:

因此,我发现通过这样做可以避免深层堆栈跟踪

def foo(x):
    bar = K.variable(baz, name="baz")
    return x - bar
因此,在函数内部定义
bar
,而不是从外部范围捕获

然后我发现我可以保存到磁盘,但无法从磁盘加载。围绕这一点,有一系列github问题。我使用中指定的解决方法将所有变量作为参数传入,这样就可以保存和加载

以为我就快到了,我继续使用上面更新1中的方法,将一个预处理模型堆叠在一个经过训练的模型前面。 这会导致
模型未编译
错误。解决了这些问题,但最终我始终未能实现以下目标:

  • 建立和训练一个模型
  • 将其保存到磁盘
  • 加载它,预处理模型
  • 将堆叠模型作为冻结pb文件导出到磁盘
  • 从磁盘加载冻结的pb
  • 将其应用于某些看不见的数据
我得到了一个没有错误的点,但无法使归一化张量传播到冻结的pb。在这方面花了太多时间后,我放弃了,转而采用不那么优雅的方法:

  • 从一开始就在模型中使用预处理操作构建模型,但设置为无操作(平均值=0,标准值=1)
  • 对模型进行培训,建立一个相同的模型,但这次使用适当的平均值/标准值
  • 转移重量
  • 将模型导出并冻结到pb
所有这些现在都完全按照预期工作。训练的开销很小,但对我来说可以忽略不计

仍然无法弄清楚如何在keras中设置张量变量的值(不引发
assign
exception),但现在可以不用它

我会接受@Daniel的回答,因为这让我走上了正确的方向

相关问题:


创建变量时,必须为其指定“值”,而不是形状:

mean_tensor = K.variable(mean, name="mean_tensor")
std_tensor = K.variable(std, name="std_tensor")
现在,在Keras中,您不必处理会话、图形和诸如此类的事情。您只能使用层,在Lambda层(或损失函数)中,您可以使用张量

对于Lambda层,我们需要一个更复杂的函数,因为在计算之前形状必须匹配。由于我不知道
im_shape
,我认为它有3个维度:

def myFunc(x):

    #reshape x in a way it's compatible with the tensors mean and std:
    x = K.reshape(x,(-1,1,1,3)) 
        #-1 is like a wildcard, it will be the value that matches the rest of the given shape.     
        #I chose (1,1,3) because it's the same shape of mean_tensor and std_tensor

    result = (x - mean_tensor) / (std_tensor + K.epsilon())

    #now shape it back to the same shape it was before (which I don't know)    
    return K.reshape(result,(-1,im_shape[0], im_shape[1], im_shape[2]))
        #-1 is still necessary, it's the batch size
现在我们创建Lambda层,考虑到它还需要一个输出形状(由于您的自定义操作,系统不一定知道输出形状)

在此之后,只需编译模型并对其进行训练。(通常使用
model.compile(…)
model.fit(…)


如果要包括所有内容,包括函数内部的预处理,也可以:

def myFunc(x):

    mean_tensor = K.mean(x,axis=[0,1,2]) #considering shapes of (size,width, heigth,channels)    
    std_tensor = K.std(x,axis=[0,1,2])

    x = K.reshape(x, (-1,3)) #shapes of mean and std are (3,) here.    
    result = (x - mean_tensor) / (std_tensor + K.epsilon())

    return K.reshape(result,(-1,width,height,3))

现在,所有这些都是模型中的额外计算,并且将消耗处理。
最好只做模型之外的事情。首先创建预处理的数据并将其存储,然后创建没有此预处理层的模型。这样你可以得到一个更快的模型。(如果您的数据或模型太大,这可能很重要)。

如果操作是固定的(无需学习),并且在第一层之前,可能您应该在将数据提供给模型之前直接在输入数据中执行操作。这将使您在培训期间从额外的不必要的计算中节省处理成本。
mean_tensor
std_tensor
是否具有与X相同的“批量大小”?这会大大改变答案…@Daniel这是一个稍微简化的场景。我现在忽略了培训的开销,但是你可以想象将这一层粘贴到即将投入生产的模型上,你会遇到同样的问题。如果将张量定义为常数,则不会出现形状不匹配错误。否则,我会得到如上所述的无属性错误。我正在尝试提出一个常规的Keras解决方案,但我需要形状来理解发生了什么。它很可能不起作用,因为
x-平均张量
。如果他们没有
def myFunc(x):

    mean_tensor = K.mean(x,axis=[0,1,2]) #considering shapes of (size,width, heigth,channels)    
    std_tensor = K.std(x,axis=[0,1,2])

    x = K.reshape(x, (-1,3)) #shapes of mean and std are (3,) here.    
    result = (x - mean_tensor) / (std_tensor + K.epsilon())

    return K.reshape(result,(-1,width,height,3))