레이블이 Deep Learning인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Deep Learning인 게시물을 표시합니다. 모든 게시물 표시

2018년 3월 1일 목요일

캐글 음성인식 대회 5위 솔루션(작성중)

 캐글에서 구글이 주최하고 음성인식 대회가 있었습니다.
https://www.kaggle.com/c/tensorflow-speech-recognition-challenge
우리나라에서는 텐서플로우 코리아에서 추가 10팀 선발해서 별도 상금도 주는 (1위 2천5백만,10위안에 들면 1천만) 대회 였습니다. (저는 선발 못되었구요 ㅜ)

(시간이 안나서 쓰지를 못하고 있는데 조금씩 여유 될때 쓰는 중)

  1. Input Data Pipeline
    1. Normalize 
    2. Augmentation
    3. 1D Input
    4. 2D Input
    5. 1D + 2D Combination Input
  2. model
    1. 1D CNN Simple
    2. 1D CNN Residual
    3. 2D CNN InceptionResnetV2
  3. ensemble
    1. Probability Average
    2. Corr. Weight Average

1-1 Normalize
def normalize_wav(wav):
    wav_mean = np.mean(wav)
    wav = wav - wav_mean
    wav_max = max(abs(wav))
    if wav_max == 0 : # zero divide error
        wav_max = 0.01
    wav = wav.astype(np.float32)/wav_max
    return wav

1-2 Augmenation
def white(N, state=None):
    """
    White noise.
    
    :param N: Amount of samples.
    :param state: State of PRNG.
    :type state: :class:`np.random.RandomState`
    
    White noise has a constant power density. It's narrowband spectrum is therefore flat.
    The power in white noise will increase by a factor of two for each octave band, 
    and therefore increases with 3 dB per octave.
    """
    state = np.random.RandomState() if state is None else state
    wn = state.randn(N)
    wn = normalize_wav(wn)
    return wn


def pink(N, state=None):
    """
    Pink noise. 
    
    :param N: Amount of samples.
    :param state: State of PRNG.
    :type state: :class:`np.random.RandomState`
    
    Pink noise has equal power in bands that are proportionally wide.
    Power density decreases with 3 dB per octave.
    
    """
    state = np.random.RandomState() if state is None else state
    uneven = N%2
    X = state.randn(N//2+1+uneven) + 1j * state.randn(N//2+1+uneven)
    S = np.sqrt(np.arange(len(X))+1.) # +1 to avoid divide by zero
    y = (irfft(X/S)).real
    if uneven:
        y = y[:-1]
    return normalize_wav(y)


def blue(N, state=None):
    """
    Blue noise. 
    
    :param N: Amount of samples.
    :param state: State of PRNG.
    :type state: :class:`np.random.RandomState`
    
    Power increases with 6 dB per octave.
    Power density increases with 3 dB per octave. 
    
    """
    state = np.random.RandomState() if state is None else state
    uneven = N%2
    X = state.randn(N//2+1+uneven) + 1j * state.randn(N//2+1+uneven)
    S = np.sqrt(np.arange(len(X)))# Filter
    y = (irfft(X*S)).real
    if uneven:
        y = y[:-1]
    return normalize_wav(y)


def brown(N, state=None):
    """
    Violet noise.
    
    :param N: Amount of samples.
    :param state: State of PRNG.
    :type state: :class:`np.random.RandomState`
    
    Power decreases with -3 dB per octave.
    Power density decreases with 6 dB per octave. 
    """
    state = np.random.RandomState() if state is None else state
    uneven = N%2
    X = state.randn(N//2+1+uneven) + 1j * state.randn(N//2+1+uneven)
    S = (np.arange(len(X))+1)# Filter
    y = (irfft(X/S)).real
    if uneven:
        y = y[:-1]
    return normalize_wav(y)


def violet(N, state=None):
    """
    Violet noise. Power increases with 6 dB per octave. 
    
    :param N: Amount of samples.
    :param state: State of PRNG.
    :type state: :class:`np.random.RandomState`
    
    Power increases with +9 dB per octave.
    Power density increases with +6 dB per octave. 
    
    """
    state = np.random.RandomState() if state is None else state
    uneven = N%2
    X = state.randn(N//2+1+uneven) + 1j * state.randn(N//2+1+uneven)
    S = (np.arange(len(X)))# Filter
    y = (irfft(X*S)).real
    if uneven:
        y = y[:-1]
    return normalize_wav(y)









2017년 6월 3일 토요일

opencv Mat 를 caffe datum으로 변환, datum을 Mat로 변환

 기존 opencv에서 영상처리 하던게 익숙해서 caffe를 Mat로 변환 후에 Opencv 로 처리 할 경우가 많은데, bvlc caffe에 아직 float형 image와 multi channel(4개 이상) 이미지 변환함수가 안 만들어져 있어서 만들어 보았습니다.

 아래는 Mat를 datum으로 변환하는 것.
void CVMatToDatum(const cv::Mat& cv_img, Datum* datum, int depth)
{
 if (depth == CV_8U)
 {
  CVMatToDatum(cv_img, datum);
  return;
 }

 CHECK(cv_img.depth() == CV_32F) << "data type must be 32bit float";

 datum->set_channels(cv_img.channels());
 datum->set_height(cv_img.rows);
 datum->set_width(cv_img.cols);
 datum->clear_data();
 datum->clear_float_data();
 datum->set_encoded(false);
 int datum_channels = datum->channels();
 int datum_height = datum->height();
 int datum_width = datum->width();
 int datum_size = datum_channels * datum_height * datum_width;

 for (int h = 0; h < datum_height; ++h) 
 {
  const float* ptr = cv_img.ptr<float>(h);
  int img_index = 0;
  for (int w = 0; w < datum_width; ++w) {
   for (int c = 0; c < datum_channels; ++c) {
    datum->add_float_data( ptr[img_index++]);
   }
  }
 }
 return;
}

void CVMatToDatum(const cv::Mat& cv_img, Datum* datum) {
  CHECK(cv_img.depth() == CV_8U) << "Image data type must be unsigned byte";
  datum->set_channels(cv_img.channels());
  datum->set_height(cv_img.rows);
  datum->set_width(cv_img.cols);
  datum->clear_data();
  datum->clear_float_data();
  datum->set_encoded(false);
  int datum_channels = datum->channels();
  int datum_height = datum->height();
  int datum_width = datum->width();
  int datum_size = datum_channels * datum_height * datum_width;
  std::string buffer(datum_size, ' ');
  for (int h = 0; h < datum_height; ++h) {
    const uchar* ptr = cv_img.ptr<uchar>(h);
    int img_index = 0;
    for (int w = 0; w < datum_width; ++w) {
      for (int c = 0; c < datum_channels; ++c) {
        int datum_index = (c * datum_height + h) * datum_width + w;
        buffer[datum_index] = static_cast<char>(ptr[img_index++]);
      }
    }
  }
  datum->set_data(buffer);
}

 아래는 datum을 Mat로 변환하는 것.
cv::Mat DatumToCVMat(const Datum& datum)
{
 int datum_channels = datum.channels();
 int datum_height = datum.height();
 int datum_width = datum.width();

 string strData = datum.data();
 cv::Mat cv_img;
 if (strData.size() != 0)
 {
  cv_img.create(datum_height, datum_width, CV_8UC(datum_channels));
  const string& data = datum.data();
  std::vector<char> vec_data(data.c_str(), data.c_str() + data.size());

  for (int h = 0; h < datum_height; ++h) {
   uchar* ptr = cv_img.ptr<uchar>(h);
   int img_index = 0;
   for (int w = 0; w < datum_width; ++w) {
    for (int c = 0; c < datum_channels; ++c) {
     int datum_index = (c * datum_height + h) * datum_width + w;
     ptr[img_index++] = static_cast<uchar>(vec_data[datum_index]);
    }
   }
  }
 }
 else
 {
  cv_img.create(datum_height, datum_width, CV_32FC(datum_channels));
  for (int h = 0; h < datum_height; ++h) {
   float* ptr = cv_img.ptr<float>(h);
   int img_index = 0;
   for (int w = 0; w < datum_width; ++w) {
    for (int c = 0; c < datum_channels; ++c) {
     ptr[img_index++] = static_cast<float>(datum.float_data(img_index));
    }
   }
  }
 }
 return cv_img;
}

2017년 1월 25일 수요일

caffe data augmentation

딥러닝할때 주어진 DATA의 량은 정합성을 좌우 하죠.. 때문에 DATA Augmentation 이 필요하죠.. Caffe 가 기본 제공 하는 augmentation은 random crop 과 mirror(flip vertical) 입니다. 그리고 Train Phase만 사용 가능하구요. 다른 사람들이 만들어 놓은것도 있는데, 추가로 더 필요한 것들이 많네요.

 가장 general 한 방법들이 많이 추가 된 곳이 https://github.com/kevinlin311tw/caffe-augmentation 여기인데 Train phase 만, Image Data Type만 지원합니다. 제 PC 환경에서는 Image Data Type 과 LMDB 로 Train 하는것은.. 약 3배 정도 차이납니다.


그래서 Data Augmentaion 을 추가로 만들어 보았습니다. https://github.com/ttagu99/caffe/tree/windows

 DATA AUGUMENTATION 을 추가합니다. 사용은 아래의 예처럼 쓰면되는데, 주의 할 점은 기존에는 crop_size에 값을 입력할 경우, ramdomly crop을 하게 되는데 변경된 코드에서는 crop_offset_rand를 true로 해줘야 합니다.

  1. layer {
  2. name: "train-data"
  3. type: "Data"
  4. top: "data"
  5. top: "label"
  6. include {
  7. phase: TRAIN
  8. }
  9. transform_param {
  10. mirror: true
  11. flip_hor: true
  12. crop_size: 300
  13. crop_offset_rand: true
  14. mean_file: "CAR_DISTANCE/train.binaryproto"
  15. contrast_adjustment: true
  16. smooth_filtering: true
  17. jpeg_compression: true
  18. rotation_angle_interval: 0
  19. display: false
  20. }
  21. data_param {
  22. source: "CAR_DISTANCE/Train_out/"
  23. batch_size: 10
  24. backend: LMDB
  25. }
  26. }
  27. layer {
  28. name: "val-data"
  29. type: "Data"
  30. top: "data"
  31. top: "label"
  32. include {
  33. phase: TEST
  34. }
  35. transform_param {
  36. mirror: true
  37. flip_hor: true
  38. crop_size: 300
  39.     crop_offset_rand: true
  40. mean_file: "CAR_DISTANCE/validation.binaryproto"
  41.     contrast_adjustment: true
  42. smooth_filtering: true
  43. jpeg_compression: true
  44.     rotation_angle_interval: 0
  45. display: false
  46. }
  47. data_param {
  48. source: "CAR_DISTANCE/Validation_out/"
  49. batch_size: 10
  50. backend: LMDB
  51. }
  52. }

  lmdb type 및 image data tpye 모두 가능합니다. train phase, test phase 모두 가능합니다. @kevinlin311tw/caffe-augmentation 를 기반으로 만들었습니다. Thank you for your inspiration!

2016년 8월 5일 금요일

darknet train time image resize speed issue

 darknet yolo train을 할때, image size나 net 구조, gpu, cpu 사양에 따라 다르겠지만, 내 환경에서는 아래처럼 gpu 가 idle 되는 시간이 많이 발생 했다.

profiling 을 해보니 image를 random 하게 resize 하는 부분에서 cpu 처리가 오래 걸리는 것이 었다.  

resize 부분을 opencv +ipp +gpu 로 바꾸고 나서 아래처럼 개선 되었다.

내 환경에서는 4배정도 빨리 train되고 있다.

2016년 7월 29일 금요일

darknet window용 소스코드

 CNN 에 대한 분류 외에도 detection 이 필요 하여, caffe를 사용해서 ROI Pooling Layer를 사용한 R-CNN을 사용 하려고 보니, 최근 들어 연구 되고 있는 fast R-CNN 이, faster R-CNN을 좀 찾아 보았다. R-CNN이 가진 단점들이 개선되고 있는거 같다. 특히 속도.. 그 중에 좀 특이한걸 발견했는데 darknet  이 링크를 보면 fast r-cnn 보다 100배 빠르다고 써있다. 그렇다면 당연히 이거 써야지.. 근데... caffe 처럼 ipython notebook 환경에서 쉽게 사용하기에는 작업이 많이 필요할 듯 하다.

 일단 나는 window 에서 작업할 것임으로 기존 소스코드에서 약간의 수정이 필요했다. https://github.com/ttagu99/darknet -> vs2013 + cuda 7.5 + opencv3.1.0 + cudnn ver5 환경으로 수정한 파일.

 darknet train을 위한 sample images와 sample lables들을 http://guanghan.info/blog/en/my-works/train-yolo/  이 링크에서 구해서 컴파일 후 바로 training을 해 볼수 있도록 코드 수정하였다.
 training 하는 방법은 기존 코드에서 조금 변경했다. train 이미지 경로와 모델 저장 경로가 하드코딩 되어있어서 아래처럼 변경하였다.

darknetVs2013 yolo train [cfg경로] [Init weight파일이름] [training 이미지 경로가 저장된 파일] [iter별 모델이 저장될 경로]
e.g.
darknetVs2013 yolo train ../cfg/yolo_448_448.cfg init.weights training_list.txt ./backup

2016년 3월 14일 월요일

Caffe Window Visual Studio Setting

 deep learning 이 요즘 이슈이기는 하지만, 사회적으로, ai 분야에서는 10년도 더 되었지만 여전히 hot item인거 같다.. 예전예.. 한 4,5년 전쯤 Geoffrey Hinton 의 Deep Belief NN 논문http://www.cs.toronto.edu/~hinton/absps/ncfast.pdf을 보고 비슷한 Application을 만들때만 해도 Deep Learning 이라는 거는 알겠는데.. 뭔가 부족해 보였다. 기존 NN이나 SVM도 가능한거였기 때문이던거 같다..
 작년에 오랜만에 NVIDIA 컨퍼러스에 갔다가 여러 부스에서 R-CNN 단어를 여러번 듣고, 아 이게 요즘 대세 구나 라고 생각하고, 공부해봐야겠다라고 생각만 하다가, 이제서야 여유가 좀 생겨 시작 해봐야겠다.. (그렇다고.. 스마트카 만드는건 포기한건 아니고.. 만드는 과정중에.. 공부라고 생각..ㅜ)
 일단 Open Source 부터 검색해보고, 몇가지 나오는것 중에 Caffe 를 공부해보기로 했다. 공부하는 순서는 Caffe 컴파일 하고, 샘플 돌려보고, 나만의 App을 만들어보고, Caffe를 수정해보려고 한다. 여담이지만 Open Source 세상에서는 공부하기가 너무 쉽다..(쉬운건 아니고.. 공부할 자료 찾기 편한거..)
 작년만 해도 Caffe 하려면 linux 환경에서 해야하는 구나 하고 생각해서, 가상 머신 깔아해야하는 구나하고 검색좀 해보니, 선구자들께서 이미 윈도우에서 쓰려고 fork 해다가 contribute를 하고 있었다.. https://github.com/happynear/caffe-windows
 근데 워낙 핫한 아이템이다 보니 ms에서 나서서 maintenance 역할을 해주겠다고 나섰나 보다.. https://github.com/Microsoft/caffe
 일단 github에서 소스코드를 받는다. 받은 후에 안에 내용을 보면 windows 폴더가 있다. ms에서 관리하는거 답게.. windows 안에 .sln파일이 있다. 다른 커뮤니티 들은 cmake같은 프로그램으로 만들어야 하는데 개발환경이 같은 입장에서는 클릭클릭 작업이 없어져서 편하다.

 caffe-master/windows 폴더 안에 내용을 보면 Caffe.sln 파일이 있다. vs2013으로 열어서
(2015는 아직 지원안된다. caffe가 지원하지 않는건 아니고 cuda 7.5가 지원 안됨.. 이전 qt ui를 사용할때도 그랬던거 같다.) 컴파일 해보면 props ***** 에러가 날텐데. 그러면 아래처럼 파일 이름을 바꿔 주고 나서 해보면 된다.





 그 다음 컴파일을 해보면 cuda 관련 .h파일들이 없다는 에러가 난다. 나는 가상 머신에서 test 중이라 아무것도 설치가 안되어 있다. cuda 7.5를 다운로드 받아서 설치 한다. 
 그리고 나서 다시 컴파일 하면. cudnn 관련 .h 파일 없다는 에러가 남아 있다.. cudnn은 cuda 설치시 같이 설치 되지 않았다. https://developer.nvidia.com/cudnn  여기서 다운로드 받은 후에 압축을 풀고, cuda 가 설치된 경로를 찾아서 복사한다.  다시 컴파일 해보면 c2220 warning treated as error - no 'object' file generated
에러가 난다.

libcaffe 프로젝트 속성에서 경고를 오류러처리 부분을 아니요로 바꿔주고 나서 빌드해 보면 된다!!!!
 이제 좋은 샘플을 찾아 ㄱㄱ~


------------ 질문에 대한 답변 추가 --------------
error : NuGet Error:알 수 없는 명령: 'overlay'   C:\Users\elf19\Downloads\caffe-master\windows\packages\OpenCV.2.4.10\build\native\OpenCV.targets   768   5   libcaffe

패키지 버전으로 인해 위와 같은 에러들이 있는거 같은데.
제가 setting 해서 사용 하고 있는 패키지 파일입니다.

구글 드라이브 용량이 제한이 있음으로.. 몇일 동안만 링크 걸어 놓겠습니다.