利⽤三元组tripletloss训练⾮⼈脸数据并实现分类
密码:12mh
1.训练⾃⼰的数据
先把我们所⽤到的代码说⼀下,这⾥我选择的是精简版的代码,所⽤到的代码主要是train_tripletloss和classifier,但不是其余没有⽐如facenet.py,lfw.py等等是需要被调⽤的。
⾸先我们需要准备好数据集,这个数据集要求的尺⼨是160*160,可以是⾮⼈脸数据,然后放到指定的⽂件夹(在程序中可以⾃⼰选定放在哪,也可以和我选定⼀样)。
这⾥将主要的修改代码的位置贴出来:
⼀般来讲需要我们做的就是修改⾃⼰的路径问题,看train_tripletloss部分代码中的相应注释:
def parse_arguments(argv):
parser = argparse.ArgumentParser()
parser.add_argument('--logs_base_dir',type=str,
help='Directory where to write event logs.', default='./logs/facenet')#~/logs/facenet⽇志路径,运⾏后会在当前⽂件夹下⽣产⽇志⽂件
parser.add_argument('--models_base_dir',type=str,
help='Directory where to write trained models and checkpoints.', default='./models/facenet')#~/models/facenet⽣成模型的位置,训练完后会在当前⽂件夹下models/facenet⽣成⼏个ckpt⽂件的模型
parser.add_argument('--gpu_memory_fraction',type=float,
help='Upper bound on the amount of GPU memory that will be used by the process.', default=1.0)
parser.add_argument('--pretrained_model',type=str,
help='Load a pretrained model before training starts.'
#default = './weight_decay')#.',default='模型所在路径'
,default=r'D:\research\understand_facenet-master\understand_facenet\20170512-110547')#把之前百度⽹盘下载好的预训练模型放到⾃⼰的路径下
parser.add_argument('--data_dir',type=str,
help='Path to the data directory containing aligned face patches.',
# default='~/datasets/casia/casia_maxpy_mtcnnalign_182_160')
default = r'D:\research\understand_facenet-master\understand_facenet\my_dataset\quexian')#这个很重要,就是我们⾃⼰数据的位置,
#在quexian这个⽂件夹下⾯还有⼏个⽂件夹,每个⽂件夹的名称代表⼀类,
#如果去看lfw数据集就可以看出,他们每个⽂件夹代表的是⼈名。
parser.add_argument('--model_def',type=str,
help='Model definition. Points to a module containing the definition of the inference graph.',
default='models.inception_resnet_v1')#models.inception_resnet_v1
parser.add_argument('--max_nrof_epochs',type=int,
help='Number of epochs to run.', default=500)#500
parser.add_argument('--batch_size',type=int,
help='Number of images to process in a batch.', default=3)#90
parser.add_argument('--image_size',type=int,
help='Image size (height, width) in pixels.', default=160)
parser.add_argument('--people_per_batch',type=int,
help='Number of people per batch.', default=4)#45每批次抽取多少⼈
parser.add_argument('--images_per_person',type=int,
help='Number of images per person.', default=15)#40#每⼈抽取多少张
parser.add_argument('--epoch_size',type=int,
help='Number of batches per epoch.', default=100)#批次训练1000
parser.add_argument('--alpha',type=float,
help='Positive to negative triplet distance margin.', default=0.2)
parser.add_argument('--embedding_size',type=int,
help='Dimensionality of the embedding.', default=128)
parser.add_argument('--random_crop',
help='Performs random cropping of training images. If false, the center image_size pixels from the training images are used. '+
'If the size of the images in the data directory is equal to image_size no cropping is performed', action='store_true')
parser.add_argument('--random_flip',
help='Performs random horizontal flipping of training images.', action='store_true')
parser.add_argument('--keep_probability',type=float,
help='Keep probability of dropout for the fully connected layer(s).', default=1.0)
help='Keep probability of dropout for the fully connected layer(s).', default=1.0)
parser.add_argument('--weight_decay',type=float,
help='L2 weight regularization.', default=0.0)
parser.add_argument('--optimizer',type=str, choices=['ADAGRAD','ADADELTA','ADAM','RMSPROP','MOM'], help='The optimization algorithm to use', default='ADAGRAD')
parser.add_argument('--learning_rate',type=float,
help='Initial learning rate. If set to a negative value a learning rate '+
'schedule can be specified in the file "learning_"', default=0.1)
parser.add_argument('--learning_rate_decay_epochs',type=int,
help='Number of epochs between learning rate decay.', default=100)
parser.add_argument('--learning_rate_decay_factor',type=float,
help='Learning rate decay factor.', default=1.0)
parser.add_argument('--moving_average_decay',type=float,
help='Exponential decay for tracking of training parameters.', default=0.9999)
parser.add_argument('--seed',type=int,
help='Random seed.', default=666)
parser.add_argument('--learning_rate_schedule_file',type=str,
help='File containing the learning rate schedule that is used when learning_rate is set to to -1.', default='data/learning_') # Parameters for validation on LFW
parser.add_argument('--lfw_pairs',type=str,
help='The file containing the pairs to use for validation.', default='')
parser.add_argument('--lfw_file_ext',type=str,
help='The file extension for the LFW dataset.', default='png', choices=['jpg','png'])
parser.add_argument('--lfw_dir',type=str,
help='Path to the data directory containing aligned face patches.', default='')
parser.add_argument('--lfw_nrof_folds',type=int,
help='Number of folds to use for cross validation. Mainly used for testing.', default=10)
return parser.parse_args(argv)
所⽤环境主要如下:
安装配置搭建好后,直接运⾏会在恢复模型的位置输⼊,输出的错误,⽆法顺利加载模型:这⾥需要简单修改:如下‘原始的’未原来的语句,注释掉后,改为’修改的‘语句。
这⾥⾯有⼏个参数⽐较重要;按照原论⽂所说images_per_person乘-people_per_batch为1800张图⽚,但是我们没有那么多数据,我⾃⼰只有5类数据,每类不超过100张,people_per_batch这个参数不要超过⾃⼰的类别,会报错,原⽂中的batchsize是90,⽤1800除以90得20;
因此我在设置时选择的是15*4,batchsize=3,这样可以满⾜原论⽂的nrof_batches,默认是1800/90=20批次的要求。
在这⾥最主要的就是选择⼀个合适的三元组:三元组的原理就是把学习到的特征映射成距离去不断训练。
这⾥⾯的Anchor就是随机选择的⼀类,然后positive是选择⼀个和Anchor相同的⼀类,Negative是选择和其不同的⼀类。这样就构成了三元组。但是我们要尽可能的去选择和Anchor最不像的⼀个postive,选择⼀个和Anchor最像的⼀个Negative这样才能不断的通过训练,最后去拉近相同⼀类的距离,疏远不同⼀类的距离。
2.分类
这⾥⾯⽤到的代码是clasifier.py⽂件,可以通过刚才训练好的模型与⾃⼰的⼩数据集训练⼀个⼩的分类器,其原理就是利⽤之前训练所提取出的特征向量利⽤⽀持向量机进⾏分类,下⾯贴出主要更改的位置:
def parse_arguments(argv):
random翻译parser = argparse.ArgumentParser()
parser.add_argument('--mode',type=str, choices=['TRAIN','CLASSIFY'],
help='Indicates if a new classifier should be trained or a classification '+
'model should be used for classification', default='CLASSIFY')#CLASSIFY更改模式,先TRAIN,运⾏后再CLASSIFY
parser.add_argument('--data_dir',type=str,
help='Path to the data directory containing aligned LFW face patches.',
default = r'D:\research\understand_facenet-master\understand_facenet\my_dataset\quexian')#数据集
parser.add_argument('--model',type=str,
help='Could be either a directory containing the meta_file and ckpt_file or a model protobuf (.pb) file',
default=r'D:\research\understand_facenet-master\understand_facenet\models\facenet\20200519-215056')#刚才训练好的模型注意不是最开始的百度⽹盘模型
parser.add_argument('--classifier_filename',
help='Classifier model file name as a pickle (.pkl) file. '+
'For training this is the output and for classification this is an input.',
default='D:/research/understand_facenet-master/understand_facenet/pick/classifier.pkl')#运⾏TRAIN时会⽣成⼀个pkl⽂件,以备分类时⽤
parser.add_argument('--use_split_dataset',
help='Indicates that the dataset specified by data_dir should be split into a training and test set. '+
'Otherwise a separate test set can be specified using the test_data_dir option.', action='store_true')
parser.add_argument('--test_data_dir',type=str,
help='Path to the test data directory containing aligned images used for testing.')
parser.add_argument('--batch_size',type=int,
help='Number of images to process in a batch.', default=3)
parser.add_argument('--image_size',type=int,
help='Image size (height, width) in pixels.', default=160)
parser.add_argument('--seed',type=int,
help='Random seed.', default=666)
parser.add_argument('--min_nrof_images_per_class',type=int,
help='Only include classes with at least this number of images in the dataset', default=5)
parser.add_argument('--nrof_train_images_per_class',type=int,
help='Use this number of images from each class for training and the rest for testing', default=45)
return parser.parse_args(argv)
它有两种模式,TRAIN和CLASSIF即训练和分类两种模式,先进⾏TRAIN⽣成⼀个pkl⽂件,然后再运⾏CLASSIF模式去分类.
如果好奇pkl中存储的是什么我们可以⽤程序打开看⼀下:
import pickle
fr =open(r'D:\research\understand_facenet-master\understand_facenet\pick\classifier.pkl','rb')#open的参数是pkl⽂件的路径
inf = pickle.load(fr)#读取pkl⽂件的内容
print(inf)
fr.close()
这⾥⾯还是有两个参数很重要,min_nrof_images_per_class和nrof_train_images_per_class,前者还是不要超过⾃⼰的类别数⽬,后者在不报错的情况下尽可能⼤⼀些,从⼩向⼤依次试验的去调,因为运⾏时间很快,可以多做⼏次试验,如果顺利,精度会不断增加。这个参数的具体意思就是每⼀类⽤多少数据去训练,剩下的就是⽤来测试的数据,因此当然训练数据越多越好⼀些,⼀般8:2即可,然后可以发现训练和分类的打印数据显⽰加和就是你的⼀共放⼊数据的数⽬。
训练模式:
分类模式:
可以看出176+48就是我的数据集数⽬,这⾥通过不断的调整参数,使训练模式的图⽚要尽可能的多于分类模式的图⽚,这样分类的效果会越来越好。
数据的制作很简单:
由于同样需要数据的尺⼨是160*160,这⾥提⼀下可以去resize也可以⾃⼰截图
最后说明⼀下,如果在训练过程中有什么错误很可能就是库的问题,更换⼀下应该会有所解决,欢迎⼤家⼀起讨论。
分类结果。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论