반응형

Keras mnist 데이터세트의 이미지는 보통 matplotlib.pyplot으로 표시한다.

데이터 타입을 확인하고 OpenCV로 표시해 보자.

 

import numpy as np
import matplotlib.pyplot as plt
import cv2
import keras

(train_input, train_target), (test_input, test_target) = keras.datasets.fashion_mnist.load_data()

print(train_input.shape) # (60000, 28, 28)
print(train_input[0].shape) # (28, 28)
print(type(train_input[0])) # <class 'numpy.ndarray'>

# 첫 번째 이미지 데이터 출력
np.set_printoptions(linewidth=115, threshold=np.inf) # threshold: 출력 생략 임계값. 내용이 많아도 출력이 생략되지 않는다.
print(train_input[0])

# 첫 번째 ~ 열 번째 이미지 출력(pyplot)
fig, axs = plt.subplots(1, 10, figsize=(10, 10))
for i in range(10):
	axs[i].imshow(train_input[i], cmap='gray')
	axs[i].axis('off')
plt.show()

# 첫 번째 이미지 출력(OpenCV)
image = cv2.resize(src=train_input[0], dsize=(0, 0), fx=10, fy=10) # 10배로 확대
cv2.imshow("image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

Gray 스케일 이미지의 데이터가 출력되었다. 데이터 모양만으로도 대략적인 모양을 알 수 있다.

 

matplotlib.pyplot으로 첫 10개의 이미지를 출력했다.

 

28X28 사이즈의 이미지라 너무 작아 10배 확대하고 OpenCV로 출력했다.

Keras에서 사용하는 이미지 데이터 타입도 numpy.ndarray이고, OpenCV에서 사용하는 이미지 데이터 타입도 numpy.ndarray이기 때문에 서로 호환된다.

 

 

LeNet-5 모델을 만들고 OpenCV로 로드한 이미지를 이용해 결과를 예측해 보자.

 

import numpy as np
import cv2
import keras
from keras import layers
from sklearn.model_selection import train_test_split

# LeNet-5 정의
lenet5 = keras.Sequential()
lenet5.add(layers.Input(shape=(28, 28, 1)))
lenet5.add(layers.Conv2D(filters=6, kernel_size=5, activation='sigmoid', padding='same'))
lenet5.add(layers.AveragePooling2D(pool_size=2))
lenet5.add(layers.Conv2D(filters=16, kernel_size=5, activation='sigmoid'))
lenet5.add(layers.AveragePooling2D(pool_size=2))
lenet5.add(layers.Flatten())
lenet5.add(layers.Dense(120, activation='sigmoid'))
lenet5.add(layers.Dense(84, activation='sigmoid'))
lenet5.add(layers.Dense(10, activation='softmax'))
lenet5.summary()

# 훈련 데이터 로드
(train_input, train_target), (test_input, test_target) = keras.datasets.fashion_mnist.load_data()
train_input = train_input.reshape(-1, 28, 28, 1) / 255.0
train_scaled, val_scaled, train_target, val_target = train_test_split(train_input, train_target, test_size=0.2, random_state=42)

# 콜백 함수 정의
checkpoint_cb = keras.callbacks.ModelCheckpoint('lenet5-model.keras', save_best_only=True)
early_stopping_cb = keras.callbacks.EarlyStopping(patience=2, restore_best_weights=True)

# LeNet-5 훈련
lenet5.compile(loss='sparse_categorical_crossentropy', metrics=['accuracy'])
hist = lenet5.fit(train_scaled, train_target, epochs=20, validation_data=(val_scaled, val_target), callbacks=[checkpoint_cb, early_stopping_cb])

# 예측 이미지 준비
image = cv2.imread('shoes.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image = cv2.resize(image, (28, 28))
image = cv2.bitwise_not(image) # 이미지 반전

# Fashion MNIST 클래스 정의
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

# 예측
prediction = lenet5.predict(image.reshape(-1, 28, 28, 1) / 255.0)
print(prediction)

# 출력
max_index = np.argmax(prediction)
print('Max index: ', max_index, ', Probability: ', prediction[0][max_index] * 100)
print('Name: ', class_names[max_index])

 

shoes.jpg
0.26MB
tshirt.jpg
0.56MB

 

약 94%의 확률로 신발을 정확히 예측했다.

 

아래는 shoes.jpg, tshirt.jpg 그레이스케일 이미지를 (28X28) 사이즈로 변환 전 반전한 이미지다. 

 

 

 

 

이번엔 훈련 없이 위에서 저장한 가중치(lenet5-model.keras)를 로드하고 예측해 보자.

 

import numpy as np
import cv2
import keras
from keras import layers
from sklearn.model_selection import train_test_split

# Lenet5 정의 (로드할 가중치와 동일한 모델을 만들어야 한다)
lenet5 = keras.Sequential()
lenet5.add(layers.Input(shape=(28, 28, 1)))
lenet5.add(layers.Conv2D(filters=6, kernel_size=5, activation='sigmoid', padding='same'))
lenet5.add(layers.AveragePooling2D(pool_size=2))
lenet5.add(layers.Conv2D(filters=16, kernel_size=5, activation='sigmoid'))
lenet5.add(layers.AveragePooling2D(pool_size=2))
lenet5.add(layers.Flatten())
lenet5.add(layers.Dense(120, activation='sigmoid'))
lenet5.add(layers.Dense(84, activation='sigmoid'))
lenet5.add(layers.Dense(10, activation='softmax'))
#lenet5.summary()

# 저장한 가중치 로드
lenet5.load_weights('lenet5-model.keras')

# 예측 이미지 준비
image = cv2.imread('tshirt.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image = cv2.resize(image, (28, 28))
image = cv2.bitwise_not(image) # 이미지 반전

# Fashion MNIST 클래스 정의
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

# 예측
prediction = lenet5.predict(image.reshape(-1, 28, 28, 1) / 255.0)
print(prediction)

# 출력
max_index = np.argmax(prediction)
print('Max index: ', max_index, ', Probability: ', prediction[0][max_index] * 100)
print('Name: ', class_names[max_index])

 

약 53%의 확률로 셔츠를 예측했다. 0번 인덱스의 T-shirt/top은 약 44%의 확률을 갖는다.

 

반응형
Posted by J-sean
:
반응형

Tensorflow(Keras) Kernel을 만들고 확인해 보자.

 

from keras import layers

conv = layers.Conv2D(filters=4, kernel_size=(3, 3))
print(conv.data_format) # 기본 설정에 따른 결과: channels_last

# Input shape
#4+D tensor with shape: batch_shape + (channels, rows, cols) if data_format='channels_first'
#or 4+D tensor with shape: batch_shape + (rows, cols, channels) if data_format='channels_last'

input_shape = (5, 28, 28, 1) # (batch_size, rows, cols, channels)
# 5 => batch size (5개의 이미지를 한 번에 사용한다는 의미)
# 28, 28, 1 => 28X28 gray 이미지
# image size, batch size는 kernel 사이즈에 영향이 없다.
# channels는 영향이 있다.
# 결국 kernel_size, channels, filters 인수들에 의해 kernel 사이즈가 결정된다.
# kernel = ((kernel_size), channles, filters)

conv.build(input_shape)
print(conv.kernel)

 

(3, 3, 1, 4) 사이즈의 커널이 만들어진다.

 

간단한 형태의 커널로 바꾸고 직접 커널 값을 세팅해 보자.

 

from keras import layers
import numpy as np

conv = layers.Conv2D(filters=1, kernel_size=(3, 3))
input_shape = (5, 28, 28, 1) # (batch_size, rows, cols, channels)
conv.build(input_shape)

#print(conv.kernel) # 커널만 출력
print(conv.get_weights()) # 커널과 절편 출력

# 커널과 절편 세팅
conv.set_weights([
	np.array([[[[1]], [[2]], [[3]]], [[[4]], [[5]], [[6]]], [[[7]], [[8]], [[9]]]]),
	# 커널 세팅, 4차원(3, 3, 1, 1)
	np.array([7])
	# filters가 1이므로 절편도 1개. 여기서는 절편을 7로 세팅, 1차원(1)
])

#print(conv.kernel)
print(conv.get_weights())

 

 

반응형
Posted by J-sean
:
반응형

Keras 관련 에러를 몇 가지 확인하고 해결해 보자.

 

1)

dense = keras.layers.Dense(10, activation='softmax', input_shape=(784, ))

위 명령을 실행하면 아래와 같은 경고가 출력된다.

UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When using Sequential models, prefer using an `Input(shape)` object as the first layer in the model instead.

경고이므로 무시하고 넘어간다.


model = keras.Sequential(dense)
이어서 위 명령은 아래와 같은 에러가 출력된다.

TypeError: 'Dense' object is not iterable
아래와 같이 바꿔서 해결한다.
model = keras.Sequential([dense])

 

아니면 처음부터 아래와 같이 입력하면 경고나 에러 없이 진행 된다.
model = keras.Sequential([keras.Input(shape=(784, )), keras.layers.Dense(10, activation='softmax')])

 

2)

model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')

위 명령을 실행하면 아래와 같은 에러가 출력된다.

ValueError: Expected `metrics` argument to be a list, tuple, or dict. Received instead: metrics=accuracy of type <class 'str'>

아래와 같이 바꿔서 해결한다.
model.compile(loss='sparse_categorical_crossentropy', metrics=['accuracy'])

 

 

 

※ 참고

혼자 공부하는 머신러닝 + 딥러닝

 

반응형
Posted by J-sean
: