4 분 소요


신경망 적용해보기

무슨옷과 무슨색?

In [1]:
!pwd
Out [1]:
/content

In [2]:
!mkdir clothes_dataset
In [3]:
!unzip '/content/drive/MyDrive/Colab Notebooks/deep_learning/clothes_dataset.zip' -d ./clothes_dataset/
Out [3]:
  inflating: ./clothes_dataset/brown_shoes/30ef20bcb027c99409c81fd6127957502b0e693e.jpg  
  inflating: ./clothes_dataset/brown_shoes/312cf581fd4ec3678b8794f9f488aa1dad2f2908.jpg  

...

  inflating: ./clothes_dataset/white_shorts/fb625925bc55cd5c0a147d8214b63d806ac7ecb1.jpg  
  inflating: ./clothes_dataset/white_shorts/fd76a8fe7e6c5d2fe5f346c3207f75325a781d82.jpg  

데이터 정리하기

In [4]:
import numpy as np
import pandas as pd
import tensorflow as tf
import glob as glob
import cv2

all_data = np.array(glob.glob('/content/clothes_dataset/*/*.jpg', recursive=True))

# 색과 옷의 종류를 구별하기 위해 해당되는 label에 1을 삽입합니다.
def check_cc(color, clothes):
    labels = np.zeros(11,)
    
    # color check
    if(color == 'black'):
        labels[0] = 1
        color_index = 0
    elif(color == 'blue'):
        labels[1] = 1
        color_index = 1
    elif(color == 'brown'):
        labels[2] = 1
        color_index = 2
    elif(color == 'green'):
        labels[3] = 1
        color_index = 3
    elif(color == 'red'):
        labels[4] = 1
        color_index = 4
    elif(color == 'white'):
        labels[5] = 1
        color_index = 5
        
    # clothes check
    if(clothes == 'dress'):
        labels[6] = 1
    elif(clothes == 'shirt'):
        labels[7] = 1
    elif(clothes == 'pants'):
        labels[8] = 1
    elif(clothes == 'shorts'):
        labels[9] = 1
    elif(clothes == 'shoes'):
        labels[10] = 1
        
    return labels, color_index

# label과 color_label을 담을 배열을 선언합니다.
all_labels = np.empty((all_data.shape[0], 11))
all_color_labels = np.empty((all_data.shape[0], 1))

for i, data in enumerate(all_data):
    color_and_clothes = all_data[i].split('/')[-2].split('_')

    color = color_and_clothes[0]
    clothes = color_and_clothes[1]
    
    labels, color_index = check_cc(color, clothes)
    all_labels[i] = labels
    all_color_labels[i] = color_index
    
all_labels = np.concatenate((all_labels, all_color_labels), axis = -1)
In [5]:
from sklearn.model_selection import train_test_split

# 훈련, 검증, 테스트 데이터셋으로 나눕니다.
train_x, test_x, train_y, test_y = train_test_split(all_data, all_labels, shuffle = True, test_size = 0.3,
                                                   random_state = 99)
train_x, val_x, train_y, val_y = train_test_split(train_x, train_y, shuffle = True, test_size = 0.3,
                                                 random_state = 99)
In [6]:
train_df = pd.DataFrame({'image':train_x, 'black':train_y[:, 0], 'blue':train_y[:, 1],
                        'brown':train_y[:, 2], 'green':train_y[:, 3], 'red':train_y[:, 4],
                        'white':train_y[:, 5], 'dress':train_y[:, 6], 'shirt':train_y[:, 7],
                        'pants':train_y[:, 8], 'shorts':train_y[:, 9], 'shoes':train_y[:, 10],
                        'color':train_y[:, 11]})

val_df = pd.DataFrame({'image':val_x, 'black':val_y[:, 0], 'blue':val_y[:, 1],
                        'brown':val_y[:, 2], 'green':val_y[:, 3], 'red':val_y[:, 4],
                        'white':val_y[:, 5], 'dress':val_y[:, 6], 'shirt':val_y[:, 7],
                        'pants':val_y[:, 8], 'shorts':val_y[:, 9], 'shoes':val_y[:, 10],
                        'color':val_y[:, 11]})

test_df = pd.DataFrame({'image':test_x, 'black':test_y[:, 0], 'blue':test_y[:, 1],
                        'brown':test_y[:, 2], 'green':test_y[:, 3], 'red':test_y[:, 4],
                        'white':test_y[:, 5], 'dress':test_y[:, 6], 'shirt':test_y[:, 7],
                        'pants':test_y[:, 8], 'shorts':test_y[:, 9], 'shoes':test_y[:, 10],
                        'color':test_y[:, 11]})
In [7]:
train_df.head()
Out [7]:
image black blue brown green red white dress shirt pants shorts shoes color
0 /content/clothes_dataset/green_shorts/e74d11d3... 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 3.0
1 /content/clothes_dataset/black_dress/f1be32393... 1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0
2 /content/clothes_dataset/black_shoes/04f78f68a... 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0
3 /content/clothes_dataset/brown_pants/0671d132b... 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 2.0
4 /content/clothes_dataset/white_shoes/59803fb01... 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 5.0
In [8]:
!pwd
Out [8]:
/content

In [9]:
!mkdir csv_data
In [10]:
train_df.to_csv('/content/csv_data/train.csv', index=False)
val_df.to_csv('/content/csv_data/val.csv', index=False)
test_df.to_csv('/content/csv_data/test.csv', index=False)

이미지 제네레이터 정의 및 모델 구성하기

In [11]:
from keras.preprocessing.image import ImageDataGenerator
In [12]:
train_datagen = ImageDataGenerator(rescale=1./255) # 불러온 값을 rescale로 지정한 값과 곱함->범위 축소
val_datagen = ImageDataGenerator(rescale=1./255)

# 스탭 계산하는 함수
def get_steps(num_samples, batch_size):
    if (num_samples % batch_size) > 0:
        return (num_samples // batch_size) + 1
    else:
        return num_samples // batch_size
  • 모델 구성
In [13]:
from keras.models import Sequential
from keras.layers import Dense, Flatten
In [14]:
model = Sequential()

model.add(Flatten(input_shape=(112, 112, 3))) # RGB라 3차원
model.add(Dense(128, activation='relu'))
model.add(Dense(64, activation='relu'))
model.add(Dense(11, activation='sigmoid')) # softmax는 가능성 높은것 중 하나, sigmoid는 모든 값을 0과 1사이값으로

model.compile(optimizer='adam',
              loss='binary_crossentropy', # 손실함수: 바이너리 크로스엔트로피
              metrics=['binary_accuracy'])
In [15]:
model.summary()
Out [15]:
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 flatten (Flatten)           (None, 37632)             0         
                                                                 
 dense (Dense)               (None, 128)               4817024   
                                                                 
 dense_1 (Dense)             (None, 64)                8256      
                                                                 
 dense_2 (Dense)             (None, 11)                715       
                                                                 
=================================================================
Total params: 4,825,995
Trainable params: 4,825,995
Non-trainable params: 0
_________________________________________________________________

데이터 제네레이터 정의하기

In [16]:
train_df.columns
Out [16]:
Index(['image', 'black', 'blue', 'brown', 'green', 'red', 'white', 'dress',
       'shirt', 'pants', 'shorts', 'shoes', 'color'],
      dtype='object')
In [17]:
batch_size = 32
class_col = ['black', 'blue', 'brown', 'green', 'red', 'white',
             'dress', 'shirt', 'pants', 'shorts', 'shoes']
In [18]:
# 제네레이터 만들기
train_generator = train_datagen.flow_from_dataframe(
    dataframe=train_df, x_col='image', y_col=class_col,
    target_size=(112, 112), color_mode='rgb', class_mode='raw',
    batch_size=batch_size, shuffle=True, seed=42)

val_generator = val_datagen.flow_from_dataframe(
    dataframe=val_df, x_col='image', y_col=class_col,
    target_size=(112, 112), color_mode='rgb', class_mode='raw',
    batch_size=batch_size, shuffle=True)
Out [18]:
Found 5578 validated image filenames.
Found 2391 validated image filenames.

제네레이터를 통해 모델 학습시키기

In [19]:
model.fit(train_generator,
          steps_per_epoch=get_steps(len(train_df), batch_size),
          validation_data=val_generator,
          validation_steps=get_steps(len(val_df), batch_size),
          epochs=10)
Out [19]:
Epoch 1/10
175/175 [==============================] - 31s 158ms/step - loss: 0.6019 - binary_accuracy: 0.8315 - val_loss: 0.3970 - val_binary_accuracy: 0.8343
Epoch 2/10
175/175 [==============================] - 27s 155ms/step - loss: 0.3113 - binary_accuracy: 0.8790 - val_loss: 0.2709 - val_binary_accuracy: 0.8987
Epoch 3/10
175/175 [==============================] - 27s 155ms/step - loss: 0.2832 - binary_accuracy: 0.8913 - val_loss: 0.2794 - val_binary_accuracy: 0.8905
Epoch 4/10
175/175 [==============================] - 29s 164ms/step - loss: 0.2347 - binary_accuracy: 0.9062 - val_loss: 0.2622 - val_binary_accuracy: 0.9001
Epoch 5/10
175/175 [==============================] - 27s 152ms/step - loss: 0.2218 - binary_accuracy: 0.9120 - val_loss: 0.2417 - val_binary_accuracy: 0.9004
Epoch 6/10
175/175 [==============================] - 27s 154ms/step - loss: 0.2011 - binary_accuracy: 0.9193 - val_loss: 0.2290 - val_binary_accuracy: 0.9156
Epoch 7/10
175/175 [==============================] - 27s 153ms/step - loss: 0.1905 - binary_accuracy: 0.9244 - val_loss: 0.2051 - val_binary_accuracy: 0.9205
Epoch 8/10
175/175 [==============================] - 28s 159ms/step - loss: 0.1802 - binary_accuracy: 0.9290 - val_loss: 0.2301 - val_binary_accuracy: 0.9138
Epoch 9/10
175/175 [==============================] - 32s 181ms/step - loss: 0.1873 - binary_accuracy: 0.9262 - val_loss: 0.1955 - val_binary_accuracy: 0.9252
Epoch 10/10
175/175 [==============================] - 27s 154ms/step - loss: 0.1659 - binary_accuracy: 0.9346 - val_loss: 0.1960 - val_binary_accuracy: 0.9233

<keras.callbacks.History at 0x7f1867fb1790>

테스트 데이터 예측하기

In [20]:
test_datagen = ImageDataGenerator(rescale=1./255)

test_generator = test_datagen.flow_from_dataframe(
    dataframe=test_df, x_col='image',
    target_size=(112, 112), color_mode='rgb', class_mode=None,
    batch_size=batch_size, shuffle=False)

preds = model.predict(test_generator, steps=get_steps(len(test_df), batch_size), verbose=1)
Out [20]:
Found 3416 validated image filenames.
107/107 [==============================] - 12s 110ms/step

In [21]:
np.round(preds[0], 2)
Out [21]:
array([0.  , 0.  , 0.  , 1.  , 0.  , 0.  , 0.  , 1.  , 0.  , 0.17, 0.  ],
      dtype=float32)
In [22]:
import matplotlib.pyplot as plt
In [23]:
do_preds = preds[:8]

for i, pred in enumerate(do_preds):
    plt.subplot(2, 4, i+1)
    prob = zip(class_col, list(pred))
    prob = sorted(list(prob), key=lambda x: x[1], reverse=True)[:2] # 내림차순 정렬

    image = cv2.imread(test_df['image'][i]) # 경로 지정 읽어오기
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # BGR 패턴을 RGB 패턴으로 변경

    plt.imshow(image)
    plt.title(f'{prob[0][0]}: {round(prob[0][1]*100, 2)}% \n {prob[1][0]}:{round(prob[1][1]*100, 2)}%')

plt.tight_layout()
plt.show()
Out [23]:

img

실제 데이터 가져와 예측하기

In [24]:
data_datagen = ImageDataGenerator(rescale=1./255)
data_glob = sorted(glob.glob('/content/drive/MyDrive/Colab Notebooks/deep_learning/06_clothes_img/*/*.png'))
data_generator = data_datagen.flow_from_directory(
    directory='/content/drive/MyDrive/Colab Notebooks/deep_learning/06_clothes_img',
    target_size=(112, 112), color_mode='rgb', class_mode=None,
    batch_size=batch_size, shuffle=False)
Out [24]:
Found 3 images belonging to 1 classes.

In [25]:
result = model.predict(data_generator, steps=get_steps(3, batch_size), verbose=1)
Out [25]:
1/1 [==============================] - 0s 35ms/step

In [26]:
np.round(result, 2)
Out [26]:
array([[0.  , 0.  , 0.  , 0.  , 1.  , 0.  , 0.01, 0.  , 0.22, 0.  , 0.64],
       [0.  , 1.  , 0.  , 0.  , 0.  , 0.  , 0.01, 0.  , 0.05, 0.04, 0.65],
       [0.02, 0.  , 1.  , 0.02, 0.14, 0.  , 0.  , 0.  , 0.92, 0.08, 0.45]],
      dtype=float32)
In [27]:
for i, pred in enumerate(result):
    plt.subplot(1, 3, i+1)
    prob = zip(class_col, list(pred))
    prob = sorted(list(prob), key=lambda x: x[1], reverse=True)[:2] # 내림차순 정렬

    image = cv2.imread(data_glob[i]) # 경로 지정 읽어오기
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # BGR 패턴을 RGB 패턴으로 변경

    plt.imshow(image)
    plt.title(f'{prob[0][0]}: {round(prob[0][1]*100, 2)}% \n {prob[1][0]}:{round(prob[1][1]*100, 2)}%')

plt.tight_layout()
plt.show()
Out [27]:

img

Reference

  • 이 포스트는 SeSAC 인공지능 자연어처리, 컴퓨터비전 기술을 활용한 응용 SW 개발자 양성 과정 - 심선조 강사님의 강의를 정리한 내용입니다.

댓글남기기