Category: Python

  • results는 사용할 수 없어요

    조건이 좀 제한점이 있는데 results라는 이름의 리스트를 사용할 수 없는 경우가 있다.

    • PyTorch 이용할 것
    • def 로 정의된 함수에서 Tensor 이용할 것. 그러니까 모델을 이용한다는 뜻.
  • ipynb 파일을 py로 변환하기

     jupyter nbconvert --to script *.ipynb

    웹에서 하는 방법이 있으나 서버로 파일을 옮겨야 하는 불편함이 있다. 저렇게 커맨드 명령어로 하면 바로 생성된다.

  • Accuracy plot을 위한 CSV 파일 저장

    논문은 예쁜 그림이 있어야 한다. 그래서 따로 그림을 그리기 위하여 결과값을 별도로 저장하여 CSV로 저장한다.

    • global 과 local 변수가 분리되고 서로 간섭이 어렵기도 하고 안되는 부분도 있다.
    • 학습과 평가하는 함수 내부에서 결과를 모두 모아서 CSV로 저장하는 방법을 이용한다.
    import csv

    학습 시키는 함수 내부 상단에 header로 첫 자료를 입력시킨다. 그리고 진행 과정마다 계속 마지막에 추가시킨다. accuracy는 tensor로 저장되므로 숫자 부분만 가져오기 위해서 .tolist()를 붙인다. CSV 저장하는 부분은 파이썬 홈페이지 예시에서 동일하게 가져왔다.

    def train_model(model, criterion, optimizer, epochs):
        ...
        result_list = [['epoch', 'phase', 'loss', 'accu']]
        ...
        for epoch in range(epochs):
            for phase in ['train', 'val']:
                ...
                result_list.append([epoch, phase, epoch_loss, 
                                    epoch_acc.tolist()])
    
        ...
        with open('result.csv', 'w') as f:
            writer = csv.writer(f)
            writer.writerows(result_list)
        return model
  • 데이터 분할

    train, val, test 등으로 자료를 분할해서 사용할 수 밖에 없는 여건이 대부분인 경우가 많다. 이러한 3개가 아니면 train, val 등으로 2개로 나누어서 사용하기도 한다. 자료를 분할하는 방법은 여러가지가 있는데, class가 있는 경우에도 비율을 유지하며 분할하는 것에 대한 것은 찾지 못했다. PyTorch에서 제공하는 함수 중에서 torch.utils.data.SubsetRandomSampler이 가장 비슷한 것 같은데 예시를 보면 왠지 내가 원하는 기능이 아닌 것 같다.

    Class마다 개별적으로 코딩해서 넣어주어야 하지만, 나에게 가장 맞는 방법을 구현해 보았다.

    일단 파일 목록을 섞어 준다. 그리고 코드 오류를 확인하기 위하여 데이터셋을 줄일 수 있도록 한다. 예시는 0.02로 들었다.

    props = 0.02
    file_A = os.listdir('...')
    numpy.random.seed(21)
    numpy.random.shuffle(file_A)

    train, val, test 나눌 위치를 정한다. 임의로 섞었으니 앞부분부터 선택해도 상관없을 것이다.필요한 것은 train과 val 사이의 숫자와 val과 test 사이의 숫자이다. 정수에서 0~1 실수를 곱하는 것이니 소수점이 나오지만, 데이터는 정수이니 이와 관련된 부분을 고려한다.

    data_split_rate = (0.8, 0.1, 0.1)
    train_idx = int(len(file_A) * data_split_rate[0] * props)
    val_idx   = train_idx + int(len(file_A) * data_split_rate[1] * props)
    test_idx = int(len(file_A) * props)

    이제 0부터 진행하면서 기준 위치를 지나면 복사할 폴더를 변경하도록 해준다.

    for i, file_name in enumerate(file_A):
        if i < train_idx:
            os.system('cp FROM경로'+file_name+' TO_train/경로')
        if i >= train_idx and i < val_idx:
            os.system('cp FROM경로'+file_name+' TO_val/경로')
        if i >= val_idx and i < test_idx:
            os.system('cp FROM경로'+file_name+' TO_test/경로')