2번째 프로젝트의 키워드는 CNN이다. CNN을 활용해서 두 가지의 프로젝트를 진행했다.
첫 번째로 진행한 프로젝트는 에어팟을 이용해서 고장 여부를 진단했다. 실질적인 고장 판단이 되지 않기에, 각 클래스에 대해 임의의 상황을 가정한다.
프로젝트를 진행하면서 가장 힘들었던 점은 양질의 데이터셋 확보였다. 다이소 캠을 이용해서 에어팟의 각도에 변화를 주기도 하고, 물체의 일부분을 가리면서 각 경우마다 10장씩 수집했는데, 생각보다 좋지 못한 결과를 확인했다. 따라서 아래의 5번의 추가 수집 과정을 거쳤고, 그 이유는 아래와 같다.
1회차 : 각 경우마다 10장은 너무 많은가 해서 각 경우별로 5장씩으로 줄여보았다.
2회차 : 1회차와 같은 이유로, 3장으로 줄여보았다.
3회차 : 명백한 특징점이 없나 하여 케이스를 끼운 상태로 수집했다.
4회차 : 다이소 캠의 경우, 품질이 좋지 않아 사진에 줄무늬가 쳐지는 현상이 발생하여 휴대폰으로 영상을 촬영하고 해당 영상에서 이미지를 캡쳐하며 수집했다. 또한 물체의 일부분을 가리는 행위가 학습에 방해가 되나 싶어 일부분을 가리지 않고 물체만 타이트하게 잡아 촬영하였다.
5회차 : 마찬가지로 휴대폰으로 수집을 진행하되, 각도를 조금 더 세밀하게 조정하여 촬영하였다.
일반화가 잘 되지 않아 새로운 각도나 배경에 대해서는 예측을 잘 해내지 못하는 편이었다. 나름대로의 원인 분석을 진행한 결과는 아래와 같다.
2번째 프로젝트는 웹 캠 대신에 DroidCam
을 이용하는 것이 핵심이었다. 주제는 밟으면 아플만한 물건들을 실시간으로 예측하기
였다. 선정 의의는 아래와 같다.
교수님께서 제시하신 주제 예시들 중, 맹인분들을 위한 Line Tracing을 CNN으로 진행하는 예시가 있었는데, 이에 약간의 변화를 주어 맹인 분들이 집에서 활동하시다가 바닥에 떨어진 물건들 중 밟으면 아플만한 물건들이나 밟으면 안되는 귀중품(ex. 레고 블럭, 콘센트, 에어팟, 시계 등등..)을 실시간으로 예측하는게 어떨까 했다.
DroidCam을 사용하는 것이 핵심이었기에, 휴대폰을 이용하여 데이터셋을 수집했다. 수집한 클래스는 3개이며, 아래와 같다.
두 프로젝트를 놓고 비교했을 때, 데이터 수집 부분에서 차이를 두었던 핵심 키워드는 특징점
이다. 보다 더 확실한 특징점을 만들기 위해서 클래스 구성할 때 부터 특색이 확실한 클래스들로 구성했고, 데이터 수집 시 배경 또한 더 다양한 배경색을 바탕으로 촬영했다.
첫번째 프로젝트보단 좀 더 다양한 각도에서도 예측을 잘 하는 편이었으나, 완벽한 결과를 내뱉진 못했다. 그래도 이정도는 만족스러운 결과였다.
두 프로젝트를 진행한 순서는 아래와 같다
직접 CNN모델을 빌드하고, 첫 번째 프로젝트에는 DenseNet을 활용한 전이학습도 진행해보았다. 아래 예시들은 첫 번째 프로젝트에 사용한 모델들이다.
[basic CNN Model]
def get_model():
model = Sequential()
model.add(Conv2D(32, (3, 3), activation = "relu", input_shape = (480, 640, 3)))
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(64, (3, 3), activation = "relu"))
model.add(MaxPooling2D(2, 2))
model.add(Flatten())
model.add(Dense(64, activation = "relu"))
model.add(Dropout(0.3))
model.add(Dense(5, activation = "softmax"))
return model
model = get_model()
model.compile(optimizer = "adam", loss = "categorical_crossentropy", metrics = ['acc'])
[Transfer Learning with DenseNet]
def get_pretrained_model():
my_params = {
'weights' : 'imagenet',
'include_top' : False,
'pooling' : 'max',
'classes' : 5,
'classifier_activation' : 'softmax',
'input_shape' : (480, 640, 3)
}
pred_model = densenet.DenseNet201(**my_params)
for layer in pred_model.layers:
layer.trainable = False
pre_input_layer = pred_model.input
pre_output_layer = pred_model.output
x = Dense(64, activation = "relu")(pre_output_layer)
x = Dropout(0.3)(x)
x = Dense(5, activation = "softmax")(x)
pretrained_model = Model(pre_input_layer, x)
optim = Adam(0.001)
pretrained_model.compile(optimizer = optim, loss = "categorical_crossentropy", metrics = ['acc'])
return pretrained_model
이후 하이퍼 파라미터 조정 및 데이터 수정 등등의 작업을 거쳐 가장 학습이 잘 된 가중치 파일만 사용했다.
캠을 연결하여 캡쳐 후, 캡쳐된 화면을 예측하는 방식을 사용했다.
[첫 번째 프로젝트]
[두 번째 프로젝트]
데이터를 수집하는 부분에 있어 가장 어려움을 많이 느꼈다. 아무래도 에어팟의 경우 모양을 변형(깎거나, 다른 형상으로 놓거나..)시키는 선택지가 없다 보니 각도를 달리하는 선택지밖에 없어 더 어려웠던 것 같다.
전이학습은 만능이 아니라는 피드백을 들었다. 첫 번째 프로젝트의 경우에는 과연 DenseNet까지 사용했어야 하는가 하는 의문이 든다는 교수님의 피드백이 있었는데, 어떤 상황에서 어떤 모델을 채택해서 전이학습을 사용하는 것이 효율적인지를 확실하게 인지하고 사용해야 할 듯 하다.
하이퍼 파라미터들을 조정하거나 모델을 수정할 때 과대적합을 위한 방법들로는 Dropout 이나 훈련용 데이터셋에 Fake Data들을 섞기도 한다고 하여 이런 과정들을 수행해 보았지만 결국엔 과대적합을 막지 못했다. 모델을 설계하고 나서 1차적인 평가를 마쳤을 때 각 케이스에 대한 모델 수정 방향을 정리해놔야 할 필요성을 느꼈다.
데이터 Augmentation의 경우 데이터의 유형에 따라 사용 시 주의해야 하는 것을 확실하게 인지했다. 예를 들어 데이터들 중 20장 정도가 사진의 끝쪽에 위치해 있는데 width_shift_range
를 적용시켜 버리면 아예 화면 밖으로 나가버리는 현상이 발생할 수 있기에, 각 증강기 옵션들을 확실하게 숙지하고 데이터의 유형에 따라 사용해야할 것 같다.
프로젝트를 진행한 전체적인 과정은 https://github.com/LeeHeonWoo1/Intel/blob/master/projects/CompletionSignal/conpletion_signal.ipynb
에서 확인할 수 있습니다.
👍 데이터셋 수집 시 조명 환경 일치, 혹은 다양한 조명 환경 설정 !! 👍
코드 한줄한줄 이해하는 것도 중요하지만, 특정 파라미터가 변할 때 모델에 어떤 영향을 미치는지 정리해야할 것 같다는 생각이 많이 들었다.
그리고 생각보다 다른 조들이 가져온 주제들이 너무 흥미로웠다. 섯다 족보 인식, 공정에서 진행되는 물품들의 고장진단, 반도체 셀 고장 진단, 야구 스트라이크 볼 판정까지.. 어떻게 저렇게 재밌고 신박한 주제들이 나올 수 있을까 하는 생각도 들었는데 특정 분야에 대한 지식이 중요한 것 같다는 생각을 했다.