【问题标题】:Siamese network for feature similarity特征相似性的连体网络
【发布时间】:2021-02-22 16:42:33
【问题描述】:

我有大约 20k 个不同域的图像,其中已经使用 GLCM 和 HOG 提取了特征。每张图像的特征尺寸约为 2000。我想使用连体网络找到特征之间的相似性。我将所有内容都存储在一个数据框中。我不确定我们如何为神经网络提供输入特征。 使用 1DCNN / Dense 层只有一种可能性。

encoder = models.Sequential(name='encoder')
encoder.add(layer=layers.Dense(units=1024, activation=activations.relu, input_shape=[n_features]))
encoder.add(layers.Dropout(0.1))
encoder.add(layer=layers.Dense(units=512, activation=activations.relu))
encoder.add(layers.Dropout(0.1))
encoder.add(layer=layers.Dense(units=256, activation=activations.relu))
encoder.add(layers.Dropout(0.1))

在上面的代码中,我们只将特征数量作为编码器的输入,但我的两张图像的特征数量是相同的。 我应该分别训练两个编码器并在最后加入它们以形成嵌入层吗? 但是我应该如何测试呢?

【问题讨论】:

    标签: python tensorflow similarity siamese-network


    【解决方案1】:

    对于连体网络,您可能希望拥有一个网络,并在不同的数据集上对其进行训练。

    假设你有两组数据 X0X1 具有相同的形状,你会这样做

    from tensorflow.keras import models
    from tensorflow.keras import layers
    from tensorflow.python.keras.utils import losses_utils
    
    
    # number of features
    n_features = 2000
    
    # fake data w/batch size 4
    X0 = tf.random.normal([4, n_features])
    X1 = tf.random.normal([4, n_features])
    
    # siamese encoder model
    encoder = models.Sequential(name='encoder')
    encoder.add(layer=layers.Dense(
        units=1024, activation="relu", input_shape=[n_features]))
    encoder.add(layers.Dropout(0.1))
    encoder.add(layer=layers.Dense(units=512, activation="relu"))
    encoder.add(layers.Dropout(0.1))
    encoder.add(layer=layers.Dense(units=256, activation="relu"))
    encoder.add(layers.Dropout(0.1))
    
    # send both sets of data through same model
    enc0 = encoder(X0)
    enc1 = encoder(X1)
    
    # compare the two outputs
    compared = tf.keras.losses.CosineSimilarity(
        reduction=losses_utils.ReductionV2.NONE)(enc0, enc1)
    print(f"cosine similarity of output: {compared.numpy()}")
    # cosine similarity of output: [-0.5785658, -0.6405066, -0.57274437, -0.6017716]
    
    # now do optimization ...
    

    有很多方法可以比较输出,余弦相似度就是其中之一,但我只是将其包括在内以进行说明,您可能需要一些其他指标。

    【讨论】:

    【解决方案2】:

    只有一个网络是刚刚复制的。所有的权重都是共享的。因此,您正在训练一个网络,只需在每个学习步骤中运行两次。 你应该从你的数据集中挑选两个样本,如果来自同一类,则将其标记为 1,否则标记为 0。

    from tensorflow.keras import models
    from tensorflow.keras import layers
    import tensorflow.keras.backend as K
    
    n_features = 2000
    
    def cos_similarity(x):
        x1,x2 = x
        return K.sum(x1*x2)/(K.sqrt(K.sum(x1*x1))*K.sqrt(K.sum(x2*x2)))
    
    inp1 = layers.Input(shape=(n_features))
    inp2 = layers.Input(shape=(n_features))
    
    encoder = models.Sequential(name='encoder')
    encoder.add(layer=layers.Dense(
        units=1024, activation="relu", input_shape=[n_features]))
    encoder.add(layers.Dropout(0.1))
    encoder.add(layer=layers.Dense(units=512, activation="relu"))
    encoder.add(layers.Dropout(0.1))
    encoder.add(layer=layers.Dense(units=256, activation="relu"))
    encoder.add(layers.Dropout(0.1))
    
    out1 = encoder(inp1)
    out2 = encoder(inp2)
    
    similarity = layers.Lambda(cos_similarity)([out1,out2])
    
    model = models.Model(inputs=[inp1,inp2],outputs=[similarity])
    
    model.compile(optimizer='adam',loss='mse')
    

    为了测试,首先你应该计算你说它有 2000 个特征的 HOG 特征。然后运行

    model.predict(hog_feature)
    

    你有输出功能。 顺便说一句,我建议不要使用 hog 功能和连体网络。仅使用此网络提取图像特征。更改输入形状并使用图像进行训练。

    【讨论】:

    • 我可以使用同一个网络进行异常检测,即训练相似特征对并预测不同特征对吗?
    • 是的,但是如果你也用不同的特征对训练网络,网络的学习效果会更好。网络应该学习类间和类间分布。但如果网络可以学习类间分布,它应该能够在不同对之间产生差异。
    猜你喜欢
    • 2018-12-03
    • 1970-01-01
    • 1970-01-01
    • 2011-12-23
    • 2013-04-15
    • 1970-01-01
    • 2021-02-05
    • 2012-04-10
    • 2018-11-15
    相关资源
    最近更新 更多