2
$\begingroup$

Is there any way to constrain weights of some fully connected layer of CNN(classification task) to be binary (0,1) or near binary(and then just threshold to binary)?

Update: I want to use binary features from this layer to search similar images using hamming distance, something like {1}.


References:

  • {1} Lin, Kevin, Huei-Fang Yang, Jen-Hao Hsiao, and Chu-Song Chen. "Deep learning of binary hash codes for fast image retrieval." In Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition Workshops, pp. 27-35. 2015. http://www.iis.sinica.edu.tw/%7Ekevinlin311.tw/cvprw15.pdf
$\endgroup$
4

1 Answer 1

1
$\begingroup$

In the paper you mentioned in your question, the weights of the network are not binary. Instead, the output of one layer is binarized (so that it can be use as a binary hash of the input, which in this case is an image, to be used later for quickly retrieving similar images by computing some distance between the hashes of the images).

From the paper:

In our design, the neurons in the latent layer H are activated by sigmoid functions so the activations are approximated to {0, 1}

The latent layer H in green is shown in figure 1 (module 2):

enter image description here

The code provided with the paper for the module 2 shows the latent layer H are activated by sigmoid function: https://github.com/kevinlin311tw/caffe-cvprw15/blob/master/examples/cvprw15-cifar10/train_CIFAR10_48.prototxt ("fc8_kevin" layer)

name: "KevinNet_CIFAR10"
layers {
  layer {
    name: "data"
    type: "data"
    source: "cifar10_train_leveldb"
    meanfile: "../../data/ilsvrc12/imagenet_mean.binaryproto"
    batchsize: 32
    cropsize: 227
    mirror: true
    det_context_pad: 16
    det_crop_mode: "warp"
    det_fg_threshold: 0.5
    det_bg_threshold: 0.5
    det_fg_fraction: 0.25
  }
  top: "data"
  top: "label"
}
layers {
  layer {
    name: "conv1"
    type: "conv"
    num_output: 96
    kernelsize: 11
    stride: 4
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0.
    }
    blobs_lr: 1.
    blobs_lr: 2.
    weight_decay: 1.
    weight_decay: 0.
  }
  bottom: "data"
  top: "conv1"
}
layers {
  layer {
    name: "relu1"
    type: "relu"
  }
  bottom: "conv1"
  top: "conv1"
}
layers {
  layer {
    name: "pool1"
    type: "pool"
    pool: MAX
    kernelsize: 3
    stride: 2
  }
  bottom: "conv1"
  top: "pool1"
}
layers {
  layer {
    name: "norm1"
    type: "lrn"
    local_size: 5
    alpha: 0.0001
    beta: 0.75
  }
  bottom: "pool1"
  top: "norm1"
}
layers {
  layer {
    name: "pad2"
    type: "padding"
    pad: 2
  }
  bottom: "norm1"
  top: "pad2"
}
layers {
  layer {
    name: "conv2"
    type: "conv"
    num_output: 256
    group: 2
    kernelsize: 5
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 1.
    }
    blobs_lr: 1.
    blobs_lr: 2.
    weight_decay: 1.
    weight_decay: 0.
  }
  bottom: "pad2"
  top: "conv2"
}
layers {
  layer {
    name: "relu2"
    type: "relu"
  }
  bottom: "conv2"
  top: "conv2"
}
layers {
  layer {
    name: "pool2"
    type: "pool"
    pool: MAX
    kernelsize: 3
    stride: 2
  }
  bottom: "conv2"
  top: "pool2"
}
layers {
  layer {
    name: "norm2"
    type: "lrn"
    local_size: 5
    alpha: 0.0001
    beta: 0.75
  }
  bottom: "pool2"
  top: "norm2"
}
layers {
  layer {
    name: "pad3"
    type: "padding"
    pad: 1
  }
  bottom: "norm2"
  top: "pad3"
}
layers {
  layer {
    name: "conv3"
    type: "conv"
    num_output: 384
    kernelsize: 3
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0.
    }
    blobs_lr: 1.
    blobs_lr: 2.
    weight_decay: 1.
    weight_decay: 0.
  }
  bottom: "pad3"
  top: "conv3"
}
layers {
  layer {
    name: "relu3"
    type: "relu"
  }
  bottom: "conv3"
  top: "conv3"
}
layers {
  layer {
    name: "pad4"
    type: "padding"
    pad: 1
  }
  bottom: "conv3"
  top: "pad4"
}
layers {
  layer {
    name: "conv4"
    type: "conv"
    num_output: 384
    group: 2
    kernelsize: 3
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 1.
    }
    blobs_lr: 1.
    blobs_lr: 2.
    weight_decay: 1.
    weight_decay: 0.
  }
  bottom: "pad4"
  top: "conv4"
}
layers {
  layer {
    name: "relu4"
    type: "relu"
  }
  bottom: "conv4"
  top: "conv4"
}
layers {
  layer {
    name: "pad5"
    type: "padding"
    pad: 1
  }
  bottom: "conv4"
  top: "pad5"
}
layers {
  layer {
    name: "conv5"
    type: "conv"
    num_output: 256
    group: 2
    kernelsize: 3
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 1.
    }
    blobs_lr: 1.
    blobs_lr: 2.
    weight_decay: 1.
    weight_decay: 0.
  }
  bottom: "pad5"
  top: "conv5"
}
layers {
  layer {
    name: "relu5"
    type: "relu"
  }
  bottom: "conv5"
  top: "conv5"
}
layers {
  layer {
    name: "pool5"
    type: "pool"
    kernelsize: 3
    pool: MAX
    stride: 2
  }
  bottom: "conv5"
  top: "pool5"
}
layers {
  layer {
    name: "fc6"
    type: "innerproduct"
    num_output: 4096
    weight_filler {
      type: "gaussian"
      std: 0.005
    }
    bias_filler {
      type: "constant"
      value: 1.
    }
    blobs_lr: 1.
    blobs_lr: 2.
    weight_decay: 1.
    weight_decay: 0.
  }
  bottom: "pool5"
  top: "fc6"
}
layers {
  layer {
    name: "relu6"
    type: "relu"
  }
  bottom: "fc6"
  top: "fc6"
}
layers {
  layer {
    name: "drop6"
    type: "dropout"
    dropout_ratio: 0.5
  }
  bottom: "fc6"
  top: "fc6"
}
layers {
  layer {
    name: "fc7"
    type: "innerproduct"
    num_output: 4096
    weight_filler {
      type: "gaussian"
      std: 0.005
    }
    bias_filler {
      type: "constant"
      value: 1.
    }
    blobs_lr: 1.
    blobs_lr: 2.
    weight_decay: 1.
    weight_decay: 0.
  }
  bottom: "fc6"
  top: "fc7"
}
layers {
  layer {
    name: "relu7"
    type: "relu"
  }
  bottom: "fc7"
  top: "fc7"
}
layers {
  layer {
    name: "drop7"
    type: "dropout"
    dropout_ratio: 0.5
  }
  bottom: "fc7"
  top: "fc7"
}
layers {
  layer {
    name: "fc8_kevin"
    type: "innerproduct"
    num_output: 48
    weight_filler {
      type: "gaussian"
      std: 0.005
    }
    bias_filler {
      type: "constant"
      value: 1.
    }
    blobs_lr: 1.
    blobs_lr: 2.
    weight_decay: 1.
    weight_decay: 0.
  }
  bottom: "fc7"
  top: "fc8_kevin"
}
layers {
  layer {
    name: "fc8_kevin_encode"
    type: "sigmoid"
  }
  bottom: "fc8_kevin"
  top: "fc8_kevin_encode"
}
layers {
  layer {
    # We name this fc8_pascal so that the initialization
    # network doesn't populate this layer with its fc8
    name: "fc8_pascal"
    type: "innerproduct"
    num_output: 10
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
    blobs_lr: 10.
    blobs_lr: 20.
    weight_decay: 1.
    weight_decay: 0.
  }
  bottom: "fc8_kevin_encode"
  top: "fc8_pascal"
}
layers {
  layer {
    name: "loss"
    type: "softmax_loss"
  }
  bottom: "fc8_pascal"
  bottom: "label"
}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.