数据集预处理

(1)对每一张图片进行resize, resize到特定的大小50*150

(2)rebalance处理,对少数类样本进行随机选择n张进行数据增强之后重新加入到dataset中。

(3)划分训练集和测试集,0.2

(4)对训练集进行数据增强。 扩大训练数据量。 (操作包括: 翻转,滤波等)

#-*- encoding: utf-8 -*-import os, sys, cv2
import numpy as np
import randomimage_cnt = 0
MIN_HEIGHT = 120           #处理的最小尺寸
MIN_WIDTH = 40
targetLabel = []positive_cnt = 0
negative_cnt = 0def readImage( filePath , targetDir ): #制定标签global image_cnt, positive_cnt, negative_cntglobal targetLabelif not os.path.isdir( filePath ):print('{} is not a dir'.format(filePath))return NonelistFile = os.listdir( filePath )labelDict = {}with open( filePath + 'Label.txt', 'r') as reader:for line in reader:lines = line.split()for i in range(1, len(lines)):if lines[i] == 'personalMale': #男设为1label = 1elif lines[i] == 'personalFemale': #女设为0label = 0else:continuelabelDict[lines[0]] = labelbreakfor i in range(len(listFile)):if len(listFile[i]) > 4 and (listFile[i][-4:] == '.bmp' or listFile[i][-4:] == '.jpg' or \listFile[i][-4:] == '.png' or listFile[i][-5:] == '.jpeg'):imageName = filePath + listFile[i]img = cv2.imread( imageName )if not img.data:continueheight, width = img.shape[:2]if height < MIN_HEIGHT or width < MIN_WIDTH:continuefileName = str( image_cnt ) + '.jpeg'identity = listFile[i].find('_') if  identity == -1:identity = len(listFile[i]) idd = listFile[i][:identity]if labelDict.has_key( idd ) :targetLabel.append([ fileName, labelDict[idd]])if labelDict[idd] == 0:negative_cnt += 1else:positive_cnt += 1img = cv2.resize(img, (50, 150), interpolation=cv2.INTER_CUBIC) #60*60cv2.imwrite(targetDir + fileName, img)image_cnt += 1else:print('file {} do not have label'.format(listFile[i]) )####### pyramid operator
def MinAndEnlarge(img, Minus_pixel = 3):   #定义放缩图片大小50*150img = img[(3*Minus_pixel):(150 - 3*Minus_pixel), Minus_pixel:(50 - Minus_pixel), :]img = cv2.resize(img, (50, 150), interpolation = cv2.INTER_CUBIC )return img####### rotate operator
def Flip(img, operator = 1):if operator == 1:img = cv2.flip(img, 1)else:img = cv2.flip(img, 0)return img####### median blurring the image
def Blur(img, kernel_size=5):img = cv2.medianBlur(img, kernel_size)return imgdef saveLabel( targetDir ):      #存储标签global targetLabelwith open(targetDir + 'label.txt', 'w') as writer:for i in range(len(targetLabel)):writer.write( str( targetLabel[i][0] ) + ' ' + str(targetLabel[i][1]) + '\n' )##### ReBalance operator
#######  num (the number of minority class should added)
#######  n_or_p (the label of minority class)
#######  op_chose( 1--symmetrical flip; 0--rotate image; )
def ReBalance( targetDir, num, n_or_p, op_chose = 0):  #平衡正负样本global targetLabel, image_cnt total_sample = len(targetLabel)Contain = {}while 1:if num <= 0:breakkey_id = random.randint(0, total_sample-1)if Contain.has_key( key_id ) or targetLabel[key_id][1] != n_or_p:continueimg = cv2.imread( targetDir + targetLabel[key_id][0] )if op_chose == 0:img = cv2.flip(img, 1) elif op_chose == 1:img = cv2.flip(img, 0)fileName = str(image_cnt) + '.jpeg' cv2.imwrite(targetDir + fileName, img)image_cnt += 1 targetLabel.append([fileName, n_or_p])num -= 1print('Finish add {} images'.format(image_cnt - total_sample)) print('Now the class is balanced and total num is {}'.format(image_cnt)) print('image_cnt is {} and len(_targetLabel_) is {} '.format(image_cnt, len(targetLabel)))def DivideSet( targetDir, trainDir, testDir, test_ratio = 0.20):global targetLabeltotal_sample = len(targetLabel)assert( test_ratio < 1 )test_num = int(test_ratio * total_sample)test_half_num = test_num //2 ; ml_cnt = test_half_num; fm_cnt = test_half_num testLabel = [] ; trainLabel = [] ; testDict = {}while ml_cnt > 0 or fm_cnt > 0:idd = random.randint(0, total_sample-1)if testDict.has_key( targetLabel[idd][0] ):continueif targetLabel[idd][1] == 1 and ml_cnt > 0:img = cv2.imread( targetDir + targetLabel[idd][0] )cv2.imwrite( testDir + targetLabel[idd][0], img )testLabel.append( targetLabel[idd] )testDict[targetLabel[idd][0]] = iddml_cnt -= 1if targetLabel[idd][1] == 0 and fm_cnt > 0:img = cv2.imread( targetDir + targetLabel[idd][0] )cv2.imwrite( testDir + targetLabel[idd][0], img )testLabel.append( targetLabel[idd] )testDict[targetLabel[idd][0]] = iddfm_cnt -= 1for i in range(total_sample):if not testDict.has_key( targetLabel[i][0] ):trainLabel.append( targetLabel[i] )img = cv2.imread( targetDir + targetLabel[i][0] )cv2.imwrite( trainDir + targetLabel[i][0], img )## save the trainset and testsetwith open( trainDir + 'label.txt', 'w') as writer:for i in range(len(trainLabel)):writer.write( str( trainLabel[i][0] ) + ' ' + str(trainLabel[i][1]) + '\n' )   with open( testDir + 'label.txt', 'w') as writer:for i in range(len(testLabel)):writer.write( str(testLabel[i][0]) + ' ' + str(testLabel[i][1]) + '\n')print('has divide into train with {} samples and test with {} samples'.format(len(trainLabel), len(testLabel)) ) return trainLabel, testLabeldef EnlargeTrain( fileDir, targetDir, trainLabel , start_cnt):      #扩大训练集total_sample = len(trainLabel)new_cnt = start_cnt    for i in range(total_sample):img = cv2.imread( fileDir + trainLabel[i][0] )fileLabel = trainLabel[i][1]if not img.data:print('no exits image file {}'.format( fileDir + trainLabel[i][0]) )continue#img1 = MinAndEnlarge(img, 3)fileName = str(new_cnt) + '.jpeg'cv2.imwrite( targetDir + fileName, img1 )new_cnt += 1trainLabel.append( [fileName, fileLabel] )#img2 = Flip(img1)fileName = str(new_cnt) + '.jpeg'cv2.imwrite( targetDir + fileName, img2 )new_cnt += 1trainLabel.append( [fileName, fileLabel] )#img3 = Blur(img, 5)fileName = str(new_cnt) + '.jpeg'cv2.imwrite( targetDir + fileName, img3 )new_cnt += 1trainLabel.append( [fileName, fileLabel] )#img4 = Blur(img1, 5)fileName = str(new_cnt) + '.jpeg'cv2.imwrite( targetDir + fileName, img4 )new_cnt += 1trainLabel.append([fileName, fileLabel])#img5 = Blur(img2, 5)fileName = str(new_cnt) + '.jpeg'cv2.imwrite( targetDir + fileName, img5 )new_cnt += 1trainLabel.append([fileName, fileLabel])print('The total number of training images is {}'.format(new_cnt))with open( targetDir + 'label.txt', 'w') as writer:for i in range(len(trainLabel)):writer.write( str( trainLabel[i][0] ) + ' ' + str(trainLabel[i][1]) + '\n' )print('The trainLabel size is {}'.format(len(trainLabel)) )if __name__ == '__main__':fileHead = 'D:/caffe/caffe-master/data/myself/PETA/PETA dataset/'filePath = ['3DPeS', 'CAVIAR4REID', 'CUHK', 'GRID','MIT', 'PRID']     #原数据集路径,因为太多很慢,只用了一半数据##,'SARC3D','TownCentre', 'VIPeR','i-LID'##] savePath = 'D:/caffe/caffe-master/data/chuliDATA/'                          #处理后的数据和标签存放地址for i in range(len(filePath)):path = fileHead + filePath[i] + '/archive/'print ('runing dataset {}'.format(filePath[i]) ) readImage( path, savePath )print ('The cnt is {}'.format( image_cnt ))#EnlargeData( savePath, savePath )saveLabel( savePath )print( 'we have {} positive labels and {} negative labels '.format( positive_cnt, negative_cnt ))if positive_cnt > negative_cnt:add_num = positive_cnt - negative_cntReBalance( savePath, add_num, 0, 0)else:add_num = negative_cnt - positive_cntReBalance( savePath, add_num, 1, 0)print('The total dataset is in {}'.format(savePath))TrainsavePath = 'D:/caffe/caffe-master/data/myself/petaTrain/'       #训练集存放地址TestsavePath = 'D:/caffe/caffe-master/data/myself/petaTest/'     #测试集存放地址trainLabel, testLabel =  DivideSet(savePath, TrainsavePath, TestsavePath, 0.2 )        #0.2比例划分start_cnt = len(targetLabel)EnlargeTrain( TrainsavePath, TrainsavePath, trainLabel, start_cnt )print('the end')

完成后得到训练集56460,测试集2361
这里图片越大,数据集越大,训练的越慢,还可能爆显存,不得不降低batchsize,图片大小对准确率的影响还不清楚

转换格式

#!/usr/bin/env sh
# Create the imagenet lmdb inputs
# N.B. set the path to the imagenet train + val data dirsEXAMPLE=D:/caffe/caffe-master/data/myself/convertdata
DATA=D:/caffe/caffe-master/data/myself/
TOOLS=D:/caffe/caffe-master/Build/x64/ReleaseTRAIN_DATA_ROOT=D:/caffe/caffe-master/data/myself/petaTrain/
VAL_DATA_ROOT=D:/caffe/caffe-master/data/myself/petaTest/echo "Creating train lmdb..."GLOG_logtostderr=1 $TOOLS/convert_imageset \--shuffle=1 \$TRAIN_DATA_ROOT \$DATA/petaTrain/label.txt \$EXAMPLE/peta_train_lmdbecho "Creating val lmdb..."GLOG_logtostderr=1 $TOOLS/convert_imageset \--shuffle=1 \$VAL_DATA_ROOT \$DATA/petaTest/label.txt \$EXAMPLE/peta_val_lmdbecho "Done."
#需要提前建立文件夹及空标签文件

得到2GB训练集,64M测试集

训练

采用他人的模型,修改描述文件复制到操作文件夹,使用命令行训练,修改模型描述文件如下

name: "petaNet"
layer {name: "peta"type: "Data"top: "data"top: "label"include{phase: TRAIN}data_param{source:"D:/caffe/caffe-master/data/myself/convertdata/peta_train_lmdb"batch_size:32backend: LMDB}
}layer {name: "peta"type: "Data"top: "data"top: "label"include{phase: TEST}data_param{source:"D:/caffe/caffe-master/data/myself/convertdata/peta_val_lmdb"batch_size:100backend: LMDB}
}### ------------layer {name: "conv1"type: "Convolution"bottom: "data"top: "conv1"param {lr_mult: 1}param {lr_mult: 2}convolution_param {num_output: 20kernel_size: 3stride: 1weight_filler {type: "xavier"}bias_filler {type: "constant"}}
}
layer {name: "relu1"type: "ReLU"bottom: "conv1"top: "conv1"
}##-------
# Inception 3a
##-------layer {name: "inc1_conv1"bottom: "conv1"top: "inc1_conv1"type: "Convolution"param { lr_mult: 1 }param { lr_mult: 2 }convolution_param {num_output: 20kernel_size: 7stride: 1weight_filler { type: "xavier" }bias_filler { type: "constant" }}
}
layer {name: "inc1_conv1_relu"type: "ReLU"bottom: "inc1_conv1"top: "inc1_conv1"
}layer {name: "inc1_conv2_1"type: "Convolution"bottom: "conv1"top: "inc1_conv2_1"param { lr_mult: 1 }param { lr_mult: 2 }convolution_param {num_output: 50kernel_size: 3stride: 1weight_filler { type: "xavier" }bias_filler { type: "constant" }}
}
layer {name: "inc1_conv2_1_relu"type: "ReLU"bottom: "inc1_conv2_1"top:    "inc1_conv2_1"
}layer {name: "inc1_conv2_2"type: "Convolution"bottom: "inc1_conv2_1"top:    "inc1_conv2_2"param { lr_mult: 1 }param { lr_mult: 2 }convolution_param {num_output: 50kernel_size: 3stride: 1weight_filler { type: "xavier" }bias_filler { type: "constant" }}
}
layer {name: "inc1_conv2_2_relu"type: "ReLU"bottom: "inc1_conv2_2"top: "inc1_conv2_2"
}layer {name: "inc1_conv2_3"type: "Convolution"bottom: "inc1_conv2_2"top:    "inc1_conv2_3"param { lr_mult: 1 }param { lr_mult: 2 }convolution_param {num_output: 50kernel_size: 3stride: 1weight_filler { type: "xavier" }bias_filler { type: "constant" }}
}
layer {name: "inc1_conv2_3_relu"type: "ReLU"bottom: "inc1_conv2_3"top:    "inc1_conv2_3"
}layer {name: "inc1_conv3_1"type: "Convolution"bottom: "conv1"top:    "inc1_conv3_1"param { lr_mult: 1 }param { lr_mult: 2 }convolution_param {num_output: 20kernel_size: 5stride: 1weight_filler { type: "xavier" }bias_filler { type: "constant" }}
}
layer {name: "inc1_conv3_1_relu"type: "ReLU"bottom: "inc1_conv3_1"top: "inc1_conv3_1"
}layer {name: "inc1_conv3_2"type: "Convolution"bottom: "inc1_conv3_1"top:    "inc1_conv3_2"param { lr_mult: 1 }param { lr_mult: 2 }convolution_param {num_output: 20kernel_size: 3stride: 1weight_filler { type: "xavier" }bias_filler { type: "constant" }}
}
layer {name: "inc1_conv3_2_relu"type: "ReLU"bottom: "inc1_conv3_2"top:    "inc1_conv3_2"
}layer {name: "inc1_concat"type: "Concat"bottom: "inc1_conv1"bottom: "inc1_conv2_3"bottom: "inc1_conv3_2"top:    "inc1_concat"
}#-----end of Inception 3alayer {name: "pool1"type: "Pooling"bottom: "inc1_concat"top: "pool1"pooling_param {pool: MAXkernel_size: 2stride: 2}
}##------
# Inception 2B
##------layer {name: "inc2_conv1_1"type: "Convolution"bottom: "pool1"top: "inc2_conv1_1"param { lr_mult: 1 }param { lr_mult: 2 }convolution_param {num_output: 120kernel_size: 3stride: 1weight_filler { type: "xavier" }bias_filler { type: "constant" }}
}
layer {name: "inc2_conv1_1_relu"type: "ReLU"bottom: "inc2_conv1_1"top: "inc2_conv1_1"
}layer {name: "inc2_conv1_2"type: "Convolution"bottom: "inc2_conv1_1"top:    "inc2_conv1_2"param { lr_mult: 1 }param { lr_mult: 2 }convolution_param {num_output: 120kernel_size: 3stride: 1weight_filler { type: "xavier" }bias_filler { type: "constant" }}
}
layer {name: "inc2_conv1_2_relu"type: "ReLU" bottom: "inc2_conv1_2"top: "inc2_conv1_2"
}layer {name: "inc2_conv2"type: "Convolution"bottom: "pool1"top:    "inc2_conv2"param { lr_mult: 1 }param { lr_mult: 2 }convolution_param {num_output: 120kernel_size: 5stride: 1weight_filler { type: "xavier" }bias_filler { type: "constant" }}
}
layer {name: "inc2_conv2_relu"type: "ReLU"bottom: "inc2_conv2"top:    "inc2_conv2"
}layer {name: "inc2_concat"type: "Concat"bottom: "inc2_conv1_2"bottom: "inc2_conv2"top: "inc2_concat"
}##----end of Inception 2Blayer {name: "pool2"type: "Pooling"bottom: "inc2_concat"top:    "pool2"pooling_param {pool: MAXkernel_size: 2stride: 2}
}layer {name: "fc1"type: "InnerProduct"bottom: "pool2"top:    "fc1"param { lr_mult: 1 }param { lr_mult: 2 }inner_product_param {num_output: 2weight_filler { type: "xavier" }bias_filler { type: "constant" }}
}#### ----------
layer {name: "accuracy"type: "Accuracy"bottom: "fc1"bottom: "label"top:"accuracy"include{phase: TEST}
}layer {name: "loss"type: "SoftmaxWithLoss"bottom: "fc1"bottom: "label"top:"loss"
}

主要修改了全连接层输出个数,输入层来源等。

修改solver如下

# 训练网络描述文件
# The train/test net protocol buffer definition
net: "D:/caffe/caffe-master/data/myself/petaNet-train-test.prototxt"# 测试全部测试集的迭代次数
test_iter: 23
# 每500次迭代测试一次
test_interval: 500
# T基础学习率,上一次梯度更新的权重,权重衰减项,防止过拟合
base_lr: 0.0001
momentum: 0.9
weight_decay: 0.0005
# 学习率变化方式
lr_policy: "inv"
gamma: 0.0001
power: 0.75
# 每100次展示一次准确率
display: 100
# 最大迭代次数
max_iter: 10000
# 每5000次迭代得到一个模型
snapshot: 5000
snapshot_prefix: "D:/caffe/caffe-master/data/myself/Net/"
# 用cpu或gpu
solver_mode: GPU

一开始出现爆显存的问题,方法是把batch-size变小,或者把图片变小,对准确率影响尚不知
之后出现loss不变,始终为87.3365,网上查到原因很多,总结下有以下几种解决办法

  1. 降低学习率,提高batchsize,最初为0.01,一直往小调
  2. 降低weight 没尝试
  3. 输入归一化
  4. 查看输入数据、标签是否有异常 应该没有数据错误
  5. 数据shuffle
  6. batch normalization的设置 未尝试

最终改来改去就可以了,大多数情况下应该是学习率问题,以及在网上查看了loss变化与准确率变化情况。

于是最终得到准确率76的模型,若数据集再大一些,应该可以达到80左右,但太慢了,放弃尝试,也可能是学习率比较小导致收敛比较慢,用数据集测试准确率也是76左右。但是准备单张图片测试时,永远预测为0,应该是我的代码写错了,目前没解决。将loss和accuracy生成可视化曲线没解决。

Peta数据集识别性别相关推荐

  1. 用姓名识别性别对超级飞侠中的人物性别进行统计

    有一天傍晚,在陪孩子看完一集又一集的动画片<超级飞侠>的时候,我发现每集的主人公性别不是有规律的,然后就无聊的想统计一下男性和女性的性别,就是想知道<超级飞侠>有没有间接暗示小 ...

  2. 机器学习Tensorflow基于MNIST数据集识别自己的手写数字(读取和测试自己的模型)

    机器学习Tensorflow基于MNIST数据集识别自己的手写数字(读取和测试自己的模型)

  3. 根据×××号码识别性别年龄生日的JS代码

    根据×××号码识别性别年龄生日的JS代码: function discriCard(){ //获取输入×××号码 var UUserCard = ""; //获取出生日期 UUse ...

  4. vue 身份证校验、识别性别/生日/年龄

    vue 身份证格式校验_chen_ai_tao的博客-CSDN博客_vue 身份证校验 Vue中根据输入的身份证号识别年龄.性别_cx&lavender的博客-CSDN博客_vue中根据省份证 ...

  5. 【计算机视觉40例】案例40:识别性别与年龄

    [导读]本文是专栏<计算机视觉40例简介>的第40个案例<识别性别与年龄>.该专栏简要介绍李立宗主编<计算机视觉40例--从入门到深度学习(OpenCV-Python)& ...

  6. java 跟据身份证识别性别年龄

    java 跟据身份证识别性别年龄 package com.bdzk.sys.config.utils;import java.text.SimpleDateFormat; import java.ut ...

  7. Opencv 深度学习识别性别和检测年龄

    目录 1基于CNN的性别分类建模原理 1.1 人脸识别 1.2 性别预测 1.3 年龄预测 1.4 结果 2 代码 参考 本教程中,我们将讨论应用于面部的深层学习的有趣应用.我们将估计年龄,并从单个图 ...

  8. 深度学习之基于卷积神经网络实现超大Mnist数据集识别

    在以往的手写数字识别中,数据集一共是70000张图片,模型准确率可以达到99%以上的准确率.而本次实验的手写数字数据集中有120000张图片,而且数据集的预处理方式也是之前没有遇到过的.最终在验证集上 ...

  9. TensorFlow:实战Google深度学习框架(四)MNIST数据集识别问题

    第5章 MNIST数字识别问题 5.1 MNIST数据处理 5.2 神经网络的训练以及不同模型结果的对比 5.2.1 TensorFlow训练神经网络 5.2.2 使用验证数据集判断模型的效果 5.2 ...

  10. 语音性别识别_语音识别识别性别_语音文字识别 - 云+社区 - 腾讯云

    广告关闭 腾讯云双11爆品提前享,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高满返5000元! 一句话识别,错误码,产品简介,产品优势,应用场景,计费概述,购买方式,欠费说明,功 ...

最新文章

  1. fprintf、printf、sprintf、fscanf、scanf、sscanf 格式化输入输出
  2. 利用kickstart自动安装虚拟机
  3. H5移动端开发学习总结
  4. Scala _01介绍安装使用
  5. Taro+react开发(2)--简介2
  6. python——rang函数、for、braek循环
  7. Spring框架声明式事务管理
  8. 优秀的测试网站(转载)
  9. HYSBZ/BZOJ 1007 [HNOI2008] 水平可见直线 - 计算几何
  10. AI2想从常识测试开始让AI理解物理世界,数据集已公布
  11. 基于java的智能手表_基于安卓Android智能手环(计步器)APP设计(含录像)
  12. Ubuntu12.04 64位 无法运行32位程序 吉林大学校园网客户端Drcom DrClient
  13. 【火炉炼AI】机器学习023-使用层次聚类算法构建模型
  14. 删除打印机重新安装驱动
  15. 计算机会计内容是什么,会计电算化包括什么内容
  16. (FAQ)现购的采购发票保存时提示:超过最大可钩稽数值[金蝶K/3]
  17. opencv图像处理-常见绘图函数
  18. 限行的处罚标准是什么
  19. Lesson_3 作业_1 ---- 十六进制转换器
  20. 微信小程序--订阅消息推送

热门文章

  1. YYC松鼠短视频系统完整版的文件结构目录介绍以及自定义目录详解
  2. 这款萌到吐血的医疗无人机,速度惊人且支持空气动力充电
  3. 关于长城!你可能不知道......
  4. p2psear正在连接服务器,P2PSearcher无法连接到网络,也无法连接到服务器
  5. 学术写作 系列1 HOW TO WRITE AN INTRODUCTION
  6. Golang 企业级web后端框架
  7. 【mud】xyj450里的toy下的buwawa脚本问题
  8. 基本类型偏执-平行继承体系-令人着迷的暂时值域
  9. tic tac toe php,Python函数找出tic tac toe获胜者
  10. 程序员进阶必看!Java进阶书籍推荐