03. CNN with TF
(참고) udemy - TF Developer in 2022
Contents
- Inspecting data
- end-to-end example
- Baseline model
- ConvNet with max pooling & Data augmentation
- Prediction
- Multi-class Classification
(1) Inspecting data
Example of file structure
pizza_steak <- top level folder
└───train <- training images
│ └───pizza
│ │ │ 1008104.jpg
│ │ │ 1638227.jpg
│ │ │ ...
│ └───steak
│ │ 1000205.jpg
│ │ 1647351.jpg
│ │ ...
│
└───test <- testing images
│ └───pizza
│ │ │ 1001116.jpg
│ │ │ 1507019.jpg
│ │ │ ...
│ └───steak
│ │ 100274.jpg
│ │ 1653815.jpg
│ │ ...
특정 directory 내부 샅샅히 뒤지기
import os
for dirpath, dirnames, filenames in os.walk("pizza_steak"):
print(f"There are {len(dirnames)} directories and {len(filenames)} images in '{dirpath}'.")
There are 2 directories and 0 images in 'pizza_steak'.
There are 2 directories and 0 images in 'pizza_steak/test'.
There are 0 directories and 250 images in 'pizza_steak/test/steak'.
There are 0 directories and 250 images in 'pizza_steak/test/pizza'.
There are 2 directories and 0 images in 'pizza_steak/train'.
There are 0 directories and 750 images in 'pizza_steak/train/steak'.
There are 0 directories and 750 images in 'pizza_steak/train/pizza'.
특정 경로 내 파일 개수
len(os.listdir("pizza_steak/train/steak"))
# 750
요약 : class 별로,
- 750개의 train image
- 250개의 test image
(2) end-to-end example
- Import Packages
- Load Images
- Build Model
- Train Model
- Import Packages
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
- Load Images
tf.random.set_seed(42)
# normalization
train_datagen = ImageDataGenerator(rescale=1./255)
valid_datagen = ImageDataGenerator(rescale=1./255)
train_dir = "pizza_steak/train/"
test_dir = "pizza_steak/test/"
train_data = train_datagen.flow_from_directory(train_dir,
batch_size=32,
target_size=(224, 224),
class_mode="binary",
seed=42)
valid_data = valid_datagen.flow_from_directory(test_dir,
batch_size=32,
target_size=(224, 224),
class_mode="binary",
seed=42)
참고 : data loader ( iterator )에서 하나의 예시 ( =하나의 batch ) 뽑아내기
images, labels = train_data.next()
len(images), len(labels)
# 32, 32
- Build Model
Tiny VGG - https://poloclub.github.io/cnn-explainer/
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(filters=10,
kernel_size=3, # (3, 3)
activation="relu",
input_shape=(224, 224, 3)), # (H, W, C)
tf.keras.layers.Conv2D(10, 3, activation="relu"),
tf.keras.layers.MaxPool2D(pool_size=2, # (2, 2)
padding="valid"), # or 'same'
tf.keras.layers.Conv2D(10, 3, activation="relu"),
tf.keras.layers.Conv2D(10, 3, activation="relu"),
tf.keras.layers.MaxPool2D(2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(1, activation="sigmoid")
])
- Train Model
model.compile(loss="binary_crossentropy",
optimizer=tf.keras.optimizers.Adam(),
metrics=["accuracy"])
history = model.fit(train_data,
epochs=5,
steps_per_epoch=len(train_data),
validation_data=valid_data,
validation_steps=len(valid_data))
(3) Baseline model
일반적인 구조
- Input
- ( Conv + ReLU + Pooling ) x n
- Flatten
- FC layer
Padding
same
: zero padding으로, 크기 유지되도록valid
: padding 안함
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPool2D, Activation
from tensorflow.keras import Sequential
model = Sequential([
Conv2D(filters=10,
kernel_size=3,
strides=1,
padding='valid',
activation='relu',
input_shape=(224, 224, 3)),
Conv2D(10, 3, activation='relu'),
Conv2D(10, 3, activation='relu'),
Flatten(),
Dense(1, activation='sigmoid')
])
(4) ConvNet with max pooling & data augmentation
Data Augmentation
train_datagen_augmented = ImageDataGenerator(rescale=1/255.,
rotation_range=20,
shear_range=0.2,
zoom_range=0.2,
width_shift_range=0.2,
height_shift_range=0.2,
horizontal_flip=True)
train_datagen = ImageDataGenerator(rescale=1/255.)
test_datagen = ImageDataGenerator(rescale=1/255.)
- Augment 된 이미지
train_data_augmented = train_datagen_augmented.flow_from_directory(train_dir,
target_size=(224, 224),
batch_size=32,
class_mode='binary',
shuffle=False)
- Augment 안된 (원본) 이미지
train_data = train_datagen.flow_from_directory(train_dir,
target_size=(224, 224),
batch_size=32,
class_mode='binary',
shuffle=False) # Don't shuffle for demonstration purposes
test_data = test_datagen.flow_from_directory(test_dir,
target_size=(224, 224),
batch_size=32,
class_mode='binary')
Max pooling
순서 : ( conv-relu-maxpool )
model = Sequential([
Conv2D(10, 3, activation='relu', input_shape=(224, 224, 3)),
MaxPool2D(pool_size=2),
Conv2D(10, 3, activation='relu'),
MaxPool2D(),
Conv2D(10, 3, activation='relu'),
MaxPool2D(),
Flatten(),
Dense(1, activation='sigmoid')
])
(5) Prediction
Input Size
- (O) : (n, H,W,C)
- (X) : (H,W,C)
맨 앞의 차원에 , n ( 이미지의 개수 )가 들어가야한다
pred = model.predict(tf.expand_dims(img, axis=0))
(6) Multi-class Classification
class_mode='categorical'
train_data = train_datagen.flow_from_directory(train_dir,
target_size=(224, 224),
batch_size=32,
class_mode='categorical')
loss="categorical_crossentropy"
model.compile(loss="categorical_crossentropy",
optimizer=tf.keras.optimizers.Adam(),
metrics=["accuracy"])