Week09 Day42

 


위 과정은 문제를 정의하고 어떤 데이터를 수집할 것이며 이 데이터에는 어떤 특성이 있고 전처리를 한 후 모델링을 하고 학습하는 과정을 나타낸다.
이 중 어떤 부분이 가장 시간을 많이 사용할까?

전처리(pre-processing)

Data preprocessing is an important step in the data mining process.
The phrase “garbage in, garbage out” is particularly applicable to data mining and machine learning projects.
Data-gathering methods are often loosely controlled, resulting in out-of-range values (e.g., Income: −100), impossible data combinations (e.g., Sex: Male, Pregnant: Yes), and missing values, etc.
Analyzing data that has not been carefully screened for such problems can produce misleading results.
Thus, the representation and quality of data is first and foremost before running any analysis.1

전처리 과정은 data mining 과정에서 중요한 단계이다.
“garbage in, garbage out”은 직역하면 쓰레기가 들어가면 쓰레기가 나온다. 라는 말로, 적절하지 못한 입력을 넣으면 좋지 못한 출력을 얻는다는 뜻이다.
데이터를 수집하다 보면 적절하지 못한 데이터를 수집할 수 있다, 예를 들어 소득이 음수이거나 나이가 999 라던지, 혹은 결측치가 있을 수 있다.
이런 데이터를 분석하면 잘못된 결과를 얻을 수 있다.
따라서 분석을 하기 전에 데이터의 품질을 고려하는 것이 먼저이다.

전처리 과정은 모델에 입력하기 위해 raw data를 적절하게 가공하는 과정을 말한다.
그럼 어떻게 적절하게 가공할까?
business rule에 의해 전처리를 한다.
예를 들어 고등학생 명부라는 시스템을 만든다고 하자.
여기에 필요한 데이터는 이름, 생년월일, 전화번호, 학년, 담임선생님 등이 있다.
이름은 글자(ex: 홍길동), 생년월일은 숫자(ex: 19990304), 전화번호는 글자(ex: 010-1234-9434), 학년은 숫자(ex: 2) 등으로 수집된다.
만약 학년의 값이 99 혹은 -3 이라면 정확한 값이라고 볼 수 있을까?
학년별 중간고사 수학 평균을 구한다고 하면 1학년 83, 2학년 85, 3학년 87, 99학년 80 이라는 결과를 얻게 된다.
혹은 수학점수가 9999라면 전체 평균이 비정상적으로 높아질 수 있다.
이런 데이터를 분석 모델에 넣는다면 정확하지 못한 결과를 얻게 된다.
그래서 좋은 결과를 얻기 위해 문제 정의를 명확하게 하고 다루는 영역에 대한 이해를 하여 사전에 정상적이지 못한 값들을 적절하게 처리하는 과정이 필요하다.
이 과정을 전처리 과정이라 한다.

전처리는 모델을 만들고 분석하는 것보다 훨씬 더 많은 시간을 사용한다.
결측치가 있는지, 있다면 어떻게 처리할 것인가, 제외할 것인가, 아니면 interpolation을 할 것인가, 어느 데이터의 크기가 너무 커서 학습을 하는데 방해가 되는 건 아닌지, business rule에 의해 비정상적인 값이 있는지 등을 확인한다.

dataset implementation

data pipeline을 구현했다.
코드 이해를 위해 상수를 변수에 할당하여 사용하도록 했다.

import pandas as pd
from torch.utils.data import Dataset


class MaskDataset(Dataset):
    def __init__(self, csv_file, root_dir, transform=None):
        self.mask_frame = pd.read_csv(csv_file, usecols=["gender", "age", "path"])
        self.root_dir = root_dir  # image root directory; input/data/train
        self.transform = transform
        self.IMAGES_PER_PERSON = 7  # each person has 7 images

    def __len__(self) -> int:
        return len(self.mask_frame) * self.IMAGES_PER_PERSON

    def __getitem__(self, index: int):
        person_idx, idx = divmod(index, self.IMAGES_PER_PERSON)
        image_dir = self.mask_frame.iloc[person_idx, 2]
        image_dir = os.path.join(self.root_dir, image_dir, "*")
        image_path = sorted(glob(image_dir))[idx]
        label = self.path2label(image_path, person_idx)
        img = Image.open(image_path)
        if self.transform is None:
            return img, label
        return self.transform(img), label

    def path2label(self, path, person_idx):
        gender = self.mask_frame.iloc[person_idx, 0]
        age = self.mask_frame.iloc[person_idx, 1]
        mask = path.split("/")[-1]
        young_age = 30
        old_age = 60

        def age2label(val):
            if age < young_age: return val
            if age >= old_age: return val + 2
            return val + 1

        def gender2label(val):
            if "male" == gender:
                return age2label(val)
            return age2label(val + 3)

        if "incorrect" in mask:
            return gender2label(6)
        if "normal" in mask:
            return gender2label(12)
        return gender2label(0)

pytorch에서 제공하는 여러가지 모델이 있다.
예를 들어 VGG, ResNet, GoogLeNet 등 구현이 되어 있고 심지어 pre-trained 모델을 사용할 수 있다.
origin image에 대해 어떤 모델의 성능이 가장 좋은지 찾으려고 한다.
모델 후보군으로 VGG16, AlexNet, ResNet18, SqueezeNet1_0, DenseNet, Inception_V3, GoogLeNet, shufflenet_v2_x1_0, mobilenet_v2, resnet50_32x4d, wide_resnet50_2, mnanet 정하고 하나씩 학습한다.
18개의 class를 분류해야 하며 이 모델들의 출력 차원은 1000이다.
그래서 마지막 FC layer를 바꿔주었다.
또한 사전 학습되지 않은 모델을 사용하였다.
epoch은 5, batch size는 16, learning_rate는 1e-3, optimizer는 Adam을 사용했다.
cross validation으로 평균 accuracy를 확인하기 보다는 일단 어떤 모델이 좋은지 대략적으로 확인하기 위해 모든 학습 데이터를 사용했다.
매 epoch마다 accuracy를 기록하는 logging 함수를 구현했다.
batch size를 작게 설정해서 그런지 오래걸리는 것 같다.
모델마다 parameter 수가 다르고 origin image 사이즈를 그대로 사용하다보니 높은 batch size를 사용하면 OOM이 발생했다.

To do

  • 가장 좋은 모델 찾아서 집중적으로 학습
    epoch 늘리고 cross validation으로 성능 확인
  • pytorch transform 사용하여 학습
  • 피어세션에서 efficientNet이 좋다고 해서 학습해보기