IPv6: IPv4 의 주소 개수 한계로 등장한 주소 체계, 현재는 전부 IPv6를 사용하는데 IPv4로 설정하면 자동으로 변환을 수행. 128비트 주소 체계로 16비트씩 8개의 영역으로 구분을 하고 각 16비트는 16진수 4자리로 표현하고 중복되는 부분을 생략할 수 있도록 설계
GTSRB\Final_Training\Images 디렉토리 안에 디렉토리 별로 이미지가 ppm 확장자로 분류되어 있다.
- ppm: 무손실 압축 이미지 파일 형식
- image 크기: 32 x 32
- 신경망 구조를 만들 때 선택 사항
2차원 컨볼루션에서 필터 개수 와 커널 크기
Max Pool 에서의 커널 크기
Fully Connected 계층(Dense)에서의 유닛 개수
계층 별 배치 크기, 최적화 알고리즘, 학습률, 할성화 함수, epoch 수 등
- 이미지 전처리
이미지 크기를 32*32로 수정
43개의 레이블을 생성: 디렉토리 이름이 레이블
표지판의 경우 구분해야 할 것은 색상이 아니라 모양: 이미지를 흑백으로 변경
데이터를 다룰 때 목적을 먼저 생각하고 작업을 시작해야 한다. (도메인)
- 필요한 패키지 와 상수 선언
클래스 개수와 이미지의 크기를 변수에 저장
이 두개의 절대로 변하지 않을 값
변하지 않는 값을 장할 변수의 이름은 모두 대문자로 작성하는 것이 좋다.
SNAKE 표기법이라고 한다.
N_CLASSES = 43
RESIZED_IMAGE = (32, 32)
# 모듈
import matplotlib.pyplot as plt
#디렉토리를 핸들링 할 때 사용하는 모듈import glob
from skimage.color import rgb2lab
from skimage.transform import resize
import numpy as np
from collections import namedtuple
from sklearn.model_selection import train_test_split
- 이미지 전처리를 위한 함수
이름이 있는 튜플 생성 - 다른 언어에서는 튜플을 이런 형태로 만든다.
튜플의 원래 목적은 변경할 수 없는 하나의 행(record, row)을 표현하기 위한 것
인덱스가 아니라 이름으로 구별하는 것이 타당
Dataset = namedtuple('Dataset', ['X', 'y'])
# 포맷 변경해주는 함수
defto_tf_format(imgs):
return np.stack([img[:, :, np.newaxis] for img in imgs], axis=0).astype(np.float32)
- 이미지 디렉토리에 있는 모든 이미지들에 라벨링을 하기 위한 작업 - 이미지의 크기 변경도 여기서 수행
defread_dataset_ppm(rootpath, n_labels, resize_to):
#이미지 데이터 와 라벨을 저장할 list
images = []
labels = []
for c inrange(n_labels):
#루트경로/00001/ 형태로 이미지 경로를 생성
full_path = rootpath + "/" + format(c, '05d') + "/"#각 이미지 디렉토리를 순회하면서 확장자가 ppm 인 파일의 경로를 가지고for img_name in glob.glob(full_path + "*.ppm"):
#이미지 읽어오기
img = plt.imread(img_name).astype(np.float32)
#이미지를 정규화
img = rgb2lab(img / 255.0)[:, :,0]
#이미지 크기를 조정if resize_to:
img = resize(img, resize_to, mode='reflect')
#라벨 생성#43개 짜리 배열을 만들어서 자신의 인덱스에 해당하는 값에만 1을 대입#원핫 인코딩 된 라벨
label = np.zeros((n_labels, ), dtype=np.float32)
label[c] = 1.0
images.append(img.astype(np.float32))
labels.append(label)
return Dataset(X = to_tf_format(images).astype(np.float32), y = np.matrix(labels).astype(np.float32))
#모델 만들기
model = keras.Sequential()
#입력 층을 합성곱 층을 사용
model.add(keras.layers.Conv2D(32, kernel_size=3, activation="relu",
padding='same', input_shape=(28, 28, 1)))
model.add(keras.layers.MaxPooling2D(2))
model.add(keras.layers.Conv2D(64, kernel_size=3, activation="relu",
padding='same'))
model.add(keras.layers.MaxPooling2D(2))
#데이터를 1차원으로 만들어주는 층
model.add(keras.layers.Flatten())
#Dense 는 1차원의 데이터만 사용
model.add(keras.layers.Dense(100, activation="relu"))
#드랍 아웃 적용
model.add(keras.layers.Dropout(0.4))
model.add(keras.layers.Dense(10, activation="softmax"))
# 모델 확인
model.summary()
4. 모델 컴파일 (훈련)
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy",
metrics=["accuracy"])
#체크 포인트
checkpoint_cb = keras.callbacks.ModelCheckpoint("best-cnn-model.keras")
#2번의 epoch 동안 점수가 좋아지지 않으면 조기 종료
early_stopping_cb = keras.callbacks.EarlyStopping(patience=2,
restore_best_weights=True)
history = model.fit(train_scaled, train_target, epochs=20,
validation_data=(val_scaled, val_target),
callbacks=[checkpoint_cb, early_stopping_cb])
4. 모델 평가
model.evaluate(val_scaled, val_target)
아래 합성곱 층으로 내려갈 때 뉴런의 개수를 늘렸는데 중간에 MaxPooling2D(Dropout을 적용해도 동일) 을 적용했기 때문에 실제 파라미터의 개수가 줄어들어 사용되므로 늘린 티가 나지 않음
plt.figure(figsize=(8, 11))
# 지역 이름 표시for idx, row in draw_korea_raw_stacked.iterrows():
# 광역시는 구 이름이 겹치는 경우가 많아서 시단위 이름도 같이 표시# (중구, 서구)iflen(row['ID'].split())==2:
dispname = '{}\n{}'.format(row['ID'].split()[0], row['ID'].split()[1])
elif row['ID'][:2]=='고성':
dispname = '고성'else:
dispname = row['ID']
# 시도 경계 그리기
for path in BORDER_LINES:
ys, xs = zip(*path)
plt.plot(xs, ys, c='black', lw=1.5)
#y축의 위아래 변경
plt.gca().invert_yaxis()
#plt.gca().set_aspect(1)#축과 라벨 제거
plt.axis('off')
#자동 레이아웃 설정
plt.tight_layout()
plt.show()
# draw_korea_raw_stacked와 pop의 도시이름 일치시키기
#draw_korea_raw_stacked 와 pop 의 도시이름 비교print(set(draw_korea_raw_stacked['ID'].unique()) - set(pop['ID'].unique()))
print(set(pop['ID'].unique()) - set(draw_korea_raw_stacked['ID'].unique()))
#일치하지 않는 데이터 삭제
tmp_list = list(set(pop['ID'].unique()) - set(draw_korea_raw_stacked['ID'].unique()))
for tmp in tmp_list:
pop = pop.drop(pop[pop['ID']==tmp].index)
print(set(pop['ID'].unique()) - set(draw_korea_raw_stacked['ID'].unique()))