이번에는 남녀 판독기를 만들어보았다.
정확도 부분에서 좀 아쉽다.
왜 실제 이미지에서는 제대로 힘을 발휘하지 못하는지.. 아쉽다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # 데이터를 담을 list 선언 train_data = [] # trainning data set 을 만드는 함수 정의 import cv2 import numpy as np def make_train_set(sex, root, file_type, num_img): for idx in range(1, num_img): if idx<10: idx = '00'+str(idx) elif idx<100: idx = '0'+str(idx) else: idx = str(idx) path = root+idx+file_type img = cv2.imread(path) if img is not None: train_data.append([img[:224,:224,:], np.array(sex)]) | cs |
- 훈련 데이터 셋을 만들어주는 함수를 선언했다.
- 이전 프로젝트와는 달리, 이미지 크기 조절을 받자마자 해줬기 때문에 코드 길이가 줄어들었다.
또한, 함수로 만들어줘서 가독성을 좋게 만들어주었다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # 여자 연예인 사진 가져오기 (1) - 로제, 여자 라벨=0 make_train_set(0, '/content/drive/My Drive/로제___Google_검색/pic_', '.jpg', 100) # 여자 연예인 사진 가져오기 (2) - 지수, 여자 라벨=0 make_train_set(0, '/content/drive/My Drive/지수_블랙핑크___Google_검색/pic_', '.jpg', 100) # 여자 연예인 사진 가져오기 (2) - 여자 연예인, 여자 라벨=0 make_train_set(0, '/content/drive/My Drive/cat-and-dog/여자_연예인___Google_검색/pic_', '.jpg', 100) # 남자 연예인 사진 가져오기 (1) - 임시완, 남자 라벨=1 make_train_set(1, '/content/drive/My Drive/임시완_얼굴___Google_검색/pic_', '.jpg', 200) # 남자 연예인 사진 가져오기 (2) - 강동원, 남자 라벨=1 make_train_set(1, '/content/drive/My Drive/강동원_얼굴___Google_검색/pic_', '.jpg', 40) # 남자 연예인 사진 가져오기 (3) - 정우성, 남자 라벨=1 make_train_set(1, '/content/drive/My Drive/정우성_얼굴___Google_검색/pic_', '.jpg', 130) | cs |
- 이런식으로 해서, 훈련 데이터를 만들어주었다.
- 이 부분에서 잘못 훈련된 것 같다.
훈련 데이터들이 괜찮아야지 테스트 데이터에서도 제대로 작동하는데,
훈련 데이터에서는 성능이 좋음에도 불구하고 테스트 데이터에서는 잘못 작동했다.
오버피팅이 일어나지 않았나 싶다.
- 훈련 데이터 양을 늘리고싶지만, 더 이상의 노동은 별로 하고싶지 않고,
별 다른 방법이 없다.
- 다른 블로그에서 봤던 내용처럼, 아무래도 사진의 배경이 뚜렸한 경우에는 잘 못 훈련되도록 유도하는 것 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # 섞기 import random train_data = np.array(train_data) random.shuffle(train_data) train_data = train_data.tolist() # train_X, train_Y 따로 만들어주기 train_X, train_Y = zip(*train_data) train_X = np.array(train_X) train_Y = np.array(train_Y) | cs |
- 데이터를 섞어주었다.
- 이전 프로젝트와는 달리, 이번에는 y 데이터를 원핫 처리 하지 않았다.
그 이유는 다음 코드를 보면서 설명하겠다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # 모델 설계하기 from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Flatten, Conv2D model = Sequential() model.add(Conv2D(filters=64, kernel_size=3, activation='relu', input_shape=(224,224,3))) model.add(Conv2D(filters=32, kernel_size=3, activation='relu')) model.add(Flatten()) model.add(Dense(1, activation='sigmoid')) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc']) model.fit(x=train_X, y=train_Y, batch_size=50, epochs=5) | cs |
- 맨 마지막 layer 에서, 출력값이 1차원이며 활성화 함수를 시그모이드로 설정했다.
따라서, 남자인지 여자인지를 확률적으로 계산해 출력하겠다는 것이다.
- 원핫 처리를 할 경우엔, 각 값이 너무 작게 나와서 눈에 보기 쉽지 않았기에 이런 선택을 했다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # 테스트 케이스 실험해보기 함수 정의 import matplotlib.pyplot as plt def test_case(sex, path): img = cv2.imread(path) photo_img = img img = np.array(img[:224, :224, :]) img = img.reshape(-1, 224, 224, 3) probability = model.predict(x=img) if probability < 0.5: print("predict : 여자다!") else: print("predict : 남자다!") print("accuracy : ", probability[0][0]*100,"%") if sex == 0: print("real value : 여자임") else: print("real value : 남자임") plt.imshow(cv2.cvtColor(photo_img, cv2.COLOR_BGR2RGB)) | cs |
- 테스트 케이스에도 제대로 작동하는지를 판별하기 위한 함수다.
- 확률 값이 1/2보다 작으면 여자, 크면 남자라고 설정했다.
- 원본 사진을 색상 문제 없이 출력해주기 위해 cv2.cvtColor() 함수를 사용해 주었다.
>> 이 두 사진만 봤을때는 엄청 잘 훈련된 모델이라고 생각했는데...
다른 사진들에 적용해보니 정확도가 너무 낮았다.
훈련이 잘 안 된 것 같다.......
# 총평
- 이진 분류 문제는 이 코드를 그대로 사용만 해도 풀리는 것 같다.
다른 실습을 할때도 이 코드를 활용하도록 하자
- 문제는, 제대로 된 훈련 데이터를 얻는 것이다.
어디서 그런 데이터를 얻어야 하는 것일까
대가리 아프다
'기계학습 > 이미지 머신러닝' 카테고리의 다른 글
MNIST 실습 - GAN (0) | 2020.02.11 |
---|---|
MNIST 실습 - CNN 모델 (0) | 2020.02.10 |
MNIST - 일반 딥러닝 모델 (0) | 2020.02.09 |
MNIST - 기본 1 layer 머신러닝 (0) | 2020.02.08 |