如何在Keras中加快具有自定义损失功能的模型的训练?

三角洲IV

我为Keras中的深度度量学习定义了自定义损失函数,尽管问题很简单,但在Colab中使用GPU加速器的性能却很差。我该怎么做才能加快训练速度?

示例代码:该代码编写为可以在Colab / Jupyter中运行,但是我想它也可以作为脚本运行(我没有尝试过,但是我看不出任何不起作用的明显原因)。

import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.layers import Flatten, Dense
from tensorflow.keras.datasets import mnist

(X_train, y_train), (X_test, y_test) = mnist.load_data()

X_train = (X_train / 255.0).astype('float32')
X_test = (X_test / 255.0).astype('float32')

X_train = X_train.reshape(X_train.shape[0], 28, 28, 1)
X_test = X_test.reshape(X_test.shape[0], 28, 28, 1)
input_shape = (28, 28, 1)

tf.keras.backend.clear_session()

embedding_size = 3
model = keras.Sequential()
model.add(Flatten(input_shape = input_shape))
model.add(Dense(128, activation='relu'))
model.add(Dense(128, activation='relu'))
model.add(Dense(embedding_size))

model.summary()

margin = 0.2
def contrastive_loss(y_true, embeddings):
  loss = 0.0

  b = embeddings.shape[0]
  
  for i in range(0,b):
    yi = y_true[i]
    xi = embeddings[i]

    for j in range(i+1,b):
      yj = y_true[j]
      xj = embeddings[j]

      yij = tf.minimum(1.0, tf.abs(tf.cast(yi-yj, dtype = tf.float32)))
      distance = tf.norm(xi-xj)
      loss = loss + (1-yij)*distance**2 + yij*tf.maximum(0.0, margin-distance)**2
    
  loss = 0.5 * loss 
  return loss

model.compile(keras.optimizers.Adam(learning_rate=1e-4), loss=contrastive_loss)
history = model.fit(X_train, y_train, batch_size=32, epochs=10, shuffle=True)

print(X_test.shape)
emb = model.predict(X_test)
print(emb.shape, "emb")
print(y_test.shape, "y_test")
plt.scatter(emb[:,0], emb[:,1], c=y_test, cmap='tab10')

在带有GPU加速器的Colab上,培训非常慢。关于如何加快速度的任何提示?现在,我获得了> 200 ms / step,即每个时期≈380 s。

编辑:最初,我编写了实际代码的简化版本,但是,根据一些评论,加快代码速度的方法可能取决于我在损失函数中实际计算的内容,因此现在我将实际代码放入。抱歉,如果这样会使代码运行缓慢...

EDIT2:我试图在Jeff的答案中实施解决方案,但出现错误,原因是我不明白。这是新的代码:

import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.layers import Flatten, Dense
from tensorflow.keras.datasets import mnist

(X_train, y_train), (X_test, y_test) = mnist.load_data()

X_train = (X_train / 255.0).astype('float32')
X_test = (X_test / 255.0).astype('float32')

X_train = X_train.reshape(X_train.shape[0], 28, 28, 1)
X_test = X_test.reshape(X_test.shape[0], 28, 28, 1)
input_shape = (28, 28, 1)
tf.keras.backend.clear_session()

embedding_size = 3
model = keras.Sequential()
model.add(Flatten(input_shape = input_shape))
model.add(Dense(128, activation='relu'))
model.add(Dense(128, activation='relu'))
model.add(Dense(embedding_size))

model.summary() 

margin = 0.2
def contrastive_loss(y_true, embeddings):

  # it's easier to work with a flattened array
  flat_y_true = tf.reshape(y_true, (-1)) 

  # matrix of absolute differences, clipped to 1 (if yi!=yj then yij =1)
  yijs = abs(np.subtract.outer(flat_y_true, flat_y_true)).clip(max=1) 

  # we only need the upper triangular part of the matrix
  yijs = yijs[np.triu_indices_from(yijs)] 

  # first compute row differences of the embeddings matrix, the compute norms for
  # each row with axis=2
  distances = np.linalg.norm(embeddings[:,None] - embeddings[None], axis=2)

  # we only need the upper triangular part, again
  distances = distances[np.triu_indices_from(distances)]

  loss = ((1-yijs)*(distances**2) + (yijs*((margin-distances).clip(min=0)**2))).sum()*0.5

  return loss

model.compile(keras.optimizers.Adam(learning_rate=1e-4), loss=contrastive_loss)
history = model.fit(X_train, y_train, batch_size=32, epochs=10, shuffle=True)
    

我收到以下错误:

Epoch 1/10
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-5-1ae713ccf38c> in <module>()
      4 
      5 # When setting batch size, remember we are *quadratically* expanding it in our loss.
----> 6 history = model.fit(X_train, y_train, batch_size=32, epochs=10, shuffle=True)

10 frames
/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/func_graph.py in wrapper(*args, **kwargs)
    971           except Exception as e:  # pylint:disable=broad-except
    972             if hasattr(e, "ag_error_metadata"):
--> 973               raise e.ag_error_metadata.to_exception(e)
    974             else:
    975               raise

ValueError: in user code:

    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:806 train_function  *
        return step_function(self, iterator)
    <ipython-input-4-6c3b8535eb43>:5 contrastive_loss  *
        flat_y_true = tf.reshape(y_true, (-1))
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/util/dispatch.py:201 wrapper  **
        return target(*args, **kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/array_ops.py:195 reshape
        result = gen_array_ops.reshape(tensor, shape, name)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/gen_array_ops.py:8234 reshape
        "Reshape", tensor=tensor, shape=shape, name=name)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/op_def_library.py:744 _apply_op_helper
        attrs=attr_protos, op_def=op_def)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/func_graph.py:593 _create_op_internal
        compute_device)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ops.py:3485 _create_op_internal
        op_def=op_def)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ops.py:1975 __init__
        control_input_ops, op_def)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ops.py:1815 _create_c_op
        raise ValueError(str(e))

    ValueError: Shape must be rank 1 but is rank 0 for '{{node contrastive_loss/Reshape}} = Reshape[T=DT_UINT8, Tshape=DT_INT32](ExpandDims, contrastive_loss/Reshape/shape)' with input shapes: [32,1], [].
杰夫

如果不是您想要的,我们将亲自实施。

由于损失函数中的python for循环可能是问题所在,因此我们将重点放在此处。

编辑:我想我需要多睡一会,因为我可能发誓我以前numpy可以在自定义tensorflow损失函数中使用函数。将所有操作切换为tensorflow操作,因为实际上并非如此。


编辑完整功能:

def contrastive_loss(y_true, embeddings):
    
    yijs = tf.cast(tf.reshape((y_true[:,None]!=y_true),(y_true.get_shape()[0],y_true.get_shape()[0])),tf.dtypes.float32)
    distances = tf.norm(tf.cast(embeddings[:,None]-embeddings,tf.dtypes.float32),axis=2)
    dist_len = distances.get_shape()[0]
    return tf.math.reduce_sum((1-yijs)*distances**2 + yijs*(tf.maximum(0.2-distances,tf.zeros((dist_len,dist_len)))**2))*0.25

编辑的逐行演练:

def contrastive_loss(y_true, embeddings):
    y_true_len = y_true.get_shape()[0] #shape (None,1)
    yijs = tf.cast(
        tf.reshape(
            (
                #Max clipping abs diff of every value and all other values 
                #to 1 is essentially checking whether 
                #the other values are equal to itself or not
                #this would be a much faster method of doing so
                y_true[:,None]!=y_true
            ),
            #resize to square matrix of shape (batch_size,batch_size)
            (y_true_len,y_true_len) 
        ),
        tf.dtypes.float32 
    )
    
    distances = tf.norm(
        tf.cast(
            #find difference between each row and all other rows
            embeddings[:,None]-embeddings,
            tf.dtypes.float32
        ),
        #normalize every row to find 
        #magnitude of every row vector
        axis=2 
    )
    
    #get len to setup equivalent square matrix tensor of 0's later
    dist_len = distances.get_shape()[0] 
    #Sums all values in tensor
    loss = tf.math.reduce_sum(
        (1-yijs)*(distances**2) 
        + yijs*(
            #clip all values to be above 0
            tf.maximum(
                0.2-distances,
                #declare tensor of same dimension as 0.2-distances
                #for element wise comparison so tf.maximum can do its thing
                tf.zeros((dist_len,dist_len))
            )**2
        )
    )*0.25 #since we didn't drop lower triangle, need to multiply by 0.25 instead of 0.5
    
    return loss

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

具有自定义损失功能的Tensorflow模型无需培训

来自分类Dev

Keras中具有自定义损失功能的批次大小错误

来自分类Dev

Keras 自定义损失具有使用的功能之一和条件

来自分类Dev

如何在Keras模型的自定义损失中访问Tensor的内容

来自分类Dev

如何为Keras使用自定义损失功能

来自分类Dev

如何在Keras中实现此自定义损失功能?

来自分类Dev

Keras上的自定义损失功能

来自分类Dev

在 Keras 中加载模型、自定义数据、大量论证后损失函数大幅增加

来自分类Dev

如何编写具有加权平均的keras自定义f1损失函数?

来自分类Dev

自定义Keras层具有可训练的标量

来自分类Dev

PyTorch中具有自定义后向功能的损失-简单的MSE示例中的爆炸损失

来自分类Dev

在具有多个Keras模型的TF2自定义训练循环中应用渐变的正确方法

来自分类Dev

如何在Opencart中加载自定义模型

来自分类Dev

如何使用TensorBoard可视化具有自定义模型子类的keras模型?

来自分类Dev

Keras模型-在自定义损失函数中获取输入

来自分类Dev

Keras:无法在模型中使用自定义损失函数

来自分类Dev

自定义keras损失

来自分类Dev

如何将tensorflow自定义损失用于keras模型?

来自分类Dev

Keras自定义损失函数InvalidArgumentError:In [1]不是矩阵。相反,它具有形状[]

来自分类Dev

具有自定义功能的Keras自定义图层

来自分类Dev

如何在Keras自定义损失函数中使用张量?

来自分类Dev

如何在Keras的自定义批处理培训中获得每个时期的损失?

来自分类Dev

如何在Keras中实现具有动态形状的自定义输出层?

来自分类Dev

如何在具有自定义输入功能的元素上添加onclick事件

来自分类Dev

在keras自定义损失函数中获取训练数据形状

来自分类Dev

如何使用自定义损失功能(PU学习)

来自分类Dev

张量流中具有循环的自定义损失

来自分类Dev

如何在内置的预训练模型中放置自定义层?

来自分类Dev

如何在自定义训练循环中使用tf.keras.layers.BatchNormalization()?

Related 相关文章

  1. 1

    具有自定义损失功能的Tensorflow模型无需培训

  2. 2

    Keras中具有自定义损失功能的批次大小错误

  3. 3

    Keras 自定义损失具有使用的功能之一和条件

  4. 4

    如何在Keras模型的自定义损失中访问Tensor的内容

  5. 5

    如何为Keras使用自定义损失功能

  6. 6

    如何在Keras中实现此自定义损失功能?

  7. 7

    Keras上的自定义损失功能

  8. 8

    在 Keras 中加载模型、自定义数据、大量论证后损失函数大幅增加

  9. 9

    如何编写具有加权平均的keras自定义f1损失函数?

  10. 10

    自定义Keras层具有可训练的标量

  11. 11

    PyTorch中具有自定义后向功能的损失-简单的MSE示例中的爆炸损失

  12. 12

    在具有多个Keras模型的TF2自定义训练循环中应用渐变的正确方法

  13. 13

    如何在Opencart中加载自定义模型

  14. 14

    如何使用TensorBoard可视化具有自定义模型子类的keras模型?

  15. 15

    Keras模型-在自定义损失函数中获取输入

  16. 16

    Keras:无法在模型中使用自定义损失函数

  17. 17

    自定义keras损失

  18. 18

    如何将tensorflow自定义损失用于keras模型?

  19. 19

    Keras自定义损失函数InvalidArgumentError:In [1]不是矩阵。相反,它具有形状[]

  20. 20

    具有自定义功能的Keras自定义图层

  21. 21

    如何在Keras自定义损失函数中使用张量?

  22. 22

    如何在Keras的自定义批处理培训中获得每个时期的损失?

  23. 23

    如何在Keras中实现具有动态形状的自定义输出层?

  24. 24

    如何在具有自定义输入功能的元素上添加onclick事件

  25. 25

    在keras自定义损失函数中获取训练数据形状

  26. 26

    如何使用自定义损失功能(PU学习)

  27. 27

    张量流中具有循环的自定义损失

  28. 28

    如何在内置的预训练模型中放置自定义层?

  29. 29

    如何在自定义训练循环中使用tf.keras.layers.BatchNormalization()?

热门标签

归档