第一part:手把手教你用tensorflow object-detection API 训练自己的模型

第一part:手把手教你用tensorflow object-detection API 训练自己的模型

  • 机器和系统的配置
    • 1.原理
      • 1.1使用迁移学习的好处:
      • 2. 准备训练自己数据集
        • 2.1 找图片
      • 3. 打标签
      • 4. 转换标签文件 XML--->CSV--->TFRecord
      • 5. 训练自己的模型
      • 6. 检测我们训练的模型

机器和系统的配置

方法一:本人使用系统是Ubuntu16.04 LTS GPU是 GeForce GTX 1050Ti(实验室没钱买更好的GPU了),具体教程到CSDN上或google上搜一下,大概花半天的时间就能全部装好。PS:最好别在windows上跑,真的超级多bug,当时我跑官网上的模型调bug都调了二天,可能自己太笨。。不能的同学在GitHub上搜索lantern上面有中文教程教你。https://github.com/getlantern/download, 做学术我想应该不会被查水表吧hhhhh.

方法二:选择腾讯云或者阿里云或Google的云服务,这样更加方便,直接在服务器上跑,有按使用时间计费的,算起来也不贵。

接下来主要记录跑自己的数据集遇到的困难和解决的方法,适合想做训练自己数据集的同学,比如你想识别柠檬和橘子,但是找不到现成的模型。有其他疑问可以留言或者参考CSDN上的一些人的博客 ,如果有错误的地方,希望大家能在留言处及时指正!!Thx:)

1.原理

这里的原理是迁移学习(transfer learning),维基百科上迁移学习的定义是:(属于机器学习)专注于存储已有问题的解决模型,并将其利用在其他不同但相关的问题上,例如:用来识别汽车的知识,也可以用来识别卡车。

1.1使用迁移学习的好处:

1.在最终结果精度差不多的情况下,迁移学习训练的时间大大的缩短了,能节约大量的时间和硬件资源。(有paper做了对比实验,使用迁移学习后识别的精度比自己从头开始训练的精度结果持平或者更高。)

2.每个人想识别的模型都不会完全一样,如果恰好该模型的数据集很难找到,或者说数据集非常小,原本是无法用深层的神经网络的,因为此网络参数太多,如果数据集小的话,会造成结果过拟合。

3.避免自己造轮子。“造轮子”的含义:明知道你做的不可能比前辈做得更好,却仍然坚持要做。
  比如,车轮子是圆形的,这是大家公认的最合适的形状。而自己非要发明另一种形状的轮子,这种行为就叫「重复发明轮子(Reinventing the wheel)」,即“造轮子”。
  这样会浪费自己的大量的时间和精力,毕竟得到的结果也会很不理想。
  (P.S :在这个part用到的迁移学习的知识后面还会详细再讲)

2. 准备训练自己数据集

2.1 找图片

step1: 在桌面上右键,新建文件夹改名为 object-detection,然后再文件夹下创建images.

step2:在GitHub上下载一个超级火的项目:https://github.com/hardikvasa/google-images-download 下载图片(或者到imagenet dataset里下载,不过需要注册账号,有三种安装方式,我选的是Manually install using CLI:(也是在桌面上)输入:
$ git clone https://github.com/hardikvasa/google-images-download.git
$ cd google-images-download && sudo python setup.py install
安装成功,点开桌面上的google-images-down文件夹,右键点击open in terminal,输入命令 $ googleimagesdownload [Arguments…],例如我准备识别的是螺钉(screw)和螺母(bolt nut),中文也可以搜出来下载,不过感觉英文更准确一点,输入 $ googleimagesdownload -k “kobe” -f jpg -l 5 (意思就是下载关键词“kobe”,类型JPG,数量5张),在download文件夹会出现你下载图片的文件夹,并且已经跟你编好号。如图:第一part:手把手教你用tensorflow object-detection API 训练自己的模型_第1张图片

如果想要一次性下载超过100张图片,就需要Installing the chromedriver (with Selenium),不然就会报错。
第一part:手把手教你用tensorflow object-detection API 训练自己的模型_第2张图片

在Google上面搜索如何安装,就会有以下步骤:
这些命令都可以在桌面进行,下载的文件等等都放在桌面就好。
Step1: Prerequisites

   $ sudo apt-get update
   $ sudo apt-get install -y unzip xvfb libxi6 libgconf-2-4

Step 2 – Install Google Chrome (有这个浏览器的不用安装)

$ sudo curl -sS -o - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add
$ sudo echo "deb [arch=amd64]  http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list
$ sudo apt-get -y update
$ sudo apt-get -y install google-chrome-stable

Step 3 – Install ChromeDriver (step2跳过的同学需要在https://sites.google.com/a/chromium.org/chromedriver/downloads)找到自己浏览器对应的版本并安装,如果版本太低建议先升级自己的浏览器)

$ wget https://chromedriver.storage.googleapis.com/2.41/chromedriver_linux64.zip
$ unzip chromedriver_linux64.zip
$ sudo mv chromedriver /usr/bin/chromedriver
$ sudo chown root:root /usr/bin/chromedriver
$ sudo chmod +x /usr/bin/chromedriver

Step 4 – Download Required Jar Files

$ wget https://selenium-release.storage.googleapis.com/3.13/selenium-server-standalone-3.13.0.jar
$ wget http://www.java2s.com/Code/JarDownload/testng/testng-6.8.7.jar.zip
$ unzip testng-6.8.7.jar.zip

Step 5 – Start Chrome via Selenium Server

$ xvfb-run java -Dwebdriver.chrome.driver=/usr/bin/chromedriver -jar selenium-server-standalone-3.13.0.jar
$ chromedriver --url-base=/wd/hub  

这两个命令输入完后,点开googleimagesdownload文件输入

 $ googleimagesdownload   -k  "kobe"    -f  jpg   -l  200  --chromedriver="usr/bin/chromedriver"

第一part:手把手教你用tensorflow object-detection API 训练自己的模型_第3张图片

3. 打标签

把下载的图片全部放到images文件夹里,接下来的一步就是给图片打标签了,为什么要有这一步呢?因为训练数据集就是希望它的LOSS达到最小,原始的数据集必须要有标签。打标签的工具选择github上的labelimg工具(https://github.com/tzutalin/labelImg),如果你想识别人脸的话,可以尝试下labelme工具。安装命令如下:
Python 3 + Qt5 (Recommanded)

$ sudo apt-get install pyqt5-dev-tools
$ sudo pip3 install -r requirements/requirements-linux-python3.txt
$ make qt5py3
$ python3 labelImg.py

这时候就弹出了QT的窗口,我们可以修改open dir 和 save dir 把这个两个路径设为相同,使生成的标签和图片在一个文件夹下面。
例如下图:第一part:手把手教你用tensorflow object-detection API 训练自己的模型_第4张图片
打标签的快捷键如下:
w -Create a rect box(自己填标签)
d -Next image
a -Previous image
ctrl+s-Save label
如图,大概500张图片花了2个小时打标签打完。接下来,在images下创建两个文件夹分别使 test 和 train, 我们选择20%的图片复制图片和对应的标签放入test文件夹,剩下的80%放入train文件夹。

图片已经准备好了,最艰难的时刻已经过去啦

4. 转换标签文件 XML—>CSV—>TFRecord

我们用labelimg打出来的标签是XML文件,最终在机器学习中使用的文件必须是TFRecord文件,为此我们需要运用两个py脚本,xml_to_csv.py和 generate_tfrecord.py。首先放上原始脚本,然后把其中的代码做一些修改。(这里用到datitran’s github,感谢:) 链接: link.)
step1:点击连接,点击xml_to_csv.py,点击右边的 raw,复制全部代码。
step2:在object-detection的目录下,新建文件,重命名为xml_to_csv.py,将代码复制到文件里。
step3 :修改部分代码并保存:

def main():
   image_path = os.path.join(os.getcwd(), 'annotations')
   xml_df = xml_to_csv(image_path)
   xml_df.to_csv('raccoon_labels.csv', index=None)
   print('Successfully converted xml to csv.')

改为:

def main():
      for directory in ['train','test']:
         image_path = os.path.join(os.getcwd(), 'images/{}'.format(directory))
         xml_df = xml_to_csv(image_path)
         xml_df.to_csv('data/{}_labels.csv'.format(directory), index=None)
         print('Successfully converted xml to csv.')

step4:在object-detection 创建两个文件夹分别是data和training。并且在object-detection 点击打开终端,输入如下命令python xml_to_csv.py。运行成功后,此时在data文件夹下就会出现两个文件。分别是
step5: 继续在datitran’s github的页面,找到generate_tfrecord.py文件,同理将代码复制到object-detection下。
step6 :修改部分代码。 这里唯一要修改的代码只是class_text_to_int 函数,例如我的修改:(如果你的类别超过一类的话,就在if else 不断往下加就行,记住始终是从1开始。)

 def class_text_to_int(row_label):
    if row_label == 'screw':
       return 1
    else:
       None
    if row_label == 'bolt nut':
       return 2
    else:
       None

step7 : Install the object detection API.(如果已经下载了并且进行了setup.py的同学可以跳过这一步)
首先:讲物体检测的model 克隆到桌面:

  $ git clone https://github.com/tensorflow/models.git
  $ sudo apt-get install protobuf-compiler python-pil python-lxml
  $ sudo pip install jupyter
  $ sudo pip install matplotlib

然后 在下载的 tensorflow/models/research的目录下,运行代码:

 $ protoc object_detection/protos/*.proto --python_out=.

没有报错就不用管了,如果这行代码报错,检查它的版本运行命令 protoc --version ,如果想升级版本进入 https://github.com/protocolbuffers/protobuf/releases 下载相对应系统的版本,解压到目录,输入如下命令:

$ sudo ./configure
$ sudo make check
$ sudo make install

然后继续运行上述代码,

$ protoc object_detection/protos/*.proto --python_out=.

最后在 tensorflow/models/research目录下输入

$ export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim

结尾的命令是,在model/research下运行:

$ sudo python3 setup.py install

这时就可以run generate_tfrecord.py文件了

step8 :在object-detection下输入命令

 $ python generate_tfrecord.py --csv_input=data/test_labels.csv --output_path=data/test.record --image_dir=images/test/
 $ python generate_tfrecord.py --csv_input=data/train_labels.csv --output_path=data/train.record --image_dir=images/train/

OK 到这里已经完成了前期的任务,此时你的文件目录应该是这样的:

Object-Detection
-data/
----test_labels.csv
----train_labels.csv
----test.record
----train.record
-images/
----test/
----------testingimages.jpg
----------对应的标签.xml
----train/
----------testingimages.jpg
----------对应的标签.xml
----你所有的图.jpg
----对应的标签.xml
-training
-xml_to_csv.py
-generate_tfrecord.py

5. 训练自己的模型

原理:这个做法的原理

transfer learning
pre-training
fine-tuning:
checkpoint:保存了网络的权重和偏置等参数
configuration file:规定了网络训练的一些参数

我们使用预训练的模型(一般的参数量比较大),进行fine-tuning操作(修改config文件里的一些训练参数,例如训练步数等),用来训练我们自己的模型。

能这样做的原理是:许多low-level的features 代表一些边边角角,而high-level features代表具体物体的大致轮廓,能使用迁移学习的主要原因是两张不同的种类的图片,它们的low-level features具有很高的相似性,所以可以拿过来直接使用,这样能节省更多的时间并能显著提高效率。

step1: 下载config file和checkpoints

config file在这里寻找:https://github.com/tensorflow/models/tree/master/research/object_detection/samples/configs 我选的是ssd_mobilenet_v2_coco.config。(大家可以选择自己想用的 config file和checkpoints模型,对比效果。)

checkpoints在这里寻找:https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md 我选择的训练模型是ssd_mobilenet_v2_coco,因为想把该应用植入到手机里,所以选的mobilnet,优点是速度快,识别精度相对不错。(speeds是31ms,COCO MAP是22)

step2:将config file 放到training文件中,解压ssd_mobilenet_v2_coco文件到models/object_detection目录。

step3:修改config file文件

1.我修改的num_classes=2(你识别的类型是多少就填几,这个操作相当于修改了网络结构的最后一层,改变其输出的类别是2)
2.在train_config中,适当修改batch_size,如果训练中错误,出现内存不够的警告。降低batch_size的值,我修改的batch_size=10。
3.fine_tune_checkpoint修改为其路径=ssd_mobilenet_v2_coco_2018_03_29/model.ckpt
4. num_steps代表训练loss的步数,默认的是200000步,我机器用着个步数训练太久了,我修改成了50000步.
5.在train_input_reader中,input_path修改为=data/train.record ,label_map_path修改为=training/object-detection.pbtxt
6.在eval_input_reader中,input_path修改为=data/test.record , label_map_path修改为=training/object-detection.pbtxt

step4: 在training 目录下新建文件,命名为object-detection.pbtxt,本列中只用识别两个,如果你识别两个以上的物体,一直按照这个形式往上加,记住要从id=1开始。
**
item {
id: 1
name: ‘screw’
}
item {
id: 2
name: ‘bolt nut’
}
**


现在的文件目录为:
Object-Detection
-data/
----test_labels.csv
----train_labels.csv
----test.record
----train.record
-images/
----test/
----------testingimages.jpg
----------对应的标签.xml
----train/
----------testingimages.jpg
----------对应的标签.xml
----你所有的图.jpg
----对应的标签.xml
-training
----object-detection.pbtxt
----ssd_mobilenet_v2_coco.config
-ssd_mobilenet_v2_coco
-xml_to_csv.py
-generate_tfrecord.py

如图:第一part:手把手教你用tensorflow object-detection API 训练自己的模型_第5张图片

step5: 将以下4个文件夹复制到下载的models/research/object_detection/legacy里
ssd_mobilenet_v2_coco
training
images
data

如果出现提醒,点击合并所有文件。
在legacy下面运行命令:python train.py --logtostderr --train_dir=training/ --pipeline_config_path=training/ssd_mobilenet_v2_coco.config

会出现以下情景:
INFO:tensorflow:global step 11788: loss = 1.6717 (0.398 sec/step)
INFO:tensorflow:global step 11789: loss = 1.5310 (0.436 sec/step)
INFO:tensorflow:global step 11790: loss = 1.6614 (0.405 sec/step)
INFO:tensorflow:global step 11791: loss = 1.7758 (0.460 sec/step)
INFO:tensorflow:global step 11792: loss = 1.7164 (0.378 sec/step)
INFO:tensorflow:global step 11793: loss = 1.8096 (0.393 sec/step)

此时你可以打开tensorboard去观察total loss,当训练步数到达一定步数时,tensorboard上的图才会记录值。机器训练的时候,你可以随时按ctrl + c 让程序终止,然后再输入train.py命令,机器会再上次你终止的步数那里继续训练。当total loss下降到一定值的时候就可以停止了,比如我的例子,训练到1.5后,再怎么训练都没有很明显的下降,就直接停止了,大概训练了6万步左右。打开tensorboard,在legacy下面运行命令,
tensorboard --logdir=‘training’ (最好用Google浏览器)
我的total loss graph 如下:
第一part:手把手教你用tensorflow object-detection API 训练自己的模型_第6张图片

训练完毕后,我们要看看训练后的效果。

6. 检测我们训练的模型

step1: 输出 the inference graph
在 models/research/object_detection目录下,有一个export_inference_graph.py文件。在当前目录输入以下命令:(例如我的,其中trained_checkpoint_prefix 的model.ckpt-10856 这个值每个人都不是相同的,自己要在training目录下看看,选择最大的数字,并且这个最大的数字要在3个文件中存在,例如存在model.ckpt-10856.data-00000-of-00001;model.ckpt-10856.index;model.ckpt-10856.meta。如果缺失一个文件,就选择第二大的数)
python export_inference_graph.py
–input_type image_tensor
–pipeline_config_path legacy/training/ssd_mobilenet_v2_coco.config
–trained_checkpoint_prefix legacy/training/model.ckpt-10856
–output_directory screw_n_bolt_inference_graph

screw_n_bolt_inference_graph在object-detection目录下,
如果这时出现错误:no module named ‘nets’
回到tensorflow/models/research目录下,输入命令
export PYTHONPATH=$PYTHONPATH:pwd:pwd/slim
再回到原目录输入上述命令。
运行完毕后,文件目录为:
screw_n_bolt_inference_graph
-saved_model
-checkpoint
-model.ckpt.data-00000-of-00001
-model.ckpt.meta
-model.ckpt.index
-pipeline
-screwnblot_frozen_inference_graph.pb

step2: 首先到网上找几张你要检测物体的照片,记住要找几张,既不在train集里,也不在test集里。然后到test集里找几张照片,并给它们一次命名为image3.jpg, image4.jpg…等等。并将这些图片放到models/research/object_detection/test_images目录下。

step3: 在models/research/object_detection目录下,运行命令jupyter notebook 点击 object_detection_tutorial.ipynb文件,进入demo界面。

step4: 修改demo的部分代码。
imports 不修改
Env setup 不修改
Object detection imports不修改

variables只留下以下四行代码:

MODEL_NAME = 'screw_n_bolt_inference_graph'

PATH_TO_CKPT = MODEL_NAME + '/frozen_inference_graph.pb'

PATH_TO_LABELS = os.path.join('legacy','training', 'object-detection.pbtxt')

NUM_CLASSES = 2

Download Model全部删除

Load a temsorflow model into memory不修改
Loading label map不修改
Helper code不修改

Detection修改的部分如下:其余不变

TEST_IMAGE_PATHS = [ os.path.join(PATH_TO_TEST_IMAGES_DIR, 'image{}.jpg'.format(i)) for i in range(3, 8) ]  (P.S这个范围根据你的图片多少去设定)

step5:点击cell --run all 结果如下:
第一part:手把手教你用tensorflow object-detection API 训练自己的模型_第7张图片
最后一张图,没有识别出来,可能是背景的原因让机器无法识别,总共我一共用了320张图片,能得到这样的效果算是挺不错的了。

P.S. 1.本流程参考了Youtube博主sentdex的object-detection的教程。
2.如有错误地方希望大家指出。
3.下一部分准备记录将这个软件系统移植到手机上,因为用的Mobile net,所以软件的大小比较友好。

你可能感兴趣的:(Ares)