반응형

안녕하세요

 

이번 포스팅은 현재 연습중인 Tensorflow를 통해 pb 파일 생성하기 위한 과정으로

 

이미지셋을 통한 라이브러리 설치 및 학습 그리고 학습된 라이브러리에 대한 평가 방법에 대한 포스팅을

 

해볼께요

 

첫번째로 Anaconda와 텐서플로우 설치를 먼저해야 합니다

 

설치 방법에 대해서는 아래 링크를 통해 확인하시기 바랍니다

 

https://codingman.tistory.com/77 

 

[Deep Learning] Anaconda3 + Tensorflow 사용하기

안녕하세요 코딩연습생 입니다ㅠ 개발 블로그를 운영하면서 이것저것 많이 정보를 올리고 있는데 해보고자 하는 연습물이 잘 안풀려서 요즘 1일 1포스팅이 잘 안 이루어지고 있습니다ㅠ 대충 포스팅 글 올리기에..

codingman.tistory.com

참고로 이번 포스팅에 사용된 버전 정보는 다음과 같습니다

 

=============================================================

1) Anaconda3

2) Python 3.7

3) Tensorflow 1.14

4) CUDA 8.0

==============================================================

 

위의 리스트 순서로 설치를 진행하시면 됩니다

 

CUDA 설치 방법은 아래 링크 포스팅을 참조해주세요

https://codingman.tistory.com/81

 

[Nvidia CUDA] 윈도우에서 CUDA 설치 하기

안녕하세요 요즘 딥러닝 구현을 위해 열심히 공부 중인 코딩연습생입니다ㅎㅎ Anaconda3 설치 부터 하나씩 배워가며 포스팅을 진행하고 있는데요 과정중에 하나인 CUDA에 대해 포스팅 해보도록 하겠습니다 제일 먼..

codingman.tistory.com

 

이렇게 환경 설정을 모두 마치셨으면

 

다음 진행해야할 것은 Slim 이미지셋 설치와 TFRecord 생성 방법입니다

 

위의 내용은 아래 포스팅을 참조해서 따라해 주세요

 

https://codingman.tistory.com/78

 

[Deep Learning] Tensorflow slim 라이브러리 설치

안녕하세요 이번 시간 포스팅 내용은 텐소플로우에 모델을 추가하고 학습할수 있게 하기 위한 slim 라이브러리 설치 방법입니다 해당 포스팅을 검색해서 찾아오셨다면 이미 기본 적인 내용을 알고 오셨으리라 생각..

codingman.tistory.com

 

내용이 상당히 길기 때문에 포스팅을 나누어 올리고 있습니다

 

다소 헷갈릴수 있는데 어쩔수 없이 나눠 포스팅한점을 양해 주시기 바랍니다

 

이제 위의 레코드 파일 생성까지 완료 되셨다면 모든 환경 설정은 끝났습니다

 

이제 Deep Learning중 학습 방법에 대해서 Slim 모델을 통해 설명하도록 하겠습니다

 

저도 공부 중에 찾은 내용입니다만 학습 방법에 대해 여러가지 방법이 있습니다

 

그중에 제가 찾은것은 세가지 방법이 있었는데요

 

그중에 한가지 방법은 Tensorflow의 구버전으로 사용되는것으로 현재 저희 환경과 맞지 않아 구현이 불가능했습니다

 

그래서 저희가 설정한 환경에서 동작이 가능한 방법인 두가지를 설명해 드리겠습니다

 

1) Trainng a model from scratch

    - 저희가 만든 이미지셋을 가지고 신규 모델을 학습 하는 방법

    - Anaconda Prompt를 통해 다음 명령어를 실행

    * 명령어 간략 설명

      python train_image_classifier.py

      --train_dir=\tmp\train_inception_v1_flowers_logs # 모델 저장될 폴더
      --dataset_name=flowers # 이미지 셋 이름
      --dataset_split_name=train # 학습에 사용할 이미지 선택
      --dataset_dir=\tmp\flowers # 이미지 셋 위치
      --batch_size=16 # 기본 32이나 메모리 부족 에러 발생 -> 16 설정
      --model_name=inception_v1 # 사용할 모델 이름

python train_image_classifier.py --train_dir=\tmp\train_inception_v1_flowers_logs --dataset_name=flowers --dataset_split_name=train --dataset_dir=\tmp\flowers --batch_size=16 --model_name=inception_v1

오류가 발생하실수 있습니다 오류가 발생하였을 경우 py 파일을 약간 수정해 줍니다

 

다음 경로에 있는 train_image_classifier.py파일을 Spyder을 통해 열어 줍니다

 

아래와 같이 변경한뒤 저장합니다

 

다시 명령어를 실행 합니다

 

명령어가 실행되면사 step별 학습을 시작하는것을 보실수 있습니다

 

 

학습이 GPU의 성능에 따라 차이가 있을수 있지만 상당한 수분이 소요 됩니다

 

그래서 학습 중간에 중지 하고 싶으시면 Ctrl + C를 누루시면 종료 됩니다

 

학습이 완료되어 지면 다음과 같은 checkpoint 형식의 log가 생성됩니다

 

이어서 두번째 방식 입니다

 

2-1) Fine-tuning a model from an existing checkpoint

    - 마지막 layer만 새롭게 학습하는 과정

    - 완성도가 높은 모델을 사용할 수록 정확도가 올라가기 때문에 ImgaeNet에서 미리 학습된 모델을 다운 받아

      사용합니다

      (http:// http://download.tensorflow.org/models/inception_v1_2016_08_28.tar.gz)

불러오는 중입니다...

   - 압축을 푼뒤 inception_v1.ckpt 파일을  \tmp\my_checkpoints 폴더로 복사하세요.

 

   - 다음 명령어를 1번 방법과 동일하게 실행 시킵니다

python train_image_classifier.py
  --train_dir=\tmp\train_inception_v1_flowers_FineTune_logs
  --dataset_name=flowers
  --dataset_split_name=train
  --dataset_dir=\tmp\flowers
  --model_name=inception_v1
  --checkpoint_path=\tmp\my_checkpoints/inception_v1.ckpt
  --checkpoint_exclude_scopes=InceptionV1/Logits
  --trainable_scopes=InceptionV1/Logits
  --max_number_of_steps=1000
  --batch_size=16
  --learning_rate=0.01
  --learning_rate_decay_type=fixed
  --save_interval_secs=60
  --save_summaries_secs=60
  --log_every_n_steps=100
  --optimizer=rmsprop
  --weight_decay=0.00004

  - 1000번의 step이 완료된후 다음과 같이 checkpoint가 생성된 log가 생성됩니다

2-2) # Fine-tune all the new layers for 500 steps.

    - 전체 layer 학습하는 과정

python train_image_classifier.py


  --train_dir=\tmp\train_inception_v1_flowers_FineTune_logs\all
  --dataset_name=flowers
  --dataset_split_name=train
  --dataset_dir=\tmp\flowers

  --model_name=inception_v1

  --checkpoint_path=\tmp\train_inception_v1_flowers_FineTune_logs
  --max_number_of_steps=500
  --batch_size=16
  --learning_rate=0.0001
  --learning_rate_decay_type=fixed
  --save_interval_secs=60
  --save_summaries_secs=60
  --log_every_n_steps=10
  --optimizer=rmsprop
  --weight_decay=0.00004

 

이렇게 생성된 두가지 방법을 통해 3가지의 딥러닝 모델을 학습 시켜 봤습니다

 

정확도 확인을 위한 평가 방법입니다

 

1) Flowers로부터 새롭게 만든 모델

결과를 보시면 eval/Recall_5[1]의 의미는 5개의 Class 중에 하나라도 맞으면 맞다고 보는 정확도 입니다

[1]의 결과로 보면 100%로 라는 말이네요

실예측정확도의 경우는 eval/Accuracy[0.3675] -> 36% 정도로가 평가가 나오네요

 

2) 이미 잘 만들어진 모델로부터 Flowers로 마지막 layer만 학습해 만든 모델

매칭 유사율 100%

실예측정확도 86%라고 평가가 나오네요

 

3) 2)으로 만들어진 모델에서 전체 layer를 학습해 만든 모델

매칭 유사율은 역시 100%

실예측정확도는 90%로 평가가 됩니다

 

결론은 기존에 잘 학습된 모델을 활용해서 그 위에 분류하고 싶은 추가적인 이미지를 학습하는 것이

 

실예측 정확도를 가장 효과적으로 올릴수 있다는 결론이 나온거 같네요

반응형
반응형

안녕하세요

 

이번 시간 포스팅할 부분은 OpenCvSharp를 이용한 PCA(Principal Component Analysis)를 구현해 볼려고 합니다

 

근데 아무 저와 똑같이 PCA가 뭐지??라는 분들이 많으실거 같아서 검색을 통해 제가 알아본 내용을

 

간략하게 소개 하고 구현 해보도록 할께요

 

▶ 주성분분석(Principal Component Analysis)

      - PCA는 분포된 데이터들의 주성분(Principal Component)를 찾아 고차원의 데이터를 저차원의 데이터로 환원

        시키는 기법

 

 

음... 정의를 보아도 무슨말인지 잘 이해가 되지 않습니다. 제가 이해한것을 표현하자면 어떤한 데이터의 주성분을

 

분석하여 데이터로 환원한뒤 그 환원된 값의 분포도에 따라 어떠한 형태를 띄고 있는지를 보는 거라고 이해하고

 

있는데 이게 맞는것인지를 모르겠습니다

 

제가 이해한 정의를 가지고 프로그래밍을 분석하여 구현하였는데

 

프로그램적 순서를 보면 이렇습니다 

 

① 원본 이미지

② 대상 이미지

③ 형상 비교를 통한 매치율 분석

 

이론은 간단하지만 구현하고 분석을 쉽지가 않더라구요 아무 저도 프로그래머다 보니 논리적 이론 보다는

 

프로그램적 구현쪽을 더 많이 파고 있는 입장이라 완벽한 설명은 불가합니다

 

좀 더 구체적 이해와 설명이 필요하시면 검색을 통해 이해 하시는게 좋을거 같습니다

 

그럼 다시 본론으로 돌아와서 프로그램 구현을 시작해 보겠습니다

 

해당 포스팅의 글 역시 기존 OpenCvSharp 포스팅 자료와 이어서 진행되오니

 

이해가 안가거나 중간 생략된 부분은 이전 포스팅을 참조하시기 바랍니다

 

https://codingman.tistory.com/49

 

[C#]OpenCvSharp 라이브러리 사용하기 #1

안녕하세요 저번 포스팅에 C#으로 OpenCvSharp 라이브러리를 등록하여 구현하는 포스팅을 준비하던중에 OpenCv 3,4 버전에서 오류가 발생하는 문제가 있다는 얘길 듣고 부랴부랴 포스팅 내용을 검토해봤는데 역시..

codingman.tistory.com

 

그럼 프로그램 동작을 위한 디자인 부분부터 설명하겠습니다

 

[디자인]

- 메뉴에 머쉰런닝 탭에 PCA 버튼을 만들고 학습과 검출의 세부 버튼을 생성합니다

 

- 학습과 검출 세부 버튼에 클릭시 동작 할 수 있도록 이벤트를 활성화 시킵니다

 

- 해당 이벤트에 다음과 같이 코딩합니다

 

* 학습

        private void 학습ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            using (PCA pca = new PCA())
            using (IplImage temp = pca.LearnPCA())
            {
                if (temp == null)
                {
                    MessageBox.Show("데이타 파일 오류");
                    return;
                }
                result = temp.Clone();

            }
            pictureBoxIpl2.ImageIpl = result;
        }

 

*검출

        private void 검출ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (PCA pca = new PCA())
            {
                String[] temp = pca.recognize();
                if (temp == null) MessageBox.Show("오류발생 확인요망");
                for (int i = 0; i < temp.Length; i++)
                    listBox1.Items.Add(temp[i]);

            }
        }

 

- PCA 기능 동작을 위한 클래스 파일 생성합니다

 

- 생성된 클래스에 다음과 같이 소스코드를 작성 합니다

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using OpenCvSharp;

namespace OpenCV_V1
{
    class PCA : IDisposable
    {
        #region 초기값
        int nTrainFaces = 0;
        int nEigens = 0;

        IplImage result;
        IplImage[] faceImgArr;
        IplImage[] eigenVectArr;
        IplImage pAvgTrainImg;
        float[,] projectedTrainFaceMat;
        float[] eigenValMat;
        CvMat personNumTruthMat;

        public void Dispose()
        {
            if (result != null) Cv.ReleaseImage(result);
            if (!pAvgTrainImg.IsDisposed) pAvgTrainImg.Dispose();
            if (!faceImgArr[0].IsDisposed)
            {
                for (int i = 0; i < nTrainFaces; i++)
                {
                    faceImgArr[i].Dispose();
                }
            }
            if (!eigenVectArr[0].IsDisposed)
            {
                for (int i = 0; i < nEigens; i++)
                    eigenVectArr[i].Dispose();
            }
            if (!personNumTruthMat.IsDisposed) Cv.ReleaseMat(personNumTruthMat);
        }
        #endregion

        #region PCA 학습

        public unsafe IplImage LearnPCA()
        {
            //학습할 이미지 사진 파일명을 나열한 텍스파일 읽기
            nTrainFaces = loadFaceImgArray("train.txt");
            if (nTrainFaces < 2)
            {
                //MessageBox.Show("데이타 파일이 잘못 되었슴");
                return null;
            }

            doPCA();

            projectedTrainFaceMat = new float[nTrainFaces, nEigens];
            float[] tempProject = new float[nEigens];

            for (int i = 0; i < nTrainFaces; i++)
            {
                Cv.EigenDecomposite(faceImgArr[i], eigenVectArr, pAvgTrainImg, tempProject);//projectedTrainFaceMat[i]);
                projectedTrainFaceMat[i, 0] = tempProject[0];
                projectedTrainFaceMat[i, 1] = tempProject[1];
            }


            storeTraingData();
            return result;
        }

        private int loadFaceImgArray(String file)
        {
            //텍스트 파일에 나열되어진 파일명대로 이미지 읽어서 메모리에 저장하기   
            int i = 0;
            string[] lines = File.ReadAllLines(file); //학습할 파일명 획득
            faceImgArr = new IplImage[lines.Length]; //학습할 얼굴 갯수만큼 메모리 확보

            foreach (string line in lines) //텍스트 파일에서 읽은 파일명으로
            {
                faceImgArr[i] = new IplImage(lines[i], LoadMode.GrayScale); //사진이미지 읽어 오기
                i++;
            }
            return lines.Length;

        }

        private unsafe void doPCA()
        {
            CvTermCriteria calcLimit;
            CvSize faceImgSize;
            nEigens = nTrainFaces - 1;

            faceImgSize.Width = faceImgArr[0].Width;
            faceImgSize.Height = faceImgArr[0].Height;

            eigenVectArr = new IplImage[nEigens];

            for (int i = 0; i < nEigens; i++)
                eigenVectArr[i] = new IplImage(faceImgSize, BitDepth.F32, 1);

            eigenValMat = new float[nEigens];
            pAvgTrainImg = new IplImage(faceImgSize, BitDepth.F32, 1);
            calcLimit = new CvTermCriteria(CriteriaType.Iteration, nEigens, 1);
            Cv.CalcEigenObjects(faceImgArr, eigenVectArr, 0, calcLimit, pAvgTrainImg, eigenValMat);

        }

        //학습된 데이타 저장하기
        private void storeTraingData()
        {
            int[] faceID = { 1, 2, 4, 5 };//사실은 텍스트 파일에 같이 써야 하지만 분리하기 귀찮아서
            personNumTruthMat = new CvMat(1, nTrainFaces, MatrixType.S32C1, faceID);

            using (CvFileStorage fs = new CvFileStorage("facedata.xml", null, FileStorageMode.Write))
            using (CvMat eigen = new CvMat(1, nEigens, MatrixType.F32C1, eigenValMat))
            using (CvMat projected = new CvMat(nTrainFaces, nEigens, MatrixType.F32C1, projectedTrainFaceMat))
            {
                fs.WriteInt("nEigens", nEigens);
                fs.WriteInt("nTrainFaces", nTrainFaces);
                fs.Write("trainPersonNumMat", personNumTruthMat);
                fs.Write("eigenValMat", eigen);
                fs.Write("projectedTrainFaceMat", projected);
                fs.Write("avgTrainImg", pAvgTrainImg);

                for (int i = 0; i < nEigens; i++)
                {
                    String varName = String.Format("eigenVect_{0}", i);
                    fs.Write(varName, eigenVectArr[i]);
                }
                result = new IplImage(pAvgTrainImg.Size, BitDepth.U8, 1);
                //Currentley, bitmap converter can read not only BitDeth.U8 but also 32F
                Cv.CvtScale(pAvgTrainImg, result);
            }
        }
        #endregion

        #region PCA 인식

        public unsafe String[] recognize()
        {
            String[] str;

            int nTestFaces = 0; //비교할 이미지 숫자
            CvMat trainPersonNumMat; //학습으로 저장된
            float[] projectedTestFace;

            nTestFaces = loadFaceImgArray("test.txt"); //얼굴갯수 리턴
            projectedTestFace = new float[nEigens];

            if (!loadTranningData(out trainPersonNumMat)) return null;

            projectedTrainFaceMat = new float[trainPersonNumMat.Rows, trainPersonNumMat.Cols];//배열확보
            float[] tempProject = new float[nEigens];

            for (int i = 0; i < trainPersonNumMat.Rows; i++)
                for (int j = 0; j < trainPersonNumMat.Cols; j++)
                    projectedTrainFaceMat[i, j] = (float)Cv.mGet(trainPersonNumMat, i, j); //저장된 값 이동

            str = new String[nTestFaces]; //비교할 파일 갯수 만큼

            for (int i = 0; i < nTestFaces; i++)
            {
                int iNearest, nearest, truth;

                Cv.EigenDecomposite(faceImgArr[i], eigenVectArr, pAvgTrainImg, tempProject);

                iNearest = findNearestNeighbor(tempProject); //근접도
                truth = (int)Cv.mGet(personNumTruthMat, 0, i); //실제 명기된 ID
                nearest = (int)Cv.mGet(personNumTruthMat, 0, iNearest);

                str[i] = String.Format("nearest ID ={0}, Real ID = {1}", nearest, truth);

            }
            return str;


        }

        private int findNearestNeighbor(float[] projecTestFace)
        {
            double leastDistSq = 1e12;// DBL_MAX;
            int iTrain, iNearest = 0;

            for (iTrain = 0; iTrain < nTrainFaces; iTrain++) //비교할 얼굴 갯수
            {
                double distSq = 0;

                for (int i = 0; i < nEigens; i++)
                {
                    float d_i = projecTestFace[i] - projectedTrainFaceMat[iTrain, i];//학습 파일에서 읽은 값과
                    //distSq += d_i*d_i / eigenValMat->data.fl;  // 마할노비스 거리
                    distSq += d_i * d_i; // 유클리디안 거리
                }

                if (distSq < leastDistSq) //더 근접한 값이 있는지 찾음
                {
                    leastDistSq = distSq;
                    iNearest = iTrain;     //몇번째 얼굴인지
                }
            }
            return iNearest;
        }

        //저장된 학습 데이타 읽어 오기
        private bool loadTranningData(out CvMat pTrainPersonNumMat)
        {
            CvFileNode param;

            using (CvFileStorage fs = new CvFileStorage("facedata.xml", null, FileStorageMode.Read))
            {
                pTrainPersonNumMat = null;
                if (fs == null) return false;

                nEigens = fs.ReadIntByName(null, "nEigens");//고유치
                nTrainFaces = fs.ReadIntByName(null, "nTrainFaces"); //학습 갯수
                param = Cv.GetFileNodeByName(fs, null, "trainPersonNumMat");
                personNumTruthMat = fs.Read<CvMat>(param); //얼굴ID

                param = Cv.GetFileNodeByName(fs, null, "projectedTrainFaceMat");//학습된 값
                pTrainPersonNumMat = fs.Read<CvMat>(param);

                param = Cv.GetFileNodeByName(fs, null, "avgTrainImg"); //학습한 평균 이미지
                pAvgTrainImg = fs.Read<IplImage>(param);
                eigenVectArr = new IplImage[nEigens];
                for (int i = 0; i < nEigens; i++)
                {
                    String varName = String.Format("eigenVect_{0}", i);
                    param = Cv.GetFileNodeByName(fs, null, varName);
                    eigenVectArr[i] = fs.Read<IplImage>(param);
                }

            }
            int[] faceID = { 1, 2, 4, 5, 1, 2, 4, 5, 1, 2, 4, 5, 1, 2, 4, 5, 1, 2, 4, 5, 1, 2, 4, 5 };//사실은 텍스트 파일에 같이 써야 하지만 분리하기 귀찮아서
            personNumTruthMat = new CvMat(1, nTrainFaces, MatrixType.S32C1, faceID);//ID 배정

            return true;
        }
        #endregion
    }
}

 

- 해당 클래스가 정상 동작을 하기 위한 기초 첨부파일을 다운 받습니다

S1245_XML.zip
0.39MB

 

- 첨부파일의 내용을 Debug 폴더에 붙여 넣기 합니다

 

*첨부파일 내용

1) s1,s2,s4,s5 비교 그룹 이미지 (형식 : bpm)

   (샘플 얼굴 이미지 사진 입니다)

 

2) test.txt

   : 그룹에 포함되어 있는 파일 정보

 

3) train.txt

   : 그룹에 대표 이미지 지정

 

3) facedata.xml

   : 학습 정보 기록을 위한 xml

 

- 실행 한뒤 각 그룹 이미지 폴더에서 1.bpm을 불러와 검출을 시도합니다

 

[결과 창]

 

 

- 저는 샘플 사진으로 트와이스 맴버를 bpm으로 전환하여 비교 하여 다른 얼굴들과 어느정도 분석이 가능한지

  테스트를 해봤습니다(좋아하니깐!)

 

- 쯔위는 s5 그룹에 대표입니다

 

- 좌측 listBox1의 결과를 분석하면 해당 폴더의 그룹별 매칭 상태가 나타나는데 90%로 정도 쯔위를 판별해

  내는것을 볼수 있습니다

 

- 해당 자료를 구현하여 다른 샘플을 통해 다른 각도로 수정하여 응용해 보시기 바랍니다

 

반응형

+ Recent posts