이것 저것 하느라 블로그에 글 쓸 시간이 없었는데, 오늘 시간 내서 써봅니다.

먼저 저번 포스팅에서 데이터 수집과 라벨링까지 했었는데요. 이번에는 수집한 데이터를 가지고 custom model을 만들어 봅시다.

caffe는 설치했다고 가정하겠습니다. caffe 설치는 caffe home page 가면 자세히 나와있으니, 보고 하시면 됩니다.


1. Custom CNN을 만들자!


흠. 말 그대로 일단 Custom CNN model을 만들어야 하니 학습시킬 CNN 구조를 만들어줘야 합니다. Custom CNN 구조를 만드는 방법은 Caffe Tutorial에 자세히 나와있습니다. 하지만 이 포스팅에서는 귀찮으니 bvlc_reference_caffenet의 모델을 사용하도록 하겠습니다. caffe/models/bvlc_reference_caffenet directory에 들어가보면 deploy.prototxt, solver.prototxt, train_val.prototxt 파일이 있을겁니다. 만약 없으신분은 caffe github에서 다운받으시면 됩니다. 그럼 이 세개의 파일을 복사해서 자신이 원하는 폴더에 붙여넣기를 합니다. 저같은 경우는 caffe/models directory에 model_test_5라는 directory를 만들어서 붙여넣기를 하였습니다. 여기서 우리가 수정해줘야 할 파일은 solver.prototxt, train_val.prototxt 입니다. 먼저 train_val.prototxt를 살펴 보겠습니다.

빨간색으로 박스를 쳐 놓은 곳이 우리가 수집한 이미지로 만든 학습 데이터 경로입니다. 물론 아직 수집한 이미지를 데이터화 시키진 않았지만 수집한 이미지를 데이터화 시키는 작업은 Custom CNN의 구조와 밀접한 관계가 있으므로 train_val.prototxt 분석 먼저 하고 설명하도록 하겠습니다. (물론 진정한 CNN custom model을 만드는 작업을 하려면 이 CNN 구조도 스스로 만들어야겠죠. 하지만 여기서 그런것까지 일일히 설명하기에는 CNN에 대한 설명까지 나와야 하기 때문에 생략하도록 하겠습니다.) 

일단 위 그림에서 보면 data layer가 두개가 있죠.  위에 있는 data layer는 train data layer이고 아래에 있는 data layer는 valid data layer입니다. 빨간 박스는 위에서부터 순서대로 image mean data, train data, image mean data, valid data 입니다. image mean 값은 train data나 valid data나 같으므로 두 레이어에 모두 같은 값을 넣어주고, train layer에는 train data를, valid layer에서는 valid data를 사용하겠다고 각각 경로를 설정해 준 것입니다. 물론 이 파일들은 아직 만들어지지 않았습니다. 우리가 저렇게 설정을 했으니 train data와 valid data, image mean data를 각각 저 경로에 만들어 줘야겠죠? 그리고 각각 layer에 data param을 보면 batch_size라는 parameter가 있는데, 저 값이 의미하는 바는 한번에 처리하려는 input의 갯수입니다. 또 backend는 data layer source로 LEVELDB를 사용할지 LMDB를 사용할지 선택하는 것입니다. Default값은 LEVELDB입니다. 우리는 LMDB를 사용할 것이므로 저렇게 설정되어 있습니다. 흠... 하나하나 설명하려니 점점 설명해야 하는게 늘어가는 군요. 직접 CNN을 만드실려면 Caffe Tutorial을 참조하세요. 나중에 시간나면 하나하나 자세히 설명하는 시간을 가지도록 하겠습니다.(언제가 될지는 확실하지 않습니다.) 어쨋든 우리는 caffenet model을 그대로 사용할 것이기 때문에 그냥 mean_file과 source 값만 바꿔줍시다. 

마지막으로 여기서 한가지 더 짚고 넘어갈 부분이 있습니다. train_val.prototxt의 마지막 InnerProduct layer를 보면 output number가 1000으로 되어 있는데 이는 이 CNN은 imagenet의 data set에 맞춰서 설계되었고, imagenet data set의 class가 1000개이기 때문입니다. 우리가 수집한 데이터의 class가 몇개인지는 모르겠지만 어차피 나중에 synset_words.txt만 수정해주면 되므로 그냥 pass합시다. 자신이 학습시킬 모델의 class 갯수에 맞추어 CNN을 디자인 하는 것이 옳지만 저 output number 값을 바꿀거면 그냥 CNN을 직접 설계하는게 나을듯 합니다. 그대로 써도 어느정도 성능은 나옵니다. (물론 over fitting이 될 확률이 있지만...)

deploy.prototxt는 바꿀 필요가 없습니다. 당연히 deploy.prototxt도 output이 1000개 입니다. (train_val.prototxt는 학습을 시키기 위한 구조고, deply.prototxt는 학습이 완료된 모델을 이용하여 classifying 할때 쓰는 구조입니다.)

이제 solver.prototxt를 봅시다. solver.prototxt는 두 곳만 수정하면 됩니다.

먼저 net은 학습시킬때 사용할 CNN의 경로를 적어주면 됩니다. 바로 금방 전까지 다룬 파일의 경로를 위와 같이 적어줍니다. snapshot_prefix는 중간 중간 학습시킨 모델들을 저장할때, 어디에 앞에 어떤 이름으로 저장할지 설정하는 것입니다. snapshot 이 10000으로 설정되어 있는데, 이는 iteration이 10000번 돌때마다 그때까지 학습시킨 모델을 저장하겠다는 것입니다. max_iter은 말 그대로 iteration의 최대값입니다. 즉, iteration이 450000을 돌면 학습을 그만 두겠다는 거죠. 이 solver.prototxt file을 가지고 학습을 시키면 caffe/models/model_test_5 directory에 model5_train_iter_10000.caffemodel, model5_train_20000.caffemodel ~ model5_train_iter_450000.caffemodel이 저장되겠죠.(solverstate도 같이 저장됩니다.) solver_mode는 gpu로 연산하겠다는 것입니다. cpu로 하면 엄청 오래 걸리니까 gpu로 하시는게 좋습니다.



2. 수집한 Image data를 이용해 LMDB를 만들자!


이제 우리가 수정한 CNN에 학습시키기 위해 수집한 image를 LMDB 파일로 만들어야 합니다. 앞선 train_val.prototxt에서 data layer의 layer type이 data고, backend값이 LMDB이기 때문입니다. 물론 Data layer의 layer type을 ImageData로 설정하고 source를 학습시킬 image의 filename이 적혀있는 text file로 설정을 했으면 이 단계가 필요 없지만, 그러지 않았기 때문에 image data들을 LMDB file로 만들어야 합니다. (나중에 시간이 나면 layer type들에 대하여 설명해 드리도록 하죠. 궁금하신 분은 caffe layers를 보시기 바랍니다.)

다행스럽게도 caffe에서 create_imagenet.sh라는 파일을 제공해 주고 있습니다. 보통 caffe/examples/imagenet/create_imagenet.sh에 있으며 만약 없다면 BVLC/caffe github에서 다운받으시길 바랍니다. caffe/examples/imagenet directory를 보면 create_imagenet.sh, make_imagenet_mean.sh, train_caffenet.sh, resume_training.sh가 있습니다. create_imagenet.sh는 LMDB 파일을 만드는 bash file이고 만약 image를 resize하지 않았다면 이 파일을 통하여 resize도 할 수 있습니다. (정확히 말하면 convert_imageset이 하는거지만 그냥 각 bash file의 기능만 말하겠습니다.) make_imagenet_mean.sh는 말 그대로 image의 평균값을 계산해 주는 파일입니다. 마지막으로 train_caffenet.sh는 CNN을 training시키는 기능을 합니다. 저는 이 세 파일들을 caffe/examples/model_test_5라는 directory를 만들어 복사했으며, 이 전 포스팅에서 만든 train.txt와 val.txt는 caffe/data/model_test_5 directory에 넣어놨습니다. 그럼 create_imagenet.sh를 보겠습니다.

먼저 EXAMPLE 경로와 DATA 경로를 수정해야합니다. LMDB는 EXAMPLE 경로에 만들어지며, DATA는 train.txt와 val.txt가 있는 경로로 설정해 주면 됩니다. TOOLS는 convert_imageset이 있는 경로입니다. TRAIN_DATA_ROOT와 VAL_DATA_ROOT 값도 살포시 변경해줍니다. train.txt에 라벨링한 학습할 이미지 경로는 n0/n_*.JPEG로 작성했었습니다. 저는 train image 파일들을 caffe/imageSet/train2에 넣었으므로 이 이미지 파일들을 제대로 참조하려면 TRAIN_DATA_ROOT값을 imageSet/train2/로 설정해줘야 n0/n_*.JPEG와 합쳐져 온전한 경로가 될것입니다. (절대 경로로 써도 당연히 됩니다.) RESIZE는 256*256 size로 resize 할 것인가 설정하는 것인데, 현재 제가 모은 image들은 크기가 제각각이므로 이 값을 true로 설정했습니다. default는 false로 되어있습니다. image들을 어떤값을 어떤 순서로 데이터화 시키느냐에 따라서 모델의 성능이 은근히 달라지기 때문에 BVLC에서는 각자 알아서 data 변환 하는것을 추천하는 편입니다. 하지만 여기선 그냥 resize합니다. 마지막으로 $EXAMPLE/model5_train_lmdb와 $EXAMPLE/model5_val_lmdb로 값을 변경해줬습니다. 저는 train_val.prototxt에서 위와 같은 directory로 경로를 설정했기 때문입니다. --shuffle은 학습시킬 이미지들을 섞겠다는 건데, train.txt 작성할때 그냥 순서대로 써서 --shuffle은 그냥 놔두는게 좋습니다. train.txt 와 val.txt 작성할 때 shuffle을 했다면 저 option은 지워도 상관 없습니다. (shuffle을 안해주면 학습이 제대로 안될수도 있습니다. 이게 무엇인지 계속 학습시키다가 그다음 이게 무엇인지 계속 학습을 시키면 어느 한 class에만 over fitting 될 수가 있기 때문입니다. 때문에 그 다음에 학습시키는 class들이 제대로 학습되지 않을 수 있습니다.)

make_imagenet_mean.sh에서도 EXAMPLE, DATA 경로를 바꿔주고, $EXAMPLE/ilsvrc12_train_lmdb값을 앞서 설정한 train_lmdb 경로로 바꿔주면 됩니다. 저 같은 경우는 EXAMPLE = examples/model_test_5, DATA = data/model_test_5, $EXAMPLE/ilsvrc12_train_lmdb -> $EXAMPLE/model5_train_lmdb가 되겠군요. 

train_caffenet.sh는 solver의 경로만 바꿔주면 됩니다. 저같은 경우는 --solver = models/bvlc_reference_caffenet/solver.prototxt -> --solver = models/model_test_5/solver.prototxt가 되겠군요.

이제 create_imagenet.sh, make_imagenet_mean.sh, train_caffenet.sh를 순서대로 실행시켜주시면 됩니다. 저는 이마저도 make_model.sh라는 파일을 만들어서 했습니다. 어쨋든 $bash examples/model_test_5/create_imagenet.sh를 하면 다음과 같이 LMDB 파일이 만들어 집니다.

/home/san/caffe/examples/model_test_5

create_imagenet.sh를 실행시킨 모습

잘못된 image file들이 몇개 있네요.

graphic memory 사용량


$bash examples/model_test_5/make_imagenet_mean.sh를 하면 mean값이 금방 계산됩니다. 마지막으로 train_caffenet.sh를 실행합니다.

train_caffenet.sh를 실행한 모습

graphic memory 사용량


이제 그냥 컴퓨터 켜놓고 다른거 하시면 됩니다. 제 컴퓨터 성능으로는 450000 iteration 도는데 36시간 정도 걸리더군요. 시간 없으신 분들은 solver.prototxt 에서 max_iter를 50000 정도만 해서 학습시키세요. class가 적으면 50000번만 돌아도 그럭저럭 학습이 됩니다. 어쨋든 학습이 완료되고나서 models/model_test_5에 가면 다음과 같이 학습된 caffemodel file들이 저장되어 있는 것을 확인할 수 있습니다. 그러면 이제 인터넷에서 이미지를 하나 다운받아서 정말 분류가 되나 확인해봅시다. 

먼저 output의 갯수가 1000이므로 output되었을때 출력될 word들도 1000 라인이어야 합니다. 저같은 경우는 총 12개의 class를 학습시켰는데, CNN은 caffenet의 구조를 그대로 사용했으므로 output node가 1000개가 되어 버렸습니다. 물론 학습시키지 않은 output이 나올리가 없지만 그래도 output이 1000개 이므로 word들도 1000로 맞춰줘야합니다. 저는 제가 학습시킨 class에 대해서는 직접쓰고 나머지는 synset_words.txt에서 복사 붙여넣기 해서 1000라인을 채웠습니다.

1번째 줄에서 12줄 까지는 제가 학습시킨 class들이기 때문에 직접 해당하는 node 번호에 맞춰서 출력할 text를 써주고 나머지는 아무렇게나 채웠습니다. 이제 분류기를 이용해서 image 분류를 해봅시다.

분류는 caffe/build/examples/cpp_classification.classification.bin file을 이용해서 합니다. 사용방법은 다음과 같습니다.


~/caffe$ ./build/exaples/cpp_classification/classification.bin deploy.prototxt network.caffemodel mean.binaryproto labels.txt img.jpg

제 경우는 다음과 같이 사용합니다.


~/caffe$ ./build/exaples/cpp_classification/classification.bin ./models/model_test_5/deply.prototxt 
             ./models/model_test_5/model5_train_iter_450000.caffemodel
             ./data/model_test_5/imagenet_mean.bynaryproto 
             ./data/model_test_5/sysset_words2.txt 
             ./imageSet/test/1.JPG

결과


뭐 그럭저럭 학습이 된거 같긴 하네요. 분류율을 높이기 위해서는 CNN을 잘 만들고, 학습 데이터도 잘 모으는 등 여러가지 인자들을 바꿔가며 좋은 모델을 만들어야 합니다. 언제가 될지 모르겠지만 내킬때 caffe tool에 대하여 자세히 이야기 하도록 하겠습니다. caffe tool에 대하여 자세히 설명하려면 어쩔 수 없이 CNN에 대하여 설명을 하면서 진행해야 겠네요. 이 포스팅이 도움되실 분들이 얼마나 있을지 모르겠지만 몇몇 분들에게라도 도움이 되길 바라면서 이번 포스팅은 여기까지입니다.

    얼마전에 Deep Learning 중 Convolutional Neural Network (CNN)에 대한 강의를 연다는 소식을 메일로 받게 되었습니다. 그런데 강의 내용 계획을 보니 Caffe 설치 방법이랑 Caffe 예제 실습이더군요. 처음에는 Caffe home page에만 가봐도 자세히 써져 있는 내용을 왜 강의를 할까 생각했습니다. 그러나 의외로 Caffe 사용방법에 대한 내용을 궁금해 하시는 분들이 있을 것 같아서 제가 해본 것 중 Caffe를 이용하여 CNN custom model 만드는 방법을 이 글에서는 소개하려고 합니다. 이 글에서는 DNN과 CNN에 대한 설명들은 안하고 정말 그냥 custom model 만드는 방법 중 한가지만 소개하려고 합니다. 뭐 CNN에 대한 내용이나, Neural Network에 대한 내용은 여기 저기 자세히 설명해 놓으신 블로그나 논문이 많으니 읽어보시기 바랍니다.



1. Training 시킬 데이터를 수집하자!


    먼저, CNN을 학습시키기 위해서는 많은 양의 image data가 필요합니다. 사실 이 작업 육체적으로나 정신적으로나 어마어마하게 힘듭니다. Custom model을 만들 필요가 없이 그저 실습을 해보실 생각이라면 ImageNet에서 데이터를 다운받는 것을 추천합니다. (저는 3년 전에 가입해서 기억이 가물가물 합니다만, 제 기억상으로는 연구소 mail이나 학교 mail로 연구용으로 사용한다는 것을 인증하면 바로 다운 받을 수 있었던 것 같습니다. image net data를 사용할 경우 data의 크기가 매우 크니 HDD 용량이 넉넉하지 않으시다면 용량을 확보하시고 다운 받으시기 바랍니다. 해외서버라서 좀 느릴 수도 있습니다.)

먼저 데이터를 모으는 방법은 크게 다음과 같이 2가지가 있습니다.


1. 직접 찍는다.

2. 웹에서 다운로드를 받는다.


    사실 위의 두 방법은 너무 당연한 이야기죠. 개인적으로 제가 custom model을 만들때는 직접 찍은 데이터를 적절하게 섞어줘야 인식할때 원하는 결과가 나왔습니다. 예를 들어 제가 다니는 학교 문은 웹상에 올라와 있는 일반적인 문들과는 조금 생김새가 다르기 때문에 웹에서 다운받은 데이터로만 하다가는 학습이 잘 안 될 수도 있습니다. (제가 다니는 학교 문은 image net data로 학습시킨 모델로 classification을 진행하면 금고로 나옵니다. 사실 image net data에는 1000개의 class만 있기 때문에 우리가 원하는 class가 없을 수도 있습니다. 예를들어 ILSVRC2012 data set에서 door 종류는 sliding door밖에 없고, elevator도 없죠. 우리가 custom model을 만드는 이유 중 하나이기도 합니다. 하지만 atm과 cat, vending machine같은 class는 있기 때문에 만약 training 시키고자 하는 class가 image net data set에 있다면 적절히 활용하는 것이 image data를 수집하는 과정에서 발생하는 stress를 줄여 줄 수 있을 것 같습니다.) 

    직접 image를 찍는 것도 힘든 일이지만 웹에서 다운로드 받는 것도 많은 시간이 듭니다. MNIST 데이터 셋은 60000장의 image data를 training set으로 사용하고 Image Net은 class당 1300장의 데이터를 사용 하죠. 한 class 당 1000장만 수집하고 class가 10개만 되도 10000장의 image를 수집해야 합니다. 때문에 저 같은 경우는 python을 이용하여 crawler를 만들어서 image를 수집했습니다. crawler를 이용해 image를 수집하니 연관없는 사진들도 많이 수집되었습니다. 몇몇 분들은 image에 존재하는 pixel값을 이용하여 필터링을 하실 수도 있겠지만, 사실 pixel값을 이용해서 필터링을 해도 연관없는 사진들은 여전히 많습니다. 이러한 연관없는 사진을 없애는 일은 사람이 직접 할 수 밖에 없습니다. 완벽하게 연관없는 사진을 코드로 필터링 할 수 있다면 training set을 이용하여 CNN을 학습시킬 이유도 없죠^^

    다음은 제가 image를 수집하기 위해 작성한 간단한 python code입니다. 정말 image 수집만을 목적으로 했기 때문에 매우 간단하게 만들었습니다. 아마 직접 작성하시는게 더 좋을 겁니다. 하지만 그냥 빨리 custom data set을 수집하고, 실습을 하고 싶으신 분들이 사용하거나, 참조하실 분들은 참조하시라고 올립니다.


#-*- coding: utf-8 -*-
from bs4 import BeautifulSoup
import requests
import urllib
import urllib2
import os
from os.path import os
import html5lib
import codecs

count = 28
index = 1
max_count = 1000 #number that you want to download

imageDataDir = "F:/image/"
#imageDataDir = "/home/san/image/" #linux directory
querySet = ['door','현관문','cat','fire extinguisher','tiger'] #query for searching


def get_soup(url,header):
    return BeautifulSoup(urllib2.urlopen(urllib2.Request(url,headers=header)))

if not os.path.isdir(imageDataDir):
    os.mkdir(imageDataDir)
    
for query in querySet:
    image_naming = query #image name
    query= query.split()
    tempDirName = '_'.join(query)
    query='+'.join(query)
    isQueryKorean = False

    targetDir = imageDataDir+tempDirName

    try:
        if not os.path.isdir(targetDir):
            os.mkdir(targetDir)
    except:
        isQueryKorean = True
        image_naming="temp"
        targetDir = imageDataDir+"temp"
        dirNum=0
        while(True):
            tempTargetDir = targetDir+str(dirNum)
            dirNum+=1
            if not os.path.isdir(tempTargetDir):
                targetDir = tempTargetDir
                os.mkdir(targetDir)
                break
        
    index = 1 #init index
    
    for i in range(max_count/count):
        url="http://www.bing.com/images/search?q="+query+"&first="+str(index)+"&count="+str(count)+"&FORM=HDRSC2"
        index = index+count
        print url #print query url

        page = urllib.urlopen(url).read()
        soup = BeautifulSoup(page, 'html5lib')

        for img_temp in soup.find_all("a", "thumb"):
            img = img_temp.get('href')
            try:
                print img
                raw_img = urllib2.urlopen(img).read()
                cntr = len([i for i in os.listdir(targetDir) if image_naming in i]) + 1
                print cntr
                f = open(targetDir+"/" + image_naming + "_"+ str(cntr)+".jpg", 'wb')
                f.write(raw_img)
                f.close()
            except:
                print("fail to download")

    제가 주석쓰는걸 귀찮아 하고 python이 주로 사용하는 언어가 아니라서 이상한 점이 있더라도 양해 부탁드립니다. 먼저 query url을 bing을 사용한 이유는 bing source code 분석 결과, bing이 thumbnail이 아닌 원본 image 다운로드가 편했기 때문입니다. 구글로 검색하시고 싶으신 분은 google source code 보고 download 받으시면 됩니다. 개인적으로 google은  thumbnail은 받기 쉬운데 원본 source image 받기가 힘들더군요. (google에서 원본 image 받는 방법 아시는 분은 알려주시면 감사하겠습니다. 뭐 들리는 이야기로는 구글에 돈내면 한달에 1000 query인가 검색할 수 있다고 합니다. 확실하진 않습니다. selenium, mechanize 제외) max_count 변수는 다운로드할 image의 갯수입니다. 하지만 실제로 저 만큼 받아지진 않습니다. 제가 올린 코드에서는 jpg format만 받게 해놔서 jpg가 아닌 이미지들은 안받아지거든요. (가끔식 jpg가 아닌 파일도 받아지긴 합니다.) 때문에 필요한 image 갯수보다 넉넉하게 설정하시는게 좋습니다.

    모아진 데이터를 보면 cat같은 데이터는 noise 없이 잘 모아지는 편이나, fire extinguisher 같은 경우에는 noise가 껴있는 경우가 있습니다. class에 따라서 제대로 된 데이터가 별로 없는 경우도 있습니다. (ex. door sign, elevator 등)

    데이터 필터링을 하시면 됩니다. 이것 추가하고 저건 지우고 하는 방식으로 데이터 셋을 변경해가며 실험하는 것도 좋을거 같습니다. 이게 또 데이터가 많다보면 하기 귀찮을 때가 있는데 그냥 대충하세요^^. CNN을 학습시킬때 목적에 따라 좋은 데이터가 있고 좋지 않은 데이터가 있을 수 있습니다. 저 같은 경우는 일상생활 중에 찍은 사진을 분류하기 위해 모델을 만들었으므로 위 그림에서 fire extinguisher_12.jpg 같은 경우에는 좋은 데이터였습니다. 왜냐하면 2~6번 image와 같이 배경이 흰색인 경우는 일상생활에서 별로 접하기 힘들기 때문이죠. 이 부분도 개인의 목적에 맞게 데이터를 선별하시면 됩니다. (Image Net data set들도 download해서 보시면 이건 좀 이상한데 싶은 이미지들 섞여 있습니다. 필터링 하다가 귀찮았나 보죠?) 저같은 경우는 이 데이터에 제가 직접 찍은 사진들도 추가했습니다.

    이제 train set과 valid set을 분류해 주세요. 필요할 경우 test set도 마련하면 좋지만 필수 사항은 아닙니다. 저같은 경우는 train set의 라벨링을 먼저 진행 한다음에 train set 중에 valid 용으로 사용할 이미지들을 따로 선별했습니다.



2. Labeling을 하자!


    이렇게 데이터를 모았으면 이제 라벨링을 해야합니다. 솔직히 caffe에서는 file path명만 써주면 되서 그냥 listdir() 함수를 이용해서 train list 작성을 해도 됩니다만 저는 원본 파일은 놔두고 라벨링을 한 set을 따로 만들었습니다.


from os import listdir
from os.path import isfile, join
import os
from shutil import copyfile

dirSet = ['atm','door','door_sign','elevator','emergency_exit','extinguisher', 'outlet','trash_bin', 'vending_machine']
sourcePath = '/home/san/imageSet/'
destPath = '/home/san/caffe/imageSet/'

newDirName = 0

for targetDir in dirSet:
    onlyFiles = [f for f in listdir(sourcePath+targetDir) if isfile(join(sourcePath+targetDir),f))]

    newName = 0
    newTargetDir = destPath+'n'+str(newDirName)
    os.mkdir(newTargetDir)

    for name in onlyFiles:
        print ('copy '+sourcePath+targetDir+'/'+name)
        copyfile(sourcePath+targetDir+'/'+name,newTargetDir+'/'+str(newDirName)+'_'+str(newName)+'.JPEG')
        newName+=1
    newDirName+=1

    갑자기 linux로 바뀌었죠? 저는 그냥 이 작업부터 linux로 진행했습니다. (data 모으는 것은 오래 걸리기 때문에 linux로 하면 그 오랜 시간동안 카카오톡을 못하거든요^^) 일단 저는 위와 같이 python을 이용하여 labeling을 진행하였습니다. 라벨링을 하고 나서 val 폴더에 valid set을 선별하여 넣었습니다. 저 같은 경우는 그냥 30개 씩했는데 원하는 만큼씩 valid set을 선별하세요.

~/caffe/imageSet Directory의 모습

train set의 모습

valid set의 모습


라벨링을 하고 나면 train list가 적혀 있는 train.txt와 valid.txt를 작성해야 합니다. 저는 다음과 같이 작성하였습니다.

이것도 사람이 작성하기엔 힘들어서 있어서 code로 작성했습니다. 이 코드는 굳이 올릴 필요성을 못느끼겠네요. 파일 경로 옆에 써져있는 숫자들은 index입니다. 이 index는 몇번 output node로 해당 클래스를 학습시킬지 알려주는 것입니다. 저같은 경우는 n0 class(atm)는 0번, n1 class(door)는 1번으로 학습시켰습니다. 이것도 자신이 정하기 나름입니다. 하지만 아직 언급하진 않았지만 자신이 만든 CNN의 output node 숫자보다는 적어야 합니다. 또한 여러 클래스를 같은 index number로 학습시켜도 상관 없지만 그러면 그 클래스들 간에 구분이 되지 않으니 의미가 없겠죠? 

오늘 포스트는 여기까지입니다. 사실 저는 이렇게 학습 데이터를 모으는게 가장 힘들었습니다. 학습은 CNN구조를 바꾸거나, 여러가지 인자들을 변경한 다음 돌려놓고 30~40시간 동안 다른 일을 하면 되서 별로 안힘들었거든요. 어쨋든 다음 포스팅에서는 imagenet lmdb data만드는 것에서 부터 CNN training 시키는 것과 classification 하는 데까지 써보도록 하겠습니다.

+ Recent posts