토비의 스프링 요약 (ch2 - 테스트)


[ 2.1 UserDaoTest 다시보기 ]

문제점

  • main()에서 테스트 수행
  • UserDao를 가지고와서 직접 호출
  • 테스트할 값 직접 입력
  • 테스트 결과는 콘솔로…

작은단위의 테스트 (Unit Test)

  • 테스트 대상을 쪼개서 분석하고자 하는 대상에만 집중
  • ‘관심사의 분리’라는 원리가 테스트에도 적용
  • 기능에 따라 웹 인터페이스, 서버 등의 기능과 분리
  • 개발자가 의도한대로 동작하는지 스스로 빨리 확인하기 위해!

[ 2.2 UserDaoTest 개선 ]

자동으로 수행되게!

  • 테스트 결과를 콘솔창으로 출력하기 때문에 개발자가 눈으로 확인하는 절차를 줄여야함.

효율적인수행과 결과관리

  • main()으로 테스트 : 규모가 커지면 부담… -> JUnit
  • JUnit이 개발자가만든 코드를 실행 -> IoC의 동작원리
  • JUnit테스트 프레임워크가 수행해주는 조건
      1. 메소드가 public 으로 선언
      1. @Test 라는 애노테이션 붙이기
  • 검증코드의 전환
//main에서 테스트하던 UserDaoTest
if(!user.getName().equals(user3.getName())){
	System.out.println("테스트 실패 (name)");
}
//JUnit으로 개선된 코드
//is() : .equals()의 역할을 대신함
assertThat(user2.getName(), is(uiser.getName()));

[ 2.3 개발자를 위한 테스팅 프레임워크 JUnit ]

테스트실행

  • 다양한 IDE가 지원함 (이하 이클립스 기준)
  • Run As - JUnit Test 로 한번에 실행가능
  • Alt+Shift+x , t
  • Ant, Maven같은 빌드 툴, 슼므립트 사용가능

테스트의 일관성

  • 반복되어도 항상 같은 결과가 나와야함 (일관성)
  • DB검사의 경우 deleteAll()과 같은 기능을 통해 확인가능 - deleteAll()도 테스트해야함

에러 테스트

  • 발생할 것으로 기대하는 예외 클래스 지정.( 예외 발생 안하면 테스트 실패)
//expected 라는 문구는, 정상수행시 fail하게 만든다!
@Test (expected = EmptyResultDataAccessException.class)
  • 작성하는 코드에는 예외 클래스로 던지게 만든다,
if(user == null) throw new EmptyResultDataAccessException(1);
  • 성공하는 테스트만 만들지말고, 실패하는 경우도 생각하자!
    • 내pc에는 되는데,.,,,
    • 항상 부정적인 테스트먼저 만들어 보자

테스트 주도 개발 (TDD - Test Driven Development)

  • 테스트 우선개발 (Test First Development) 이라고도 함.
  • 테스트 조건을 하나의 기능 정의서 처럼 생각함.
  • 테스트를 성공시키기위한 목적이 아닌 코드는 작성하지 않음.
  • 빠른 피드백과 확신
  • 작업의 주기가 짧아진다 (개발-테스트-원인파악-…)

테스트코드 최적화

  • 중복된 코드는 하나의 함수로 분리한다(ex. db 연결)
  • @Before 같은 애노테이션을 적극 활용
  • JUnit의 동작방식
  1. @Test, public, void, 파라미터없는것을 찾음
  2. 테스트 클래스의 오브젝트 만듬
  3. @Before를 수행
  4. @Test 를 호출하고 저장
  5. @After 수행
  6. 2~5반복
  7. 결과를 보여줌
  • 픽스처 fixture
    • 반복적으로 사용되는 데이터들 ex. DB에 넣기위한 user데이터들
    • private로 변수를 선언하고 @Before에서 초기화 하여 중복 제거

[ 2.4 스프링 테스트 적용 ]

출처 : 토비의 스프링 3.1 vol1. - 이일민 지음

2017-01-15-Toby-Spring-3.1(ch1)

토비의 스프링 - 요약

ch1 오브젝트와 의존관계

리팩토링 , 디자인페턴

  • 기능은 그대로,다른코드
  • 관심사항을 분리하고 , 영향을 끼치지 않게 독립적으로
  • GoF의 디자인페턴 , 헤드퍼스트 추천 !

템플릿메소드 페턴

  • 상속을 통해 슈퍼클래스의 기능을 확장
  • 슈퍼 : 추상메소드정의 , 기본알고리즘구현
  • 서브 : 구현해서 확자사용

펙토리 메소드 페턴

  • 상속을 통해 기능확장하는점은 같음
  • 주로 인터페이스형태로 리턴

OCD - ( Open - Closed Principle )

  • 확장에는 열려있고 변경에는 약하게

응집도와 결합도

  • 응집도 : 높을수록 하나의 관심사에 집중
  • 결합도 : 높을수록 다른 기능에 영향을 주고 받는다
  • 높은 응집도와 낮은 결합도를 가진 프로그래밍. 관심있는 기능끼리는 모으고, 관심외 분야에 영향을 적게 받게 만든다.

IoC 제어역전

  • 자신이 사용할 오브젝트를 스스로 결정하지 않는다.
  • 수동적으로 사용되게
  • 내가만든 코드가 어떻게 사용될지 모른다 !

라이브러리 vs 프래임워크

  • 라이브러리 : 에플리케이션이 라이브러리를 사용한다.
  • 프래임 워크 : 프레임워크가 에플리케이션 코드를 실행한다.

용어정리

  • bean
    • 스프링이 IoC 방식으로 관리하는 오브젝트
  • bean factory
    • IoC를 담당하는 핵심 컨테이너, 빈을 등록 생성 조회 반환 등 관리
  • application context
    • 빈 팩토리를 확장한 IoC컨테이너
  • configuration metadata
    • IoC를 적용하기 위해 사용하는 정보
  • IoC container
    • IoC방식으로 빈을 관리한다는 의미에서 bean factory나 application context를 container라고 함

동일성과 동등성

  • 동일성
    • ==
    • dentical
    • 사실상 같음
  • 동등성
    • equality
    • .equals()
    • 기능상 같음(같은기능을 하는)

싱클톤 레지스트리

  • private로 생성자를 만드는 싱글톤 기법을 사용하지 않고도 싱글톤을 보장함
  • 일반 싱글톤으로는 상속 불가, 테스트힘듬, 서버환경에서 싱글톤 보장불가 등 다양한 이슈가 있어서 이를 해결하기위해 나옴

DI 의존성 주입

  • 의존성 : A가 B에 의존적이다 : B에따라 A가 바뀐다 : A가 B를 사용하고 있다 : A - - -> B
  • 생성자 보다는 Setter !
  • 외부 (제 3자가 )에서 의존성을 맺어준다 ! - > application context , bean factory , IoC container

XML 설정

  • 위와같은 패턴으로 DI를 할 경우 반복적으로 정형화된 패턴이 나타나므로 XML포멧으로 나타 낼 수 있음 .
  • 예제는....

출처 : 토비의 스프링 3.1 vol1. - 이일민 지음

아침부터 성남으로 올라가 집구하기에 돌입했다.

어제에 비해 추워진 날씨와 갑자기 내리는 눈때문에 더 힘들었다..


집을 구하기 위해서 아래외 같은 사항을 고려하였다.


1. 테크노 벨리 출근가능 ( 걷기 / 지하철 / 버스 )

2. 수납공간 및 건물상태 + 가격

3. 관리비 등 기타 유지비

4. 주변시설 (편의점, 마트 ...)



결론은 다니게 될 건물과 제일 가까운곳으로 선택.



돌아다니면서 가장 인상적이었던것은 여러 회사들의 건물이다.




NHN



안랩



NC




집구하기.. 힘들다

'Life' 카테고리의 다른 글

해장라면  (2) 2016.11.03

많은 사람들이 reverse engneering을 위해 winDBG를 사용하고 있습니다.

이 중 프로그램의 위험도를 분류해주는 !exploitable이라는 도구를 소개합니다.

두 도구는 모두 MicroSoft사에서 제작된 도구입니다.


!exploitable는 프로그램에서 크래시가 발생한 경우, 현제 메모리상태나 레지스터 상태 등을 고려하여 위험도를 판단합니다.

이 정보는 크래시를 통해 취약점을 찾는 방법에 사용됩니다.


1. Fuzzer를 이용하여 크래시가 날만한 입력파일을 생성한다.

2. 발생한 크래시가 위험한지 !exploitable로 검사한다.

3. 취약하다고 판단된 크래시를 분석해 원인을 찾고, exploit이 가능한지 판단한다

4. exploit 을 만든다.


이 중 2번에 해당하는 내용인 !exploitable 사용법에 대해 다루도록 하겠습니다.

( 1,3,4 모두 상당한 전문적인 지식이 필요합니다. )




사용법 (Windows 7 , i7-4790K , 16G DDR3 RAM)


1. 파일을 다운로드합니다.

2. winDBG 설치 장소인 C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\winext 경로에

  !exploitable plugin인 msec.dll 을 넣습니다.


3. 크래시가 발생하는 입력파일을 준비합니다. ( fuzzer 등을 활용)

4. winDBG로 입력파일을 실행하고 크래시를 확인합니다.


5. 아래 명령어로 !exploitable을 실행합니다,

!load msec               - 플러그인을 로드합니다.

!exploitable              - 플러그인을 실행합니다.



위험도는 총 4가지로 분류됩니다.

exploitable

probably exploitable

probably not exploitable

not exploitable


위 스샷에서는 probably exploitable로 분류되었습니다.



'Programming > Program Analysis' 카테고리의 다른 글

BinNavi 바이너리 분석도구  (0) 2016.11.03

친구들과 술을 많이 먹은 다음날....



레시피 

1. 물 평소보다 조금더넣기 

2. 스푸 다넣기

3. 끓은 후 콩나물 넣고 3분 기다리기

4. 면넣기 

5. 취향에따라 달걀, 파 등 추가

6. 먹는다. (김치와 함께)

'Life' 카테고리의 다른 글

판교에서 집구하기  (0) 2016.12.14

BinNavi 는 zynamics에서 만든 바이너리 분석 도구이다.


주 목적은 disassembled code에서 취약점을 찾기위해 reverse engineering을 하는 것이다.


장점으로는 REIL 중간언어를 사용하여 x86, ARM, MIPS, PowerPC  형태로 되어있는 다양한 바이너리를 분석 할 수 있다는 점



사용법 


Binnavi 5.x 는 유료로 라이센스를 구입해야 했지만 2015년 8월경 부터 소스를 공개하였다. 

Git : https://github.com/google/binnavi


자세한 설치법 또한 Git에 나와 있다.


TIP : 

대부분 java로 구현되어 있으며 jdk를 설치해야 한다. 


IDA pro(유료)로 dissassemble정보, 함수정보 등이 들어있는 .idb 파일이 필요하다.


DB로 postgreSQL을 사용한다. - (다운로드는 아래 공식 홈페이지에서 받을 수 있다)

http://www.enterprisedb.com/products-services-training/pgdownload#windows




BinNavi graph window


zynamics는 2011년 구글이 인수하였다.


plug-in 으로 위에 나온 Basic Block과 assembly code 등을 활용할 수 있다.

이를 통해 다양한 코드분석을 할 수 있다.







요즘 관심을 가지고 있는 TensorFlow를 시작하기 위한 정보이다.


Tensor Flow 시작하기 - haje01 님이 작성


https://gist.github.com/haje01/202ac276bace4b25dd3f





텐서플로우 시작하기

글쓴이: 김정주(haje01@gmail.com)

이 문서는 텐서플로우 공식 페이지 내용을 바탕으로 만들어졌습니다.


소개

텐서플로우(TensorFlow)는 기계 학습과 딥러닝을 위해 구글에서 만든 오픈소스 라이브러리입니다. 데이터 플로우 그래프(Data Flow Graph) 방식을 사용하였습니다.

데이터 플로우 그래프

데이터 플로우 그래프는 수학 계산과 데이터의 흐름을 노드(Node)와 엣지(Edge)를 사용한 방향 그래프(Directed Graph)로 표현합니다.

data flow graph

노드는 수학적 계산, 데이터 입/출력, 그리고 데이터의 읽기/저장 등의 작업을 수행합니다. 엣지는 노드들 간 데이터의 입출력 관계를 나타냅니다.

엣지는 동적 사이즈의 다차원 데이터 배열(=텐서)을 실어나르는데, 여기에서 텐서플로우라는 이름이 지어졌습니다.

텐서(Tensor)는 과학과 공학 등 다양한 분야에서 이전부터 쓰이던 개념입니다. 수학에서는 임의의 기하 구조를 좌표 독립적으로 표현하기 위한 표기법으로 알려져 있지만, 분야마다 조금씩 다른 의미로 사용됩니다. 여기에서는 학습 데이터가 저장되는 다차원 배열 정도로 이해하시면 되겠습니다.

특징

텐서플로우는 다음과 같은 특징을 가집니다:

  • 데이터 플로우 그래프를 통한 풍부한 표현력
  • 코드 수정 없이 CPU/GPU 모드로 동작
  • 아이디어 테스트에서 서비스 단계까지 이용 가능
  • 계산 구조와 목표 함수만 정의하면 자동으로 미분 계산을 처리
  • Python/C++를 지원하며, SWIG를 통해 다양한 언어 지원 가능

이후의 설명은 Python을 중심으로 진행하겠습니다. (pip를 통한 Python3설치는 개발 중으로, Python2 기반으로 하겠습니다.)

"구글이 텐서플로우를 오픈소스로 한 것은, 기계 학습이 앞으로 제품과 기술을 혁신하는데 가장 필수적인 요소라고 믿기 때문입니다." - Google Brain Team

설치

텐서플로우는 설치가 비교적 쉬운 편입니다만, 다음과 같은 제약이 있습니다:

  • Unix계열 OS(Linux/Mac OSX)만 지원합니다.
  • GPU 버전은 Linux만 지원합니다.

Linux / Mac OSX

Unix 계열 OS를 사용하시는 분들은 공식 페이지의 설치 문서를 참고하시면 쉽게 설치할 수 있습니다.

윈도우

윈도우 사용자 분들은 가상 머신을 이용하거나, 도커 툴박스 설치 후 진행하시기 바랍니다.

이미지를 받고 컨테이너 실행

텐서플로우의 도커 이미지는 소스코드, 예제, 툴도 포함되어 있기에 풀 버전을 받는 것을 권합니다.

Linux / Mac OSX

Unix 계열 OS에서는 아래의 명령을 실행하면 이미지를 받고 컨테이너가 실행됩니다. 컨테이너 실행 후 자동으로 컨테이너 안의 쉘 환경으로 들어가게 됩니다.

docker run -it b.gcr.io/tensorflow/tensorflow-full

컨테이너 안의 /tensorflow 폴더에 소스가 설치되어 있습니다. (주의: 이 폴더에서 모듈을 import 하시면 에러가 발생합니다. )

윈도우

윈도우의 경우 Docker QuickStart Terminal 실행 후(이때 고래 그림 아래의 IP를 기억해 둡니다) 아래와 같이 실행하시기 바랍니다.

winpty docker run -it -p 8888:8888 b.gcr.io/tensorflow/tensorflow-full

이미지를 받은 후 컨테이너가 실행되면, Jupyter 노트북 서버가 자동으로 시작된 상태입니다. 웹브라우저에서 '위의IP:8888'을 입력하면 Jupyter Notebook 환경에 접속됩니다. 여기에서 tensorflow를 사용하실 수 있습니다.

동작 확인

설치가 잘 되었는지 다음의 코드로 확인해봅니다.

$ python

>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
>>> print sess.run(hello)
Hello, TensorFlow!
>>> a = tf.constant(10)
>>> b = tf.constant(32)
>>> print sess.run(a+b)
42
>>>

기본 개념 익히기

일단 기본 용어부터 살펴보겠습니다.

용어

오퍼레이션(Operation)

그래프 상의 노드는 오퍼레이션(줄임말 op)으로 불립니다. 오퍼레이션은 하나 이상의 텐서를 받을 수 있습니다. 오퍼레이션은 계산을 수행하고, 결과를 하나 이상의 텐서로 반환할 수 있습니다.

텐서(Tensor)

내부적으로 모든 데이터는 텐서를 통해 표현됩니다. 텐서는 일종의 다차원 배열인데, 그래프 내의 오퍼레이션 간에는 텐서만이 전달됩니다. (Caffe의 Blob과 유사합니다.)

세션(Session)

그래프를 실행하기 위해서는 세션 객체가 필요합니다. 세션은 오퍼레이션의 실행 환경을 캡슐화한 것입니다.

변수(Variables)

변수는 그래프의 실행시, 패러미터를 저장하고 갱신하는데 사용됩니다. 메모리 상에서 텐서를 저장하는 버퍼 역할을 합니다.

예제

간단한 예제를 통해 기본 개념을 확인하겠습니다.

import tensorflow as tf

# 변수를 0으로 초기화
state = tf.Variable(0, name="counter")

# state에 1을 더할 오퍼레이션 생성
one = tf.constant(1)
new_value = tf.add(state, one)
update = tf.assign(state, new_value)

# 그래프는 처음에 변수를 초기화해야 합니다. 아래 함수를 통해 init 오퍼레이션을 만듭니다.   
init_op = tf.initialize_all_variables()

# 그래프를 띄우고 오퍼레이션들을 실행
with tf.Session() as sess:
  # 초기화 오퍼레이션 실행
  sess.run(init_op)
  # state의 초기 값을 출력
  print(sess.run(state))
  # state를 갱신하는 오퍼레이션을 실행하고, state를 출력
  for _ in range(3):
    sess.run(update)
    print(sess.run(state))

결과

0
1
2
3

문제 풀이

이제 본격적으로 텐서플로우를 사용해 보겠습니다.

경사 하강법(Gradient Descent)으로 인자 찾아내기

아래의 예제는 가중치 행렬W와 바이어스b를 경사하강법을 통해서 찾아내는 것을 보여줍니다. 목표값은 간단한 식으로 산출되도록 합니다.

import tensorflow as tf
import numpy as np

# Numpy 랜덤으로 100개의 가짜 데이터 채우기. (float64 -> float32로 변환)
x_data = np.float32(np.random.rand(2, 100))
# 학습 레이블(목표값)은 아래의 식으로 산출. (W = [0.1, 0.2], b = 0.3)
y_data = np.dot([0.100, 0.200], x_data) + 0.300

입력 데이터와 W, b를 사용해 선형 모델을 정의합니다.

# b는 0,
b = tf.Variable(tf.zeros([1]))
# W는 1x2 형태의 웨이트 변수 (균등 랜덤값으로 초기화)
W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0))
y = tf.matmul(W, x_data) + b

이제 손실과 학습 함수를 정의 합니다. 평균 제곱 오차가 최소화 되는 지점을 경사하강법으로 구하게 됩니다.

# 손실 함수 정의
loss = tf.reduce_mean(tf.square(y - y_data))
# 경사하강법으로 손실 함수를 최소화 (0.5는 학습 비율)
optimizer = tf.train.GradientDescentOptimizer(0.5)
# 학습 오퍼레이션 정의
train = optimizer.minimize(loss)

학습 세션을 시작합니다.

# 모든 변수를 초기화.
init = tf.initialize_all_variables()

# 세션 시작
sess = tf.Session()
sess.run(init)

# 200번 학습.
for step in xrange(0, 201):
    sess.run(train)
    if step % 20 == 0:
        print step, sess.run(W), sess.run(b)

결과는 다음과 같습니다.

0 [[ 0.8228116   0.25179306]] [-0.21591029]
20 [[ 0.31065419  0.22789511]] [ 0.17903577]
40 [[ 0.15808699  0.20829338]] [ 0.26633102]
60 [[ 0.11601268  0.20247138]] [ 0.29062203]
80 [[ 0.10441278  0.20073807]] [ 0.2973859]
100 [[ 0.10121564  0.20022091]] [ 0.29927069]
120 [[ 0.10033476  0.20006624]] [ 0.29979634]
140 [[ 0.10009213  0.20001991]] [ 0.29994306]
160 [[ 0.10002533  0.20000601]] [ 0.29998407]
180 [[ 0.10000696  0.20000178]] [ 0.29999554]
200 [[ 0.10000192  0.20000054]] [ 0.29999873]    

처음에 설정한 W와 b를 훌륭히 찾아냈습니다. 어떠신가요? 개인적인 느낌은 코드가 깔끔한 것 같습니다. 텐서플로우는 기존에 나와있는 딥러닝 프레임워크에 비해 단순하면서도 표현력이 풍부합니다.

텐서플로에 대해 좀 더 자세히 살펴보기 위해 MNIST 예제를 보겠습니다. (자세한 설명은 MNIST 예제 페이지를 참고하세요.)

MNIST

MNIST는 아래와 같이 손으로 쓴 숫자의 이미지 데이터베이스입니다. 이 데이터를 학습하여 분류기를 만드는 예제입니다. mnist

먼저 필요한 데이터를 받아주는 input_data모듈을 설치합니다.

$ wget https://gist.githubusercontent.com/haje01/14b0e5d8bd5428df781e/raw/5b6d04c55f30191a0e32d0ae627716413c808c1c/input_data.py

Python을 실행하고 아래와 같이 데이터를 가져옵니다.

# MNIST 데이터 가져옴
import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

MNIST의 레이블은 0~9의 값이지만, 이것은 연속된 숫자가 아닌 카테고리 값입니다. 따라서 One-Hot Encoding이 필요합니다. 5는 [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], 0은 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] 식으로 됩니다.

enter image description here

MNIST에는 55,000개의 학습용 이미지 + 10,000개의 테스트 이미지 + 5,000개의 검증 이미지가 있습니다. 각 이미지는 28x28 크기를 가집니다. 이것을 펼치면 784 차원의 벡터가 됩니다.

read_data_sets에서 반환되는 값은 mnist.train.image 타입의 [55000, 784] 크기의 텐서입니다.

enter image description here

펼쳐지면서 2D 이미지의 구조적 정보는 사라지지만, 우리가 사용할 간단한 메소드(=Softmax)에서는 문제가 되지 않습니다.

import tensorflow as tf

# 이미지 데이터 플레이스홀더
x = tf.placeholder("float", [None, 784])

x는 2D 텐서를 위한 플레이스 홀더(Placeholder)인데, 이곳에 데이터가 채워지게 됩니다. None은 행의 수가 한정되지 않는다는 뜻입니다.

가중치와 바이어스 변수는 기본값 0으로 채웁니다. 이 변수들에 학습의 결과가 저장됩니다. W는 [784, 10]의 행태를 가지는데, 이것은 784차원의 이미지 벡터를 곱해, 10차원(인코딩된 0~9)의 결과를 내기 위한 것입니다. b는 결과에 더하기 위해 10차원이 됩니다.

# 웨이트와 바이어스 변수
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))

모델은 한 줄로 간단히 정의됩니다. 액티베이션 함수는 소프트맥스(Softmax)를 사용합니다. x와 W의 위치가 바뀐 것은 x를 확장 가능한 입력을 가지는 2D텐서로 하기 위해서입니다. (행렬 곱의 순서가 바뀐 부분이 걸리는데, 이 상태로 학습이 진행되어 도출될 행렬이기에 문제가 없다고 생각됩니다.)

# 모델 구현
y = tf.nn.softmax(tf.matmul(x,W) + b)

# 정답 레이블용 플레이스 홀더
y_ = tf.placeholder("float", [None,10])

y_에 학습용 정답이 채워집니다. 손실 함수는 정보 이론의 크로스 엔트로피(Cross-Entropy) 방식으로 정의합니다.

# Loss 함수
cross_entropy = -tf.reduce_sum(y_*tf.log(y))

이 함수는 하나의 예측에 대한 것이 아니라 한 배치(Batch)내 모든 예측의 로스를 더한 것입니다.

이제 텐서플로우는 우리 모델이 어떤 동작을 해야하는지 알기에, 역전파 방법(Backpropagation)을 통해 변수를 결정할 수 있습니다. 경사하강법에 0.01의 학습률로 최적화기(Optimizer)를 만들고, 그것을 통해 손실을 최소화하도록 학습 오퍼레이션을 정의합니다.

# 학습 오퍼레이션
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

세션 시작 전에 변수를 초기화 하고,

# 모든 변수 초기화
init = tf.initialize_all_variables()

sess = tf.Session()
sess.run(init)

스텝 당 100개 단위로 샘플링하여 1000번 진행합니다.

# 임의로 100개 샘플링
for i in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

샘플링된 데이터는 feed_dict 인자를 참고해서 플레이스 홀더에 공급됩니다. 이렇게 랜덤한 작은 배치로 학습 하는 것을 스토캐스틱 학습(Stochastic Training)이라고 합니다. 비용이 싸고 결과는 비슷합니다.

이제 계산된 레이블들 중 가장 점수가 높은 것을 선택합니다. 아래에 나오는 tf.argmax함수는 텐서 내의 지정된 축에서 가장 높은 값의 인덱스를 반환합니다.

tf.equal에서는 예측 값과 정답이 같으면 True 아니면 False 값이 반환되는데, 이것을 float형으로 바꾸고 평균을 계산해 정확도를 구합니다. 정확도는 학습 데이터가 아닌 테스트 데이터를 사용해야합니다.

# 정답율
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

print sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})

출력

0.9155

돌려보면 91% 정도의 정확도가 나옵니다. 좀 더 개선이 필요하겠지만, 이렇게 짧은 코드로 MNIST 학습을 구현한 것은 놀랍습니다.

마무리

Tensor Board

텐서플로우를 사용해서 딥뉴럴 넷 같은 복잡한 계산을 할 때는 학습 과정이 복잡하고 이해하기 힘들 때가 있습니다. 이럴 때는 텐서 보드를 사용하면 복잡한 학습 과정을 시각화하여 볼 수 있습니다.

tensor board

소감

텐서플로우는 구글의 이름이 부끄럽지 않게 잘 설계된 라이브러리인 것 같습니다. 앞으로도 지속적인 발전을 기대합니다.구글 내에서는 분산처리가 가능한 버전으로 사용되는 것으로 알려졌으나, 공개된 버전은 이 부분이 빠진 점은 아쉽습니다.


감사합니다.

+ Recent posts