페이지

2022년 7월 29일 금요일

4.3.1 신경망을 위한 데이터 전처리

 데이터 전처리 목적은 주어진 원본 데이터를 신경망에 적용하기 쉽도록 만드는 것입니다. 벡터화(vectorization), 정규화(normalization), 누락된 값 다루기, 특성 추출 등이 포함됩니다.


- 벡터화

신경망에서 모든 입력과 타깃은 부동 소수 데이터로 이루어진 텐서여야 합니다(또는 특정 경우에 정수로 이루어진 테서입니다). 사운드, 이미지, 텍스트 등 처리햐야 할 것이 무엇이든지 먼저 텐서로 벼ㅑㄴ환해야 합니다. 이 단계를 데이터 벡터화(data vectorization)라고 합니다. 예를 들어 이전에 나온 2개의 텍스트 분류 예에서 텍스트를 (단어 시퀀스를 의미하는) 정수 리스트로 변환했습니다. 그다음 원-핫 인코딩을 사용하여 float32타입 데이터로 이루어진 텐서로 바꾸었습니다. 숫자 이미지 분류와 주택 가격 예측의 예에서는 이미 데이터가 벡터 형태로 주어졌으므로 이 단계를 건너 뛰었씁니다.


- 값 정규화

숫자 이미지 분류 예에서 이미지 데이터를 그레이스케일 인코딩 0-255 사이의 정수로 인코딩했습니다. 이 데이터를 네트워크에 주입하기 전에 float32 타입으로 변경하고 255로 나누어서 최종적으로 0-1 사이의 부동 소수 값으로 만들었습니다. 주택 가격을 예측할 때는 특성들의 범위가 제각각이었습니다. 어떤 특성은 작은 부동 소수 값이고 다른 특성은 매우 큰 정수 값을 가졌습니다. 이 데이터를 네트워크에 주입하기 전에 각 특성을 독립적으로 정규화하여 평균이 0이고 표준편차가 1이 되도록 만들었습니다.

일반적으로 비교적 큰 값(예를 들어 네트워크의 가중치 초깃값보다 훨씬 큰 여러 자릿수를 가진 정수)이나 균일하지 않은 데이터(옐르 들어 한 특성의 범위는 0-1이고 다른 특성은 100-200인 데이터)를 신경망에 주입한느 것은 위험합니다. 이렇게 하면 업데이트할 그래디언트가 컼져 네트워크가 수렴하는 것을 방해합니다. 네트워크를 쉽게 학습시키려면 데이터가 다음 특징을 따라야 합니다.

1) 작은 값을 취합니다. 일반적으로 대부분의 값이 0-1 사이여야 합니다.

2) 균일해야 합니다. 즉 모든 특성이 대체로 비슷한 범위를 가져야 합니다.

추가적으로 다음에 나오는 엄격한 정규화 방법은 꼭 필수적이지는 않지만(예를 들어 숫자 이미지 분류 예에서는 사용하지 않습니다) 자주 사용되고 도움이 될수 있습니다.

3) 각 특성별로 평균 0이 되도록 정규화합니다.

4) 각 특성별로 표준 편차가 1이 되도록 정규화합니다.

넘파이 배열에서 방법은 간단합니다.

x -= x.mean(ㅁ탼=0) .................. x가 (샘플, 특성)크기인 2D 행렬이라고 가정합니다.

x /= x.std(axis=0)


- 누락된 값 다루기

이따름 데이터에 값이 누락된 경우가 있습니다. 예를 들어 주택 가격 예측 문제에서 첫 번째 특성(데이터에서 인텍스가 0인컬럼)은 1인당 범쥐율입니다.

이 특성이 모든 샘플에 들어 있지 않으면 어떻게 될까요? 훈련 데이터나 테스트 데이터에 누락된 값이 포함됩니다. 일반적으로 신경망에서 0이 사건에 정의된ㄴ 의미 있는 값이 아니라면 누락된 값을 0으로 입력해도 괜찮습니다. 네트워크가 0이 누락된 데이터를 의미한다는 것을 학습하면 이 값을 무시하기 시작할 것입니다.

테스트 데이터에 누라된 값이 포함될 가능성이 있다고 가정합시다. 하지만 네트워크가 누락된 값이 없는 데이터에서 훈련되었다면 이 네트워크는 누라된 값을 무시하는 법을 알지 못합니다. 이런 경우에는 누락된 값이 있는 훈련 샘플을 고의적으로 만들어야 합니다. 훈련 샘플의 일부를 여러별 복사해서 테스트 데이터에서 빠질 것 같은 즉성을 제거합니다.

4.3 데이터 전처리, 특성 고학, 특성 학습

 모델 평가 외에도 모델 개발로 들어가기 전에 우리가 넘어야 할 중요한 질문이 있습니다. 신경만에 입력 데이터와 타깃 데이터를 주입하기 전에 어떻게 준비해야 할까요? 많은 데이터 전처리와 특성 공학 기법은 특정 도메인에 종속적입니다(예를 들어 텍스트 데이터나 이미지 데이터에 특화되어 있습니다). 이 후 장에서 실전 문제를 보면서 이에 대해 다루겠습니다. 여기서는 모든 종류의 데이터에 공통되는 기본 사항을 살펴보겠습니다.

4.2.2 기억해야 할것

 평가 방식을 선택할 때 다음 사항을 유념해야 합니다.

1) 대표성 있는 데이터: 훈련 세트와 데이터 세트가 주어진 데이터에 대한 대표성이 있어야 합니다. 옐르 들어 숫자 이미지를 분류하는 문제에서 샘플 배열이 클래스 순서대로 나영되어 있다고 가정합시다. 이 배열의 처음 80%를 훈련 세트로 나머지 20%를 테스트 세트로 만들면 훈련 세트에는 0-7 숫자만 담겨 있고 테스트 세트에는 8-9 숫자만 담기게 됩니다. 어처구니없는 실수처럼 보이지만 놀랍게도 자주 일어나는 일입니다. 이런 이유 때문에 훈련 세트와 테스트 세트로 나누기 전에 데이터를 무작위로 섞는 것이 일반적입니다.

2) 시간의 방향: 과거로부터 미래를 예측하려고 한다면(예를 들어 내일의 날씨, 주식 시세등) 데이터를 분할하기 전에 무작위로 섞어서는 절대 안 됩니다. 이렇게 하면 미래의 정보가 누설되기 때문입니다. 이런 문제에서는 훈련 세트에 있는 데이터보다 테스트 세트에 있는 모든 데이터가 미래의 것이어야 합니다.

3) 데이터 중복: 한 데이터셋에 어떤 데이터 포인트가 두 번 등장하면(실제 데이터셋에서 아주 흔한 일입니다.) 데이터를 섞고 훈련 세트와 검증 세트로 나누었을 때 훈련 세트와 검증 세트에 데이터 포인트가 중복될 수 있습니다. 이로 인해 훈련 데이터의 일부로 테스트하는 최악의 경우가 됩니다. 훈련 세트와 검증 세트가 중복되지 않는지 확인하세요.

4.2.1 훈련, 검증, 데스트 세트

 모델 평가의 핵심은 가용한 데이터를 항상 훈련,  검증, 테스트 3개의 세트로 나누는 것입니다. 훈련 세트에서 모델을 훈련하고 검증 세트에서 모델을 평가합니다. 모델을 출시할 준비가 되면 테스트 세트에서 최종적으로 따 한 번 모델을 테스트 합니다.

훈련 세트와 테스트 세트 2개를 사용하면 어떨까요? 훈련 세트에서 훈련하고 테스트 세트에서 평가한느 것이죠. 훨씬 간단하네요!

이렇게 하지 않는 이유는 모델을 개발할 때 항상 모델의 설정을 튜닝하기 때문입니다. 예를 들어 층의 수나 층의 유닛 수를 선택합니다(이런 파라미터를 네트워크의 가중치와 구분하기 위해 하이퍼파라미터(hyperparameter)라고 부릅니다). 검증 세트에서 모델의 성능을 평가하여 이런 튜닝을 수행합니다. 본질적으로 이런 튜닝도 어떤 파라미터 공간에서 좋은 설정을 찾는 학습입니다. 결국 검증 세트의 성능을 기반으로 모델의 설정을 튜닝하면 검증 세트로 모델을 직접 훈련하지 않더라도 빠르게 검증 세트에 과대적합될 수 있습니다.

이 현상의 핵슴은 정보 누설(Information leak)개념에 있습니다. 검증 세트의 모델 성능에 기반하여 모델의 하이퍼파라미터를 조정할 때마다 검증 데이터에 관한 정보가 모델로 새는 것입니다. 하나의 파라미터에 대해서 단 한 번만 튜닝한다면 아주 적은 정보가 누설됩니다. 이런 검증 세트로는 모델을 평가할 만합니다. 하지만 한 번 튜닝하고 나서 검증 세트에 평가한 결과를 가지고 다시 모델을 조정하는 과정을 여러 번 반복하면, 검증 세트에 관한 정보를 모델에 아주 많이 노출시키게 됩니다.

결국 검증 데이터에 맞추어 최적화했기 때문에 검증 데이터에 의도적으로 잘 수행되는 모델이 만들어집니다. 검증 데이터가 아니고 완전히 새로운 데이터에 대한 성능이 관심 대상이라면 모델을 평가하기 위해 이전에 본 적 없는 완전히 다른 데이터셋을 사용해야 합니다. 바로 테스트 세트입니다. 모델을 간접적으로다도 테스트 세트에 대한 어떤 정보도 얻어서는 안됩니다. 테스트 세트 성능에 기초하여 튜닝한 모델의 모든 설정은 일반화 성능을 왜곡시킬 것입니다.

데이터를 훈련, 검증, 테스트 세트로 나누는 것은 간단해 보일 수 있지만 데이터가 적을 때는 몇 가지 고급 기법을 사용하면 도움이 됩니다. 대표적인 세 가지 평가 방법인 단순 홀드아웃 검증(hold-out validation), K-겹 교차 검증(K-fold cross-validation), 셔플링(shuffling)을 사용한 반복 K-겹 교차 검증(iterated K-fold cross-validation)을 살펴보겠습니다.


- 단순 홀드아웃 검증

데이터의 일정량을 테스트 세트로 떼어 놓습니다. 남은 데이터에서 훈련하고 테스트 세트로 평가합니다. 앞 절에서 설명했듯이 정보 누설을 막기 위해 테스트 세트를 사용하여 모델을 튜닝해서는 안 됩니다. 이런 이유로 검증 세트로 따로 떼어 놓아야 합니다.

    num_validation_sample = 10000

    np.random.shuffle(data)  ....................... 데이터를 섞는 것(셔플링)이 일반적으로 좋습니다.

    data = data[num_validation_samples:]


    training_data = add[:] ...................... 훈련 세트를 만듭니다.

    

    model = get_model()                                                훈련 세트에서 모델을              

    model.train(training_data)                                           훈련하고 검증 세트로

    validation_score = model.evaluate(validation_data)  ........      평가합니다.


    # 여기에서 모델을 튜닝하고,

    # 다시 훈련하고, 평가하고, 또 다시 튜닝하고 ........

    model = get_model()                                                 하이퍼파라미터 튜닝이 끝나면

    model.train(np.concatenate([training_data, validation_data]))  테스트 데이터를 제외한 모든

    test_score = model.evaluate(test_data)         데이터를 사용하여 모델을 다시 훈련시킵니다.


이 평가 방법은 단순해서 한 가지 단점이 있습니다. 데이터가 적을 때는 검증 세트와 테스트 세트의 샘플이 너무 적어 주어진 전체 데이터를 통계적으로 대표하지 못할 수 있습니다. 쉽게 일르 확인할 수 있습니다. 다른 난수 초깃값으로 셔플링해서 데이터를 나누었을 때 모델의 성능이 매우 달라지면 바로 이 문제입니다. 다음에 이야기할 K-겹 교차 검증과 반복 K-겹 교차 검증이 이 문제를 해결할 수 있습니다.


K-겹 교차 검증

이 방식에서는 데이터를 동일한 크기를 가진 K개 분할로 나눕니다. 각 분할 i에 대해 남은 K-1 개의 분할로 모델을 훈련하고 분할 i에서 모델을 평가합니다. 최종 점수는 이렇게 얻은 K개의 점술르 평균합니다. 이 방법은 모델의 성능이 데이터 분할에 따라 편차가 클 때 도움이 됩니다. 홀드 아웃 검증처럼 이 방법은 모델의 튜닝에 별개의 검증 세트를 사용하게 됩니다.

    k = 4

    num_validation_samples = len(data) // k


    np.random.shuffle(data)

    validation_scores = []

    for fold in range(k):

        validation_data = data[num_validation_samples * fold:

            num_validation_samples * ( fold +1)]            ......... 검증 데이터 부분을 선택합니다.

        training_data = data[:num_validation_samples * fold] + ..... 남은 데이터를 훈련 데이터로

            data[num_validationi_samples * (fold + 1):]    ..... 사용합니다. 리스트에서 + 연산자

                                                     ...... 는 두 리스트를 더하는 것이 아니고 연결합니다.

        model = get_mode() .......훈련이 되지 않은 새로운 모델을 만듭니다.

        model.train(training_data)

        validation_score = model.evaluate(validation_data) 

        validation_scores.append(validation_score)

    validation_score = np.average(validation_scores) ...검증 점수: K개 폴드의 검증 점수 평균

    

    model = get_model()                  ........ 테스트 데이터를 제외한 전체 데이터로

    model.train(data)                       ........ 최종 모델을 훈련합니다.

    test_score = model.evaluate(test_data)


- 셔플링을 사용한 반복 K-겹 교차 검증

이 방법은 비교적 가용 데이터가 작고 가능한 정확하게 모델을 평가하고 할 때 사용합니다. 캐글 경연에서는 이 방법이 아주 크게 도움이 됩니다. 이 방법은 K-겹 교차 검증을 여러 번 적용하기되 K개의 분할로 나누기 전에 매번 데이터를 무작위로 섞습니다. 최종 점수는 모든 K-겹 교차 검증을 실행해서 얻은 점수의 평균이 됩니다. 결국 P * K개 (P는 반복횟수)의 모델을 훈련하고 평가하므로 비용이 매우 많이 듭니다.


4.2 머신 러님 모델 평가

 3장에서 본 3개의 예제에서 데이터를 훈련 세트, 검증 세트, 테스트 세트로 나누었습니다. 훈련에 사용된 동일한 데이터로 모델을 평가하지 않는 이유는 금방 드러났습니다. 몇 번의 에포크 후에 3개의 모델이 모두 과대적합되기 시작했습니다. 즉 훈련 데이터의 성능에 비해 처음 본 데이터에 대한 성능이 좋아지지 않습니다(또는 더 나빠집니다). 반면에 훈련 데이터의 성능은 훈련이 진행될 수록 항상 증가됩니다.

머신 러닝의 목표는 처음 분 데이터에서 잘 작동하는 일반화된 모델을 얻는 것입니다. 여기에서 과대적합은 주요 장애물입니다. 관측할 수 있는 것만 제어할 수 있으므로 모델의 일반화 성능에 대한 신뢰할 수 있는 측정 밥업이 아주 중요합니다. 다음 절에 과대적합을 완화하고 일반화를 최대화하기 위한 전략을 살펴보겠습니다. 이 절에서는 일반화, 즉 머신 러닝 모델의 성능을 어떻게 측정하는지에 집중합니다.

2022년 7월 28일 목요일

4.1.4 강화 학습

 오랫동안 간과되었던 강화 학습(reainforcement learning)은 구글 딥마인드(DeepMind)가 아타리(Atri)게임 플레이를 학습하는 데 성공적으로 적용하면서 최근에 많은 관심을 받기 시작했습니다(그 이후 최고 수준의 바둑 실력을 학습했습니다). 강화 학습에서 에이전트(agent)는 환경에 대한 정보를 받아 보상을 최대화하는 행동을 선택하도록 학습됩니다. 옐르 들어 강화 학습으로 훈련된 신경망은 비디오 게임 화면을 입력으로 받고 게임 점수를 최대화하기 위한 게임 내의 행동을 축력할 수 있습니다.

현재 강화 학습은 대부분 연구 영역에 속해 있고 게임 이외에 실제적인 성공 사례는 아직 없습니다. 하지만 때가 되면 강화 학습이 실제 세상의 많은 애플리케이션을 대체할 것으로 기대하고 있습니다. 이런 애플리케이션에서 자율 주행 자동차, 자원 과리, 교육 등이 있습니다. 아마 그때가 왔거나 이제 곧 올 것입니다.

분류와 회귀에서 사용하는 용어

분류와 회귀에는 븍별한 용어가 많습니다. 이전 예제에서 일부 용어를 보았고 앞으로 어어지는 장들에서 더 많이 등장합니다. 이런 용어들은 머신 러닝에 특별화된 구체적인 정의를 가지므로 친숙해야 합니다.

1) 샘플 또는 입력: 모델에 주입될 하나의 데이터 포인트

2) 예측 또는 출력: 모델로부터 나오는 값

3) 타깃: 정답, 외부 데이터 소스에 근거하여 모델이 완벽하게 예측해야 하는 값

4) 예측 오차 또는 손실 값: 모델의 예측과 타깃 사이의 거리를 측정한 값

5) 클래스: 분류 문제에서 선택할 수 있는 가능한 레이블의 집합. 예를 들어 고양이와 강아지 사진을 분류할 때 클래스는 '고양이', '강아지' 2개 입니다.

6) 레이블: 분류 문제에서 클래스 할당의 구체적인 사례. 예를 들어 사진 #123에 '강아지'클래스가 들어 있다고 표시 한다면 '강아지'는 사진 #1234의 레이블이 됩니다.

7) 참 값(ground-truth)또는 꼬리표(annotation): 데이터셋에 대한 모든 타깃. 일반적으로 사람에 의해 수집됩니다.

8) 이진 분류: 각 입력 샘플이 2개의 배타적인 범주로 구분되는 분류 작업

9) 다중 분류: 각 입력 샘플이 2개 이상의 범주로 구분되는 분류 작업. 예를 들어 손글씨 숫자 분류를 말합니다.

10)다중 레이블 분류: 각 입력 샘플이 여러 개의 레이블에 할당될 수 있는 분류 작업. 예를 들어 하나의 이미지에 고양이와 강아지가 모두 들어 있을 때는 '고양이'레이블과 '강아지'레이블을 모두 할당해야 합니다. 보통 이미지마다 레이블의 개수는 다릅니다.

11) 스칼라 회귀: 타깃이 연속적인 스칼라 값인 작업. 주택 가격 예측이 좋은 예입니다. 각기 다른 타깃 가격이 연속적인 공간을 형성합니다.

12) 벡터 회귀: 타깃이 연속적인 값의 집합인 작업, 예를 들어 연속적인 값으로 이루어진 벡터입니다.(이미지에 있는 경계 상자의 좌표 같은) 여러 개의 값에 대한 회귀를 한다면 벡터 회귀입니다.

13) 미니 배치 또는 배치: 모델에 의해 동시에 처리되는 소량의 샘플 묶음(일반적으로 8개에서 128개 사이). 샘플 개수는 GPU의 메모리 할당이 용이하도록 2의 거듭제곱으로 하는 경우가 많습니다. 훈련할 때 미니 배치마다 한 번씩 모델의 가중치에 적용할 경사 하강법 업데이트 값을 계산합니다.

4.1.3 자기 지도 학습

 자기 지도 학습(self-supervised learning)은 지도 학습의 특별한 경우지만 별도의 범주로 할 만큼 충분히 다릅니다. 자기 지도 학습은 지도 학습이지만 사람이 만든 레이블을 사용하지 않습니다. 즉 학습 과정에 사람이 개입하지 않는 지도 학습이라고 생각할 수 있습니다.(학습이 무언가에 지도되어야 하므로) 레이블이 여전히 필요하지만 보통 경험적인 알고리즘(heuristic algorithm)을 사용해서 입력 데이터로 부터 생성합니다. 예를 들어 오토인코더(autoencoder)가 잘 알려진 자기 지도 학습의 예입니다. 여기에서 생성된 타깃은 수정하지 않은 원본 입력입니다. 같은 방식으로 지난 프레임이 주어졌을 때 비디오의 다음 프레임을 예측하는 것이나, 이전 단어가 주어졌을 때 다음 단어를 예측하는 것이 자기 지도학습의 예입니다( 이 경우에는 미래의 입력 데이터로 부터 지도되기 때문에 시간에 따른 지도학습(temporally superviesed learnintg)입니다). 지도 학습, 자기 지도  학습, 비지도학습의 구분은 가끔 모호할 수 있습니다. 이 범주들은 명확한 경계가 없고 연속적입니다. 자기 지도 학습 메커니즘과 애플리케이션 측면 중 어디에 중점을 두는지에 따라 지도 학습 또는 비지도 학습으로 재해석 될 수 있습니다.

지도 학습이 광범위한 산업계의 애플리케이션에 적용되어 오늘날 딥러닝의 대부분을 차지하고 있기 때문에 이 책에서는 특히 지도학습에 집중하겠ㅅ브니다. 책의 후반부에서 자기 지도 학습에 대해 잠깐 살펴봅니다.