keras-siamese用自己的数据集实现详解

Siamese网络不做过多介绍,思想并不难,输入两个图像,输出这两张图像的相似度,两个输入的网络结构是相同的,参数共享。

主要发现很多代码都是基于mnist数据集的,下面说一下怎么用自己的数据集实现siamese网络。

首先,先整理数据集,相同的类放到同一个文件夹下,如下图所示:

接下来,将pairs及对应的label写到csv中,代码如下:

import os
import random
import csv
#图片所在的路径
path = '/Users/mac/Desktop/wxd/flag/category/'
#files列表保存所有类别的路径
files=[]
same_pairs=[]
different_pairs=[]
for file in os.listdir(path):
  if file[0]=='.':
    continue
  file_path = os.path.join(path,file)
  files.append(file_path)
#该地址为csv要保存到的路径,a表示追加写入
with open('/Users/mac/Desktop/wxd/flag/data.csv','a') as f:
  #保存相同对
  writer = csv.writer(f)
  for file in files:
    imgs = os.listdir(file)
    for i in range(0,len(imgs)-1):
      for j in range(i+1,len(imgs)):
        pairs = []
        name = file.split(sep='/')[-1]
        pairs.append(path+name+'/'+imgs[i])
        pairs.append(path+name+'/'+imgs[j])
        pairs.append(1)
        writer.writerow(pairs)
  #保存不同对
  for i in range(0,len(files)-1):
    for j in range(i+1,len(files)):
      filea = files[i]
      fileb = files[j]
      imga_li = os.listdir(filea)
      imgb_li = os.listdir(fileb)
      random.shuffle(imga_li)
      random.shuffle(imgb_li)
      a_li = imga_li[:]
      b_li = imgb_li[:]
      for p in range(len(a_li)):
        for q in range(len(b_li)):
          pairs = []
          name1 = filea.split(sep='/')[-1]
          name2 = fileb.split(sep='/')[-1]
          pairs.append(path+name1+'/'+a_li[p])
          pairs.append(path+name2+'/'+b_li[q])
          pairs.append(0)
          writer.writerow(pairs)

相当于csv每一行都包含一对结果,每一行有三列,第一列第一张图片路径,第二列第二张图片路径,第三列是不是相同的label,属于同一个类的label为1,不同类的为0,可参考下图:

然后,由于keras的fit函数需要将训练数据都塞入内存,而大部分训练数据都较大,因此才用fit_generator生成器的方法,便可以训练大数据,代码如下:

from __future__ import absolute_import
from __future__ import print_function
import numpy as np
from keras.models import Model
from keras.layers import Input, Dense, Dropout, BatchNormalization, Conv2D, MaxPooling2D, AveragePooling2D, concatenate, \
  Activation, ZeroPadding2D
from keras.layers import add, Flatten
from keras.utils import plot_model
from keras.metrics import top_k_categorical_accuracy
from keras.preprocessing.image import ImageDataGenerator
from keras.models import load_model
import tensorflow as tf
import random
import os
import cv2
import csv
import numpy as np
from keras.models import Model
from keras.layers import Input, Flatten, Dense, Dropout, Lambda
from keras.optimizers import RMSprop
from keras import backend as K
from keras.callbacks import ModelCheckpoint
from keras.preprocessing.image import img_to_array

"""
自定义的参数
"""
im_width = 224
im_height = 224
epochs = 100
batch_size = 64
iterations = 1000
csv_path = ''
model_result = ''

# 计算欧式距离
def euclidean_distance(vects):
  x, y = vects
  sum_square = K.sum(K.square(x - y), axis=1, keepdims=True)
  return K.sqrt(K.maximum(sum_square, K.epsilon()))

def eucl_dist_output_shape(shapes):
  shape1, shape2 = shapes
  return (shape1[0], 1)

# 计算loss
def contrastive_loss(y_true, y_pred):
  '''Contrastive loss from Hadsell-et-al.'06
  http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf
  '''
  margin = 1
  square_pred = K.square(y_pred)
  margin_square = K.square(K.maximum(margin - y_pred, 0))
  return K.mean(y_true * square_pred + (1 - y_true) * margin_square)

def compute_accuracy(y_true, y_pred):
  '''计算准确率
  '''
  pred = y_pred.ravel() < 0.5
  print('pred:', pred)
  return np.mean(pred == y_true)

def accuracy(y_true, y_pred):
  '''Compute classification accuracy with a fixed threshold on distances.
  '''
  return K.mean(K.equal(y_true, K.cast(y_pred < 0.5, y_true.dtype)))

def processImg(filename):
  """
  :param filename: 图像的路径
  :return: 返回的是归一化矩阵
  """
  img = cv2.imread(filename)
  img = cv2.resize(img, (im_width, im_height))
  img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  img = img_to_array(img)
  img /= 255
  return img

def Conv2d_BN(x, nb_filter, kernel_size, strides=(1, 1), padding='same', name=None):
  if name is not None:
    bn_name = name + '_bn'
    conv_name = name + '_conv'
  else:
    bn_name = None
    conv_name = None

  x = Conv2D(nb_filter, kernel_size, padding=padding, strides=strides, activation='relu', name=conv_name)(x)
  x = BatchNormalization(axis=3, name=bn_name)(x)
  return x

def bottleneck_Block(inpt, nb_filters, strides=(1, 1), with_conv_shortcut=False):
  k1, k2, k3 = nb_filters
  x = Conv2d_BN(inpt, nb_filter=k1, kernel_size=1, strides=strides, padding='same')
  x = Conv2d_BN(x, nb_filter=k2, kernel_size=3, padding='same')
  x = Conv2d_BN(x, nb_filter=k3, kernel_size=1, padding='same')
  if with_conv_shortcut:
    shortcut = Conv2d_BN(inpt, nb_filter=k3, strides=strides, kernel_size=1)
    x = add([x, shortcut])
    return x
  else:
    x = add([x, inpt])
    return x

def resnet_50():
  width = im_width
  height = im_height
  channel = 3
  inpt = Input(shape=(width, height, channel))
  x = ZeroPadding2D((3, 3))(inpt)
  x = Conv2d_BN(x, nb_filter=64, kernel_size=(7, 7), strides=(2, 2), padding='valid')
  x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), padding='same')(x)

  # conv2_x
  x = bottleneck_Block(x, nb_filters=[64, 64, 256], strides=(1, 1), with_conv_shortcut=True)
  x = bottleneck_Block(x, nb_filters=[64, 64, 256])
  x = bottleneck_Block(x, nb_filters=[64, 64, 256])

  # conv3_x
  x = bottleneck_Block(x, nb_filters=[128, 128, 512], strides=(2, 2), with_conv_shortcut=True)
  x = bottleneck_Block(x, nb_filters=[128, 128, 512])
  x = bottleneck_Block(x, nb_filters=[128, 128, 512])
  x = bottleneck_Block(x, nb_filters=[128, 128, 512])

  # conv4_x
  x = bottleneck_Block(x, nb_filters=[256, 256, 1024], strides=(2, 2), with_conv_shortcut=True)
  x = bottleneck_Block(x, nb_filters=[256, 256, 1024])
  x = bottleneck_Block(x, nb_filters=[256, 256, 1024])
  x = bottleneck_Block(x, nb_filters=[256, 256, 1024])
  x = bottleneck_Block(x, nb_filters=[256, 256, 1024])
  x = bottleneck_Block(x, nb_filters=[256, 256, 1024])

  # conv5_x
  x = bottleneck_Block(x, nb_filters=[512, 512, 2048], strides=(2, 2), with_conv_shortcut=True)
  x = bottleneck_Block(x, nb_filters=[512, 512, 2048])
  x = bottleneck_Block(x, nb_filters=[512, 512, 2048])

  x = AveragePooling2D(pool_size=(7, 7))(x)
  x = Flatten()(x)
  x = Dense(128, activation='relu')(x)
  return Model(inpt, x)

def generator(imgs, batch_size):
  """
  自定义迭代器
  :param imgs: 列表,每个包含一对矩阵以及label
  :param batch_size:
  :return:
  """
  while 1:
    random.shuffle(imgs)
    li = imgs[:batch_size]
    pairs = []
    labels = []
    for i in li:
      img1 = i[0]
      img2 = i[1]
      im1 = cv2.imread(img1)
      im2 = cv2.imread(img2)
      if im1 is None or im2 is None:
        continue
      label = int(i[2])
      img1 = processImg(img1)
      img2 = processImg(img2)
      pairs.append([img1, img2])
      labels.append(label)
    pairs = np.array(pairs)
    labels = np.array(labels)
    yield [pairs[:, 0], pairs[:, 1]], labels

input_shape = (im_width, im_height, 3)
base_network = resnet_50()

input_a = Input(shape=input_shape)
input_b = Input(shape=input_shape)

# because we re-use the same instance `base_network`,
# the weights of the network
# will be shared across the two branches
processed_a = base_network(input_a)
processed_b = base_network(input_b)

distance = Lambda(euclidean_distance,
         output_shape=eucl_dist_output_shape)([processed_a, processed_b])
with tf.device("/gpu:0"):
  model = Model([input_a, input_b], distance)
  # train
  rms = RMSprop()
  rows = csv.reader(open(csv_path, 'r'), delimiter=',')
  imgs = list(rows)
  checkpoint = ModelCheckpoint(filepath=model_result+'flag_{epoch:03d}.h5', verbose=1)
  model.compile(loss=contrastive_loss, optimizer=rms, metrics=[accuracy])
  model.fit_generator(generator(imgs, batch_size), epochs=epochs, steps_per_epoch=iterations, callbacks=[checkpoint])

用了回调函数保存了每一个epoch后的模型,也可以保存最好的,之后需要对模型进行测试。

测试时直接用load_model会报错,而应该变成如下形式调用:

model = load_model(model_path,custom_objects={'contrastive_loss': contrastive_loss }) #选取自己的.h模型名称

emmm,到这里,就成功训练测试完了~~~写的比较粗,因为这个代码在官方给的mnist上的改动不大,只是方便大家用自己的数据集,大家如果有更好的方法可以提出意见~~~

以上这篇keras-siamese用自己的数据集实现详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 使用keras实现densenet和Xception的模型融合

    我正在参加天池上的一个竞赛,刚开始用的是DenseNet121但是效果没有达到预期,因此开始尝试使用模型融合,将Desenet和Xception融合起来共同提取特征. 代码如下: def Multimodel(cnn_weights_path=None,all_weights_path=None,class_num=5,cnn_no_vary=False): ''' 获取densent121,xinception并联的网络 此处的cnn_weights_path是个列表是densenet和xce

  • 使用Keras预训练模型ResNet50进行图像分类方式

    Keras提供了一些用ImageNet训练过的模型:Xception,VGG16,VGG19,ResNet50,InceptionV3.在使用这些模型的时候,有一个参数include_top表示是否包含模型顶部的全连接层,如果包含,则可以将图像分为ImageNet中的1000类,如果不包含,则可以利用这些参数来做一些定制的事情. 在运行时自动下载有可能会失败,需要去网站中手动下载,放在"~/.keras/models/"中,使用WinPython则在"settings/.ke

  • 使用Keras 实现查看model weights .h5 文件的内容

    Keras的模型是用hdf5存储的,如果想要查看模型,keras提供了get_weights的函数可以查看: for layer in model.layers: weights = layer.get_weights() # list of numpy array 而通过hdf5模块也可以读取:hdf5的数据结构主要是File - Group - Dataset三级,具体操作API可以看官方文档.weights的tensor保存在Dataset的value中,而每一集都会有attrs保存各网络

  • keras-siamese用自己的数据集实现详解

    Siamese网络不做过多介绍,思想并不难,输入两个图像,输出这两张图像的相似度,两个输入的网络结构是相同的,参数共享. 主要发现很多代码都是基于mnist数据集的,下面说一下怎么用自己的数据集实现siamese网络. 首先,先整理数据集,相同的类放到同一个文件夹下,如下图所示: 接下来,将pairs及对应的label写到csv中,代码如下: import os import random import csv #图片所在的路径 path = '/Users/mac/Desktop/wxd/fl

  • Python基于keras训练实现微笑识别的示例详解

    目录 一.数据预处理 二.训练模型 创建模型 训练模型 训练结果 三.预测 效果 四.源代码 pretreatment.py train.py predict.py 一.数据预处理 实验数据来自genki4k 提取含有完整人脸的图片 def init_file():     num = 0     bar = tqdm(os.listdir(read_path))     for file_name in bar:         bar.desc = "预处理图片: "      

  • SQLserver中cube:多维数据集实例详解

    1.cube:生成多维数据集,包含各维度可能组合的交叉表格,使用with 关键字连接 with cube 根据需要使用union all 拼接 判断 某一列的null值来自源数据还是 cube 使用GROUPING关键字 GROUPING([档案号]) = 1 : null值来自cube(代表所有的档案号) GROUPING([档案号]) = 0 : null值来自源数据 举例: SELECT * INTO ##GET FROM (SELECT * FROM ( SELECT CASE WHEN

  • PyTorch加载自己的数据集实例详解

    数据预处理在解决深度学习问题的过程中,往往需要花费大量的时间和精力. 数据处理的质量对训练神经网络来说十分重要,良好的数据处理不仅会加速模型训练, 更会提高模型性能.为解决这一问题,PyTorch提供了几个高效便捷的工具, 以便使用者进行数据处理或增强等操作,同时可通过并行化加速数据加载. 数据集存放大致有以下两种方式: (1)所有数据集放在一个目录下,文件名上附有标签名,数据集存放格式如下: root/cat_dog/cat.01.jpg root/cat_dog/cat.02.jpg ...

  • keras 自定义loss model.add_loss的使用详解

    一点见解,不断学习,欢迎指正 1.自定义loss层作为网络一层加进model,同时该loss的输出作为网络优化的目标函数 from keras.models import Model import keras.layers as KL import keras.backend as K import numpy as np from keras.utils.vis_utils import plot_model x_train=np.random.normal(1,1,(100,784)) x_

  • Keras 利用sklearn的ROC-AUC建立评价函数详解

    我就废话不多说了,大家还是直接看代码吧! # 利用sklearn自建评价函数 from sklearn.model_selection import train_test_split from sklearn.metrics import roc_auc_score from keras.callbacks import Callback class RocAucEvaluation(Callback): def __init__(self, validation_data=(), interv

  • nlp计数法应用于PTB数据集示例详解

    目录 PTB数据集 ptb.py 使用ptb.py 计数方法应用于PTB数据集 PTB数据集 内容如下: 一行保存一个句子:将稀有单词替换成特殊字符 < unk > :将具体的数字替换 成“N” we 're talking about years ago before anyone heard of asbestos having any questionable properties there is no asbestos in our products now neither <

  • Python深度学习之Keras模型转换成ONNX模型流程详解

    目录 从Keras转换成PB模型 从PB模型转换成ONNX模型 改变现有的ONNX模型精度 部署ONNX 模型 总结 从Keras转换成PB模型 请注意,如果直接使用Keras2ONNX进行模型转换大概率会出现报错,这里笔者曾经进行过不同的尝试,最后都失败了. 所以笔者的推荐的情况是:首先将Keras模型转换为TensorFlow PB模型. 那么通过tf.keras.models.load_model()这个函数将模型进行加载,前提是你有一个基于h5格式或者hdf5格式的模型文件,最后再通过改

  • keras 自定义loss损失函数,sample在loss上的加权和metric详解

    首先辨析一下概念: 1. loss是整体网络进行优化的目标, 是需要参与到优化运算,更新权值W的过程的 2. metric只是作为评价网络表现的一种"指标", 比如accuracy,是为了直观地了解算法的效果,充当view的作用,并不参与到优化过程 在keras中实现自定义loss, 可以有两种方式,一种自定义 loss function, 例如: # 方式一 def vae_loss(x, x_decoded_mean): xent_loss = objectives.binary_

  • 使用Keras预训练好的模型进行目标类别预测详解

    前言 最近开始学习深度学习相关的内容,各种书籍.教程下来到目前也有了一些基本的理解.参考Keras的官方文档自己做一个使用application的小例子,能够对图片进行识别,并给出可能性最大的分类. 闲言少叙,开始写代码 环境搭建相关就此省去,网上非常多.我觉得没啥难度 from keras.applications.resnet50 import ResNet50 from keras.preprocessing import image from keras.applications.res

随机推荐