본문 바로가기

Computer Vision/Classification

개와 고양이 분류하기 - 1

2020/06/18 - [분류 전체보기] - 개와 고양이 분류하기 - 0

이전 포스팅에서 데이터를 받아왔으니 가장 먼저 우리가 해야할 일은

데이터를 분석하는 일이다. 

Dogs vs Cats 데이터는 다음 포스팅에서 할 일이 있기 때문에 넘어가고

이번 포스팅에서 진행하는 일은 breed데이터들을 분석하고 정리하는 일이다.

 

데이터 분석이라 해서 그리 거창한 걸 하는 건아니고, 데이터 확인 정도라고 보면 된다.

데이터 셋

먼저 cat_breed폴더에 있는 고양이의 종류(혈통)을 알아 보면,

import os
import shutil
import pandas as pd
import matplotlib.pyplot as plt

cat_breed_path = './cat_breed/images/'
cat_breed = os.listdir(cat_breed_path)

cat_breed_count = []

for breed in cat_breed :
    cat_breed_count.append(len(os.listdir(cat_breed_path+breed)))
    
cat_breed_list = pd.DataFrame(data=[],columns=['breed','count'])
cat_breed_list['breed'] = cat_breed
cat_breed_list['count'] = cat_breed_count

cat_breed_list

이렇게 총 67종의 고양이가 분류되어 있다. 데이터 프레임만 간단하게 봐도,

Domesitc Short Hair는 5만장이 넘는 반면 Canadian Hairless는 4장, York Chocolate은 1장인 걸 보면

엄청난 데이터 불균형이 존재하는 걸 알 수 있다. 심지어 1장~4장인 경우, test데이터를 넣어 인식하기란 불가능에 가깝다고 볼 수있다.

이 부분을 해결하기 위해서는 Selenium과 beatifulsoup을 이용해서 웹 크롤링을 통해 불균형 데이터를 채워 넣어 균형을 맞출 수 있겠다.

(여담으로, 다른 이미지의 경우 6000장 이상인 폴더가 한 개도 없는데, Domestic Short Hair만 왜 5만장이나 되나.. 궁금해서 구글에 검색한 결과 길냥이 였다. 즉, 동네 돌아다니는 고양이라서 Domestic 이란 이름이 붙은 것 같다.) 

쨋든, 각설하고 그래프로 확인해보면 그 불균형을 좀 더 확실하게 느낄 수 있다.

엄청난 불균형 현상을 가지고 있다.

 이번에는 dog에 대해서 알아보자.

dog데이터는 2가지를 받아주었다. 한가지 데이터 셋은 cat breed와 마찬가지로

강아지들의 종류(혈통)별 폴더에 이미지가 담겨 있다.

dog breed1 data

cat breed와 마찬가지 코드로 데이터를 확인해 보면

강아지 데이터는 고양이와 다르게 약 133개의 종류로 분류가 되어 있다.

각 종류별 데이터의 개수는 100개 이하로 그래프로 확인해 보면, 고양이 데이터보다 균형있는 분포를 그리고 있다.

강아지의 인기를 실감하는 순간..? 그럼 이번에는 두번째 데이터를 확인해 보자.

두번째 데이터는 Train set이 종류별 디렉토리 분류가 되어 있지 않다.

dog breed2 data

대신 이미지 넘버링에 대한 csv 파일을 제공하고 있다.

dog_breed2 = pd.read_csv('./dog_breed/Dog_Breed_Recognition_Competition_Datasets/Dog_Breed_trainingdata.csv')
dog_breed2

breed말고도 여러가지 데이터를 담고 있다. 머신러닝 competition에 도 이용할 수 있게 데이터 셋을 만들어 머신러닝 기법을 이용하여 앙상블하면 더 분류를 잘할 수 있거나, 다양한 데이터를 함께 제공할 수도 있으나 당초 목적과 맞지 않으므로 일단은 무시하도록 하자.

이제 breed칼럼을 이용하여 count를 하는 data frame을 다시 생성 해보자.

dog_breed_list2 = pd.DataFrame(data=[],columns=['breed','count'])

breed_tmp = []
count_tmp = []

for breed in dog_breed2['breed'] :
    if breed not in breed_tmp :
        breed_tmp.append(breed)
        count_tmp.append(1)
    
    else :
        count_tmp[breed_tmp.index(breed)] += 1
        
dog_breed_list2['breed'] = breed_tmp
dog_breed_list2['count'] = count_tmp

dog_breed_list2

총 226개 종류가 있고, 역시 대충 봐도 데이터 불균형이 심각해 보인다. 역시 그래프로 확인해 보면,

역시 데이터 전체가 불균형한 모습을 보이고 있다. 하지만 좋은 데이터 나쁜 데이터를 판가름 하기에는 세상 모든 데이터가 균형적으로 수집될리가 없기 때문에 이런 현상은 당연한 것이라는 생각이 많이 든다.

마지막으로, 개와 고양이의 종류(혈통)이 함께 있는 데이터를 확인해보자.

통합 데이터셋

마지막 데이터를 확인해보면 개와 고양이 이미지가 한 폴더에 전부 있고, 이미지에 이름으로 labeling이 되어있는 상태이다. 이것들의 데이터를 위와 같이 확인해보자.

catdog_breed_path = './dataset/images/images/'
catdog_breed = os.listdir(catdog_breed_path)

catdog_breed_list = pd.DataFrame(data=[],columns=['breed','count'])

breed_tmp2 = []
count_tmp2 = []

for breed in catdog_breed :
    txt = '_'.join(breed.split('_')[:-1])
    if txt not in breed_tmp2 :        
        breed_tmp2.append(txt)
        count_tmp2.append(1)
    
    else :
        count_tmp2[breed_tmp2.index(txt)] += 1
        
catdog_breed_list['breed'] = breed_tmp2
catdog_breed_list['count'] = count_tmp2

catdog_breed_list

총 36종류의 개와 고양이의 종류(혈통)이 있고 (어떻게, 합쳐진게 제일 적어 ㅜㅜ) 데이터는 거의 200개를 맞추어 놓은 것을 확인할 수 있다. 데이터프레임에서 데이터들의 개수가 확인이 전부 되므로 그래프를 따로 그리진 않았다.
(하나 특이한 점이 있다면, breed의 맨앞이 대문자로 시작하면 고양이, 소문자로 시작하면 강아지라는 특징이 있었다.)

그래서 물론 내가 훈련을 시킬 때 특별한 목적이 있지 않는한 데이터를 확인하는 일은 당연한 것이고 해야하는 일이지만 사실 필자의 가장 큰 목적은 데이터 셋이 현재 4가지로 나누어져 있고, 4가지 모두 데이터 셋을 나누는 방법이 다르기 때문에, 

모든 데이터 셋을 훈련하기 좋은 형태. 즉, 내가 좋아하는 형태로 만들기 위해 데이터를 통합하고 정리하는 작업을 진행해야 한다.

가장 먼저 cat breed같은 경우에 폴더별 정리가 되어 있으므로 많이 건들 것은 없고 이름이 띄어쓰기로 되어 있기 때문에 이 부분을underbar로 변환해 주도록 하자.

 print(cat_breed[:5])

 

['Japanese Bobtail', 'Domestic Medium Hair', 'Dilute Tortoiseshell', 'Siamese', 'Domestic Short Hair']

for i in cat_breed :
    os.rename(cat_breed_path+i,cat_breed_path+i.replace(' ','_'))
    
cat_breed_path = './cat_breed/images/'
cat_breed = os.listdir(cat_breed_path)

print(cat_breed[:5])

['Japanese_Bobtail', 'Domestic_Medium_Hair', 'Dilute_Tortoiseshell', 'Siamese', 'Domestic_Short_Hair']

요렇게 변환된 걸 확인할 수 있다.