해당 포스트는 책 “골빈해커의 3분 딥러닝 텐서플로맛”의 11장 “구글의 핵심 이미지 인식 모델 Inception”을 학습하고 내용을 정리한 글입니다.
인셉션(Inception)
- 구글이 만든 공개 모델
- 이미지 인식 모델
- 이미지 인식 대회인 ILSVRC에서 2014년 우승
- 인셉션은 기본적으로 작은 컨볼루션 계층을 매우 많이 연결한 것
- 위 그림에서 보듯이 구성이 꽤 복잡해 구현하기가 조금 까다로움
- 하지만 구글이 텐서플로로 구현해 공개하고 있음
-
또 그 모델을 다양한 목적에 쉽게 활용할 수 있도록 간단한 스크립트까지 제공
- 이번 장에서는 이 스크립트를 사용해 꽃 사진을 학습시키고 꽃의 종류를 알아내는 간단한 스크립트를 작성하고 테스트 해봄
11.1 자료 준비
- 두 개의 자료 다운로드 필요
(1) 학습을 위한 꽃 사진
(2) 일정한 기준에 따라 사진을 학습시키는 스크립트 - 이 두 자료 모두 텐서플로의 홈페이지에 있으며 아래의 링크에서 다운로드 가능
-
- 꽃 사진
- 다운로드
-
- 학습 스크립트
- 다운로드
- 학습 자료와 학습시킨 모델을 저장할 디렉토리를 workspace라는 이름으로 생성
- 그런 다음 꽃 사진을 workspace 디렉토리에 위치시키고, 학습 스크립트는 현재 디렉토리에 저장
- 구성된 디렉토리 구조는 아래와 같음
/retrain.py
/workspace
/flower_photos
/daisy
/dandelion
/roses
/sunflowers
/tulips
- 꽃의 이름별로 디렉토리가 나뉘어 있음
- retrain.py 스크립트는 디렉토리 이름을 레이블(꽃 이름)로 하여 각 디렉토리에 있는 사진들을 학습
11.2 학습시키기
- retrain.py 스크립트로 꽃 사진들을 학습시킴
- 터미널(명령 프롬프트)에서 retrain.py 파일이 있는 위치에서 다음 명령어 실행
python retrain.py \
--bottleneck_dir=./workspace/bottlenecks \
--model_dir=./workspace/inception \
--output_graph=./workspace/flowers_graph.pb \
--output_labels=./workspace/flowers_labels.txt \
--image_dir=./workspace/flower_photos \
--how_many_training_steps 1000
스크립트에 사용한 옵션들의 의미
-
--bottleneck_dir
- 학습할 사진을 인셉션용 학습 데이터로 변환해서 저장해둘 디렉토리
-
--model_dir
- 인셉션 모델을 내려받을 경로
-
--output_graph
- 학습된 모델(.pb)을 저장할 경로
-
--output_labels
- 레이블 이름들을 저장해 둘 파일 경로
-
--image_dir
- 원본 이미지 경로
-
--how_many_training_steps
- 반복 학습 횟수
- 스크립트를 실행하면 다음 메시지와 함께 학습이 이루어짐
2019-02-28 22:42:31.908401: Step 970: Train accuracy = 95.0%
2019-02-28 22:42:31.908401: Step 970: Cross entropy = 0.239813
2019-02-28 22:42:32.054013: Step 970: Validation accuracy = 89.0% (N=100)
2019-02-28 22:42:33.561979: Step 980: Train accuracy = 91.0%
2019-02-28 22:42:33.561979: Step 980: Cross entropy = 0.291035
2019-02-28 22:42:33.710549: Step 980: Validation accuracy = 86.0% (N=100)
2019-02-28 22:42:35.189594: Step 990: Train accuracy = 97.0%
2019-02-28 22:42:35.190591: Step 990: Cross entropy = 0.219651
2019-02-28 22:42:35.346176: Step 990: Validation accuracy = 85.0% (N=100)
2019-02-28 22:42:36.664649: Step 999: Train accuracy = 95.0%
2019-02-28 22:42:36.665663: Step 999: Cross entropy = 0.217191
2019-02-28 22:42:36.810285: Step 999: Validation accuracy = 88.0% (N=100)
Final test accuracy = 88.7% (N=708)
Converted 2 variables to const ops.
11.3 예측 스크립트
- 예측 스크립트 predict.py를 간략화한 버전을 작성하면서 어떤 내용으로 채워져 있는 지 확인
11.3.1 라이브러리 Import
import tensorflow as tf
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import sys
- matplotlib 라이브러리 : 맨 마지막에 예측 결과가 맞는 지 눈으로 확인할 수 있도록 이미지 출력하는 데 사용
NOTE
- 이미지 처리에 pillow 라이브러리가 필요
11.3.2 옵션 및 기본값 설정
- 텐서플로의 모듈
app.flags
를 사용해 스크립트에서 받을 옵션과 기본값 설정 tf.app
모듈을 사용하면 터미널(명령 프롬프트)에서 입력받는 옵션을 쉽게 처리할 수 있음
tf.app.flags.DEFINE_string("output_graph", "./workspace/flowers_graph.pb", "학습된 신경망이 저장된 위치")
tf.app.flags.DEFINE_string("output_labels", "./workspace/flowers_labels.txt", "학습할 레이블 데이터 파일")
tf.app.flags.DEFINE_boolean("show_image", True, "이미지 추론 후 이미지를 보여줍니다.")
FLAGS = tf.app.flags.FLAGS
- retrain.py 로 학습을 진행하면 workspace 디렉토리의 flowers_labels.txt 파일에 꽃의 이름들을 전부 저장함
- 한 줄에 하나씩 들어가 있고, 줄 번호를 해당 꽃 이름의 인덱스로 하여 학습을 진행
(정확히는 인덱스는 줄번호 -1, 배열의 인덱스는 0부터 시작하기 때문)
# flowers_labels.txt
daisy
dandelion
roses
sunflowers
tulips
예측 후 출력하는 값
- 모든 인덱스에 대해 총합이 1인 확률을 나열한 softmax 값
# daisy dandelion roses sunflowers tulips
[ 0.65098846 0.1175265 0.01479027 0.20992769 0.00676709]
11.3.3 꽃 이름 가져오기
- 테스트 결과를 확인할 때 사용하기 위해 파일에 담긴 꽃 이름들을 가져와 배열로 저장
- 이름을 출력하는 데 사용할 것
11.3.4 신경망 그래프 생성
- retrain.py를 실행해 학습이 끝나면 flowers_graph.pb 파일이 생성됨
- 학습 결과를 프로토콜 버퍼(Protocol Buffers)라는 데이터 형식으로 저장해 둔 파일
- 꽃 사진 예측을 위해 이 파일을 읽어 들여 신경망 그래프를 생성할 것
11.3.5 모델 예측 텐서 지정
- 읽어 들인 신경망 모델에서 예측에 사용할 텐서 지정
- 저장되어 있는 모델에서 최종 출력층은
final_result:0
이라는 이름의 텐서임 - 이 텐서를 가져와 예측에 사용
11.3.6 이미지를 예측 모델에 입력
- 예측 스크립트 실행 시 주어진 이름의 이미지 파일을 읽어 들인 뒤, 그 이미지를 예측 모델에 넣어 예측을 실행
-
코드의
DecodeJpeg/contents:0
은 이미지 데이터를 입력값으로 넣을 플레이스홀더의 이름 - 프로토콜 버퍼 형식으로 저장되어 있는 다른 모델들도 이와 같은 방법으로 읽어 들여 사용할 수 있음
11.3.7 예측 결과 출력
- 앞에서 읽어 온 레이블(꽃 이름)들에 해당하는 모든 예측 결과를 출력
NOTE
- 확률이 가장 높은 결과 하나만 출력하려면 해당 코드 대신 다음 코드 사용
print('=== 예측 결과 ===')
top_result = int(np.argmax(prediction[0]))
name = labels[top_result]
score = prediction[0][top_result]
print(' %s (%.2f%%)' % (name, score * 100))
11.3.8 이미지 출력
- 주어진 이름의 이미지 파일을 matplotlib 모듈을 이용해 출력
def main(_):
# 11.3.3 꽃 이름 가져오기
labels = [line.rstrip() for line in tf.gfile.GFile(FLAGS.output_labels)]
# 11.3.4 신경망 그래프 생성
with tf.gfile.FastGFile(FLAGS.output_graph, 'rb') as fp:
graph_def = tf.GraphDef()
graph_def.ParseFromString(fp.read())
tf.import_graph_def(graph_def, name='')
# 11.3.5 모델 예측 텐서 지정
with tf.Session() as sess:
logits = sess.graph.get_tensor_by_name('final_result:0')
# 11.3.6 이미지를 예측 모델에 입력
image = tf.gfile.FastGFile(sys.argv[1], 'rb').read()
prediction = sess.run(logits, {'DecodeJpeg/contents:0': image})
# 11.3.7 예측 결과 출력
print('=== 예측 결과 ===')
for i in range(len(labels)):
name = labels[i]
score = prediction[0][i]
print(' %s (%.2f%%)' % (name, score * 100))
# 11.3.8 이미지 출력
if FLAGS.show_image:
img = mpimg.imread(sys.argv[1])
plt.imshow(img)
plt.show()
11.3.9 main() 함수 실행
- 스크립트 실행 시 주어진 옵션들과 함께 main() 함수 실행하는 코드 작성
if __name__ == "__main__" :
tf.app.run()
- 터미널(명령 프롬프트)에서 위의 코드를 포함한 predict.py 스크립트 파일이 위치한 곳에서 아래 명령어 실행
python predict.py workspace/flower_photos/roses/3065719996_c16ecd5551.jpg
11.3.10 전체 코드
# 11.3.1
import tensorflow as tf
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import sys
# 11.3.2
tf.app.flags.DEFINE_string("output_graph", "./workspace/flowers_graph.pb", "학습된 신경망이 저장된 위치")
tf.app.flags.DEFINE_string("output_labels", "./workspace/flowers_labels.txt", "학습할 레이블 데이터 파일")
tf.app.flags.DEFINE_boolean("show_image", True, "이미지 추론 후 이미지를 보여줍니다.")
FLAGS = tf.app.flags.FLAGS
def main(_):
# 11.3.3
labels = [line.rstrip() for line in tf.gfile.GFile(FLAGS.output_labels)]
# 11.3.4
with tf.gfile.FastGFile(FLAGS.output_graph, 'rb') as fp:
graph_def = tf.GraphDef()
graph_def.ParseFromString(fp.read())
tf.import_graph_def(graph_def, name='')
# 11.3.5
with tf.Session() as sess:
logits = sess.graph.get_tensor_by_name('final_result:0')
# 11.3.6
image = tf.gfile.FastGFile(sys.argv[1], 'rb').read()
prediction = sess.run(logits, {'DecodeJpeg/contents:0': image})
# 11.3.7
print('=== 예측 결과 ===')
for i in range(len(labels)):
name = labels[i]
score = prediction[0][i]
print(' %s (%.2f%%)' % (name, score * 100))
# 11.3.8
if FLAGS.show_image:
img = mpimg.imread(sys.argv[1])
plt.imshow(img)
plt.show()
# 11.3.9
if __name__ == "__main__" :
tf.app.run()
11.4 더 보기
- 텐서플로 모델 저장소에는 이외에도 다양한 모델이 공개되어 있음
- ex) 물체 검출 API(Object Detection API) 모델 : 그림에서 물체를 검출해 그 종류와 확률을 표시해줌
댓글남기기