이번 포스팅에서는 파일 형태의 이미지 데이터를 TensorFlow와 Keras 메소드를 사용하여


(1) 웹에서 압축 이미지 파일을 다운로드하여 압축을 해제하고,

(2) 폴더 이름을 확인하고 폴더 밑에 있는 파일 이름을 리스트로 만들기

(3) 이미지 파일을 로딩하여 시각화하고 라벨 이름 출력하기


를 해보겠습니다.



  (1) 웹에서 압축 이미지 파일을 다운로드하여 압축 해제하기


먼저 TensorFlow 와 객체지향 파일시스템 경로(object-oriented filesystem paths)를 관리할 때 사용하는 pathlib 모듈을 importing 하겠습니다.



import tensorflow as tf

import pathlib

import os


print(tf.__version__)

[Out] 2.4.0-dev20200913

 



이제 준비가 되었으니 https://storage.googleapis.com 의 예제 이미지로 압축되어 저장되어 있는 'flower_photos.tgz' 압축 파일을 Keras의 get_file() 메소드를 사용하여 가져와서 압축을 풀어(untar = True)보겠습니다.



flowers_root = tf.keras.utils.get_file(
    'flower_photos',
    'https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz',
    untar=True)




이러면 압축이 풀린 파일이 '.keras/datasets/flower_photos 라는 폴더에 저장되어 있습니다. 이를 pathlib.Path() 메소드로 Mac, Linux, Windows OS에 상관없이 경로를 인식할 수 있도록 PurePath로 만들어주었습니다.


* source: https://docs.python.org/3/library/pathlib.html




print(flowers_root)

[Out] /Users/xxx/.keras/datasets/flower_photos


flowers_root = pathlib.Path(flowers_root)

flowers_root

[Out] PosixPath('/Users/xxx/.keras/datasets/flower_photos')

 



저는 Mac OS 에서 작업을 했는데요, Mac OS에서 숨겨진 폴더, 파일을 보려면 Finder 에 커서를 가져다대고 'Shift + Command + .' 을 동시에 눌러주면 됩니다. 그러면 아래의 화면 캡쳐처럼 '/.keras/datasets/flower_photos/' 경로에 다운로드 후 압축해제한 이미지 파일들이 들어있음을 눈으로 직접 확인할 수 있습니다.






  (2) 폴더 이름을 확인하고 폴더 밑에 있는 파일 이름을 리스트로 만들기


다음으로, root directory 밑에 있는 하위 디렉토리와 파일 이름들을 모두(flowers_root.glob("*") ) 가져다가 for loop 으로 순회하면서 하나씩 차례대로 출력해서 확인해보겠습니다.


위의 화면캡쳐에서 숨겨진 폴더, 파일을 눈으로 봤던 것과 동일하게 하위 폴더에는 'roses', 'sunflowers', 'daisy', 'dandelion', 'tulips' 폴더와 'LICENSE.txt' 텍스트 파일이 들어있군요.



# The root directory contains a directory for each class.
for item in flowers_root.glob("*"):
    print(item.name)


[Out]

roses sunflowers daisy dandelion tulips LICENSE.txt




이제 TensorFlow.Dataset.list_files() 메소드를 사용해서 각 꽃 이름 폴더 ('roses', 'sunflowers', 'daisy', 'dandelion', 'tulips' 폴더) 밑에 있는 이미지 파일 이름(jpg 포맷) 들의 리스트를 만들어보겠습니다.


그리고 이중에서 3개만 가져와서(take(3)) 하나씩 차례대로 '전체 경로/파일이름'을 출력해보겠습니다.



# The files in each class directory are examples:
list_ds = tf.data.Dataset.list_files(str(flowers_root/'*/*'))


for f in list_ds.take(3):
    print(f.numpy())


b'/Users/xxx/.keras/datasets/flower_photos/daisy/4440480869_632ce6aff3_n.jpg' b'/Users/xxx/.keras/datasets/flower_photos/daisy/1879567877_8ed2a5faa7_n.jpg' b'/Users/xxx/.keras/datasets/flower_photos/sunflowers/969913643_9d5cd2fe45_m.jpg'

 




  (3) 이미지 파일을 로딩하여 시각화하고 라벨 이름 출력하기


이제 이미지 파일이 준비가 되었으니 TensorFlow.keras.preprocessing.image 메소드를사용하여 꽃 이미지 3개를 크기가 (250, 250)인 이미지로 변환하여 로딩하고, matplotlib 모듈로 시각화(plt.imshow(img))해보겠습니다. ( tf.Tensor() 파일을 f.numpy() 로 변환하여 로딩)


이때 TensorFlow.strings.split(f, os.sep)[-2] 로 '전체 경로/파일이름' 리스트에서 뒤에서 부터 두번째에 위치한 라벨을 파싱해서 가져와서 이미지를 시각화할 때 라벨도 같이 출력을 해보겠습니다.


해바라기(sunflowers), 장미(roses), 민들레(dandelions) 이 차례대로 시각화되었네요.



from tensorflow.keras.preprocessing import image
import matplotlib.pyplot as plt

for f in list_ds.take(3):
    img = image.load_img(f.numpy(), target_size=(250, 250))
    label = tf.strings.split(f, os.sep)[-2]
    print(label.numpy())
    plt.imshow(img)
    plt.show()




* Reference: https://www.tensorflow.org/guide/data?hl=en



많은 도움이 되었기를 바랍니다.

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요.



728x90
반응형
Posted by Rfriend
,

지난번 포스팅에서는 TensorFlow 1.x 버전이 지연(게으른) 실행 (Lazy Execution) 인데 반해 TensorFlow 2.x 버전은 즉시 실행 (Eager Execution) 으로 바뀌었다는 점에 대해서 TenforFlow의 대표적인 자료구조인 상수, 변수, Placeholder 별로 간단한 예를 들어서 비교 설명해 보았습니다. 


이번 포스팅에서는 TensorFlow 2.x 버전에서 크게 바뀐 것 중에서 "고수준 API (High-Level API) 로서 Keras API를 채택"하였다는 것에 대해서 소개하겠습니다. 


TensorFlow 2.x 는 텐서 연산은 C++로 고속으로 수행하며, 저수준 API에는 Python wrapper 의 TensorFlow가 있고, 고수준 API로는 Keras 를 사용하는 아키텍처입니다. Keras도 당연히 CPU 뿐만 아니라 GPU 를 사용한 병렬처리 학습이 가능하며, 다양한 애플리케이션/디바이스에 배포도 가능합니다. 



Keras는 Google 에서 딥러닝 연구를 하고 있는 Francois Chollet 이 만든 Deep Learning Library 인데요, TensorFlow 2.x 버전에 고수준 API 로 포함이 되었습니다. (고마워요 Google!!!)


TensorFlow 1.x 버전을 사용할 때는 TensorFlow 설치와 별도로 Native Keras를 따로 설치하고 또 Keras를 별도로 import 해서 사용해야 했습니다. 


하지만 TensorFlow 2.x 버전 부터는 TensorFlow 만 설치하면 되며, Keras는 별도로 설치하지 않아도 됩니다. 또한 Keras API를 사용할 때도 TensorFlow를 Importing 한 후에 tf.keras.models 와 같이 tf.keras 로 시작해서 뒤에 Keras의 메소드를 써주면 됩니다. (아래의 MNIST 분류 예시에서 자세히 소개)


 

TensorFlow 1.x 

TensorFlow 2.x 

 설치 (Install)

 $ pip install tensorflow==1.15

 $ pip install keras

 $ pip install tensorflow==2.3.0 

 (Keras는 별도 설치 필요 없음)

 Importing

 import tensorflow as tf

from keras import layers

 import tensorflow as tf

 from tf.keras import layers




위의 Kreas 로고 이미지는 https://keras.io 정식 홈페이지의 메인 화면에 있는 것인데요, "Simple. Flexible. Powerful." 가 Keras의 모토이며, Keras를 아래처럼 소개하고 있습니다. 


"Keras는 TensorFlow 기계학습 플랫폼 위에서 실행되는 Python 기반의 딥러닝 API 입니다. Keras는 빠른 실험을 가능하게 해주는데 초점을 두고 개발되었습니다. 아이디어에서부터 결과를 얻기까지 가능한 빠르게 할 수 있다는 것은 훌륭한 연구를 하는데 있어 매우 중요합니다" 

* Keras reference: https://keras.io/about/


백문이 불여일견이라고, Keras를 사용하여 MNIST 손글씨 0~9 숫자를 분류하는 매우 간단한 DNN (Deep Neural Network) 모델을 만들어보겠습니다.


DNN Classifier 모델 개발 및 적용 예시는 (1) 데이터 준비, (2) 모델 구축, (3) 모델 컴파일, (4) 모델 학습, (5) 모델 평가, (6) 예측의 절차에 따라서 진행하겠습니다. 




[ MNIST 데이터 손글씨 숫자 분류 DNN 모델 ]



  (1) 데이터 준비 (Preparing the data)


먼저 TensorFlow 를 importing 하고 버전(TensorFlow 2.3.0)을 확인해보겠습니다. 

 


import tensorflow as tf

import numpy as np


print(tf.__version__)

2.3.0




Keras 에는 MNIST 데이터셋이 내장되어 있어서 tf.keras.datasets.mnist.load_data() 메소드로 로딩을 할 수 있습니다. Training set에 6만개, Test set에 1만개의 손글씨 숫자 데이터와 정답지 라벨 데이터가 있습니다. 



(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()


print('shape of x_train:', x_train.shape)

print('shape of y_train:', y_train.shape)

print('shape of x_test:', x_test.shape)

print('shape of y_test:', y_test.shape)

shape of x_train: (60000, 28, 28)
shape of y_train: (60000,)
shape of x_test: (10000, 28, 28)
shape of y_test: (10000,)




 MNIST 데이터셋이 어떻게 생겼는지 확인해보기 위해서 Training set의 0번째 이미지 데이터 배열(28 by 28 array)과 정답지 라벨 ('5'), 그리고 matplotlib 으로 시각화를 해보겠습니다. 



x_train[0]

[Out] array([[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 18, 18, 18, 126, 136, 175, 26, 166, 255, 247, 127, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 30, 36, 94, 154, 170, 253, 253, 253, 253, 253, 225, 172, 253, 242, 195, 64, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 49, 238, 253, 253, 253, 253, 253, 253, 253, 253, 251, 93, 82, 82, 56, 39, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 18, 219, 253, 253, 253, 253, 253, 198, 182, 247, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 80, 156, 107, 253, 253, 205, 11, 0, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 1, 154, 253, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 253, 190, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 190, 253, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 241, 225, 160, 108, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 240, 253, 253, 119, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 186, 253, 253, 150, 27, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 93, 252, 253, 187, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 253, 249, 64, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 130, 183, 253, 253, 207, 2, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 148, 229, 253, 253, 253, 250, 182, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 114, 221, 253, 253, 253, 253, 201, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 23, 66, 213, 253, 253, 253, 253, 198, 81, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 18, 171, 219, 253, 253, 253, 253, 195, 80, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 55, 172, 226, 253, 253, 253, 253, 244, 133, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 136, 253, 253, 253, 212, 135, 132, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)



y_train[0]

[Out] 5


import matplotlib.pyplot as plt

plt.rcParams['figure.figsize'] = (5, 5)

plt.imshow(x_train[0])

plt.show()




Deep Neural Network 모델의 input으로 넣기 위해 (28 by 28) 2차원 배열 (2D array) 이미지를 (28 * 28 = 784) 의 옆으로 길게 펼친 데이터 형태로 변형(Reshape) 하겠습니다(Flatten() 메소드를 사용해도 됨). 그리고 0~255 사이의 값을 0~1 사이의 실수 값으로 변환하겠습니다.  



# reshape and normalization

x_train = x_train.reshape((60000, 28 * 28)) / 255.0

x_test = x_test.reshape((10000, 28 * 28)) / 255.0





  (2) 모델 구축 (Building the model)


이제 본격적으로 Keras를 사용해보겠습니다. Keras의 핵심 데이터 구조로 모델(Models)층(Layers)있습니다. 모델을 구축할 때는 (a) 순차적으로 층을 쌓아가는 Sequential model 과, (b) 복잡한 구조의 모델을 만들 때 사용하는 Keras functional API 의 두 가지 방법이 있습니다. 


이미지 데이터 분류는 CNN (Convolutional Neural Network) 을 사용하면 효과적인데요, 이번 포스팅에서는 간단하게 Sequential model 을 사용하여 위의 (1)에서 전처리한 Input 이미지 데이터를 받아서, 1개의 완전히 연결된 은닉층 (Fully Connected Hidden Layer) 을 쌓고, 10개의 classes 별 확률을 반환하는 FC(Fully Connected) Output Layer 를 쌓아서 만든 DNN(Deep Neural Network) 모델을 만들어보겠습니다.  (Functional API 는 PyTorch 와 유사한데요, 나중에 별도의 포스팅에서 소개하도록 하겠습니다.)


add() 메소드를 사용하면 마치 레고 블록을 쌓듯이 차곡차곡 순서대로 원하는 층을 쌓아서 딥러닝 모델을 설계할 수 있습니다. (Dense, CNN, RNN, Embedding 등 모두 가능). Dense() 층의 units 매개변수에는 층별 노드 개수를 지정해주며, 활성화 함수는 activation 매개변수에서 지정해줍니다. 은닉층에서는 'Relu' 활성화함수를, Output 층에는 10개 classes에 대한 확률을 반환하므로 'softmax' 활성화함수를 사용하였습니다. 



# Sequential model

model = tf.keras.models.Sequential()


# Stacking layers

model.add(tf.keras.layers.Dense(units=128, activation='relu', input_shape=(28*28,)))

model.add(tf.keras.layers.Dense(units=10, activation='softmax'))




이렇게 층을 쌓아서 만든 DNN (Deep Neural Network) 모델이 어떻게 생겼는지 summary() 함수로 출력해보고, tf.keras.utils.plot_model() 메소드로 시각화해서 확인해보겠습니다. 



model.summary()

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 128)               100480    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                1290      
=================================================================
Total params: 101,770
Trainable params: 101,770
Non-trainable params: 0
_____________________________________


# keras model visualization

tf.keras.utils.plot_model(model, 

                          to_file='model_plot.png', 

                          show_shapes=True)


* 참고로 Keras의 tf.keras.utils.plot_model() 메소드를 사용하려면 사전에 pydot, pygraphviz 라이브러리 설치, Graphviz 설치가 필요합니다. 




  (3) 모델 컴파일 (Compiling the model)


위의 (2)번에서 딥러닝 모델을 구축하였다면, 이제 기계가 이 모델을 이해할 수 있고 학습 절차를 설정할 수 있도록 컴파일(Compile) 해줍니다. 


compile() 메소드에는 딥러닝 학습 시 사용하는 (a) 오차 역전파 경사하강법 시 최적화 알고리즘(optimizer), (b) 손실함수(loss function), 그리고 (c) 성과평가 지표(metrics) 를 설정해줍니다. 



model.compile(optimizer='sgd', 

              loss='sparse_categorical_crossentropy', 

              metrics=['accuracy']

)

 

* 참고로, input data의 다수 클래스에 대한 정답 레이블(ground-truth labels)을 바로 사용하여 손실함수를 계산할 때는 loss='sparse_categorical_crossentropy' 을 사용하며, One-hot encoding 형태로 정답 레이블이 되어있다면 loss='categorical_crossentropy' 를 사용합니다. 



Keras 는 위에서 처럼 optimizer='sgd' 처럼 기본 설정값을 사용해서 간단하게 코딩할수도 있으며, 만약 사용자가 좀더 유연하고 강력하게 설정값을 조정하고 싶다면 아래의 예시처럼 하위클래스(subclassing)을 사용해서 세부 옵션을 지정해줄 수도 있습니다. 



model.compile(

    optimizer=keras.optimizers.SGD(learning_rate=0.01, momentum=0.9, nesterov=True)

    loss=keras.losses.sparse_categorical_crossentropy

)

 




  (4) 모델 학습 (Training the model)


데이터 준비와 모델 구축, 그리고 모델 컴파일이 끝났으므로 이제 6만개의 훈련 데이터셋(Training set) 중에서 80% (4.8만개 데이터) 는 모델 학습(fitting)에, 20%(1.2만개 데이터)는 검증(validation)용으로 사용하여 DNN 모델을 학습해보겠습니다. (참고로, 1만개의 Test set은 모델 학습에서는 사용하지 않으며, 최종 모델에 대해서 제일 마지막에 모델 성능 평가를 위해서만 사용합니다.)


epochs = 5 는 전체 데이터를 5번 반복(iteration)해서 사용해서 학습한다는 의미입니다. 

verbose = 1 은 모델 학습 진행상황 막대를 출력하라는 의미입니다. ('1' 이 default이므로 생략 가능)

(0 = silent, 1 = progress bar, 2 = one line per epoch)

validation_split=0.2 는 검증용 데이터셋을 별도로 만들어놓지 않았을 때 학습용 데이터셋에서 지정한 비율(예: 20%) 만큼을 분할하여 (hyperparameter tuning을 위한) 검증용 데이터셋으로 이용하라는 의미입니다. 

batch_size=32 는 한번에 데이터 32개씩 batch로 가져다가 학습에 사용하라는 의미입니다. 


이번 포스팅은 Keras의 기본 사용법에 대한 개략적인 소개이므로 너무 자세하게는 안들어가겠구요, callbacks는 나중에 별도의 포스팅에서 자세히 설명하겠습니다. 


학습이 진행될수록 (즉, epochs 이 증가할 수록) 검증용 데이터셋에 대한 손실 값(loss value)은 낮아지고 정확도(accuracy)는 올라가고 있네요. 



model.fit(x_train, y_train, 

          epochs=5, 

          verbose=1, 

          validation_split=0.2)


Epoch 1/5
1500/1500 [==============================] - 1s 922us/step - loss: 0.7291 - accuracy: 0.8146 - val_loss: 0.3795 - val_accuracy: 0.8989
Epoch 2/5
1500/1500 [==============================] - 1s 811us/step - loss: 0.3605 - accuracy: 0.9007 - val_loss: 0.3081 - val_accuracy: 0.9145
Epoch 3/5
1500/1500 [==============================] - 1s 785us/step - loss: 0.3061 - accuracy: 0.9140 - val_loss: 0.2763 - val_accuracy: 0.9215
Epoch 4/5
1500/1500 [==============================] - 1s 772us/step - loss: 0.2749 - accuracy: 0.9228 - val_loss: 0.2519 - val_accuracy: 0.9290
Epoch 5/5
1500/1500 [==============================] - 1s 827us/step - loss: 0.2525 - accuracy: 0.9289 - val_loss: 0.2355 - val_accuracy: 0.9339
Out[14]:
<tensorflow.python.keras.callbacks.History at 0x7fc7920a1760>

 




  (5) 모델 평가 (Evaluating the model)


evaluate() 메소드를 사용하여 모델의 손실 값(Loss value) 과 컴파일 단계에서 추가로 설정해준 성능지표 값 (Metrics values) 을 Test set 에 대하여 평가할 수 있습니다. (다시 한번 강조하자면, Test set은 위의 (4)번 학습 단계에서 절대로 사용되어서는 안됩니다!)


Test set에 대한 cross entropy 손실값은 0.234, 정확도(accuracy)는 93.68% 가 나왔네요. (CNN 모델을 이용하고 hyperparameter tuning을 하면 99%까지 정확도를 올릴 수 있습니다.)



model.evaluate(x_test, y_test)

313/313 [==============================] - 0s 801us/step - loss: 0.2342 - accuracy: 0.9368
Out[15]:
[0.23418554663658142, 0.9368000030517578]





  (6) 예측 (Prediction for new data) 


위에서 학습한 DNN 모델을 사용해서 MNIST 이미지 데이터에 대해서 predict() 메소드를 사용하여 예측을 해보겠습니다. (별도의 새로운 데이터가 없으므로 test set 데이터를 사용함)


예측 결과의 0번째 데이터를 살펴보니 '7' 이라고 모델이 예측을 했군요. 



preds = model.predict(x_test, batch_size=128)


# returns an array of probability per classes

preds[0]

array([8.6389220e-05, 3.9117887e-07, 5.6002376e-04, 2.2136024e-03,
       2.7992455e-06, 1.4370076e-04, 5.6979918e-08, 9.9641860e-01,
       2.2985958e-05, 5.5149395e-04], dtype=float32)


# position of max probability

np.argmax(preds[0])

[Out] 7




실제 정답 레이블(ground-truth labels)과 비교해보니 '7' 이 정답이 맞네요. 



y_test[0]

[Out] 7


plt.imshow(x_test[0].reshape(28, 28))

plt.show()




  (7) 모델 저장, 불러오기 (Saving and Loading the model)


딥러닝 모델의 성과 평가 결과 기준치를 충족하여 현장 적용이 가능한 경우라면 모델의 요소와 학습된 가중치 정보를 파일 형태로 저장하고, 배포, 로딩해서 (재)활용할 수 있습니다. 


-  HDF5 파일로 전체 모델/가중치 저장하기


# Save the entire model to a HDF5 file.

model.save('mnist_dnn_model.h5') 




- 저장된 'mnist_dnn_model.h5' 모델/가중치 파일을 'new_model' 이름으로 불러오기


# Recreate the exact same model, including its weights and the optimizer

new_model = tf.keras.models.load_model('mnist_dnn_model.h5')


new_model.summary()

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 128)               100480    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                1290      
=================================================================
Total params: 101,770
Trainable params: 101,770
Non-trainable params: 0
_________________________________________________________________




TensorFlow 2.x 에서부터 High-level API 로 탑재되어 있는 Keras API 에 대한 간단한 MNIST 분류 DNN 모델 개발과 예측 소개를 마치겠습니다. 


* About Kerashttps://keras.io/about/

* Keras API Reference: https://keras.io/api/

* Save and Load model: https://www.tensorflow.org/tutorials/keras/save_and_load


많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. :-)


728x90
반응형
Posted by Rfriend
,

CNN(Convolutional Neural Network)으로 이미지 분류 모델링할 때 보통 tensorflow나 keras 라이브러리에 이미 포함되어 있는 MNIST, CIFAR-10 같은 이미지를 간단하게 load 하는 함수를 이용해서 toy project로 연습을 해보셨을 겁니다. 

그런데, 실제 이미지, 그림 파일을 분석해야 될 경우 '어? 이미지를 어떻게 업로드 하고, 어떻게 전처리하며, 어떻게 시각화해야 하는거지?'라는 의문을 한번쯤은 가져보셨을 듯 합니다. 

이번 포스팅에서는 바로 이 의문에 대한 답변 소개입니다. 


필요한 Python 라이브러리를 불러오겠습니다. 

 import numpy as np

 import pandas as pd

 import matplotlib.pyplot as plt

 import keras 



 1. 개와 고양이 사진 다운로드 (download dogs and cats images from Kaggle)

개와 고양이 사진을 아래의 Kaggle 사이트에서 다운로드 해주세요. Kaggle 회원가입을 먼저 해야지 다운로드 할 수 있습니다. 개는 1, 고양이는 0으로 라벨링이 되어 있는 25,000 개의 이미지를 다운받을 수 있습니다. 

https://www.kaggle.com/c/dogs-vs-cats/data



2. 개와 고양이 이미지 30개만 선택해서 별도 경로(폴더)에 복사하기


downloads 폴더에 들어있는 압축된 다운로드 파일을 압축 해제(unzip)해 주세요. 


윈도우 탐색기로 미리보기를 해보면 고양이 반, 개 반 입니다. 


directory, path 관리하는데 필요한 os 라이브러리, 파일을 source에서 destination 경로로 복사하는데 필요한 shutil 라이브러리를 불러오겠습니다. 

 import os # miscellaneous operating system interfaces

 import shutil # high-level file operations


이미지를 가져올 경로를 설정해보겠습니다. ('Downdoads/dogs-vs-cats/train' 경로에 train 폴더를 압축해제해 놓았습니다. 폴더 경로 확인 요함.)

# The path to the directory where the original dataset was uncompressed

 base_dir = '/Users/admin/Downloads'

 img_dir = '/Users/admin/Downloads/dogs-vs-cats/train'


train 폴더에 들어있는 개와 고양이 이미지가 총 25,000개 임을 확인했으며,  img_dir 경로에 포함되어 있는 이미지 중에서 10개만 indexing 해서 파일 제목을 확인해보았습니다. 

 len(os.listdir(img_dir))

 25000

os.listdir(img_dir)[:10]

['dog.8011.jpg',
 'cat.5077.jpg',
 'dog.7322.jpg',
 'cat.2718.jpg',
 'cat.10151.jpg',
 'cat.3406.jpg',
 'dog.1753.jpg',
 'cat.4369.jpg',
 'cat.7660.jpg',
 'dog.5535.jpg']


30개의 이미지만 샘플로 선별해서 다른 폴더로 복사해보겠습니다. 먼저, 30개 고양이 이미지를 담아둘 경로/ 폴더(cats30_dir) 를 만들어보겠습니다. 

# Directory with 30 cat pictures

 cats30_dir = os.path.join(base_dir, 'cats30')


 # Make a path directory

 os.mkdir(cats30_dir)


이제 source 경로에서 destination 경로로 shutil.copyfile(src, dst) 함수를 사용하여 고양이 이미지 30개만 이미지를 복사하겠습니다.  

# Copy first 30 cat images to cats30_dir

 fnames = ['cat.{}.jpg'.format(i) for i in range(30)]

 

 for fname in fnames:

     src = os.path.join(img_dir, fname)

     dst = os.path.join(cats30_dir, fname)

     shutil.copyfile(src, dst)


cats30_dir 경로로 복사한 30개의 고양이 이미지 파일 목록을 확인해 보았습니다. 

# check if pictures were copied well in cats30 directory

 os.listdir(cats30_dir)

['cat.6.jpg',
 'cat.24.jpg',
 'cat.18.jpg',
 'cat.19.jpg',
 'cat.25.jpg',
 'cat.7.jpg',
 'cat.5.jpg',
 'cat.27.jpg',
 'cat.26.jpg',
 'cat.4.jpg',
 'cat.0.jpg',
 'cat.22.jpg',
 'cat.23.jpg',
 'cat.1.jpg',
 'cat.3.jpg',
 'cat.21.jpg',
 'cat.20.jpg',
 'cat.2.jpg',
 'cat.11.jpg',
 'cat.10.jpg',
 'cat.12.jpg',
 'cat.13.jpg',
 'cat.9.jpg',
 'cat.17.jpg',
 'cat.16.jpg',
 'cat.8.jpg',
 'cat.28.jpg',
 'cat.14.jpg',
 'cat.15.jpg',
 'cat.29.jpg']



 3. 이미지 파일을 로딩, float array 로 변환 후 전처리하기
    (load image file and convert image data to float array format) 

Keras preprocessing 에 있는 image 클래스를 불러온 후, load_img() 함수를 사용해서 이미지 파일을 로딩하고, img_to_array() 함수를 사용해서 array 로 변환해보겠습니다. (Python OpenCV 라이브러리로도 가능함)

# a picture of one cat as an example

 img_name = 'cat.10.jpg'

 img_path = os.path.join(cats30_dir, img_name)


 # Preprocess the image into a 4D tensor using keras.preprocessing

 from keras.preprocessing import image


 img = image.load_img(img_path, target_size=(250, 250))

 img_tensor = image.img_to_array(img)


3차원 array에 이미지 샘플을 구분할 수 있도록 np.expand_dims() 함수를 사용하여 1개 차원을 추가하겠습니다. 그리고 [0, 1] 값 범위 내에 값이 존재하도록 array 값을 255.로 나누어서 표준화해주었습니다. 

  # expand a dimension (3D -> 4D)

 img_tensor = np.expand_dims(img_tensor, axis=0)

 img_tensor.shape

 (1, 250, 250, 3)

 

 # scaling into [0, 1]

 img_tensor /= 255.


첫번째 고양이 이미지의 array 데이터를 출력해보면 아래처럼 생겼습니다. 꼭 영화 메트릭스의 숫자들이 주루룩 내려오는 장면 같이 생겼습니다. 

img_tensor[0]

array([[[0.10196079, 0.11764706, 0.15294118],
        [0.07450981, 0.09019608, 0.1254902 ],
        [0.03137255, 0.04705882, 0.09019608],
        ...,
        [0.5058824 , 0.6313726 , 0.61960787],
        [0.49411765, 0.61960787, 0.60784316],
        [0.49019608, 0.6156863 , 0.6039216 ]],

       [[0.11764706, 0.13333334, 0.16862746],
        [0.13725491, 0.15294118, 0.1882353 ],
        [0.08627451, 0.10196079, 0.13725491],
        ...,
        [0.50980395, 0.63529414, 0.62352943],
        [0.49803922, 0.62352943, 0.6117647 ],
        [0.4862745 , 0.6117647 , 0.6       ]],

       [[0.11372549, 0.14117648, 0.16470589],
        [0.16470589, 0.19215687, 0.22352941],
        [0.15294118, 0.18039216, 0.21176471],
        ...,
        [0.50980395, 0.63529414, 0.62352943],
        [0.5019608 , 0.627451  , 0.6156863 ],
        [0.49019608, 0.6156863 , 0.6039216 ]],

       ...,

       [[0.69411767, 0.6431373 , 0.46666667],
        [0.6862745 , 0.63529414, 0.45882353],
        [0.6627451 , 0.6117647 , 0.4392157 ],
        ...,
        [0.7254902 , 0.70980394, 0.04313726],
        [0.6745098 , 0.6509804 , 0.03921569],
        [0.64705884, 0.6156863 , 0.05490196]],

       [[0.64705884, 0.5921569 , 0.45490196],
        [0.6117647 , 0.5568628 , 0.4117647 ],
        [0.5686275 , 0.5176471 , 0.3529412 ],
        ...,
        [0.7254902 , 0.7137255 , 0.01960784],
        [0.6862745 , 0.67058825, 0.00784314],
        [0.6509804 , 0.6313726 , 0.        ]],

       [[0.6039216 , 0.54901963, 0.4117647 ],
        [0.5882353 , 0.53333336, 0.3882353 ],
        [0.5803922 , 0.5294118 , 0.3647059 ],
        ...,
        [0.7254902 , 0.7137255 , 0.01960784],
        [0.6862745 , 0.67058825, 0.00784314],
        [0.6509804 , 0.6313726 , 0.        ]]], dtype=float32)



  4. 한개의 이미지 파일의 array 를 시각화하기 (visualizing an image array data)

matplotlib 라이브러리를 이용하여 위의 3번에서 이미지의 array 변환/ 전처리한 데이터를 시각화해보겠습니다. 예제로서 img_tensor[0] 으로 첫번째 고양이 이미지의 데이터를 시각화했습니다. 

# Image show

 import matplotlib.pyplot as plt

 plt.rcParams['figure.figsize'] = (10, 10) # set figure size

 

 plt.imshow(img_tensor[0])

 plt.show()




  5. 30개의 이미지 데이터를 6*5 격자에 나누어서 시각화하기 
    (visualizing 30 image data at 6*5 grid layout)

위의 3번에서 했던 이미지 파일 로딩, array로 변환, 1개 차원 추가, [0, 1] 범위로 표준화하는 전처리를 preprocess_img() 라는 이름의 사용자정의함수(UDF)로 만들었습니다. 

# UDF of pre-processing image into a 4D tensor

 def preprocess_img(img_path, target_size=100):

     from keras.preprocessing import image

     

     img = image.load_img(img_path, target_size=(target_size, target_size))

     img_tensor = image.img_to_array(img)

    

     # expand a dimension

     img_tensor = np.expand_dims(img_tensor, axis=0)

     

     # scaling into [0, 1]

     img_tensor /= 255.

     

     return img_tensor


이제 30개의 고양이 이미지 array 데이터를 사용해서 행(row) 6개 * 열(column) 5개의 격자 배열(grid layout) 에 시각화를 해보겠습니다. 이때 가독성을 높이기 위해서 고양이 사진 간에 검정색 구분선을 넣어서 시각화를 해보겠습니다. 

참고로, 아래 코드의 for loop 중간에 방금 전에 위에서 정의한 preprocess_img() 사용자정의함수 (빨간색으로 표기) 가 사용되었습니다. 

# layout

n_pic = 30

n_col = 5

n_row = int(np.ceil(n_pic / n_col))


# plot & margin size

target_size = 100

margin = 3


# blank matrix to store results

total = np.zeros((n_row * target_size + (n_row - 1) * margin, n_col * target_size + (n_col - 1) * margin, 3))


# append the image tensors to the 'total matrix'

img_seq = 0


for i in range(n_row):

    for j in range(n_col):


        fname = 'cat.{}.jpg'.format(img_seq)

        img_path = os.path.join(cats30_dir, fname)


        img_tensor = preprocess_img(img_path, target_size)


        horizontal_start = i * target_size + i * margin

        horizontal_end = horizontal_start + target_size

        vertical_start = j * target_size + j * margin

        vertical_end = vertical_start + target_size


        total[horizontal_start : horizontal_end, vertical_start : vertical_end, :] = img_tensor[0]

        

        img_seq += 1


# display the pictures in grid

plt.figure(figsize=(200, 200))

plt.imshow(total)

plt.show()


많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. 


728x90
반응형
Posted by Rfriend
,

Tensorflow, Keras를 사용하는 중에 'TypeError: softmax() got an unexpected keyword argument 'axis' 의 TypeError 발생 시 업그레이드를 해주면 해결할 수 있습니다. (저는 Python 2.7 버전, Tensorflow 1.4 버전 사용 중에 Keras로 softmax() 하려니 아래의 에러 발생하였습니다)





먼저, 명령 프롬프트 창에서 Tensorflow 가 설치된 conda environment 를 활성화시켜보겠습니다. 



$ conda env list

tensorflow     /Users/myid/anaconda3/envs/tensorflow


$ source activate tensorflow  # for mac OS

$ activate tensorflow # for Windows OS


(tensorflow) $ 

 




참고로 Python과 Tensorflow 버전 확인하는 방법은 아래와 같습니다. 



(tensorflow) $ python -V

Python 2.7.14 :: Anaconda custom (64-bit)


(tensorflow) $ python

Python 2.7.14 |Anaconda custom (640bit)| (default, Oct 5 2017, 02:28:52)

[GCC 4.2.1. Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin

Type "help", "copyright", "credits" ro "license" for more information.

>>> import tensorflow as tf

>>> tf.VERSION

'1.4.0'

 




  (1) TypeError: softmax() got an unexpected keyword argument 'axis' 에러 대처법


Python에서 패키지 관리할 때 사용하는 pip 를 먼저 upgrade 시켜 준 후에 Tensorflow 를 업그레이트 해줍니다. Python 3.n 버전에서는 pip3 install package_name 을 사용하구요, GPU 의 경우 tensorflow-gpu 처럼 뒤에 -gpu를 추가로 붙여줍니다. 



# --------------------
# TypeError: softmax() got an unexpected keyword argument 'axis'
# --------------------

# => upgrade tensorflow to the latest version


(tensorflow)$ pip install pip --upgrade # for Python 2.7
(tensorflow)$ pip3 install pip --upgrade # for Python 3.n

(tensorflow)$ pip install tensorflow --upgrade # for Python 2.7
(tensorflow)$ pip3 install tensorflow --upgrade # for Python 3.n
(tensorflow)$ pip install tensorflow-gpu --upgrade # for Python 2.7 and GPU

(tensorflow)$ pip3 install tensorflow-gpu --upgrade # for Python 3.n and GPU

 




Tensorflow 업그레이드 해줬더니 이번에는 numpy에서 아래의 에러가 나네요, 그래서 numpy도 업그레이드 해주었더니 문제가 해결되었습니다. 


  (2) numpy Traceback (most recent call last) RuntimeError: 

      module compiled against API version 0xc but this version of numpy is 0xb



# --------------
# Traceback (most recent call last) RuntimeError:

# module compiled against API version 0xc but this version of numpy is 0xb
# ---------------


# => upgrade numpy to the latest version


(tensorflow)$ pip install numpy --upgrade



많은 도움이 되었기를 바랍니다. 



728x90
반응형
Posted by Rfriend
,