Jupyter Notebook으로 R 실행


Anaconda 설치

Jupyter Notebook update

conda update ipython-notebook

IRkernel 설치

conda install -c r ipython-notebook r-irkernel

Rkernel을 jupyter에서 실행하기 위한 필수 package설치
아래의 명령어는 R console에서 실행 한다.

install.packages(c('rzmq','repr','IRkernel','IRdisplay'), repos = 'http://irkernel.github.io/', type = 'source')

모두 설치 후 R Console에서 다음을 입력한다.

IRkernel::installspec()
quit() # 종료

아래와 같이 R kernel이 생성 되었다.


Data Transformation: dplyr package


R의 신 Hadley Wickham의 책 R for Data Science 5장에 나오는 내용을 정리 한다.

Hadley Wickham본인이 직접 만든 패키지이므로 유용하다.
기타 그가 만든 패키지는 아래와 같다.

  • ggplot2
  • plyr
  • reshape2

plyr은 모든 함수가 R로 작성되어서 처리 속도가 느리다는 단점이 있다.
dplyr C++로 작성되어 불필요한 함수를 불러오지 않기 때문에 매우 빠른 처리 속도를 자랑한다.
결국 분할(split),적용(apply) 병합(combine)을 plyr로 하던것을 dplyr로 변경하는 패러다임 전환이다.

필자도 plyr {}{}ply를 많이 사용 했었다. 하지만 파이프연산과 조합한dplyr이 좀 더 가독성이 높고
속도도 빠르다고하니 이쪽으로 옴겨 가야 하는 것 같다.

dplyr의 지원 함수군 외의 특징

  • data.table 지원
  • 각종 DB지원: MySQL, PostgreSQL, SQLite, BigQuery
  • 데이터 큐브
함수명내용유사함수
filter()지정한 조건식에 맞는 데이터 추출subset()
select()열의 추출data[, c(“Year”, “Month”)]
mutate()열 추가transform()
arrange()정렬order(), sort()
summarise()집계aggregate()

필요 package

install.packages("nycflights13")
library("nycflights13")
library(tidyverse)

tidyverse 로딩시 아래와 같이 conflict메시지가 나올 수도 있다.

-- Attaching packages --------------------------------------- tidyverse 1.2.1 --
√ ggplot2 2.2.1     √ purrr   0.2.4
√ tibble  1.4.1     √ dplyr   0.7.4
√ tidyr   0.7.2     √ stringr 1.2.0
√ readr   1.1.1     √ forcats 0.3.0
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()

flights데이터를 출력하면 아래와 같이 출력 된다.

> flights
# A tibble: 336,776 x 19
    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay carrier flight tailnum origin dest  air_time
   <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>     <dbl> <chr>    <int> <chr>   <chr>  <chr>    <dbl>
 1  2013     1     1      517            515      2.00      830            819     11.0  UA        1545 N14228  EWR    IAH      227  
 2  2013     1     1      533            529      4.00      850            830     20.0  UA        1714 N24211  LGA    IAH      227  
 3  2013     1     1      542            540      2.00      923            850     33.0  AA        1141 N619AA  JFK    MIA      160  
 4  2013     1     1      544            545     -1.00     1004           1022    -18.0  B6         725 N804JB  JFK    BQN      183  
 5  2013     1     1      554            600     -6.00      812            837    -25.0  DL         461 N668DN  LGA    ATL      116  
 6  2013     1     1      554            558     -4.00      740            728     12.0  UA        1696 N39463  EWR    ORD      150  
 7  2013     1     1      555            600     -5.00      913            854     19.0  B6         507 N516JB  EWR    FLL      158  
 8  2013     1     1      557            600     -3.00      709            723    -14.0  EV        5708 N829AS  LGA    IAD       53.0
 9  2013     1     1      557            600     -3.00      838            846    - 8.00 B6          79 N593JB  JFK    MCO      140  
10  2013     1     1      558            600     -2.00      753            745      8.00 AA         301 N3ALAA  LGA    ORD      138  
# ... with 336,766 more rows, and 4 more variables: distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>
> class(flights)
[1] "tbl_df"     "tbl"        "data.frame"

336,776의 뉴욕에서 2013에 출발한 비행 정보를 담고 있다.
US Bureau of Transportation Statistics

tibble이라는 data.frame을 약간 변형 시킨것을 사용한다.
tibble에 대한 상세한 내용의 링크이다.

dplyr basics

중요 package 5개를 설명한다.

  • Pick obervations by their values (filter())
  • Reorder the rows (arrange())
  • Pick variables by their names(select())
  • Create new variables with functions of existing variables (mutate())
  • Collpase many values down to a single summary (summarise())

추가로 group_by()를 통해서 scope을 조절 할 수 있다.

filter()

관찰한 데이터의 subset을 쉽게 구할 수 있도록 해준다.
첫 번째 인자는 data frame이고, 아래 예제에서 그 다음 인자들은 조건을 의미한다.
아래의 예제는 January 1st를 필터링한 예제이다.

nov_dec <- filter(flights, month %in% c(11, 12))
# A tibble: 55,403 x 19
    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay carrier flight tailnum origin dest  air_time
   <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>     <dbl> <chr>    <int> <chr>   <chr>  <chr>    <dbl>
 1  2013    11     1        5           2359      6.00      352            345      7.00 B6         745 N568JB  JFK    PSE      205  
 2  2013    11     1       35           2250    105         123           2356     87.0  B6        1816 N353JB  JFK    SYR       36.0
 3  2013    11     1      455            500   -  5.00      641            651    -10.0  US        1895 N192UW  EWR    CLT       88.0
 4  2013    11     1      539            545   -  6.00      856            827     29.0  UA        1714 N38727  LGA    IAH      229  
 5  2013    11     1      542            545   -  3.00      831            855    -24.0  AA        2243 N5CLAA  JFK    MIA      147  
 6  2013    11     1      549            600   - 11.0       912            923    -11.0  UA         303 N595UA  JFK    SFO      359  
 7  2013    11     1      550            600   - 10.0       705            659      6.00 US        2167 N748UW  LGA    DCA       57.0
 8  2013    11     1      554            600   -  6.00      659            701    - 2.00 US        2134 N742PS  LGA    BOS       40.0
 9  2013    11     1      554            600   -  6.00      826            827    - 1.00 DL         563 N912DE  LGA    ATL      126  
10  2013    11     1      554            600   -  6.00      749            751    - 2.00 DL         731 N315NB  LGA    DTW       93.0
# ... with 55,393 more rows, and 4 more variables: distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>

arrange()

정렬 용도

arrange(flights, desc(arr_delay))
#> # A tibble: 336,776 × 19
#>    year month   day dep_time sched_dep_time dep_delay arr_time
#>   <int> <int> <int>    <int>          <int>     <dbl>    <int>
#> 1  2013     1     9      641            900      1301     1242
#> 2  2013     6    15     1432           1935      1137     1607
#> 3  2013     1    10     1121           1635      1126     1239
#> 4  2013     9    20     1139           1845      1014     1457
#> 5  2013     7    22      845           1600      1005     1044
#> 6  2013     4    10     1100           1900       960     1342
#> # ... with 3.368e+05 more rows, and 12 more variables:
#> #   sched_arr_time <int>, arr_delay <dbl>, carrier <chr>, flight <int>,
#> #   tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>,
#> #   distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>

select()

선택 용도

select(flights, year, month, day)
select(flights, year:day)
select(flights, -(year:day))
  • starts_with(“abc”): matches names that begin with “abc”.
  • ends_with(“xyz”): matches names that end with “xyz”.
  • contains(“ijk”): matches names that contain “ijk”.
  • matches(“(.)\1”): selects variables that match a regular expression. This one matches any variables that contain - repeated characters. You’ll learn more about regular expressions in strings.
  • num_range(“x”, 1:3) matches x1, x2 and x3.

mutate()

현재 있는 Data.Frame의 맨 뒤에다가 새로운 컬럼을 추가하는 것이다.

flights_sml <- select(flights, 
  year:day, 
  ends_with("delay"), 
  distance, 
  air_time
)
mutate(flights_sml,
  gain = arr_delay - dep_delay,
  speed = distance / air_time * 60
)
# A tibble: 336,776 x 9
    year month   day dep_delay arr_delay distance air_time   gain speed
   <int> <int> <int>     <dbl>     <dbl>    <dbl>    <dbl>  <dbl> <dbl>
 1  2013     1     1      2.00     11.0      1400    227     9.00   370
 2  2013     1     1      4.00     20.0      1416    227    16.0    374
 3  2013     1     1      2.00     33.0      1089    160    31.0    408
 4  2013     1     1     -1.00    -18.0      1576    183   -17.0    517
 5  2013     1     1     -6.00    -25.0       762    116   -19.0    394
 6  2013     1     1     -4.00     12.0       719    150    16.0    288
 7  2013     1     1     -5.00     19.0      1065    158    24.0    404
 8  2013     1     1     -3.00    -14.0       229     53.0 -11.0    259
 9  2013     1     1     -3.00    - 8.00      944    140   - 5.00   405
10  2013     1     1     -2.00      8.00      733    138    10.0    319
# ... with 336,766 more rows

plyr:transform과 다른점은 연이어서 생성한 컬럼을 바로 사용해도 된다는 것이다.

mutate(flights_sml,
  gain = arr_delay - dep_delay,
  hours = air_time / 60,
  gain_per_hour = gain / hours
)
# A tibble: 336,776 x 10
    year month   day dep_delay arr_delay distance air_time
   <int> <int> <int>     <dbl>     <dbl>    <dbl>    <dbl>
 1  2013     1     1      2.00     11.0      1400    227  
 2  2013     1     1      4.00     20.0      1416    227  
 3  2013     1     1      2.00     33.0      1089    160  
 4  2013     1     1     -1.00    -18.0      1576    183  
 5  2013     1     1     -6.00    -25.0       762    116  
 6  2013     1     1     -4.00     12.0       719    150  
 7  2013     1     1     -5.00     19.0      1065    158  
 8  2013     1     1     -3.00    -14.0       229     53.0
 9  2013     1     1     -3.00    - 8.00      944    140  
10  2013     1     1     -2.00      8.00      733    138  
# ... with 336,766 more rows, and 3 more variables: gain <dbl>,
#   hours <dbl>, gain_per_hour <dbl>

새로 생성한 variable columns만 유지하고 싶으면 transmute를 사용한다.

transmute(flights,
  gain = arr_delay - dep_delay,
  hours = air_time / 60,
  gain_per_hour = gain / hours
)
# A tibble: 336,776 x 3
     gain hours gain_per_hour
    <dbl> <dbl>         <dbl>
 1   9.00 3.78           2.38
 2  16.0  3.78           4.23
 3  31.0  2.67          11.6 
 4 -17.0  3.05         - 5.57
 5 -19.0  1.93         - 9.83
 6  16.0  2.50           6.40
 7  24.0  2.63           9.11
 8 -11.0  0.883        -12.5 
 9 - 5.00 2.33         - 2.14
10  10.0  2.30           4.35
# ... with 336,766 more rows

summarise()

그룹핑해서 하나의 single row로 합치는 역할을 한다.
그냥 summarise만 단독해서 사용하면 엄청나게 유용하진 않지만, group_by와 함께 사용하면 그 위력이 증대된다.

그냥 summarise하면 단 하나의 row로 처리됨

summarise(flights, delay = mean(dep_delay, na.rm = TRUE))
# A tibble: 1 x 1
  delay
  <dbl>
1  12.6

group_by를 이용해서 그룹핑 가능함

by_day <- group_by(flights, year, month, day)
summarise(by_day, delay = mean(dep_delay, na.rm = TRUE))
# pipe
group_by(flights, year, month, day) %>% summarise(delay = mean(dep_delay, na.rm = TRUE))
# A tibble: 365 x 4
# Groups:   year, month [?]
    year month   day delay
   <int> <int> <int> <dbl>
 1  2013     1     1 11.5 
 2  2013     1     2 13.9 
 3  2013     1     3 11.0 
 4  2013     1     4  8.95
 5  2013     1     5  5.73
 6  2013     1     6  7.15
 7  2013     1     7  5.42
 8  2013     1     8  2.55
 9  2013     1     9  2.28
10  2013     1    10  2.84
# ... with 355 more rows

파이프의 사용

아래 세개의 작업을 수행

  • flight를 destination에 따라서 그룹핑함
  • flight의 수와 거리, 평균 딜레이를 요약
  • Honolulu airport와 noisy point를 제거 한다.

파이를 사용하면 쓸 때 없는 중간 변수들을 정의하지 않아도 되기 때문에 편리하고 직관적인 이해를 달성한다.

파이프 사용

delays <- flights %>% 
  group_by(dest) %>% 
  summarise(
    count = n(),
    dist = mean(distance, na.rm = TRUE),
    delay = mean(arr_delay, na.rm = TRUE)
  ) %>% 
  filter(count > 20, dest != "HNL")

파이프 미사용

# Combining multiple operations with the pipe
by_dest <- group_by(flights, dest)
delay <- summarise(by_dest,
   count = n(),
   dist = mean(distance, na.rm = TRUE),
   delay = mean(arr_delay, na.rm = TRUE)
)
delay <- filter(delay, count > 20, dest != "HNL")

참고자료

R 데이터 처리의 새로운 강자, dplyr 패키지
dplyr로 데이터 집계와 분석


'AI > R Basic' 카테고리의 다른 글

R Studio Server Install in Ubuntu Server  (3) 2018.07.04
Jupyter Notebook으로 R 실행  (2) 2018.04.15
두 개 데이터 프레임 병합, 빼기  (0) 2018.03.04
R Factor 검색  (0) 2017.11.13
RStudio v1.1 Released  (0) 2017.10.10

openPose 설치 및 구동 (ubuntu 16.04 + 1080)


CMU의 유명 프로젝트인 딥러닝 기반 openPose 구동에 대해서 다룬다.
영상 자동 tagging시 유용하게 쓸 수 있는 오픈 코드인것 같다.

openPose 논문 리스트

  • CVPR17, Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields
  • CVPR16, Hand Keypoint Detection in Single Images using Multiview Bootstrapping
  • CVPR16, Convolutional pose machines

코드
github 주소

설치

설치 컴퓨터는 한성컴퓨터 보스몬스터 (NVIDA 1080) 스팩은 아래와 같다.
구매시기: 2017.1월, 200만원

코드 다운
git clone https://github.com/CMU-Perceptual-Computing-Lab/openpose.git

종속 프로그램 설치

  • sudo apt-get install cmake-qt-gui설치 make 위해서 visual configuration을 하기 위함이다.
  • CUDA 8 cuDNN 5.1설치. cuDNN까지 설치해야 Deep Learning 작업시 속도가 빠르다. CUDA 9.0까지 나와 있으니 버전을 잘 맞춰서 설치
    • sudo ./install_cmake.sh해당 스크립트로 설치 가능
  • Caffe 설치: sudo ./install_cmake.sh
  • OpenCV 설치: sudo apt-get install libopencv-dev

설정을 통한 Makefile 생성

Console에서 cmake-gui를 입력

아래와 같은 설정 창이 나온다.

  • where is the source code 부분에 openpose root 디렉토리를 설정
  • where to build the binaries 부분에 build 디렉토리 설정
  • configure버튼을 누르고 Unix Makefile로 선택한다.
  • Finish 버튼을 누르면 아래와 같이 진행된다.

  • generate버튼을 한번 더 누른다. done이 나오면 성공

아래와 같이 처음에 git clone으로 코드만 다운받고 설치만 하면 build디렉토리에 Makefile이 없다. 이제 정상적으로 생성 되어있다.

make -j 8을 실행해서 컴파일 한다. (8은 가능한 process 숫자이다.)

컴파일 성공

데모 실행 결과

quick-start 가이드에 따라서 한번 실행해 본다.

빌드가 성공해야만 build/examples/openpose/openpose.bin파일이 생성되어 있다.

비디오 실행 명령어

# Ubuntu
./build/examples/openpose/openpose.bin --video examples/media/video.avi
# With face and hands
./build/examples/openpose/openpose.bin --video examples/media/video.avi --face --hand

아래는 그냥 포즈만 디텍션한 것으로 1080에서 10 FPS까지 나온다.

아래는 얼굴 을 포함한 것으로 급격히 떨어져서 1.4 FPS가 된다.

두 동영상 예제를 실행 했을 때의 GPU load를 측정한 것이다.
GPU 메모리는 1.7GB 사용하고 GPU-Util 80~90%정도 점유된다.


'AI > Caffe' 카테고리의 다른 글

Faster R CNN Training  (0) 2017.02.27
Faster-R-CNN Install on Ubuntu 16.04(GTX1080 CUDA 8.0,cuDNN 5.1)  (4) 2017.02.26

두 개 데이터 프레임 병합, 빼기


공통 키를 기준으로 병합

하나이상의 key를 가지고 두 개의 데이터 프레임을 join하는 연산

# merge two data frames by ID
total <- merge(data frameA,data frameB,by="ID")

두 개의 데이터로 병합

# merge two data frames by ID and Country
total <- merge(data frameA,data frameB,by=c("ID","Country"))

빼기

Larger - Smaller

small

     ID       CSF1PO CSF1PO.1 D10S1248 D10S1248.1 D12S391 D12S391.1
203079_BA_M     10       11       14         16      -9        -9
203079_BA_F      8       12       14         17      -9        -9
203080_BA_M     10       12       13         13      -9        -9

big

      ID      CSF1PO CSF1PO.1 D10S1248 D10S1248.1 D12S391 D12S391.1
203078_MG_M     -9       -9       15         15      18        20
203078_MG_F     -9       -9       14         15      17        19
203079_BA_M     10       11       14         16      -9        -9
203079_BA_F      8       12       14         17      -9        -9
203080_BA_M     10       12       13         13      -9        -9
203080_BA_F     10       11       14         16      -9        -9
203081_MG_M     10       12       14         16      -9        -9
203081_MG_F     11       12       15         16      -9        -9
203082_MG_M     11       11       13         15      -9        -9
203082_MG_F     11       11       13         14      -9        -9

Solution

BigDF[ !(BigDF$ID %in% SmallDF$ID), ]

'AI > R Basic' 카테고리의 다른 글

Jupyter Notebook으로 R 실행  (2) 2018.04.15
Data Transformation: dplyr package  (0) 2018.04.14
R Factor 검색  (0) 2017.11.13
RStudio v1.1 Released  (0) 2017.10.10
rJava load 에러  (0) 2017.04.16

학습 모델의 재사용 (Transfer Learning)


DNN 모델을 스케치 단계서 부터 전부 다시 학습하는 것은 어려운 일이다. 정말 많은 데이터를 필요로 하기 때문에 학습이 거의 대부분 실패 한다.

여러 방법이 있을 수 있지만 여기서는 Transfer Learning을 다룬다. 잘알려진pretrainted model을 이용해서 마지막 final layer만 수정해서 본인의 목적에 맞게 다시 학습 시키는 방법이다.
혹자는 Fine tuning이라 부르기도 한다.

본인 보유한 데이터 양에 따라 어느 정도 레이어들을 수정할지가 결정된다. 보통 앞부분 layer는 추상적인 feature를 extraction하는 레이어이므로 건들지 않고 마지막 레이러들을 수정한다.

하지만 pretrained model이 현재 수행하려고 하는 작업에 전혀 관련이 없다면Transfer Learning이 의미가 퇴색 된다.
이 경우 unsupervised pre-training방법으로 RBM 또는 Autoencoder방법을 사용하거나 실제로 labeling 데이터를 왕창 모아서 학습을 해야한다.
하지만 scarth부터 random initialization 상태에서 학습하는 것은 매우 도전적인 일이므로 추천 하진 않는다.

결국 아무 때나 Deep Learning을 쓰기엔 무리가 있다.

개념설명

아래와 같이 ImageNet모델이 있다고 가정한다. 1000개를 classify할 수 있다.

이것을 가지고 고양이 Tigger, Misty, Neither 세개를 구분하는 모델을 만든다. 당연히 이런 특정 고양이 이미지는 많이 없다. 따라서 pre-trained 모델을 사용 한다.

이 때 학습할 때 마지막 softmax layer만 학습하게 된다.
이전 데이터는 freeze하게 된다. 이것은 deep learning framework에 따라 구현코드가 달라진다. 이후에는 TensorFlow를 이용해서 이 방법을 다룬다.

  • trainablePrameter =0, freeze = 1

그리고 이러한 freeze레이어의 숫자는 training data의 양에 따라서 다르게 적용할 수 있다.

Tensorflow 구현 (개념 설명)

전부다 저장하고 restore하는 코드

[...] # construct the original model

with tf.Session() as sess:
	saver.restore(sess, "./my_original_model.ckpt")
	[...] # Train it on your new task

부분적으로 복구하는 방법

init = tf.global_variables_initializer()
reuse_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope="hidden[123]")
reuse_vars_dict = dict([(var.name, var.name) for var in reuse_vars])
original_saver = tf.Saver(reuse_vars_dict) # saver to restore the original model

new_saver = tf.Saver() # saver to save the new model

with tf.Session() as sess:
	sess.run(init)
	original_saver.restore("./my_original_model.ckpt") # restore layers 1 to 3
	[...] # train the new model
	new_saver.save("./my_new_model.ckpt") # save the whole model

좀 더 상세한 내용은 이전 포스트를 참조한다.

실제코드

MNIST 데이터를 가지고 fully connected DNN의 pre-trained model을 로드해서 fine-tuning 하는 방법을 다룬다.
전체 구현코드는 Github Link에 있다.

  • 모델 학습
  • 전체 로드
  • 일부분 로드
  • 앞부분 레이어 고정후 뒷 부분만 학습
  • 고정레이어 cache후 뒷 부분만 학습 (트레이닝 속도 향상)

기본 라이브러리 로딩

import tensorflow as tf
# Common imports
import numpy as np
import os
from tensorflow.examples.tutorials.mnist import input_data

def reset_graph(seed=42):
    tf.reset_default_graph()
    tf.set_random_seed(seed)
    np.random.seed(seed)
def leaky_relu(z, name=None):
    return tf.maximum(0.01 * z, z, name=name)

mnist = input_data.read_data_sets("./")
Extracting ./train-images-idx3-ubyte.gz
Extracting ./train-labels-idx1-ubyte.gz
Extracting ./t10k-images-idx3-ubyte.gz
Extracting ./t10k-labels-idx1-ubyte.gz

모델 생성

하이퍼파라메터 설정

reset_graph()

n_inputs = 28 * 28  # MNIST
n_hidden1 = 300
n_hidden2 = 50
n_hidden3 = 50
n_hidden4 = 50
n_hidden5 = 50
n_outputs = 10

n_epochs = 20
batch_size = 50

모델 생성

X = tf.placeholder(tf.float32, shape=(None, n_inputs), name="X")
y = tf.placeholder(tf.int64, shape=(None), name="y")

with tf.name_scope("dnn"):
    hidden1 = tf.layers.dense(X, n_hidden1, activation=tf.nn.relu, name="hidden1")
    hidden2 = tf.layers.dense(hidden1, n_hidden2, activation=tf.nn.relu, name="hidden2")
    hidden3 = tf.layers.dense(hidden2, n_hidden3, activation=tf.nn.relu, name="hidden3")
    hidden4 = tf.layers.dense(hidden3, n_hidden4, activation=tf.nn.relu, name="hidden4")
    hidden5 = tf.layers.dense(hidden4, n_hidden5, activation=tf.nn.relu, name="hidden5")
    logits = tf.layers.dense(hidden5, n_outputs, name="outputs")

with tf.name_scope("loss"):
    xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
    loss = tf.reduce_mean(xentropy, name="loss")

with tf.name_scope("eval"):
    correct = tf.nn.in_top_k(logits, y, 1)
    accuracy = tf.reduce_mean(tf.cast(correct, tf.float32), name="accuracy")

learning_rate = 0.01
threshold = 1.0

optimizer = tf.train.GradientDescentOptimizer(learning_rate)
grads_and_vars = optimizer.compute_gradients(loss)
capped_gvs = [(tf.clip_by_value(grad, -threshold, threshold), var)
              for grad, var in grads_and_vars]
training_op = optimizer.apply_gradients(capped_gvs)

init = tf.global_variables_initializer()
saver = tf.train.Saver()

학습

with tf.Session() as sess:
    init.run()
    for epoch in range(n_epochs):
        for iteration in range(mnist.train.num_examples // batch_size):
            X_batch, y_batch = mnist.train.next_batch(batch_size)
            sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
        if epoch % 5 == 0:
            acc_train = accuracy.eval(feed_dict={X: X_batch, y: y_batch})
            acc_test = accuracy.eval(feed_dict={X: mnist.validation.images, y: mnist.validation.labels})
            print(epoch, "Batch accuracy:", acc_train, "Validation accuracy:", acc_test)

    save_path = saver.save(sess, "./my_model_final.ckpt")
0 Batch accuracy: 0.94 Validation accuracy: 0.9006
5 Batch accuracy: 1.0 Validation accuracy: 0.9642
10 Batch accuracy: 0.96 Validation accuracy: 0.9712
15 Batch accuracy: 0.98 Validation accuracy: 0.9772
20 Batch accuracy: 1.0 Validation accuracy: 0.9774
25 Batch accuracy: 1.0 Validation accuracy: 0.9786
30 Batch accuracy: 1.0 Validation accuracy: 0.9778
35 Batch accuracy: 1.0 Validation accuracy: 0.9776

모델 로딩후 재학습

여기서 부터 모델을 불러와서 다시 fine-tuning 하는 부분을 구현 한다.

reset_graph()
saver = tf.train.import_meta_graph("./my_model_final.ckpt.meta")

로딩가능한 operation이 무엇인지 확인한다.

for op in tf.get_default_graph().get_operations():
    print(op.name)
X
y
hidden1/kernel/Initializer/random_uniform/shape
hidden1/kernel/Initializer/random_uniform/min
hidden1/kernel/Initializer/random_uniform/max
[생략]
[생략]
save/RestoreV2_11/tensor_names
save/RestoreV2_11/shape_and_slices
save/RestoreV2_11
save/Assign_11
save/restore_all

파라메터가 너무 많기 때문에 TensorBoard로 확인한다.
그다음 아래와 같이 get_tensor_by_name get_operation_by_name으로 로드한다.

X = tf.get_default_graph().get_tensor_by_name("X:0")
y = tf.get_default_graph().get_tensor_by_name("y:0")

accuracy = tf.get_default_graph().get_tensor_by_name("eval/accuracy:0")

training_op = tf.get_default_graph().get_operation_by_name("GradientDescent")

다른 사람의 편의를 위해서 import operation collection으로 미리 정의해 줄수도 있다.

for op in (X, y, accuracy, training_op):
    tf.add_to_collection("my_important_ops", op)

이렇게 하면 다른 사람들이 쉽게 로딩 가능하다.

X, y, accuracy, training_op = tf.get_collection("my_important_ops")

아래와 같이 이제 본인의 데이터로 본격적으로 학습이 가능하다.

with tf.Session() as sess:
    saver.restore(sess, "./my_model_final.ckpt")
    # continue training the model...
INFO:tensorflow:Restoring parameters from ./my_model_final.ckpt

아니면 모델을 로드에서 Testing만 가능하다.

with tf.Session() as sess:
    saver.restore(sess, "./my_model_final.ckpt")

    for epoch in range(n_epochs):
        for iteration in range(mnist.train.num_examples // batch_size):
            X_batch, y_batch = mnist.train.next_batch(batch_size)
            sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
        accuracy_val = accuracy.eval(feed_dict={X: mnist.test.images,
                                                y: mnist.test.labels})
        print(epoch, "Test accuracy:", accuracy_val)

    save_path = saver.save(sess, "./my_new_model_final.ckpt")    
INFO:tensorflow:Restoring parameters from ./my_model_final.ckpt
0 Test accuracy: 0.9743
1 Test accuracy: 0.9744
2 Test accuracy: 0.9756
3 Test accuracy: 0.9743
4 Test accuracy: 0.9751
5 Test accuracy: 0.975
6 Test accuracy: 0.9741
7 Test accuracy: 0.9742
8 Test accuracy: 0.9751
9 Test accuracy: 0.9748
10 Test accuracy: 0.9744
11 Test accuracy: 0.9747
12 Test accuracy: 0.9746
13 Test accuracy: 0.9747
14 Test accuracy: 0.9746
15 Test accuracy: 0.9747
16 Test accuracy: 0.9742
17 Test accuracy: 0.9749
18 Test accuracy: 0.9746
19 Test accuracy: 0.9748
20 Test accuracy: 0.975
21 Test accuracy: 0.9746
22 Test accuracy: 0.9745
23 Test accuracy: 0.975
24 Test accuracy: 0.9744
25 Test accuracy: 0.9743
26 Test accuracy: 0.9743
27 Test accuracy: 0.9745
28 Test accuracy: 0.9746
29 Test accuracy: 0.9749
30 Test accuracy: 0.9746
31 Test accuracy: 0.9747
32 Test accuracy: 0.9747
33 Test accuracy: 0.9743
34 Test accuracy: 0.9746
35 Test accuracy: 0.9746
36 Test accuracy: 0.9749
37 Test accuracy: 0.9751
38 Test accuracy: 0.9748
39 Test accuracy: 0.9743

다른 방법은 그냥 원래 모델에 대한 code가 있다면 그것을 로딩해도 된다. 그렇게 하면import_meta_graph()를 호출하지 않아도 된다.

마지막 4번째 레어어만 수정해서 재학습하기 (not freezing the lower layers)

  • import_meta_graph()로 전체 graph를 모두 불러온다음 4번째 Layer를 무시한다.
  • 즉 3번째 레이어 까지만 재사용한다.
  • 그리고 output 레이어도 재설정한다.
  • 그리고 이것으로 optimizer를 이용해서 최적화한다.
  • 이렇게 생성된 결과를 새로운 파일에 저장한다.
reset_graph()

n_hidden4 = 20  # new layer
n_outputs = 10  # new layer

saver = tf.train.import_meta_graph("./my_model_final.ckpt.meta")

X = tf.get_default_graph().get_tensor_by_name("X:0")
y = tf.get_default_graph().get_tensor_by_name("y:0")

hidden3 = tf.get_default_graph().get_tensor_by_name("dnn/hidden4/Relu:0")

new_hidden4 = tf.layers.dense(hidden3, n_hidden4, activation=tf.nn.relu, name="new_hidden4")
new_logits = tf.layers.dense(new_hidden4, n_outputs, name="new_outputs")

with tf.name_scope("new_loss"):
    xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=new_logits)
    loss = tf.reduce_mean(xentropy, name="loss")

with tf.name_scope("new_eval"):
    correct = tf.nn.in_top_k(new_logits, y, 1)
    accuracy = tf.reduce_mean(tf.cast(correct, tf.float32), name="accuracy")

with tf.name_scope("new_train"):
    optimizer = tf.train.GradientDescentOptimizer(learning_rate)
    training_op = optimizer.minimize(loss)

init = tf.global_variables_initializer()
new_saver = tf.train.Saver()

새로운 레이어를 정의하고 loss namesapce를 다르게 정의 했기 때문에saver.restore()후에 값이 중복 되지 않는다.

with tf.Session() as sess:
    init.run()
    saver.restore(sess, "./my_model_final.ckpt")

    for epoch in range(n_epochs):
        for iteration in range(mnist.train.num_examples // batch_size):
            X_batch, y_batch = mnist.train.next_batch(batch_size)
            sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
        accuracy_val = accuracy.eval(feed_dict={X: mnist.test.images,
                                                y: mnist.test.labels})
        print(epoch, "Test accuracy:", accuracy_val)

    save_path = new_saver.save(sess, "./my_new_model_final.ckpt")
INFO:tensorflow:Restoring parameters from ./my_model_final.ckpt
0 Test accuracy: 0.9665
...
...
39 Test accuracy: 0.9751

마지막 4번째 레어어만 수정해서 재학습하기 (freezing the lower layers)

구현을 위해서는 2가지 방법이 존재한다.

  • tf.GraphKeys.TRAINABLE_VARIABLES, scope="outputs")을 이용한 방법
  • tf.stop_gradient를 이용한방법

tf.GraphKeys.TRAINABLE_VARIABLES 이용

reset_graph()

n_inputs = 28 * 28  # MNIST
n_hidden1 = 300 # reused
n_hidden2 = 50  # reused
n_hidden3 = 50  # reused
n_hidden4 = 20  # new!
n_outputs = 10  # new!

X = tf.placeholder(tf.float32, shape=(None, n_inputs), name="X")
y = tf.placeholder(tf.int64, shape=(None), name="y")

with tf.name_scope("dnn"):
    hidden1 = tf.layers.dense(X, n_hidden1, activation=tf.nn.relu, name="hidden1")       # reused
    hidden2 = tf.layers.dense(hidden1, n_hidden2, activation=tf.nn.relu, name="hidden2") # reused
    hidden3 = tf.layers.dense(hidden2, n_hidden3, activation=tf.nn.relu, name="hidden3") # reused
    hidden4 = tf.layers.dense(hidden3, n_hidden4, activation=tf.nn.relu, name="hidden4") # new!
    logits = tf.layers.dense(hidden4, n_outputs, name="outputs")                         # new!

with tf.name_scope("loss"):
    xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
    loss = tf.reduce_mean(xentropy, name="loss")

with tf.name_scope("eval"):
    correct = tf.nn.in_top_k(logits, y, 1)
    accuracy = tf.reduce_mean(tf.cast(correct, tf.float32), name="accuracy")

학습할 대상을 정규식에 의해서 scope을 정해서 불러온다.
결과는 아래와 같다.

tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,
                                   scope="outputs")
[<tf.Variable 'outputs/kernel:0' shape=(20, 10) dtype=float32_ref>,
<tf.Variable 'outputs/bias:0' shape=(10,) dtype=float32_ref>]
with tf.name_scope("train"):                                         # not shown in the book
    optimizer = tf.train.GradientDescentOptimizer(learning_rate)     # not shown
    train_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,
                                   scope="outputs")
    training_op = optimizer.minimize(loss, var_list=train_vars)
init = tf.global_variables_initializer()
new_saver = tf.train.Saver()

따로 새롭게 namesapce를 정의하지 않고 load할 때 정규식을 이용해서 일부분만 불러온다.
이렇게 하면 name을 변경할 필요 없다.

tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES,
                               scope="hidden[123]|outputs") # regular expression
[<tf.Variable 'hidden1/kernel:0' shape=(784, 300) dtype=float32_ref>,
 <tf.Variable 'hidden1/bias:0' shape=(300,) dtype=float32_ref>,
 <tf.Variable 'hidden2/kernel:0' shape=(300, 50) dtype=float32_ref>,
 <tf.Variable 'hidden2/bias:0' shape=(50,) dtype=float32_ref>,
 <tf.Variable 'hidden3/kernel:0' shape=(50, 50) dtype=float32_ref>,
 <tf.Variable 'hidden3/bias:0' shape=(50,) dtype=float32_ref>,
 <tf.Variable 'outputs/kernel:0' shape=(20, 10) dtype=float32_ref>,
 <tf.Variable 'outputs/bias:0' shape=(10,) dtype=float32_ref>]
reuse_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES,
                               scope="hidden[123]|outputs]") # regular expression
reuse_vars_dict = dict([(var.op.name, var) for var in reuse_vars])
restore_saver = tf.train.Saver(reuse_vars_dict) # to restore layers 1-3

init = tf.global_variables_initializer()
saver = tf.train.Saver()

with tf.Session() as sess:
    init.run()
    restore_saver.restore(sess, "./my_model_final.ckpt")

    for epoch in range(n_epochs):
        for iteration in range(mnist.train.num_examples // batch_size):
            X_batch, y_batch = mnist.train.next_batch(batch_size)
            sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
        accuracy_val = accuracy.eval(feed_dict={X: mnist.test.images,
                                                y: mnist.test.labels})
        print(epoch, "Test accuracy:", accuracy_val)

    save_path = saver.save(sess, "./my_new_model_final.ckpt")
INFO:tensorflow:Restoring parameters from ./my_model_final.ckpt
0 Test accuracy: 0.9221
...
...
39 Test accuracy: 0.9556

tf.stop_gradient 이용

reset_graph()

n_inputs = 28 * 28  # MNIST
n_hidden1 = 300 # reused
n_hidden2 = 50  # reused
n_hidden3 = 50  # reused
n_hidden4 = 20  # new!
n_outputs = 10  # new!

X = tf.placeholder(tf.float32, shape=(None, n_inputs), name="X")
y = tf.placeholder(tf.int64, shape=(None), name="y")
with tf.name_scope("dnn"):
    hidden1 = tf.layers.dense(X, n_hidden1, activation=tf.nn.relu,
                              name="hidden1") # reused frozen
    hidden2 = tf.layers.dense(hidden1, n_hidden2, activation=tf.nn.relu,
                              name="hidden2") # reused frozen
    hidden2_stop = tf.stop_gradient(hidden2)
    hidden3 = tf.layers.dense(hidden2_stop, n_hidden3, activation=tf.nn.relu,
                              name="hidden3") # reused, not frozen
    hidden4 = tf.layers.dense(hidden3, n_hidden4, activation=tf.nn.relu,
                              name="hidden4") # new!
    logits = tf.layers.dense(hidden4, n_outputs, name="outputs") # new!
with tf.name_scope("loss"):
    xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
    loss = tf.reduce_mean(xentropy, name="loss")

with tf.name_scope("eval"):
    correct = tf.nn.in_top_k(logits, y, 1)
    accuracy = tf.reduce_mean(tf.cast(correct, tf.float32), name="accuracy")

with tf.name_scope("train"):
    optimizer = tf.train.GradientDescentOptimizer(learning_rate)
    training_op = optimizer.minimize(loss)

위와 같이 hidden2_stop = tf.stop_gradient(hidden2)을 사용해서 중간 레이어를 만든다.
그 이후에는 트레이닝 코드는 위 방식과 정확히 일치한다.

%%time
reuse_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES,
                               scope="hidden[123]") # regular expression
reuse_vars_dict = dict([(var.op.name, var) for var in reuse_vars])
restore_saver = tf.train.Saver(reuse_vars_dict) # to restore layers 1-3

init = tf.global_variables_initializer()
saver = tf.train.Saver()

with tf.Session() as sess:
    init.run()
    restore_saver.restore(sess, "./my_model_final.ckpt")

    for epoch in range(n_epochs):
        for iteration in range(mnist.train.num_examples // batch_size):
            X_batch, y_batch = mnist.train.next_batch(batch_size)
            sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
        accuracy_val = accuracy.eval(feed_dict={X: mnist.test.images,
                                                y: mnist.test.labels})
        print(epoch, "Test accuracy:", accuracy_val)

    save_path = saver.save(sess, "./my_new_model_final.ckpt")
INFO:tensorflow:Restoring parameters from ./my_model_final.ckpt
0 Test accuracy: 0.9654
...
...
19 Test accuracy: 0.9738
CPU times: user 23.1 s, sys: 852 ms, total: 23.9 s
Wall time: 13.5 s

Fronzen Layer를 cache해서 학습속도를 올리는 방법

Frozen 레이어는 변화하지 않기 때문에 이것은 cache해서 재사용 할 수 있다.

reset_graph()

n_inputs = 28 * 28  # MNIST
n_hidden1 = 300 # reused
n_hidden2 = 50  # reused
n_hidden3 = 50  # reused
n_hidden4 = 20  # new!
n_outputs = 10  # new!

X = tf.placeholder(tf.float32, shape=(None, n_inputs), name="X")
y = tf.placeholder(tf.int64, shape=(None), name="y")

with tf.name_scope("dnn"):
    hidden1 = tf.layers.dense(X, n_hidden1, activation=tf.nn.relu,
                              name="hidden1") # reused frozen
    hidden2 = tf.layers.dense(hidden1, n_hidden2, activation=tf.nn.relu,
                              name="hidden2") # reused frozen & cached
    hidden2_stop = tf.stop_gradient(hidden2)
    hidden3 = tf.layers.dense(hidden2_stop, n_hidden3, activation=tf.nn.relu,
                              name="hidden3") # reused, not frozen
    hidden4 = tf.layers.dense(hidden3, n_hidden4, activation=tf.nn.relu,
                              name="hidden4") # new!
    logits = tf.layers.dense(hidden4, n_outputs, name="outputs") # new!

with tf.name_scope("loss"):
    xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
    loss = tf.reduce_mean(xentropy, name="loss")

with tf.name_scope("eval"):
    correct = tf.nn.in_top_k(logits, y, 1)
    accuracy = tf.reduce_mean(tf.cast(correct, tf.float32), name="accuracy")

with tf.name_scope("train"):
    optimizer = tf.train.GradientDescentOptimizer(learning_rate)
    training_op = optimizer.minimize(loss)
reuse_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES,
                               scope="hidden[123]") # regular expression
reuse_vars_dict = dict([(var.op.name, var) for var in reuse_vars])
restore_saver = tf.train.Saver(reuse_vars_dict) # to restore layers 1-3

init = tf.global_variables_initializer()
saver = tf.train.Saver()

핵심 방법은 1번만 트레이닝해서 h2_cache를 만든다음 이것을 suffling한 index를 가지고 epoch을 돌면서 training하는 것이다.
메모리가 충분하다면 이러한 방법이 가능하다.
뒷 부분을 계산하지 않기 때문에 training속도를 증가 시킬 수 있다.13.5초에서9.63초로 속도가 빨라진 것을 알 수 있다.

%%time
import numpy as np

n_batches = mnist.train.num_examples // batch_size

with tf.Session() as sess:
    init.run()
    restore_saver.restore(sess, "./my_model_final.ckpt")
    
    h2_cache = sess.run(hidden2, feed_dict={X: mnist.train.images})
    h2_cache_test = sess.run(hidden2, feed_dict={X: mnist.test.images}) # not shown in the book

    for epoch in range(n_epochs):
        shuffled_idx = np.random.permutation(mnist.train.num_examples)
        hidden2_batches = np.array_split(h2_cache[shuffled_idx], n_batches)
        y_batches = np.array_split(mnist.train.labels[shuffled_idx], n_batches)
        for hidden2_batch, y_batch in zip(hidden2_batches, y_batches):
            sess.run(training_op, feed_dict={hidden2:hidden2_batch, y:y_batch})

        accuracy_val = accuracy.eval(feed_dict={hidden2: h2_cache_test, # not shown
                                                y: mnist.test.labels})  # not shown
        print(epoch, "Test accuracy:", accuracy_val)                    # not shown

    save_path = saver.save(sess, "./my_new_model_final.ckpt")
INFO:tensorflow:Restoring parameters from ./my_model_final.ckpt
0 Test accuracy: 0.9648
...
...
19 Test accuracy: 0.9736
CPU times: user 20.7 s, sys: 428 ms, total: 21.1 s
Wall time: 9.63 s

참고문헌

Coursera deep learning ai, Andrew Ng.
Hands-On Machine Learning with Scikit-Learn and Tensorflow, Aureien Geron


TensorFlow 모델을 저장하고 불러오기 (save and restore)


해당 튜토리얼에 사용한 코드는 개인 GitHub Link에서 확인 할 수 있다.

저장 복구를 위해서는 두개의 파일이 필요하다.

a) Meta graph

Tensorflow graph를 저장 하게 된다. 즉 all variables, operations, collections 등을 저장 한다. .meta로 확장자를 가진다.

b) Checkpoint file

binary 파일로 weights, biases, gradients 등을 저장 한다.
0.11부터는 두개의 파일로 저장된다.

  • model.ckpt.data-00000-of-00001
  • model.ckpt.index

.data파일의 경우 training variable를 가지고 있다.
여전히 checkpoint파일도 보유하고 있지만 이것은 단순히 최근 상태만을 기록하고 있다.

모델 저장 방법

saver = tf.train.Saver()를 통해서 가능 하다.

import tensorflow as tf
w1 = tf.Variable(tf.random_normal(shape=[2]), name='w1')
w2 = tf.Variable(tf.random_normal(shape=[5]), name='w2')
saver = tf.train.Saver()
sess = tf.Session()
sess.run(tf.global_variables_initializer())
saver.save(sess, 'my_test_model')

# This will save following files in Tensorflow v >= 0.11
# my_test_model.data-00000-of-00001
# my_test_model.index
# my_test_model.meta
# checkpoint

만약 1000 interations 이후에 model을 저장하고 싶다면 아래와 같이 한다.

saver.save(sess, "my_test_model", global_step=1000)

이렇게 하면 아래처럼 모델뒤에 -1000이라는 숫자가 이름에 붙어서 나오게 됩니다.

my_test_model-1000.index
my_test_model-1000.meta
my_test_model-1000.data-00000-of-00001
checkpoint

모델의 구조는 같기 때문에 .meta파일의 경우 1000 interation당 매번 생성할 필요는 없다.

모델 값만 저장하고 graph는 저장하지 않는 코드는 아래와 같다.

saver.save(sess, 'my-model', global_step=step,write_meta_graph=False)

만약 최근 2시간동안 4개의 모델만 저장하고 싶다면 아래와 같이 옵션을 설정한다.

#saves a model every 2 hours and maximum 4 latest models are saved.
saver = tf.train.Saver(max_to_keep=4, keep_checkpoint_every_n_hours=2)

망약 tf.train.Saver()에 아무것도 지정하지 않았다면 모든 변수들을 저장하게 된다.
특정 variables/collections을 저장하고 싶다면 그것을 지정하면 된다.
List, dictionary자료구조도 받으니 그것을 잘 활용 한다.

import tensorflow as tf
w1 = tf.Variable(tf.random_normal(shape=[2]), name='w1')
w2 = tf.Variable(tf.random_normal(shape=[5]), name='w2')
saver = tf.train.Saver([w1,w2])
sess = tf.Session()
sess.run(tf.global_variables_initializer())
saver.save(sess, 'my_test_model',global_step=1000)

모델 읽기

두 가지 일을 해야한다.

a) 네트워크 생성

.meta파일을 생성 했으므로 이것을 불러오는 방식으로 network을 재생성 할 수 있다.
.meta파일을 불러오기 위해서는 tf.train.import() 함수를 이용한다.

saver = tf.train.import_meta_graph('my_test_model-1000.meta')

이렇게 하면 현재 그래프에 이어 붙는 형식으로 동작하므로tf.reset_default_graph()를 실행해서 default graph로 초기화 해주는 것이 안전하다.

b) 파라메터 로딩

tf.train.Saver()를 이용해서 파라메터를 로딩한다.

with tf.Session() as sess:
  new_saver = tf.train.import_meta_graph('my_test_model-1000.meta')
  new_saver.restore(sess, tf.train.latest_checkpoint('./'))
with tf.Session() as sess:    
    saver = tf.train.import_meta_graph('my-model-1000.meta')
    saver.restore(sess, tf.train.latest_checkpoint('./'))
    print(sess.run('w1:0'))
##Model has been restored. Above statement will print the saved value of w1.

저장된 모델로 실제 작업하기

이제 위해서 다룬 내용을 토대로 종합적으로 간단한 neural net.을 생성하고 이것을 저장한다음 다시 불러오는 코드를 작성해 본다.
이런한 작업은 추후에 transfer learning이나 testing만 별도로 작업하기 위해서 사용 될 수 있다.

아래의 코드는 $y=(w1+w2) \times b$ 를 구현한 내용이다.
여기서 핵심은 추후에 variable operation을 각각 불러오기 위해서 name을 반드시 주어야 한다.
나중에 본인 model을 공유할 때도 이름을 잘 정해주어야 다른 사람이 가져다가 본인들 목적에 맞춰서 fine-tuning해서 사용할 수 있다.

모델 생성 및 저장

import tensorflow as tf

# Prepare to feed input, i.e. feed_dict and placeholders
w1 = tf.placeholder(tf.float32, name="w1")
w2 = tf.placeholder(tf.float32, name="w2")
b1 = tf.Variable(2.0,dtype=tf.float32, name="bias")
feed_dict = {'w1': 4.0, 'w2': 8.0}

# Define a test operation that we will restore
w3 = w1 + w2
w4 = tf.multiply(w3, b1, name="op_to_restore")
sess = tf.Session()
sess.run(tf.global_variables_initializer())

# Create a saver object which will save all the variables
saver = tf.train.Saver()

# Run the operation by feeding input
result = sess.run(w4, {w1:feed_dict['w1'], w2:feed_dict['w2']})
print(result)
# Prints 24 which is sum of (w1+w2)*b1

# Now, save the graph
saver.save(sess, './my_test_model', global_step=1000)

실행결과는 24이다.

모델 불러오기와서 새로운 입력값으로 처리

모델을 복구하고 feed_dict을 다르게 입력하는 코드이다.

import tensorflow as tf

sess=tf.Session()    
#First let's load meta graph and restore weights
saver = tf.train.import_meta_graph('my_test_model-1000.meta')
saver.restore(sess,tf.train.latest_checkpoint('./'))


# Now, let's access and create placeholders variables and
# create feed-dict to feed new data

graph = tf.get_default_graph()
w1 = graph.get_tensor_by_name("w1:0")
w2 = graph.get_tensor_by_name("w2:0")
feed_dict ={w1:13.0,w2:17.0}

#Now, access the op that you want to run. 
op_to_restore = graph.get_tensor_by_name("op_to_restore:0")

print (sess.run(op_to_restore,feed_dict))
#This will print 60 which is calculated 
#using new values of w1 and w2 and saved value of b1. 

실행결과는 60이다.

위 예제는 Tensor를 이용해서 간단하게 구현하다보니 모두get_tensor_by_name()으로 가능하지만 실제로 operation과 placeholder는 각각 다르게 load해야 한다.

  • placeholder 불러오기

    • graph.get_tensor_by_name()
  • operation 불러오기

    • graph.get_operation_by_name()

로딩 가능한 현재 graph에서의 operation의 종류이다.

for op in tf.get_default_graph().get_operations():
    print(op.name)

모델을 불러오고 operation과 layer 추가

import tensorflow as tf

sess=tf.Session()    
#First let's load meta graph and restore weights
saver = tf.train.import_meta_graph('my_test_model-1000.meta')
saver.restore(sess,tf.train.latest_checkpoint('./'))


# Now, let's access and create placeholders variables and
# create feed-dict to feed new data

graph = tf.get_default_graph()
w1 = graph.get_tensor_by_name("w1:0")
w2 = graph.get_tensor_by_name("w2:0")
feed_dict ={w1:13.0,w2:17.0}

#Now, access the op that you want to run. 
op_to_restore = graph.get_tensor_by_name("op_to_restore:0")

#Add more to the current graph
add_on_op = tf.multiply(op_to_restore,2)

print (sess.run(add_on_op,feed_dict))
#This will print 120.

실행결과 120이다.

참고자료

http://cv-tricks.com/tensorflow-tutorial/save-restore-tensorflow-models-quick-complete-tutorial/


Batch 크기의 결정 방법


보통 vectorization방법으로 gradient descent알고리즘의 효율을 높이게 된다.

하지만 input 데이터가 너무 크다면 그 방법을 사용할 수 없다.
메모리 문제도 발생하고 한 번 interation (epoch)당 시간이 너무 오래 걸리기 때문이다.

Batch-gradient descent mini-bach gradient descent의 cost 그래프의 차이는 아래와 같다.

Choosing your mini-batch size

  • Mini-batch 크기가 전체 트레이닝 셋 데이터 사이즈인 m과 같다면 이것은 Batch gradient descent방법이다.

    • (+) 상대적으로 아래의 contour그래프를 보면 알 수 있듯이 적은 noise Large step으로 글로벌 미니멈에 수렴한다.
    • (+) vectorization 효율이 좋다.
    • (-) interation당 속도가 느리다.
    • (-) 메모리 여유 공간에 따라서 실행 불가능 할 수도 있다.
  • Mini-batch 크기가 1이라면,Stochastic gradient descent라고 부른다.

    • (+) 적은 메모리로 동작 가능하다. noise한 부분은 learning rate을 작게하면 완화 할 수 있다.
    • (-) vectorization 효율이 없다. training data를 1개만 사용하기 때문이다.
  • Mini-batch크기를 너무 작게도 크게도 하지 않는다.

    • (+) vectorization을 효과 본다.
    • (+) interation당 긴 시간없이 progress를 만들 수 있다.

최종적 가이드라인

  • 데이터가 별로 없다면 batch gradient descent를 쓴다.
    • ex 2,000 정도
  • mini-batch를 선택
    • 64, 128, 256, 512 사이즈로 선택한다. 메모리 사이즈에 맞춰서
  • CPU/GPU memory 사이즈에 맞춰서 조절 한다.

Take-away message
SGD GD가 같은 글로벌 cost 최소점에 도달 할 수 있다는 것은 증명이 되어 있지만, neural netwrok은 convex가 아니기 때문에 batch 크기의 설정 방법에 따라 수렴하는 조건이 다를 수 있다.

Batch size는 일반적으로 메모리가 감당할 수 있는 정도까지 최대한 크게 잡는게 좋을것 같다.

참고자료

Coursera DeepLearning ai, Andrew Ng


딥러닝 입력 데이터 정규화 (Normalizing inputs)


학습을 수행하기 전에 값의 범위를 normalization 하는 것은 중요하다. 그 이유는 아래와 같다.

입력 변수가 MLP에서와 같이 선형 적으로 결합된다면 적어도 이론 상으로는 입력을 표준화하는 것이 거의 필요하지 않습니다.
그 이유는 해당 weight bais를 변경하여 입력 벡터를 재조정하면 이전과 완전히 똑같은 결과를 남길 수 있기 때문입니다.
그러나 입력을 Standardization하면 학습을 더 빨리하고 지역 최적의 상태에 빠지게 될 가능성을 줄이는 다양한 실용적인 이유가 있습니다.
또한, 표준화 된 입력을 통해 Gradient Descent  Bayesian estimation을 보다 편리하게 수행 할 수 있습니다.

Normalization

수식 : (요소값 - 최소값) / (최대값 - 최소값)
설명 : 전체 구간을 0~1사이의 값으로 맞춰 준다.

Standardization

수식 : (요소값 - 평균) / 표준편차
설명 : 평균은 0 표준편차는

$$\mu = \frac{1}{m} \sum_{i=1}^{m}{x^{(i)}}$$
$$x := x -\mu$$
$$\sigma^{2}=\frac{1}{m}\sum_{i=1}^{m}{(x^{(i)}-\mu)^{2}}$$

직관적 이해

아래와 같이 Unnormalized된 상태에서는 Learning Rate을 매우 작게 설정해야 정상적을 학습이 된다.
이유는 cost 그래프가 elongated하기 때문이다. 따라서 elongated contour의 모습을 가진다.
아래와 같이 Input의 Range가 서로 다르다면 Gradient Descent Algorithm을 적용하는것이 매우 까다로워지는 상황이 발생 한다.

하지만 normalization을 적용하면 좀 더 spherical contour를 가지게 된다.
이렇게 하면 좀 더 Gradient Descent Algorithm으로 쉽게 그리고 빠르게 최적화 지점을 찾게 된다.

구현 코드

아래와 같은 코드를 가질 때
x가 1.0
y가 0.0
이렇게 1.0~0 사이의 값으로 입력과 출력이 정규화가 잘되면 학습이 잘 이뤄 진다.
Learning rate을 적절히 값을 잡아도 학습이 잘된다.

import tensorflow as tf
x = tf.constant(1.0, name='input')
w = tf.Variable(0.8, name='weight')
y = tf.mul(w, x, name='output')
y_ = tf.constant(0.0, name='correct_value')
loss = tf.pow(y - y_, 2, name='loss')
train_step = tf.train.GradientDescentOptimizer(0.025).minimize(loss)

for value in [x, w, y, y_, loss]:
    tf.scalar_summary(value.op.name, value)

summaries = tf.merge_all_summaries()

sess = tf.Session()
summary_writer = tf.train.SummaryWriter('log_simple_stats', sess.graph)

sess.run(tf.initialize_all_variables())
for i in range(100):
    if i % 10 ==0:
        print("epoch {}, output: {}".format(i, sess.run(y)))
    summary_writer.add_summary(sess.run(summaries), i)
    sess.run(train_step)
epoch 80, output: 0.01321229338645935
epoch 90, output: 0.007910688407719135

하지만 x의 범위르 10배만 넓혀서 10으로 하면 학습이 실패 한다.
이 때는 Learning rate을 더 작게 주어야 한다.

import tensorflow as tf
x = tf.constant(10.0, name='input')
w = tf.Variable(0.8, name='weight')
y = tf.mul(w, x, name='output')
y_ = tf.constant(0.0, name='correct_value')
loss = tf.pow(y - y_, 2, name='loss')
train_step = tf.train.GradientDescentOptimizer(0.025).minimize(loss)

for value in [x, w, y, y_, loss]:
    tf.scalar_summary(value.op.name, value)

summaries = tf.merge_all_summaries()

sess = tf.Session()
summary_writer = tf.train.SummaryWriter('log_simple_stats', sess.graph)

sess.run(tf.initialize_all_variables())
for i in range(100):
    if i % 10 ==0:
        print("epoch {}, output: {}".format(i, sess.run(y)))
    summary_writer.add_summary(sess.run(summaries), i)
    sess.run(train_step)
epoch 70, output: nan

통상의 Learning Rate의 문제와 비슷하게 발생 한다.

참고 사이트

http://stackoverflow.com/questions/4674623/why-do-we-have-to-normalize-the-input-for-an-artificial-neural-network


TensorFlow Lite 예제 실행


구글이 공개한 TensorFlow Lite의 샘플 예제를 실행하는 방법을 다룬다.

아래는 실행 예제를 Galaxy S8에서 실행한 모습이다. 

첫 번째 영상은 TF lite를 이용해서 Quantized MobileNet 딥러닝 모델을 실행한 것이다. 두 번째 영상은 TF Mobile을 이용해서

Inception v5 딥러닝 모델을 실행한 영상이다.

     


카메라로 들어온 영상을 실시간으로 처리하게 된다. 홈페이지에서는 Quantized mobilenet이 좀더 경량화 되었기 때문에 Inceptionv5보다 정확도 손실이 있다고 했지만 별 차이는 모르겠다. 

샘플 예제를 실행하는 방법은 아래 3가지가 있다.

  • prebuilt binary 다운로드
  • Android 3.0을 이용해서 App 컴파일
  • TF lite 코드와 demo app을 다운 받아서 bazel로 빌드한다.

pre-built binary 다운로드 방법

TfLiteCameraDemo.apk 이것을 다운 받아서 실행 한다.

무슨 문제가 있는지 galaxy s8에서 설치가 안된다.

Building in Android Studio using TensorFlow Lite AAR from JCenter

가장 컴파일 하기 쉬운 방법이다.

조건 사항은 아래와 같다.

  • Android Studio 3.0 이상

  • Android SDK 버전 26이상

  • Androi NDK 버전 14 이상

  • Tensorflow코드를 git clone https://github.com/tensorflow/tensorflow으로 다운 받은 다음,tensorflow/contrib/lite/java/demo 디렉터리를 Android Studio로 Import 한다.

  • Quantized Mobilenet을 다운로드 받는다. mobilenet-quant_v1_224.tflite이다. 이것을 그리고 import한 앱에서 assets에 압축을 풀어서 넣는다.

    • wget https://storage.googleapis.com/download.tensorflow.org/models/tflite/mobilenet_v1_224_android_quant_2017_11_08.zip
  • Android Studio에서 demo app을 run 한다.

소스코드로 빌드하는 방법

https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/lite#downloading-the-pre-built-binary

참고 블로그

https://soundlly.github.io/2017/11/20/tensorflowlite-moblienet-demo/


TensorFlow Lite 개발자 프리뷰 공개


2017년 11월 14일 드디어 TensorFlow Lite 개발자 프리뷰가 공개 되었다. Google Developers post를 요약해 본다.

Tensorflow Lite는 low latency inference를 on-device에서 지원 한다.

특성은 아래와 같다.

  • Lightweight: small binary size, fast initialization/startup
  • Cross-platform: Android and iOS
  • Fast: Optimized for mobile devices, including dramatically improved

재미 있는 것은 TF lite는 purpose-built custom hardware를 지원 한다는 것이다. 이를 위해서 Android Neural networks API를 포함한다.
각 하드웨어별 가속기를 사용하는 API 집단이다.

Architecture

위 전체 구조에서 각각의 컴포넌트는 다음과 같다.

  • TensorFlow Model: 디스크에 있는 TF 학습 모델
  • TensorFlow Lite Convert: model을 TF Lite file format으로 변경하는것
  • TensorFlow Lite Model File: FlatBuffers 타입에서의 최적화된 모델

그다음 해당 TensorFlow Lite Model file은 모바일앱에 탑제 된다.

이 때 앱은 다음과 같이 구성된다.

  • Java API: C++을 감싼 wrapper API
  • C++ API: 모델을 읽고 interpreter를 호출하는 기능
  • Interpreter: TF Mobile이 normal set of operators가 1.5Mb인것에 비해서 이것은 operators 포함해서 300KB 수준이다.

그리고 선택된 장치에서 interpreter가 알아서 Android Neural Networks API를 통해서 hardware acceleration을 사용하게 된다. 지원 되는게 없다면 CPU를 사용한다.

추가적으로 개발자가 custom kernel을 개발할 수도 있다. 그리고 이것을 interpreter에서 사용 가능 하다.

Models

이미 많은 최적화된 학습 모델들을 지원한다.

  • MobileNet: 1000개의 object 클래스들은 디텍션하는 모델을 모바일과 임베디드에 맞춰서 다시 진행
  • Inception v3: 약간 큰 사이즈로 더 높은 정확도를 제공한다. 기술은 MobileNet과 유사하다.
  • Smart Reply: one-touch 응답을 위한 on-device 대화 모델이다. Android Wear상에서 앱개발할 때 사용 할 수 있다.

Inception V3나 MobileNet은 ImageNet 데이터셋으로 학습되어 있으므로 본인 목적에 맞게 사용하려면 Transfer learning을 해서 모델을 재학습 하면된다.

TensorFlow Mobile과 TensorFlow Lite와의 차이점

이미 TF Mobile이 있었다. 그것과의 차이점은 무엇인가

  • Lite 버전은 Mobile 버전은 혁신판이다. 좀 더 작은 binary 사이즈와 의존성으로도 더 좋은 성능을 보장 한다.
  • TF Lite가 모든걸 커버하진 않는다. 따라서 어떠한 production case에서는 TF Mobile을 사용해서 직접 코딩 해야할 수도 있다.
  • TF Lite는 제한적인 operator들을 지원 한다. 따라서 모든 알려진 model들이 동작하긴 어렵다. TF Mobile은 모든 operator들을 지원 하므로 다 구현 할 수 있다.

앞으로 계속 향상될 것이지만, TF Lite는 잘 알려진 모델을 하드웨어 가속해서 동작하는데 초점을 맞춘다. 개발 복잡도를 낮추기 위해서이다.
더 자세한 내용은 TF Lite documentation pages를 참고한다.

출처

[원글]


'AI > Embedded Deep learning' 카테고리의 다른 글

ONNX  (4) 2020.05.04
Glow 설치법  (1) 2019.11.19
Coral Dev Board (Google Edge TPU) 설정 및 사용후기  (2) 2019.08.13
Glow: graph lowering compiler for hardware accelerators  (0) 2019.02.07
TensorFlow Lite 예제 실행  (2) 2017.12.05

R Factor 검색


factor로 구성된 vector가 있다고 가정 한다.

%in

'a' %in% v

any()
any('a' == v)
[1] TRUE

is.element()
is.element('a',v)

첫 번째 매치 index 반환

match('a',v)

모든 일치하는 index 반환

which('a' == v)
[1] 2 4


'AI > R Basic' 카테고리의 다른 글

Data Transformation: dplyr package  (0) 2018.04.14
두 개 데이터 프레임 병합, 빼기  (0) 2018.03.04
RStudio v1.1 Released  (0) 2017.10.10
rJava load 에러  (0) 2017.04.16
Swapping columns in a matrix  (0) 2017.03.31

RStudio v1.1 Released


R Studio가 정식버전으로 2017-10-09일자로 v1.1이 업데이트 되었습니다.

위와 같이 Dark 테마가 기본으로 설정됩니다. 또한 terminal이 기본으로 탑제 되었습니다.

기타 변경사항의 Highlight는 아래와 같습니다.

  • connection tab: 다양한 database들과 쉽게 연결 하여 탐색 할 수 있습니다.
  • terminal tab: shell을 지원합니다.
  • object explorer: R data 구조와 객체를 좀 더 깊이 있게 탐색 할 수 있습니다.
  • dark theme: 현대적인 Theme을 사용 할 수 있습니다.
  • 다양한 약간의 향상과 버그 수정

Pro version은 좀 더 다양한 기능을 제공 받습니다.

설치 방법

  1. 공식사이트 URL에 접속후 운영체제에 맞는 설치파을을 다운로드 한다.

  2. 기존 설치자의 경우도 알아서 uninstall후 재설치가 자동으로 이뤄 진다.

출처

R Studio 공식 블로그


'AI > R Basic' 카테고리의 다른 글

두 개 데이터 프레임 병합, 빼기  (0) 2018.03.04
R Factor 검색  (0) 2017.11.13
rJava load 에러  (0) 2017.04.16
Swapping columns in a matrix  (0) 2017.03.31
R Notebook  (0) 2016.11.02

rpy2와 Pandas를 활용한 R object 변환


Rdata파일을 읽어와서 Robject를 다루는 방법을 기술한다.
필요한 package들은 아래와 같다.

from rpy2.robjects import r
from rpy2.robjects import pandas2ri
import pandas as pd
pandas2ri.activate()

위와 같이 robjects를 다루는 r pandas r을 연결해주는 pandas2ri 두 개의 package가 필요하다.

로딩 방법

# Object를 생성 한다.

r.load("./Rdata/num10FclassDf10PassTrain.Rdata")

실행 결과

R object with classes: ('character',) mapped to:
<StrVector - Python:0x7fc114f787c8 / R:0x2cdfbd8>
['num10FclassDf10PassTrain']

데이터 출력

r['num10FclassDf10PassTrain']

실행결과

R object with classes: ('list',) mapped to:
<ListVector - Python:0x7fc115095bc8 / R:0x265d9f0>
[Matrix, Matrix, Matrix, ..., Matrix, Matrix, Matrix]
  acquaintanceSeula: <class 'rpy2.robjects.vectors.Matrix'>
  R object with classes: ('matrix',) mapped to:
<Matrix - Python:0x7fc1150877c8 / R:0x4072ca0>
[       1,        1,        1, ...,        1,        1,        1]
  ikhee: <class 'rpy2.robjects.vectors.Matrix'>
  R object with classes: ('matrix',) mapped to:
<Matrix - Python:0x7fc1150b7308 / R:0x407a9d0>
[       1,        2,        1, ...,        1,        1,        2]
  Jemin: <class 'rpy2.robjects.vectors.Matrix'>
  R object with classes: ('matrix',) mapped to:
<Matrix - Python:0x7fc1153085c8 / R:0x40843b0>
[       2,        1,        1, ...,        1,        2,        2]
  ...
  acquaintanceSeula: <class 'rpy2.robjects.vectors.Matrix'>
  R object with classes: ('matrix',) mapped to:
<Matrix - Python:0x7fc11530c048 / R:0x432ead0>
[       1,        2,        2, ...,        2,        2,        2]
  ikhee: <class 'rpy2.robjects.vectors.Matrix'>
  R object with classes: ('matrix',) mapped to:
<Matrix - Python:0x7fc114efff08 / R:0x434e400>
[       1,        1,        1, ...,        2,        2,        2]
  Jemin: <class 'rpy2.robjects.vectors.Matrix'>
  R object with classes: ('matrix',) mapped to:
<Matrix - Python:0x7fc114eff888 / R:0x4354790>
[       1,        1,        3, ...,        1,        1,        2]

ri2py로 데이터형 변환

pandas2ri.ri2py(r['num10FclassDf10PassTrain'][0])

데이터 프레임으로 변경하는 방법

df1 = pd.DataFrame(pandas2ri.ri2py(r['num10FclassDf10PassTrain'][0]), columns=['AppName', "Title", "Hours", "Days", "RecentPhoneUsage", "Proximity", "Priority", "Activity", "PhoneStatus", "SeenTime", "class"])
df1.head()

참고문헌

https://pandas.pydata.org/pandas-docs/stable/r_interface.html


Confusion Matrix in python


Tensorflow를 이용한 prediction 결과를 평가하기 위해서 Confusion Matrix을 이용한다.
단순 Accuracy에 대해서는 어느정도 문제가 발생하기 때문이다.
아래의 두 package를 각각 이용할 수도 있다.

scikit

scikit package를 이용한 방법이 존재한다.

특정 값만 표시해 줄 수도 있고 Confusion Matrix를 표현할 수도 있다.

# Import packages
from sklearn.metrics import classification_report
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score

# Data
y_true = [1, 1, 0, 1, 0]
y_pred = [1, 1, 1, 0, 0]
target_names = ['false', 'true']
print(classification_report(y_true, y_pred, target_names=target_names))
precision_score(y_true, y_pred, average='binary',pos_label=1)
recall_score(y_true, y_pred, average='binary',pos_label=1)

실행 결과

	      precision    recall  f1-score   support

false       0.50      0.50      0.50         2
true       0.67      0.67      0.67         3

avg / total       0.60      0.60      0.60         5

precision: 0.66666666666666663
recall: 0.66666666666666663

Pandas

import pandas as pd

y_true = pd.Series([2, 0, 2, 2, 0, 1, 1, 2, 2, 0, 1, 2])
y_pred = pd.Series([0, 0, 2, 1, 0, 2, 1, 0, 2, 0, 2, 2])

pd.crosstab(y_true, y_pred, rownames=['True'], colnames=['Predicted'], margins=True)

Result

Predicted  0  1  2  All
True                   
0          3  0  0    3
1          0  1  2    3
2          2  1  3    6
All        5  2  5   12


Handling Class Imbalance with R


실제 데이터에 머신러닝을 적용하려고 하다보면 한 쪽의 class가 과도하게 큰 문제인 class imbalance 문제에 직면하게 된다.

Method to improve performance on imbalanced data

  • Class weights: impose a heavier cost when errors are made in the minority class

  • Down-sampling: randomly remove instances in the majority class

  • Up-sampling: randomly replicate instances in the minority class

  • Synthetic minority sampling technique (SMOTE): down samples the majority class and synthesizes new minority instances by interpolating between existing ones

SMOTE를 그림으로 설명하면 아래와 같다.

Imbalanced Classification in R

class imbalance 문제를 해결할 수 있는방법은 ROSE DMwR 페키지를 사용하는 것이다.
여기서 사용하는 예제는 Binary Classification문제를 다룬다.

  • ROSE: Random over smapling examples packages 이다. 이것은 artifical data를 샘플링 방법에 기반해서 생성 하게 된다.
install.packages("ROSE")
library(ROSE)

내부적으로 ROSE 페키지는 imbalanced data의 하나인 hacide.train hacide.test를 보유하고 있다.

SMOTE 방법

oversampling 방법은 너무 중복된 값이 많이 생성되고 undersampling은 중요한 데이터를 너무 많이 잃어 버린다.
ROSE는 이러한 문제를 해결 한다.

구현 코드

library(ROSE)

data(hacide) # imbalanced data
str(hacide.train)
str(hacide.test)


# check table
table(hacide.train$cls)
table(hacide.test$cls)

# check classes distribution
prop.table(table(hacide.train$cls))
prop.table(table(hacide.test$cls))


# only 2% of data is positive. 
# it is a severely imbalanced data set.

library(rpart)
treeimb <- rpart(cls ~ ., data = hacide.train)
pred.treeimb <- predict(treeimb, newdata = hacide.test)

# check model accuracy 
accuracy.meas(hacide.test$cls, pred.treeimb[,2])
roc.curve(hacide.test$cls, pred.treeimb[,2], plotit = F)


# over sampling
data_balanced_over <- ovun.sample(cls~., data = hacide.train, method = "over", N=1960)$data
# N refers to number of observations in the resulting balanced set.

table(data_balanced_over$cls)

# under sampling
data_balanced_under <- ovun.sample(cls~., data = hacide.train, method = "under", N=40)$data

# under and over smapling (both)
# the minority class is oversampled with replacement and majority class is undersampled without replacement
data_balanced_both <- ovun.sample(cls ~ ., data = hacide.train, method = "both", p=0.5, N=1000, seed = 1)$data
table(data_balanced_both$cls)

data.rose <- ROSE(cls ~ ., data = hacide.train, seed = 1)$data
table(data.rose$cls)


#build decision tree models
tree.rose <- rpart(cls ~ ., data = data.rose)
tree.over <- rpart(cls ~ ., data = data_balanced_over)
tree.under <- rpart(cls ~ ., data = data_balanced_under)
tree.both <- rpart(cls ~ ., data = data_balanced_both)

#make predictions on unseen data
pred.tree.rose <- predict(tree.rose, newdata = hacide.test)
pred.tree.over <- predict(tree.over, newdata = hacide.test)
pred.tree.under <- predict(tree.under, newdata = hacide.test)
pred.tree.both <- predict(tree.both, newdata = hacide.test)

#AUC ROSE
roc.curve(hacide.test$cls, pred.tree.rose[,2])

#AUC Oversampling
roc.curve(hacide.test$cls, pred.tree.over[,2])

#AUC Undersampling
roc.curve(hacide.test$cls, pred.tree.under[,2])

#AUC Both
roc.curve(hacide.test$cls, pred.tree.both[,2])

실행결과

> roc.curve(hacide.test$cls, pred.tree.rose[,2])
Area under the curve (AUC): 0.989
> roc.curve(hacide.test$cls, pred.tree.over[,2], add.roc=TRUE)
Area under the curve (AUC): 0.798
> roc.curve(hacide.test$cls, pred.tree.under[,2], add.roc=TRUE)
Area under the curve (AUC): 0.876
> roc.curve(hacide.test$cls, pred.tree.both[,2], add.roc=TRUE)
Area under the curve (AUC): 0.798

결론적으로 SMOTE방법을 구현한 ROSE package를 이용한 방법이 가장 정확도가 높게 나온다.

참고문헌

[1] Wicked Good Data
[2] Silicon Valley Data Science blog post

[3] SMOTE Implementation in Python
[4] https://www.analyticsvidhya.com/blog/2016/03/practical-guide-deal-imbalanced-classification-problems/

[5] http://machinelearningmastery.com/tactics-to-combat-imbalanced-classes-in-your-machine-learning-dataset/


'AI > Machine Learning with R' 카테고리의 다른 글

Feature Selection with Caret (Auto)  (0) 2016.11.20
Caret의 이해  (0) 2016.03.06
Cross Validation  (0) 2016.02.26
Ensemble method: Bagging (bootstrap aggregating)  (0) 2015.11.19
Bootstrapping  (0) 2015.11.19

Tensorflow Object Detection API (SSD, Faster-R-CNN)


2017.6.15에 Google에서 Tensorflow로 구현된Object Detection코드를 공개 했다. 말은 API라고 적혀 있지만 그냥 구현 코드이다. 지원하는 모델은 아래와 같다.

  • Single Shot Multibox Detector (SSD) with MobileNet
  • SSD with Inception V2
  • Region-Based Fully Convolutional Networks (R-FCN) with ResNet 101
  • Faster R-CNN with Resnet 101
  • Faster RCNN with Inception Resnet v2

설치 및 테스팅

일단 TF관련 예제를 구글이 만들어 놓은곳은 모두 modelsgithub에 있다.

git clone https://github.com/tensorflow/models.git

클론한 다음 object detection으로 들어간 다음Jupyter Notebook으로object_detection_tutorial.ipynb을 실행 한다.

코드를 정상적으로 실행 하기 위해선 아래의 작업을 수행해 줘야 한다.

dependencies

  • Protobuf 2.6
  • Pillow 1.0
  • lxml
  • tf Slim (which is included in the "tensorflow/models" checkout)
  • Jupyter notebook
  • Matplotlib
  • Tensorflow

Ubuntu 16.04 기준

sudo apt-get install protobuf-compiler python-pil python-lxml
sudo pip install jupyter
sudo pip install matplotlib

sudo pip install pillow
sudo pip install lxml
sudo pip install jupyter
sudo pip install matplotlib

Protobuf 컴파일

clone한 models에서 실행 한다.

# From tensorflow/models/
protoc object_detection/protos/*.proto --python_out=.

실행하면 아래와 같이 python코드들이 생성된다.

jemin@jemin-desktop:~/tf_examples/models/object_detection/protos$ ls
BUILD                         losses_pb2.py
__init__.py                   matcher.proto
__pycache__                   matcher_pb2.py
anchor_generator.proto        mean_stddev_box_coder.proto
anchor_generator_pb2.py       mean_stddev_box_coder_pb2.py
argmax_matcher.proto          model.proto
argmax_matcher_pb2.py         model_pb2.py
bipartite_matcher.proto       optimizer.proto
bipartite_matcher_pb2.py      optimizer_pb2.py
box_coder.proto               pipeline.proto
box_coder_pb2.py              pipeline_pb2.py
box_predictor.proto           post_processing.proto
box_predictor_pb2.py          post_processing_pb2.py
eval.proto                    preprocessor.proto
eval_pb2.py                   preprocessor_pb2.py
faster_rcnn.proto             region_similarity_calculator.proto
faster_rcnn_box_coder.proto   region_similarity_calculator_pb2.py
faster_rcnn_box_coder_pb2.py  square_box_coder.proto
faster_rcnn_pb2.py            square_box_coder_pb2.py
grid_anchor_generator.proto   ssd.proto
grid_anchor_generator_pb2.py  ssd_anchor_generator.proto
hyperparams.proto             ssd_anchor_generator_pb2.py
hyperparams_pb2.py            ssd_pb2.py
image_resizer.proto           string_int_label_map.proto
image_resizer_pb2.py          string_int_label_map_pb2.py
input_reader.proto            train.proto
input_reader_pb2.py           train_pb2.py
losses.proto

Add Libraries to PYTHONPATH

slim 디렉터리를 append시키기 위함이다.

# From tensorflow/models/
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim

Testing the Installation
최종적으로 설치가 정상적으로 되었는지 아래의 명령어로 확인한다.

python object_detection/builders/model_builder_test.py

.......
----------------------------------------------------------------------
Ran 7 tests in 0.013s

OK

기타

  • Tensorflow 1.2.1 버전
  • Jupyter 5.4.0
  • Python 3.5.2

Troubleshooting

  • Load a Tensorflow model into memory 부분에서 에러가 발생하면 python3으로 커널을 변경하면 해결 된다.

실행 결과

COCO 이미지 두개를 불러와서 바운딩 박스를 치면 아래와 같다.

with detection_graph.as_default():
  with tf.Session(graph=detection_graph) as sess:
    for image_path in TEST_IMAGE_PATHS:
      image = Image.open(image_path)
      # the array based representation of the image will be used later in order to prepare the
      # result image with boxes and labels on it.
      image_np = load_image_into_numpy_array(image)
      # Expand dimensions since the model expects images to have shape: [1, None, None, 3]
      image_np_expanded = np.expand_dims(image_np, axis=0)
      image_tensor = detection_graph.get_tensor_by_name('image_tensor:0')
      # Each box represents a part of the image where a particular object was detected.
      boxes = detection_graph.get_tensor_by_name('detection_boxes:0')
      # Each score represent how level of confidence for each of the objects.
      # Score is shown on the result image, together with the class label.
      scores = detection_graph.get_tensor_by_name('detection_scores:0')
      classes = detection_graph.get_tensor_by_name('detection_classes:0')
      num_detections = detection_graph.get_tensor_by_name('num_detections:0')
      # Actual detection.
      (boxes, scores, classes, num_detections) = sess.run(
          [boxes, scores, classes, num_detections],
          feed_dict={image_tensor: image_np_expanded})
      # Visualization of the results of a detection.
      vis_util.visualize_boxes_and_labels_on_image_array(
          image_np,
          np.squeeze(boxes),
          np.squeeze(classes).astype(np.int32),
          np.squeeze(scores),
          category_index,
          use_normalized_coordinates=True,
          line_thickness=8)
      plt.figure(figsize=IMAGE_SIZE)
      plt.imshow(image_np)


Convolutional Neural Network for CIFAR-10


CIFAR-10은 RGB 32x32짜리 이미지이다.
이미지 카테고리는 아래와 같다. 10개여서 CIFAR-10인것이다.

airplane, automobile, bird, cat, deer, dog, frog, horse, ship, truck.

공식 사이트는 다음과 같다.
CIFAR-10 dataset

큰 이미지로 바로 테스트 하기 어렵기 때문에 일단 작은 이미지로 modeling을하고 테스팅을 해본다.

Higlights of the Tutorial

핵심 기술은 모두 AlexNet paper에 나온 것들이다.

  • convolution
  • rectified linear activations
  • max pooling
  • local response normalization

Model Architecture

기본적으로 Alex Krizhevsky의 모델을 따르며 위에 계층만 약간 튜닝한 형태를 가진다.

몇시간 동안 트레이닝을 했을 때의 최대 정확도는 86%이다.

코드의 구성

  • cifar10_input.py Reads the native CIFAR-10 binary file format.
  • cifar10.py Builds the CIFAR-10 model.
  • cifar10_train.py Trains a CIFAR-10 model on a CPU or GPU.
  • cifar10_multi_gpu_train.py Trains a CIFAR-10 model on multiple GPUs.
  • cifar10_eval.py Evaluates the predictive performance of a CIFAR-10 model.

Model Training

Prediction을 위해서 n-way classification을 수행 한다.
multinomial logistic regression 또는 softmax regression으로 알려져 있다.

  • batch size는 128로 수행
  • learning rate $10^5$

Launching and Training the Model

아래의 명령어로 실행 한다.

python3 cifar10_train.py

맨 처음에는 이미지 데이터가 없기 때문에 다운로드 부터 시작한다. 데이터 셋은 약 160MB이다.

모델링은 약 몇시간 걸린다.

레퍼런스 성능은 아래와 같다.

System        | Step Time (sec/batch)  |     Accuracy
------------------------------------------------------------------
1 Tesla K20m  | 0.35-0.60              | ~86% at 60K steps  (5 hours)
1 Tesla K40m  | 0.25-0.35              | ~86% at 100K steps (4 hours)

default가 1000k steps니 왠만하면 값을 주고 training하는것이 좋다.
GTX 1080 기준으로 1 step당 0.05인것 같다.

2017-03-03 17:26:35.188576: step 353720, loss = 0.16 (2436.1 examples/sec; 0.053 sec/batch)
2017-03-03 17:26:35.725523: step 353730, loss = 0.14 (2291.4 examples/sec; 0.056 sec/batch)
2017-03-03 17:26:36.253775: step 353740, loss = 0.18 (2391.7 examples/sec; 0.054 sec/batch)
2017-03-03 17:26:36.781440: step 353750, loss = 0.15 (2413.0 examples/sec; 0.053 sec/batch)
2017-03-03 17:26:37.313428: step 353760, loss = 0.15 (2395.6 examples/sec; 0.053 sec/batch)

결국 128 batch size로 1 step당 0.05초 정도 소요된다.

Evaluating a Model

Testing을 위해서 10,000장의 의미지를 사용 한다.

python cifar10_eval.py

레퍼런스 기준으로 precision 1 = 0.860이라고 한다.

jemin@jemin-desktop:~/tf_examples/models/tutorials/image/cifar10$ python3 cifar10_eval.py
2017-05-18 14:15:00.822222: I tensorflow/core/common_runtime/gpu/gpu_device.cc:887] Found device 0 with pro                           perties:
name: GeForce GTX 1080
major: 6 minor: 1 memoryClockRate (GHz) 1.797
pciBusID 0000:01:00.0
Total memory: 7.92GiB
Free memory: 7.66GiB
2017-05-18 14:15:00.822247: I tensorflow/core/common_runtime/gpu/gpu_device.cc:908] DMA: 0
2017-05-18 14:15:00.822253: I tensorflow/core/common_runtime/gpu/gpu_device.cc:918] 0:   Y
2017-05-18 14:15:00.822258: I tensorflow/core/common_runtime/gpu/gpu_device.cc:977] Creating TensorFlow dev                           ice (/gpu:0) -> (device: 0, name: GeForce GTX 1080, pci bus id: 0000:01:00.0)
2017-05-18 14:15:02.951141: precision @ 1 = 0.866

참고 문헌

Tensorflow tutorial, convolutional neural networks
CNN
Convolutional Neural Networks


rJava load 에러



JDK를 업데이트 하면 발생한다.


JAVA_HOME 환경변수를 다시 설정해 준다.


cmd에서 확인 방법


echo %JAVA_HOME%


환경변수가 잘 변경 되었는지 위 방법을 통해서 알 수 있다. 

'AI > R Basic' 카테고리의 다른 글

R Factor 검색  (0) 2017.11.13
RStudio v1.1 Released  (0) 2017.10.10
Swapping columns in a matrix  (0) 2017.03.31
R Notebook  (0) 2016.11.02
R Markdown  (0) 2016.11.02

Swapping columns in a matrix


그냥 간단하게 column을 swapping한다면

m[, c(1,2)] <- m[,c(2,1)]

하지만 위에 처럼 하게 되면 column의 이름이 swap되지 않는다.

아래와 같이 수행해야 column 이름까지 모두 함께 변경 된다.

m <- m[, c(2, 1, 3:ncol(m))]


'AI > R Basic' 카테고리의 다른 글

RStudio v1.1 Released  (0) 2017.10.10
rJava load 에러  (0) 2017.04.16
R Notebook  (0) 2016.11.02
R Markdown  (0) 2016.11.02
Data를 그룹별로 요약 (Summarizing data)  (0) 2016.10.27

Hands on TensorBoard TensorFlow Dev Summit-2017


그냥 TensorFlow를 이용해서 Graph를 생성하게 되면 복잡한 모양을 나타낸다.

아래 예제에서 사용할 전체 코드는 구글 개발자가 작성한 코드를 동작하도록 약간 수정한 버전이 저의 아래 github에 있습니다.
https://github.com/leejaymin/TensorFlowLecture/blob/master/7.TensorBoard/mnist.py

아래와 같이 사용할경우 scoping이 없어서 복잡한 tensorBoard를 생성한다.

def conv_layer(input, size_in, size_out, name="conv"):
    w = tf.Variable(tf.truncated_normal([5, 5, size_in, size_out], stddev=0.1))
    b = tf.Variable(tf.constant(0.1, shape=[size_out]))
    conv = tf.nn.conv2d(input, w, strides=[1, 1, 1, 1], padding="SAME")
    act = tf.nn.relu(conv + b)
    tf.summary.histogram("weights", w)
    tf.summary.histogram("biases", b)
    tf.summary.histogram("activations", act)
    return tf.nn.max_pool(act, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

Cleaning the Graph

  • Node Names
  • Name Scopes

Scope과 name을 설정한 코드는 아래와 같다.

def conv_layer(input, size_in, size_out, name="conv"):
  with tf.name_scope(name):
    w = tf.Variable(tf.truncated_normal([5, 5, size_in, size_out], stddev=0.1), name="W")
    b = tf.Variable(tf.constant(0.1, shape=[size_out]), name="B")
    conv = tf.nn.conv2d(input, w, strides=[1, 1, 1, 1], padding="SAME")
    act = tf.nn.relu(conv + b)
    tf.summary.histogram("weights", w)
    tf.summary.histogram("biases", b)
    tf.summary.histogram("activations", act)
    return tf.nn.max_pool(act, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

Variable과 Placeholder에도 Name을 넣어 줘야 한다.

x = tf.placeholder(tf.float32, shape=[None, 784], name="x")
x_image = tf.reshape(x, [-1, 28, 28, 1])
tf.summary.image('input', x_image, 3)
y = tf.placeholder(tf.float32, shape=[None, 10], name="labels")

각각의 연산 step에도 scoping을 작성해 주어야 한다.

  with tf.name_scope("train"):
    train_step = tf.train.AdamOptimizer(learning_rate).minimize(xent)

  with tf.name_scope("accuracy"):
    correct_prediction = tf.equal(tf.argmax(logits, 1), tf.argmax(y, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    tf.summary.scalar("accuracy", accuracy)

그다음 TensorBoard를 생성하면 좀 더 깔끔하게 그룹핑 되어서 그려지는것을 볼 수 있다.

Hyperparameter Search

  • What about different learning rates ?
  • What about different model architectures ?

TensorBoard를 통해서 각각의 모델을 비교할 수 있다.
서로 다른 hyperparameter를 assign하고 이것을 비교해서 나타낼 수 있다.

아래와 같이 조건을 주고 여러번 실행 하면 된다.

def main():
  # You can try adding some more learning rates
  for learning_rate in [1E-4]:

    # Include "False" as a value to try different model architectures
    for use_two_fc in [True]:
      for use_two_conv in [True]:
        # Construct a hyperparameter string for each one (example: "lr_1E-3,fc=2,conv=2)
        hparam = make_hparam_string(learning_rate, use_two_fc, use_two_conv)
        print('Starting run for %s' % hparam)

	    # Actually run with the new settings
        mnist_model(learning_rate, use_two_fc, use_two_conv, hparam)

Embedding Visualizer

high dimensional data를 3D-mentional data로 projection 시키는 것을 말한다.

Embedding과 관련된 코드는 아래와 같다.

  embedding = tf.Variable(tf.zeros([1024, embedding_size]), name="test_embedding")
  assignment = embedding.assign(embedding_input)

  config = tf.contrib.tensorboard.plugins.projector.ProjectorConfig()
  embedding_config = config.embeddings.add()
  embedding_config.tensor_name = embedding.name
  embedding_config.sprite.image_path = LOGDIR + 'sprite_1024.png'
  embedding_config.metadata_path = LOGDIR + 'labels_1024.tsv'

  # Specify the width and height of a single thumbnail.
  embedding_config.sprite.single_image_dim.extend([28, 28])
  tf.contrib.tensorboard.plugins.projector.visualize_embeddings(writer, config)

각각을 file writer를 이용해서 기록하게 된다.

    if i % 500 == 0:
      sess.run(assignment, feed_dict={x: mnist.test.images[:1024], y: mnist.test.labels[:1024]})
      saver.save(sess, os.path.join(LOGDIR, "model.ckpt"), i)

500번 실행 될 때 마다 saver를 이용해서 기록을 하게 된다.
model checkpoint는 모든 variable들과 임베딩 variable들을 포함하는 정보들을 가지고 있으며 이것을 아래의 경로에 저장하게 된다.
tensorbard --logdir /tmp/mnist_tutorial

아래 그림은 임베딩 후에 PCA를 수행한 것이다.

컬러를 넣어보면 아래와 같다. PCA결과 749이 유사한 것을 알 수 있다.
Top 3 컴포넌트만 표현한 것이다.

T-SNE를 이용해서 분석하면 local similarity를 판단할 수 있다.

이러한 유사도가 높은 이미지들은 생성한 classifier가 잘못된 분류를 할 확률도 높아지게 된다.
Embedding visualization은 image에서도 유용하지만 vocabulary에 대해서도 유용하다.
아래는 smart-reply에 대한 embedding 결과이다.

Future for TensorBoard

  • TensorFlow Debugger Integration
  • Plugins
  • domain specific visualization
  • Org-scale TensorBoard

참고자료


Transitioning to TensorFlow 1.0


TensorFlow 1.0 부터는 모든 backwards compatible을 지원하지 않는다.
깔끔한 1.N lifesycle을 위해서 이러한 작업을 수행 한다.

upgrade

$ sudo pip3 install --upgrade TF_BINARY_URL # Python 3.N

https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.0.0-cp35-cp35m-linux_x86_64.whl

Collecting tensorflow-gpu==1.0.0 from https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.0.0-cp35-cp35m-linux_x86_64.whl
  Downloading https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.0.0-cp35-cp35m-linux_x86_64.whl (95.0MB)
    100% |████████████████████████████████| 95.0MB 25kB/s
Requirement already up-to-date: six>=1.10.0 in ./.local/lib/python3.5/site-packages (from tensorflow-gpu==1.0.0)
Requirement already up-to-date: numpy>=1.11.0 in ./.local/lib/python3.5/site-packages (from tensorflow-gpu==1.0.0)
Requirement already up-to-date: wheel>=0.26 in ./.local/lib/python3.5/site-packages (from tensorflow-gpu==1.0.0)
Collecting protobuf>=3.1.0 (from tensorflow-gpu==1.0.0)
  Downloading protobuf-3.2.0-cp35-cp35m-manylinux1_x86_64.whl (5.6MB)
    100% |████████████████████████████████| 5.6MB 392kB/s
Collecting setuptools (from protobuf>=3.1.0->tensorflow-gpu==1.0.0)
  Downloading setuptools-34.3.0-py2.py3-none-any.whl (389kB)
    100% |████████████████████████████████| 399kB 2.4MB/s
Collecting appdirs>=1.4.0 (from setuptools->protobuf>=3.1.0->tensorflow-gpu==1.0.0)
  Downloading appdirs-1.4.2-py2.py3-none-any.whl
Collecting packaging>=16.8 (from setuptools->protobuf>=3.1.0->tensorflow-gpu==1.0.0)
  Downloading packaging-16.8-py2.py3-none-any.whl
Requirement already up-to-date: pyparsing in ./.local/lib/python3.5/site-packages (from packaging>=16.8->setuptools->protobuf>=3.1.0->tensorflow-gpu==1.0.0)
Installing collected packages: appdirs, packaging, setuptools, protobuf, tensorflow-gpu
  Found existing installation: setuptools 32.3.1
    Uninstalling setuptools-32.3.1:
      Successfully uninstalled setuptools-32.3.1
  Found existing installation: protobuf 3.1.0.post1
    Uninstalling protobuf-3.1.0.post1:
      Successfully uninstalled protobuf-3.1.0.post1
  Found existing installation: tensorflow-gpu 0.12.1
    Uninstalling tensorflow-gpu-0.12.1:
      Successfully uninstalled tensorflow-gpu-0.12.1
Successfully installed appdirs-1.4.2 packaging-16.8 protobuf-3.2.0 setuptools-34.3.0 tensorflow-gpu-1.0.0

버전 확인

jemin@jemin-desktop:~$ python3
Python 3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> import tensorflow as tf
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcublas.so.8.0 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcudnn.so.5 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcufft.so.8.0 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcurand.so.8.0 locally
>>> tf.__version__
'1.0.0'

Code-Upgrade

아래와 같이 Google에서 제공하는 python코드를 이용해서 업그레이드 할 수 있다.

다운로드: link

To convert a single 0,n TensorFlow source file to 1.0, enter a command of the following format:

python tf_upgrade.py --infile InputFile --outfile OutputFile

출력 결과로 report.txt도 나오게 된다. 이것은 상세한 결과와 추가적으로 수작업 해야할 부분을 알려 준다.

디렉터리에 있는 모든것을 업데이트 하기위해서는 아래의 명령어를 사용 한다.

python tf_upgrade.py --intree InputDir --outtree OutputDir

실행하면 아래와 같이 정상적으로 잘 동작하는 것을 알 수 있다.

jemin@jemin-desktop:~/ESLAB_ML/jemin$ python ~/tensorflow_source/tensorflow/tensorflow/tools/compatibility/tf_upgrade.py --intree ./TensorFlowLecture --outtree ./TensorFlowLecture_1.0
TensorFlow 1.0 Upgrade Script
-----------------------------
Converted 33 files

Detected 0 errors that require attention
--------------------------------------------------------------------------------

Make sure to read the detailed log 'report.txt'


Faster R CNN Training


실제 해당 과정을 통해서 학습을 수행해 본다.

Prepare dataset and Pre-trained model

VOC-2007 데이터를 다운 받는다.

if [ ! -d data ]; then mkdir data; fi; cd data
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCdevkit_08-Jun-2007.tar
tar xvf VOCtrainval_06-Nov-2007.tar
tar xvf VOCtest_06-Nov-2007.tar
tar xvf VOCdevkit_08-Jun-2007.tar
rm -rf *.tar; cd ../

test_format error

error: AttributeError: 'module' object has no attribute 'text_format'
해결을 위해서 train.py에 import google.protobuf.text_format을 추가 한다.

TypeError: slice indices must be integers

(caffe_py2_virtualenv) jemin@jemin-desktop:~/caffe/second/py-faster-rcnn$ TypeError: slice indices must be integers or None or have an __index__ method
TypeError:: 명령을 찾을 수 없습니다

해결을 위해서는 numpy 1.12버전을 down-grade 한다.

pip uninstall numpy
pip install 'numpy==1.11.0'

모델 학습 방법

Training + Testing = 9963

Testing = 4952

학습하는 방법

일단 free training model을 들고 온다.
$ ./data/scripts/fetch_imagenet_models.sh

학습 방법은 총 2가지이다.

  • alternating optimization algorithm
  • approximate joint training

여기선 후자를 선택한다.

# ./experiments/scripts/faster_rcnn_end2end.sh [GPU_ID] [NET] [DATASET]
# Directly run this command might have an error "AssertionError: Selective search data not found at:". For the solution, please refer to Part 4.

$ ./experiments/scripts/faster_rcnn_end2end.sh 0 ZF pascal_voc

테스팅 방법

caffe zoo model

기본제공되는 caffe zoo 모델의 경우 ./data/faster_rcnn_models/ZF_faster_rcnn_final.caffemodel에 있다.
이것을 이용해서 테스팅을 수행해 본다.

./tools/test_net.py --gpu 0 --def models/pascal_voc/ZF/faster_rcnn_end2end/test.prototxt --net ./data/faster_rcnn_models/ZF_faster_rcnn_final.caffemodel --imdb voc_2007_test --cfg experiments/cfgs/faster_rcnn_end2end.yml

위와 같이 caffe zoo 모델은 mAP 0.4518로 그다지 정확도가 높지 않은 것을 알 수 있다.

새로 학습 모델

end2end
0.6116 mAP이다.

testing 데이터를 이용해서 과적합 시켜서 학습

  • testing data
  • end2end
  • 80000

정확도는 mAP = 0.8805

**직접 테스팅 실행 **

  • 정확도: mean AP = 0.8805
./tools/test_net.py --gpu 0 --def models/pascal_voc/ZF/faster_rcnn_end2end/test.prototxt --net ./output/faster_rcnn_end2end/voc_2007_test/zf_faster_rcnn_iter_80000.caffemodel --imdb voc_2007_test --cfg experiments/cfgs/faster_rcnn_end2end.yml


Faster-R-CNN Install on Ubuntu 16.04(GTX1080 CUDA 8.0,cuDNN 5.1)


pycaffe로 구현된 py-faster R-CNN을 uBuntu 16.04에 설치하는 방법을 다룬다.
그래픽카드는 GTX 1080이며 CUDA 8.0과 cuDNN 5.1을 사용한다.

Caffe 의존성 라이브러리 설치

핵심은 BVLC에서 최신 caffe는 설치할 필요가 없다.
왜냐하면, Faster-R-CNN 소스코드에 이미 구버전 caffe가 포함되어 있기 때문이다.
해당 버전은 2015년에 Microsoft에서 기존 Caffe를 수정해서 만든것이다.
버클리 대학에서 지공하는 공식 Caffe에는 Faster R-CNN에만 있는 RoI pooling와 같은 여러 기능들을 지원하지 않아서 실행이 안된다.

따라서 http://caffe.berkeleyvision.org/에서 prerequisites를 보고 그것들만 설치해 준다.

1. CUDA, cuDNN 설치하기

GTX 1080이기 때문에 CUDA 8과 cuDNN 5.1을 설치한다.
이전 post 참조

2. CUDA 환경변수 설정하기

TensorFlow와 다르게 설정 해줘야 한다.

vi ~/.bashrc

export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH

3. python virtual environment 설정

tensorflow와의 충돌을 막기위해서 virtualenv를 사용한다.

#install
$ sudo apt-get install python-pip python-dev python-virtualenv 
$ virtualenv --system-site-packages targetDirectory 

# activate shell
$ source ~/tensorflow/bin/activate # If using bash, ksh, sh, or 

활성화 하면 shell 앞에 (caffe_py2_virtualenv) jemin@jemin-desktop:와 같이 나옵니다.
이제부터 pip로 설치하면 모두 해당 virtual environment directory에 설치가 됩니다.
이때 sudo를 붙이면 중복성이 발생하니 pip로만 설치를 합니다.

4. 필요 라이브러리 설치

uBuntu 16.04를 기준으로 한다.

의존성 가이드 공식사이트: http://caffe.berkeleyvision.org/install_apt.html

sudo apt-get install opencl-headers build-essential \
  protobuf-compiler libprotoc-dev libboost-all-dev libleveldb-dev \
  hdf5-tools libhdf5-serial-dev \
  libopencv-core-dev libopencv-highgui-dev \
  libsnappy-dev libsnappy1 libatlas-base-dev cmake libstdc++6-4.8-dbg \
  libgoogle-glog0 libgoogle-glog-dev libgflags-dev liblmdb-dev

5. openCV 설치하기

openCV를 직접 받아서 compile해서 설치해야 최신 CUDA를 잘 지원한다.
그래서 github에서 직접 받아서 cmake를 통해서 설치한다.

의존성 라이브러리들

sudo apt-get install build-essential cmake git pkg-config libjpeg8-dev \
libjasper-dev libpng12-dev libgtk2.0-dev \
libavcodec-dev libavformat-dev libswscale-dev libv4l-dev gfortran
sudo apt-get install libtiff5-dev 

앞으로도 caffe에서도 사용하는 ATLAS (among many other BLAS implementation)을 설치한다.
sudo apt-get install libatlas-base-dev
이것 역시 openCV에서도 사용한다.

openCV 설치

git clone https://github.com/opencv/opencv.git
cd opencv
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE \
	-D CMAKE_INSTALL_PREFIX=/usr/local \
	-D INSTALL_C_EXAMPLES=ON \
	-D INSTALL_PYTHON_EXAMPLES=ON \
	-D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \
	-D BUILD_EXAMPLES=ON ..
  
make -j8
sudo make -j8 install
sudo ldconfig

설치확인

py-faster-rcnn 설치

공식사이트

1. github 다운

내부에 fast-rcnn git이 또 존재하므로 반드시 --recursive option을 줘서 두 개의 git repository에서 모두 다운 받아야 한다.

# Make sure to clone with --recursive
git clone --recursive https://github.com/rbgirshick/py-faster-rcnn.git

2. 의존성 파일 설치

  • cython 필요

    • sudo apt-get install cython
  • python package 설치, virtual env 활성화 상태에서

    • pip install easydict
    • pip install scikit-learn
    • pip protobuf
  • requirements.txt에 있는 python module 설치

    • cd py-faster-rcnn/caffe-faster-rcnn/python
    • for req in $(cat requirements.txt); do pip install $req | cut -d ">" -f1; done

3. 핵심 caffe 버전 통합

BVLC Caffe 2017최신 버전과 현재 내부에 있는 2015년 버전 MS 수정 caffe를 merge해야 한다.

원래 Microsoft Caffe

(caffe_py2_virtualenv) jemin@jemin-desktop:~/caffe/second/py-faster-rcnn/caffe-f                                                                                                                                                             ast-rcnn$ git log
commit 0dcd397b29507b8314e252e850518c5695efbb83
Author: Ross Girshick <ross.girshick@gmail.com>
Date:   Sun Aug 9 13:41:39 2015 -0700

    Fast and Faster R-CNN change set
     - smooth l1 loss
     - roi pooling
     - expose phase in pycaffe
     - dropout scaling at test time (needed for MSRA-trained ZF network)

차이점은
vi src/caffe/proto/caffe.proto를 열어서 보면 아래와 같이 Faster R CNN용 옵션들이 모두 있다는 것이다.
optional ROIPoolingParameter roi_pooling_param = 8266711;

최신 버전의 caffe를 설치해서 사용할 경우 이러한 Microsoft에서 변경한 내용들이 없기 때문에 추후에 demo.py를 실행 할 때

Message type "caffe.LayerParameter" has no field named "roi_pooling_param". 에러를 발생 시킨다. 따라서 반드시 2015년에 수정된 Microsoft caffe를 기반으로 merge를 수행 해야 한다.

(caffe_py2_virtualenv) jemin@jemin-desktop:~/caffe/second/py-faster-rcnn/caffe-f                                                                                                                                                             ast-rcnn$ git remote add caffe https://github.com/BVLC/caffe.git
(caffe_py2_virtualenv) jemin@jemin-desktop:~/caffe/second/py-faster-rcnn/caffe-f                                                                                                                                                             ast-rcnn$ git remote -v
caffe   https://github.com/BVLC/caffe.git (fetch)
caffe   https://github.com/BVLC/caffe.git (push)
origin  https://github.com/rbgirshick/caffe-fast-rcnn.git (fetch)
origin  https://github.com/rbgirshick/caffe-fast-rcnn.git (push)
(caffe_py2_virtualenv) jemin@jemin-desktop:~/caffe/second/py-faster-rcnn/caffe-f                                                                                                                                                             ast-rcnn$ git fetch caffe
remote: Counting objects: 13599, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 13599 (delta 3344), reused 3341 (delta 3341), pack-reused 10251
오브젝트를 받는 중: 100% (13599/13599), 13.71 MiB | 55.00 KiB/s, 완료.
델타를 알아내는 중: 100% (9619/9619), 로컬 오브젝트 582개 마침.
https://github.com/BVLC/caffe URL에서
 * [새로운 브랜치]   device-abstraction -> caffe/device-abstraction
 * [새로운 브랜치]   gh-pages   -> caffe/gh-pages
 * [새로운 브랜치]   master     -> caffe/master
 * [새로운 브랜치]   opencl     -> caffe/opencl
 * [새로운 브랜치]   parallel   -> caffe/parallel
 * [새로운 브랜치]   tutorial   -> caffe/tutorial
 * [새로운 브랜치]   williford-patch-1 -> caffe/williford-patch-1
 * [새로운 브랜치]   windows    -> caffe/windows
 * [새로운 태그]     acm-mm-oss -> acm-mm-oss
 * [새로운 태그]     bsd        -> bsd
 * [새로운 태그]     rc         -> rc
 * [새로운 태그]     rc2        -> rc2
 * [새로운 태그]     rc3        -> rc3
 * [새로운 태그]     rc5        -> rc5
 * [새로운 태그]     rcnn-release -> rcnn-release
 * [새로운 태그]     v0.1       -> v0.1
 * [새로운 태그]     v0.9       -> v0.9
 * [새로운 태그]     v0.99      -> v0.99
 * [새로운 태그]     v0.999     -> v0.999
 * [새로운 태그]     v0.9999    -> v0.9999
 * [새로운 태그]     rc4        -> rc4
(caffe_py2_virtualenv) jemin@jemin-desktop:~/caffe/second/py-faster-rcnn/caffe-fast-rcnn$ git branch
* (HEAD 0dcd397 위치에서 분리됨)
  master

git merge -X theirs caffe/master

-X theirs의 의미는 caffe/master를 기준으로 merge 한다는 의미이다.

추가로 아래의 파일에서 해당 코드를 주석처리 하거나 제거한다.

vi ./include/caffe/layers/python_layer.hpp
Remove self_.attr("phase") = static_cast<int>(this->phase_); from include/caffe/layers/python_layer.hpp after merging.

요약하면 아래와 같으며, 해당 issue는 원래 저자 github에 있다.
issue 316

# Maybe you can try to merge caffe master branch into caffe-fast-rcnn.
cd caffe-fast-rcnn  
git remote add caffe https://github.com/BVLC/caffe.git  
git fetch caffe  
git merge -X theirs caffe/master  
#Remove self_.attr("phase") = static_cast<int>(this->phase_); 
#from include/caffe/layers/python_layer.hpp after merging.

4. py-caffe 빌드와 설치

Makefile.config 설정
py-faster-rcnn/caffe-fast-rcnn에서 caffe를 빌드할 때 사용한다.

cp Makefile.config.example Makefile.config를 한다.
각자 환경에 맞춰서 주석처리된 부분을 풀고 환경변수를 설정 해야 한다.

# cuDNN acceleration switch (uncomment to build with cuDNN).
USE_CUDNN := 1
# Uncomment if you're using OpenCV 3
OPENCV_VERSION := 3
# CUDA directory contains bin/ and lib/ directories that we need.
CUDA_DIR := /usr/local/cuda
# CUDA architecture setting: going with all of them.
# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility.
# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility.
CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \
		-gencode arch=compute_20,code=sm_21 \
		-gencode arch=compute_30,code=sm_30 \
		-gencode arch=compute_35,code=sm_35 \
		-gencode arch=compute_50,code=sm_50 \
		-gencode arch=compute_52,code=sm_52 \
		-gencode arch=compute_60,code=sm_60 \
		-gencode arch=compute_61,code=sm_61 \
		-gencode arch=compute_61,code=compute_61
# BLAS choice:
# atlas for ATLAS (default)
# mkl for MKL
# open for OpenBlas
BLAS := atlas
# NOTE: this is required only if you will compile the python interface.
# We need to be able to find Python.h and numpy/arrayobject.h.
PYTHON_INCLUDE := $(VIRTUAL_ENV)/include/python2.7 \
		$(VIRTUAL_ENV)/lib/python2.7/site-packages/numpy/core/include
# We need to be able to find libpythonX.X.so or .dylib.
PYTHON_LIB := /usr/lib
# Uncomment to support layers written in Python (will link against Python libs)
WITH_PYTHON_LAYER := 1

# Whatever else you find you need goes here.
INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include /usr/include/hdf5/serial/
LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu/hdf5/serial
# Uncomment to use `pkg-config` to specify OpenCV library paths.
# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.)
USE_PKG_CONFIG := 1
# N.B. both build and distribute dirs are cleared on `make clean`
BUILD_DIR := build
DISTRIBUTE_DIR := distribute
# The ID of the GPU that 'make runtest' will use to run unit tests.
TEST_GPUID := 0
# enable pretty build (comment to see full commands)
Q ?= @

caffe-fast-rcnn에서 빌드하기

mkdir build
cd build
cmake ..
make -j8 all
make -j8 pycaffe
make -j8 install
make -j8 runtest

cython module들 빌드

py-faster-rcnn/lib에서 make -j8

caffe 환경변수 설정

vi ~/.bashrc
export CAFFE_ROOT=/home/jemin/caffe/second/py-faster-rcnn/caffe-fast-rcnn
export PYTHONPATH=/home/jemin/caffe/second/py-faster-rcnn/caffe-fast-rcnn/python:$PYTHONPATH

5. 설치 확인

(caffe_py2_virtualenv) jemin@jemin-desktop:~/caffe/second/py-faster-rcnn/caffe-fast-rcnn$ python
Python 2.7.12 (default, Nov 19 2016, 06:48:10)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import caffe
>>> caffe.__version__
'1.0.0-rc5'

6. 미리 빌드된 모델 다운받기

caffe zoo에서 VOC2007로 미리 트레이닝된 zf net과 vgg16을 다운 받는다.

cd py-faster-rcnn
./data/scripts/fetch_faster_rcnn_models.sh

Simple demo.py 실행

이제 데모를 실행한다.

putty로 실행하더라도 X11 forwarding이 설정 되었다면 image가 정상적으로 표시된다.

./tools/demo.py --net zf

Demo for data/demo/000456.jpg
Detection took 0.038s for 300 object proposals
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Demo for data/demo/000542.jpg
Detection took 0.031s for 135 object proposals
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Demo for data/demo/001150.jpg
Detection took 0.033s for 231 object proposals
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Demo for data/demo/001763.jpg
Detection took 0.033s for 200 object proposals
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Demo for data/demo/004545.jpg
Detection took 0.037s for 300 object proposals

참고사이트

https://github.com/rbgirshick/py-faster-rcnn
http://lastone9182.github.io/2016/09/16/aws-caffe.html#index-table


'AI > Caffe' 카테고리의 다른 글

openPose 설치 및 구동 (ubuntu 16.04 + 1080)  (2) 2018.04.12
Faster R CNN Training  (0) 2017.02.27

Tensor Board


Serializing the data

summary data는 Tensor Flow실행 중에 생성된 데이터를 담고 있다.

아래는 일반적인 Tensor Board의 lifecycle을 담고 있다.

  1. TensorFlow Graph를 생성 한다. 그것은 어떻게 summary 데이터를 수집할지에 대한 정보를 담고 있다.

예를 들어서 scalar_summary를 이용해서 loss function의 진행상황을 기록할 수 있다.
추가로 gradient weight를 하고 싶다면histogram_summary를 사용 한다.

  1. summary들을 초기화 해주어야 한다.
    그것을 일일이 하나하나 하는것은 tedious한 방법이니tf.summary.merge_all을 실행 시키면single operation으로 모든 summary data를 초기화 하게 된다.

  2. merged summary op를 실행 한다.
    그리고 probuf 데이터는 결국 tf.train.SummaryWriter에 의해서 object로 기록된다.

사용방법 포인트

  • tf.global_variables_initializer().run() 전에merged = tf.summary.merge_all()을 해도 된다.tf.summary.FileWriter도 실행 해도 된다.

0.012 패치에 따른 API deplicated

init = tf.initialize_all_variables()

  • tf.global_variables_initializer().run()

tf.histogram_summary

  • tf.summary.histogram
  • tf.summary.scalar

merged = tf.merge_all_summaries()

  • merged = tf.summary.merge_all()

writer = tf.train.SummaryWriter("./logs/xor_logs", sess.graph_def)

  • train_writer = tf.summary.FileWriter(FLAGS.log_dir + '/train', sess.graph)

summary = sess.run(merged, feed_dict={X:x_data, Y:y_data})
좋은 코드 패턴 google

def feed_dict(train):
"""Make a TensorFlow feed_dict: maps data onto Tensor placeholders."""
if train or FLAGS.fake_data:
  xs, ys = mnist.train.next_batch(100, fake_data=FLAGS.fake_data)
  k = FLAGS.dropout
else:
  xs, ys = mnist.test.images, mnist.test.labels
  k = 1.0
return {x: xs, y_: ys, keep_prob: k}

summary, _ = sess.run([merged, train_step],
                      feed_dict=feed_dict(True),
                      options=run_options,
                      run_metadata=run_metadata)

Troubleshooting

kenrel panic

tensorboard를 쓰기위해서 잘못된 naming을 사용하면 발생

InvalidArguementError

Jupyter Notebook의 오류인것 같다.

관련사이트: tensorflow/tensorflow#225

그냥 python3 name.py 로 실행하거나 kernel을 껏다가 다시키면 1번은 동작한다. 똑같은 코드라도 어딘 되고 안되는게 tensorboard가 아무래도 불안정 한것 같다.

5 steps of using tensorboard

From TF graph, decide which node you want to annotate

  • with tf.name_scope("test") as scope:
  • tf.histogram_summary("weights", W), tf.scalar_summary(“accuracy", accuracy)

모두다 병합해서 하나로 보여준다.
Merge all summaries

  • merged = tf.merge_all_summaries()

Create writer

  • writer = tf.train.SummaryWriter("/tmp/mnist_logs", sess.graph_def)

실행 시킨 결과를 보여준다.
Run summary merge and add_summary

  • summary = sess.run(merged, …); writer.add_summary(summary);

Launch Tensorboard

  • tensorboard --logdir=/tmp/mnist_logs

Name variables

X = tf.placeholder(tf.float32, name='X-input')
Y = tf.placeholder(tf.float32, name='Y-input')

W1 = tf.Variable(tf.random_uniform([2, 2], -1.0, 1.0), name='Weight1')
W2 = tf.Variable(tf.random_uniform([2, 1], -1.0, 1.0), name='Weight2')

b1 = tf.Variable(tf.zeros([2]), name="Bias1")
b2 = tf.Variable(tf.zeros([1]), name="Bias2")

Add scope for between graph hierarchy

# Our hypothesis
with tf.name_scope("layer2") as scope:
    L2 = tf.sigmoid(tf.matmul(X, W1) + b1)

with tf.name_scope("layer3") as scope:
    hypothesis = tf.sigmoid(tf.matmul(L2, W2) + b2)

# Cost function
with tf.name_scope("cost") as scope:
    cost = -tf.reduce_mean(Y*tf.log(hypothesis) + (1-Y)*tf.log(1-hypothesis))
    cost_summ = tf.scalar_summary("cost", cost)

# Minimize
with tf.name_scope("train") as scope:
    a = tf.Variable(0.1) # Learning rate, alpha
    optimizer = tf.train.GradientDescentOptimizer(a)
    train = optimizer.minimize(cost)

Add histogram

# Add histogram
w1_hist = tf.histogram_summary("weights1", W1)
w2_hist = tf.histogram_summary("weights2", W2)

b1_hist = tf.histogram_summary("biases1", b1)
b2_hist = tf.histogram_summary("biases2", b2)

y_hist = tf.histogram_summary("y", Y)

Add scalar variables

# Cost function
with tf.name_scope("cost") as scope:
    cost = -tf.reduce_mean(Y*tf.log(hypothesis) + (1-Y)*tf.log(1-hypothesis))
    cost_summ = tf.scalar_summary("cost", cost)

merge summaries and create writer after creating session

# Launch the graph,
with tf.Session() as sess:
    # tensorboard --logdir=./logs/xor_logs
    merged = tf.merge_all_summaries()
    writer = tf.train.SummaryWriter("./logs/xor_logs", sess.graph_def)

매번 기록하면 너무 log데이터가 많으니 아래처럼 기술해 준다.

    # Fit the line.
    for step in xrange(20000):
        sess.run(train, feed_dict={X:x_data, Y:y_data})
        if step % 200 == 0:
            summary = sess.run(merged, feed_dict={X:x_data, Y:y_data})
            writer.add_summary(summary, step)
            print step, sess.run(cost, feed_dict={X:x_data, Y:y_data}), sess.run(W1), sess.run(W2)

실행 예제

아래의 실행 예제는 이전에 작성한 NN with XOR를 가지고 만든것이다.

전체코드

import tensorflow as tf
import numpy as np

xy = np.loadtxt('XORtrain.txt', unpack=True)


x_data = np.transpose(xy[0:-1])
y_data = np.reshape(xy[-1], (4, 1))

X = tf.placeholder(tf.float32, name='X-input')
Y = tf.placeholder(tf.float32, name='Y-input')

W1 = tf.Variable(tf.random_uniform([2, 2], -1.0, 1.0), name='Weight1')
W2 = tf.Variable(tf.random_uniform([2, 1], -1.0, 1.0), name='Weight2')

b1 = tf.Variable(tf.zeros([2]), name="Bias1")
b2 = tf.Variable(tf.zeros([1]), name="Bias2")


# Our hypothesis
with tf.name_scope("layer2") as scope:
    L2 = tf.sigmoid(tf.matmul(X, W1) + b1)

with tf.name_scope("layer3") as scope:
    hypothesis = tf.sigmoid(tf.matmul(L2, W2) + b2)

# Cost function
with tf.name_scope("cost") as scope:
    cost = -tf.reduce_mean(Y*tf.log(hypothesis) + (1-Y)*tf.log(1-hypothesis))
    cost_summ = tf.scalar_summary("cost", cost)

# Minimize
with tf.name_scope("train") as scope:
    a = tf.Variable(0.1) # Learning rate, alpha
    optimizer = tf.train.GradientDescentOptimizer(a)
    train = optimizer.minimize(cost)

# Add histogram
w1_hist = tf.histogram_summary("weights1", W1)
w2_hist = tf.histogram_summary("weights2", W2)

b1_hist = tf.histogram_summary("biases1", b1)
b2_hist = tf.histogram_summary("biases2", b2)

y_hist = tf.histogram_summary("y", Y)


# Before starting, initialize the variables. We will `run` this first.
init = tf.initialize_all_variables()


# Launch the graph,
with tf.Session() as sess:
    # tensorboard --logdir=./logs/xor_logs
    merged = tf.merge_all_summaries()
    writer = tf.train.SummaryWriter("./logs/xor_logs", sess.graph_def)

    sess.run(init)
    # Fit the line.
    for step in xrange(20000):
        sess.run(train, feed_dict={X:x_data, Y:y_data})
        if step % 200 == 0:
            summary = sess.run(merged, feed_dict={X:x_data, Y:y_data})
            writer.add_summary(summary, step)
            print step, sess.run(cost, feed_dict={X:x_data, Y:y_data}), sess.run(W1), sess.run(W2)

    # Test model
    correct_prediction = tf.equal(tf.floor(hypothesis+0.5), Y)
    # Calculate accuracy
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    print sess.run([hypothesis, tf.floor(hypothesis+0.5), correct_prediction, accuracy], feed_dict={X:x_data, Y:y_data})
    print "Accuracy:", accuracy.eval({X:x_data, Y:y_data})

실행방법

  1. chrome 브라우저를 사용한다.
  2. 전체 경로를 설정해야한다.

아래와 같이 log file이 저장된 full path를 입력해주어야 한다.

tensorboard --logdir=/root/PycharmProjects/TensorFlowTest/logs/xor_logs/

정상적으로 실행이 됬다면 아래와 같은 메시지가 나온다.

Starting TensorBoard on port 6006
(You can navigate to http://localhost:6006)

그리고 웹브라우저 크롬을 이용해서 접속하면 아래와 같은 화면을 볼 수 있다.

위에 보면 메뉴바에
EVENTSIMAGESGRAPHHISTOGRAMS이렇게 4개의 메뉴가 있는것을 알 수 있다.
각각 우리가 설정한대로 데이터를 보여주게된다.

cost 값이 interation에 따라서 감소하는 것을 시각화 해서 알 수 있다.

생성한 Neural networks를 graph로 확인 할 수 있다.

참고자료


Early Stopping 및 Index Shuffling


그런데 실제로 Deep Learning을 학습할 때에는 우리가 정한 횟수만큼의 iteration을 무조건 반복하는 것이 아니라, 적당히 학습이 완료되었다고 생각되면 학습을 중단하는 Early Stopping을 해야한다. 이것을 하지 않고 무조건 정해진 iteration을 하게되면, 모델이 주어진 데이터에만 과도하게 학습하여, 보지않은 데이터에 대한 일반화 성능이 떨어지는 overfitting이 일어나게 된다. 따라서 Early Stopping을 통해 이러한 일이 일어나기 전에 학습을 중단해야 한다.

또한 위의 MNIST 데이터는 이미 구현된 함수를 통해 미리 순서가 뒤섞이고, one-hot coding이 된 데이터를 필요한 개수만큼 가져올 수 있었다. 그러나 실제로 자신의 데이터를 학습시키기 위해서는 이러한 과정도 파이썬의 numpy를 이용해 구현해 주어야한다.

그래서 이번 예제에서는 아주 간단하면서 유명한 Iris 데이터를 이용해 위의 구현을 실습해보도록 한다.

Iris data : 50개*3종의 iris 꽃에서 4종류의 feature를 추출한 데이터

https://en.wikipedia.org/wiki/Iris_flower_data_set

%matplotlib inline
import tensorflow as tf
from tensorflow.contrib.learn.python.learn.datasets.base import load_iris
import numpy as np
tf.reset_default_graph()

def MLP_iris():
    # load the iris data.
    iris = load_iris()

    np.random.seed(0)
    random_index = np.random.permutation(150)

    iris_data = iris.data[random_index]
    iris_target = iris.target[random_index]
    iris_target_onehot = np.zeros((150, 3))
    iris_target_onehot[np.arange(150), iris_target] = 1

    accuracy_list = []
    
    # build computation graph
    x = tf.placeholder("float", shape=[None, 4], name = 'x')
    y_target = tf.placeholder("float", shape=[None, 3], name = 'y_target')

    W1 = tf.Variable(tf.zeros([4, 128]), name = 'W1')
    b1 = tf.Variable(tf.zeros([128]), name = 'b1')
    h1 = tf.sigmoid(tf.matmul(x, W1) + b1, name = 'h1')

    W2 = tf.Variable(tf.zeros([128, 3]), name = 'W2')
    b2 = tf.Variable(tf.zeros([3]), name = 'b2')
    y = tf.nn.softmax(tf.matmul(h1, W2) + b2, name = 'y')

    cross_entropy = -tf.reduce_sum(y_target*tf.log(y), name = 'cross_entropy')

    train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

    correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_target, 1))

    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) 

    sess = tf.Session(config=tf.ConfigProto(gpu_options=tf.GPUOptions(allow_growth=True)))
    sess.run(tf.initialize_all_variables())

    for i in range(500):
        sess.run(train_step, feed_dict={x: iris_data[0:100], y_target: iris_target_onehot[0:100]})

        train_accuracy = sess.run(accuracy, feed_dict={x: iris_data[0:100], y_target: iris_target_onehot[0:100]})
        validation_accuracy = sess.run(accuracy, feed_dict={x: iris_data[100:], y_target: iris_target_onehot[100:]})
        print ("step %d, training accuracy: %.3f / validation accuracy: %.3f" %(i, train_accuracy, validation_accuracy))

        accuracy_list.append(validation_accuracy)
        
        if i >= 50:
            if validation_accuracy - np.mean(accuracy_list[int(round(len(accuracy_list)/2)):]) <= 0.01 :
                break
            
    sess.close()

MLP_iris()

핵심 코드는 아래와 같다.
1,2 번 째의 validation accuracy 값은 제거하고 너무 큰 값이기 때문이
그 이후부터의 값을 누적 시켜서 평균을 계산하게 된다.
그 다음 해당 값이 현재의 validation accuracy와의 차이를 구해서 그 차이가 0.01보다 큰지 작은지를 반단해서
break 여부를 결정하게 된다.

if i >= 50:
	if validation_accuracy - np.mean(accuracy_list[int(round(len(accuracy_list)/2)):]) <= 0.01 :
	    break

실행 결과를 보면 어느정도 동작하다가 멈추는 것을알 수 있다.

step 166, training accuracy: 0.970 / validation accuracy: 0.960
step 167, training accuracy: 0.970 / validation accuracy: 0.960
step 168, training accuracy: 0.970 / validation accuracy: 0.960
step 169, training accuracy: 0.970 / validation accuracy: 0.960
step 170, training accuracy: 0.970 / validation accuracy: 0.960
step 171, training accuracy: 0.970 / validation accuracy: 0.960


Convolutional Neural Network (CNN) 구현


Introduction

고양이 실험에서 시작 되었다.
고양이에게 어떤 그림을 보여줬더니, 동시에 뉴런이 모두 시작되지 않았다.
각각의 부분에 대해서 다르게 동작 하였다.

이러한 개념을 이용해서 필터를 생성하여 각각의 부분을 추출하는 방식을 이용 한다.

CNN을 Image가 아닌 input data에 대해서 적용 할 때는 CNN이 왜 잘 동작하는지에 대한 직관적인 이해가 필요하다.
만약 적용하려는 데이터가 여전히 이것을 만족한다면 구지 Image가 아니어도 CNN은 우수한 성능을 보장한다.

convnet 적용하기 위한 데이터 특징

CNN의 핵심은 Weight Sharing이라고 한다. 왜냐하면 보통 Stride=1을 주기 때문이 다수의 필터들이 한칸씩만 옆으로 이동하면서 적용 되기 때문에 많은 weight들이 서로 공유하고 있는 형태가 된다. 따라서 사진 처럼 인접한 픽셀들이 서로 관련성이 매우 높아야 한다.

즉, convnet은 지역적으로 weight값들이 공유 된다는 가정하게 수행 되게 된다.
만약 이미지가 아니라면 최소한 근처 데이터 끼리 상관 관계가 높아야 한다.
예를 들면, Audio데이터 같은 time series라고 하면 이전의 사건이 이후의 사건과 관계가 높으므로 convnet을 적용하기 좋다.

만약 data.frame데이터의 각 컬럼이 서로 연관성이 없고 scaling이 심지어 서로 다르다면 convnet을 적용할 의미는 없다.

Implementation

TensorFlow를 이용해서 간단한 CNN을 구현해 보자.
이전에 MLP에서 사용한 MNIST set을 그대로 사용한다.

구현하고자 하는 모델을 표현하면 아래와 같다.

conv를 적용하기 위해선 아래의 함수를 이용한다.

tf.nn.conv2d(X, w, strides=[1, 1, 1, 1], padding='SAME')

위와 같을 때 SAME의 의미는 원래 Image와 같은 크기의 Activiation Map을 만들 겠다는 의미이다.

파라메터는 순서대로 아래와 같다.

  • input: [batch, in_height, in_width, in_channels] 형식. 28x28x1 형식의 손글씨 이미지.
  • filter: [filter_height, filter_width, in_channels, out_channels] 형식. 3, 3, 1, 32의 w.
  • strides: 크기 4인 1차원 리스트. [0], [3]은 반드시 1. 일반적으로 [1], [2]는 같은 값 사용.
  • padding: 'SAME' 또는 'VALID'. 패딩을 추가하는 공식의 차이. SAME은 출력 크기를 입력과 같게 유지.

28x28x1의 이미지 이다.
필터는 32 filters로 (3x3x1)이다. 필터의 사이즈는 조절이 가능하다.

필터를 만든다는 것은 weight을 생성 한다는 것이다.
초기가값은 정규분포에 따르는 랜덤 값을 주게되고
학습이 되어야 하는 필터이므로 Variable로 선언한다.

w=tf.Variable(tf.random_normal([3,3,1,32], stddev=0.01))

이제 각각의 필터들을 이동하면서 적용을 해주어야 하는데 이게 귀찮기 때문에 TensorFlow에서는 이것을 지원 한다.

tf.nn.cov2d(X,W)함수로 이것을 지원 한다.
X는 이미지가 되고 w는 필터가 된다.
strides=[1,1,1,1], padding='SAME으로 합치게 된다.
strides = [1, stride, stride, 1]

아래와 같이 결국 activation map은 32개 층을 이루며 size는 same 이기 때문에 28x28의 크기를 가지게 된다.

그리고 Convolution과 Relu를 같이 주고 싶다면 아래 코드로 간단하게 적용이 가능하다.

l1a = tf.nn.relu(tf.nn.conv2d(X, w, strides=[1, 1, 1, 1], padding='SAME'))

풀링도 아래와 같이 간단히 구현이 가능하다.
c1은 컨볼루셔널 결과를 받는 것이다.

결과는 2by2로 2,2를 하기 때문에 반 줄어든
14,14,32가 된다.
SAME 이라도 stride 2라서 14기 때문이다.

print l1a를 하면 shape을 얻을 수 있다. 오류를 막기 위해서 직접 출력해 보는 것도 좋은 방법이다.

Tensor reshape

tf.reshape(tensor, shape, name=None)

위 함수를 이용해서 주어진 tensor를 다른 모양으로 변경해서 반환 하게 된다.
-1을 쓰게 되면 평평한 1-D 모양을 생성 한다.
최종적인 the number of elements는 결국 같아야 한다.

동작 예제는 아래와 같다.

# tensor 't' is [1, 2, 3, 4, 5, 6, 7, 8, 9]
# tensor 't' has shape [9]
reshape(t, [3, 3]) ==> [[1, 2, 3],
                        [4, 5, 6],
                        [7, 8, 9]]

# tensor 't' is [[[1, 1], [2, 2]],
#                [[3, 3], [4, 4]]]
# tensor 't' has shape [2, 2, 2]
reshape(t, [2, 4]) ==> [[1, 1, 2, 2],
                        [3, 3, 4, 4]]

# tensor 't' is [[[1, 1, 1],
#                 [2, 2, 2]],
#                [[3, 3, 3],
#                 [4, 4, 4]],
#                [[5, 5, 5],
#                 [6, 6, 6]]]
# tensor 't' has shape [3, 2, 3]
# pass '[-1]' to flatten 't'
reshape(t, [-1]) ==> [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6]

# -1 can also be used to infer the shape

# -1 is inferred to be 9:
reshape(t, [2, -1]) ==> [[1, 1, 1, 2, 2, 2, 3, 3, 3],
                         [4, 4, 4, 5, 5, 5, 6, 6, 6]]
# -1 is inferred to be 2:
reshape(t, [-1, 9]) ==> [[1, 1, 1, 2, 2, 2, 3, 3, 3],
                         [4, 4, 4, 5, 5, 5, 6, 6, 6]]
# -1 is inferred to be 3:
reshape(t, [ 2, -1, 3]) ==> [[[1, 1, 1],
                              [2, 2, 2],
                              [3, 3, 3]],
                             [[4, 4, 4],
                              [5, 5, 5],
                              [6, 6, 6]]]

# tensor 't' is [7]
# shape `[]` reshapes to a scalar
reshape(t, []) ==> 7

코드

import tensorflow as tf
import numpy as np
import input_data
import time

batch_size = 128
test_size = 256

def init_weights(shape):
    return tf.Variable(tf.random_normal(shape, stddev=0.01))

# Filter weight vectors: w, w2, w3, w4, w_0
def model(X, w, w2, w3, w4, w_o, p_keep_conv, p_keep_hidden):
    l1a = tf.nn.relu(tf.nn.conv2d(X, w,                       # l1a shape=(?, 28, 28, 32)
                        strides=[1, 1, 1, 1], padding='SAME'))
    l1 = tf.nn.max_pool(l1a, ksize=[1, 2, 2, 1],              # l1 shape=(?, 14, 14, 32)
                        strides=[1, 2, 2, 1], padding='SAME')
    l1 = tf.nn.dropout(l1, p_keep_conv)

    l2a = tf.nn.relu(tf.nn.conv2d(l1, w2,                     # l2a shape=(?, 14, 14, 64)
                        strides=[1, 1, 1, 1], padding='SAME'))
    l2 = tf.nn.max_pool(l2a, ksize=[1, 2, 2, 1],              # l2 shape=(?, 7, 7, 64)
                        strides=[1, 2, 2, 1], padding='SAME')
    l2 = tf.nn.dropout(l2, p_keep_conv)

    l3a = tf.nn.relu(tf.nn.conv2d(l2, w3,                     # l3a shape=(?, 7, 7, 128)
                        strides=[1, 1, 1, 1], padding='SAME'))
    l3 = tf.nn.max_pool(l3a, ksize=[1, 2, 2, 1],              # l3 shape=(?, 4, 4, 128)
                        strides=[1, 2, 2, 1], padding='SAME')
    l3 = tf.reshape(l3, [-1, w4.get_shape().as_list()[0]])    # reshape to (?, 2048)
    l3 = tf.nn.dropout(l3, p_keep_conv)

    l4 = tf.nn.relu(tf.matmul(l3, w4))
    l4 = tf.nn.dropout(l4, p_keep_hidden)

    pyx = tf.matmul(l4, w_o)
    return pyx

# Read data
mnist = input_data.read_data_sets("MNIST_DATA/", one_hot=True)
trX, trY, teX, teY = mnist.train.images, mnist.train.labels, mnist.test.images, mnist.test.labels

# trx.reshape( n-inputs, image size, image size, depth )
 # this variable is input in model()
trX = trX.reshape(-1, 28, 28, 1)  # 28x28x1 input img
teX = teX.reshape(-1, 28, 28, 1)  # 28x28x1 input img

X = tf.placeholder("float", [None, 28, 28, 1])
Y = tf.placeholder("float", [None, 10])

w = init_weights([3, 3, 1, 32])       # 3x3x1 conv, 32 outputs
w2 = init_weights([3, 3, 32, 64])     # 3x3x32 conv, 64 outputs
w3 = init_weights([3, 3, 64, 128])    # 3x3x32 conv, 128 outputs
w4 = init_weights([128 * 4 * 4, 625]) # FC 128 * 4 * 4 inputs, 625 outputs
w_o = init_weights([625, 10])         # FC 625 inputs, 10 outputs (labels)

p_keep_conv = tf.placeholder("float")
p_keep_hidden = tf.placeholder("float")
py_x = model(X, w, w2, w3, w4, w_o, p_keep_conv, p_keep_hidden)

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(py_x, Y))
train_op = tf.train.RMSPropOptimizer(0.001, 0.9).minimize(cost)
predict_op = tf.argmax(py_x, 1)

# Launch the graph in a session
with tf.Session() as sess:
    # you need to initialize all variables
    start_time = time.time()
    tf.initialize_all_variables().run()

    for i in range(100):
        training_batch = zip(range(0, len(trX), batch_size),
                             range(batch_size, len(trX)+1, batch_size))
        for start, end in training_batch:
            sess.run(train_op, feed_dict={X: trX[start:end], Y: trY[start:end],
                                          p_keep_conv: 0.8, p_keep_hidden: 0.5})

        test_indices = np.arange(len(teX)) # Get A Test Batch
        np.random.shuffle(test_indices)
        test_indices = test_indices[0:test_size]

        print(i, np.mean(np.argmax(teY[test_indices], axis=1) ==
                         sess.run(predict_op, feed_dict={X: teX[test_indices],
                                                         Y: teY[test_indices],
                                                         p_keep_conv: 1.0,
                                                         p_keep_hidden: 1.0})))

    print("time elapsed: {:.2f}s".format(time.time() - start_time))

출력

/root/tensorflow/bin/python /root/DataScience/TensorFlowLecture/5.CNN/CNNforMNIST.py
Extracting MNIST_DATA/train-images-idx3-ubyte.gz
/usr/lib/python2.7/gzip.py:268: VisibleDeprecationWarning: converting an array with ndim > 0 to an index will result in an error in the future
  chunk = self.extrabuf[offset: offset + size]
/root/DataScience/TensorFlowLecture/5.CNN/input_data.py:47: VisibleDeprecationWarning: converting an array with ndim > 0 to an index will result in an error in the future
  data = data.reshape(num_images, rows, cols, 1)
Extracting MNIST_DATA/train-labels-idx1-ubyte.gz
Extracting MNIST_DATA/t10k-images-idx3-ubyte.gz
Extracting MNIST_DATA/t10k-labels-idx1-ubyte.gz
(0, 0.95703125)
(1, 0.96875)
(2, 0.98828125)
(3, 0.984375)
(4, 0.984375)
(5, 0.9765625)
(6, 0.99609375)
(7, 0.98046875)
(8, 1.0)
(9, 0.9921875)
(10, 0.99609375)
(11, 0.99609375)

원래 100번 Loop를 수행 해야하나 CPU로는 너무 느려서 그냥 중간에 포기했다.
대충 몇번만 Epoch해도 정확도가 1에 근접하는 놀라운 성능을 보여준다.

작성된 완전한 코드는 아래에 있습니다.
https://github.com/leejaymin/TensorFlowLecture/blob/master/5.CNN/CNNforMNIST.ipynb

참고 사이트

모두를위한 딥러닝
CNN을 Text Classification에 적용하기


'AI > TensorFlow, PyTorch, Keras, Scikit' 카테고리의 다른 글

Tensor Board  (0) 2017.02.08
Early Stopping 및 Index Shuffling  (0) 2017.01.03
Convolutional Neural Network (CNN) 이론  (1) 2016.12.31
AWS의 GPU를 이용한 TensorFlow  (1) 2016.12.31
rpy2 Windows 10에 설치 하기  (0) 2016.12.13

Convolutional Neural Network (CNN) 이론


Convolutional Neural Network (CNN)은 결국 CONVReLUPOOLDropu-out을 번갈아서 적용하는 것을 말한다.
마지막에는 Fully connected network으로 구성 된다.
Pooling은 sampling과 resizing을 의미한다.

Start with an image (width x hight x depth)으로 구성된다.
결국, 32 x 32 x 3 image 이다.
3이라고 하면 red, green, blue를 나타낸다.
gray scale일 경우 1의 depth를 나타낸다.

결국은 위와 같이 filter를 상징하는 weight를 찾는 것이 Convolutional Neural Network(CNN)의 목적이라고 할 수 있다.

필터를 이미지에 적용 (conv + ReLU)

필터를 이미지에 적용하고 Stride에 따라서 나오는 이미지의 크기가 달라지게 된다.

필터의 사이즈가 너무 작으면 Weight를 구하는것이 의미가 없어 진다.

아래의 공식대로 필터가 구해진다.
출력 크기 = 1 + (입력 크기 - 필터 크기) / stride 크기

핵심은 구하려고하는 값이 2.33과 같이 나머지가 존재해서는 안된다.
정수로 딱 떨어져야 이 방법이 적용 가능하다.


실전에서는 위와 같이 Filter를 적용할 때 마다 원본 image의 크기가 작아지는 문제가 발생 한다.
stride크기에 상관 없이 최소한 (필터 크기 -1)만큼 줄어들 수 밖에 없다.
따라서 padding을 처리하는 것이 중요 하다.

Max Pooling

Pooling의 다른 말은 Sampling 또는 Resizing이다.
Pooling을 거치면 크기가 작아지게 된다.
결국 이전에 filter를 통해서 생성 했던 activation map이 크기는 1/2로 작아지고 channel의 두께는 바뀌지 않게 되는 것이다.

MAX POOLING

Pooling 기법 중에서 가장 많이 사용하는 Max pooling이 있다.
여러 개의 값 중에서 가장 큰 값을 꺼내서 모아 놓은것을 말한다.

이전의 Convolutional Layer에서는 Filter를 곱해서 새로운 출력 결과를 만들어 낸다.
이와 다르게 polling에서는 단순하게 존재하는 값 중에서 하나를 선택하게 된다.
Max pooling은 여기서 가장 큰 값을 선택하는 것을 말한다.

참고문헌

http://pythonkim.tistory.com/52


AWS의 GPU를 이용한 TensorFlow


최근 실행해본 CNN 정도만해도 이제 CPU TensorFlow로는 학습이 느린감이 있다.

이전에 학생 크래딧 받기를 참조해서 아마존으로 부터 $100를 받아서 AWS EC2를 사용해 보자.
이전포스트

계정을 생성하고 EC2를 생성해보자.
아래와 같은 GPU Instance 모델들이 존재 한다.

필자는 아래의 모델중 g2.8xlarge를 선택 했다.

Instance를 생성 할 때 김성훈 교수님께서 이미 EC2를 공유해 주셨기 때문에 해당 Instance를 카피해서 생성한다.
AMI라고해서 Amazon Machine Instance를 검색해서 찾을 수 있다.
아래의 이름으로 검색하면 된다.

  • ami-9e39dcf3 (N. Virginia)
  • ami-38f60658 (oregon)

그리고 생성 하려고하면 아마 limit fail이 발생할 것이다.
고객센터가서 사용 목적을 적어서 이메일 보내면 30분내로 instance 갯수 허용이 늘어나고
생성할 수 있게된다.

아래와 같이 정상적으로 생성 할 수 있다.

인증키로 로그인 하기

putty로 접속을 하려면 key를 생성해야 합니다.
http://www.chiark.greenend.org.uk/~sgtatham/putty
PUtty key generator를 실행해야하므로 모든 관련 파일이 있는 putty.zip을 다운 받아야 합니다.

PUTTYGEN을 실행 합니다.
Conversions-> Import key를 선택합니다.
EC2를 생성할 때 사용 했던 key를 이용해서 접속 key를 생성해야 합니다.

키를 로드하고 save private key 버튼을 눌러서 저장합니다.

EC2 키의 확장자는 pem이고 PUTTYGEN에 의해서 생성한 키의 확장자는 ppk입니다.

Amazon EC2 관리자로가서 Public IP 주소를 확인 합니다.
Putty를 실행해서 IP 주소를 입력하고
오른쪽 창에서 SSH-> Auth로 이동합니다.
Browse버튼을 눌러서 생성한 Key를 선택합니다.
open버튼을 눌러서 접속 합니다.

각 EC2 Instance의 운영체제에 따라서 기본 사용자명이 다릅니다.

  • Amazon Linux: ec2-user
  • Red Hat Enterprise Linux: ec2-user
  • SuSE Linux: root
  • Ubuntu Linux: ubuntu

필자는 Ubuntu이므로 아이디는 ubuntu 이다.

아래와 같이 정상적으로 로그인 되는것을 알 수 있습니다.

MNIST set을 가지고 CNN모델을 트레이닝 하는것을
AWS GPU와 i7-cpu에서 트레이닝 했을 때를 녹화한 것이다.

동영상은 아래의 유투브에서 볼 수 있다.
Youtube: https://youtu.be/-kQ4fm2fqcM

대략 5배~7배 정도 차이인것 같다.
K520 GPU가 4대 있는 EC2인데 생각보다 차이는 크지 않다.

최종 결과는 아래와 같다.

EC2

MNIST로 CNN 모델을 트레이닝 하는데 총 22분 4.040초 걸렸다.

i7 CPU

결론적으로 4.8배 차이이다.


CDF stat_ecdf


누적 밀도 함수를 R의 ggplot2 페키지를 이용해서 생성한다.

mydf = data.frame(
   a = rnorm(100, 0, 1),
   b = rnorm(100, 2, 1),
   c = rnorm(100, -2, 0.5)
)

mydf_m = melt(mydf)

p0 = ggplot(mydf_m, aes(x = value)) + 
   stat_ecdf(aes(group = variable, colour = variable)) 
print(p0)


'AI > R ggplot2' 카테고리의 다른 글

ggplot2: 그래픽 라이브러리  (0) 2016.03.20
R에서 EPS 이미지 생성  (0) 2015.06.16
ggplot2 package를 이용한 Graph 그리기  (0) 2015.02.16
R 그래프 페키지 종류  (0) 2014.11.05

rpy2 Windows 10에 설치 하기

정식으로 rpy2에서 Window를 지원하지 않아서 생각 보다는 까다로운 것 같다.

설치한 환경은 아래와 같다.

  • Window 10 1주년 버전
  • Anaconda 4.x
  • python 3.5.x
  • R.3.3.2

pip instal rpy2를 실행 할경우 여러 오류가 발생 한다.

환경 변수 미 설정에 따른 오류

해당 오류는 init.py에서 R_HOME 환경변수를 참조 하기 때문이다. 기타 R을 쓰기위한 환경 변수를 모두 설정 해줘야 한다.

모두 시스템 변수로 설정 했다.

  • R_HOME: C:\Program Files\R\R-3.3.2
  • R_USER: 사용자 계정을 적는다.
  • Path: 맨뒤에 C:\Program Files\R\R-3.3.2\bin추가한다.

*.sh 스크립트 실행 불가 오류

자동 다운로드가 안되서 직접 .whl을 받아서 설치 한다.
사이트: http://www.lfd.uci.edu/~gohlke/pythonlibs/#rpy2

Python3의 환경 이므로
rpy2‑2.8.4‑cp36‑cp36m‑win_amd64.whl을 다운 받았다.

"not a supported wheel on this platform". 오류

아래 명령어를 실행 하면 위와 같은 오류가 발생한다.
파일 명을 변경해줘야한다.
Python 3.5 부터 파일 이름가지고 구분 하는것 같다.

pip install rpy2‑2.8.4‑cp36‑cp36m‑win_amd64.whl

파일명을 rpy2-2.8.4-py3-none-win_amd64.whl로 변경 한다.
즉 py3-none이 cp36-cp36m을 대체한 것이다.

실행 테스트


+ Recent posts