페이지

2022년 7월 26일 화요일

3.6.3 데이터 준비

 상이한 스케일을 가진 값을 신경망에 주입하면 문제가 됩니다. 네트워크가 이런 다양한 데이터에 자동으로 맞추려고 할 수 있지만 이는 확실히 학습을 더 어렵게 만듭니다. 이런 데이터를 다룰 때 대표적인 방법은 특성별로 정규화를 하는 것입니다. 입력 데이터에 있는 각 특성(입력 데이터 행렬의 열)에 대해서 특성의 평균을 빼고 표준 편차로 나눕니다. 특성의 중앙이 0 근처에 맞추어지고 표준 편차가 1이 됩니다. 넘파이를 사용하면 간단하게 할 수 있습니다.

    mean = train_data.mean(axis=0)

    train_data -= mean

    std = train_data.std(axis=0)

    train_data /= std

    

    test_data -= mean

    test_data /= std

테스트 데이터를 정규화할 때 사용한 값이 훈련 데이터에서 계산한 값임을 주목하세요. 머신러닝 작업 과정에서 절대로 테스트 데이터에서 계산한 어떤 값도 사용해서는 안됩니다. 데이터 정규화처럼 간단한 작업조차도 그렇습니다.

2022년 7월 25일 월요일

3.6.1 보스턴 주택 가격 데이터셋

 1970년 중반 보스턴 외곽 지역의 범죄율, 지방세율 등의 데이터가 주어졌을 때 주택 가격이 중간 값을 예측해 보겠습니다. 여기서 사용할 데이터셋은 이전 2개의 예제와 다릅니다. 데이터 포인트가 506개로 비교적 개수가 적고 404개는 훈련 샘플로, 102개는 테스트 샘플로 나눠어 있습니다. 입력 데이터에 있는 각 특성(feature)(예를 들어 범죄율)은 스케일이 서로 다릅니다. 어떤 값은 0과 1사이의 비율을 나타내고, 어떤 것은 1과 12 사이의 값을 가지거나 1과 100사이의 값을 가집니다.

    from keras.datasets import boston_housing

    

    (train_data, train_targets), (test_data, test_targets) = 

    boston_housing.load_data()

데이터를 살펴보겠습니다.

>>> train_data.shape

(404, 13)

>>> test_data.shape

(102, 13)

여기서 볼 수 있듯이 404개의 훈련 샘플과 102개의 테스트 샘플이 있고 모두 13개의 수치 특성이 있습니다. 이 특성들은 1인당 범죄율, 주택당 평균 방의 개수, 고속도로 접근성 등입니다.

타깃은 주택의 중간 가격으로 천 달러 단위입니다.

>>> train_targets

[ 15.2, 42.3, 50., ... 19.4, 19.4, 29.1]

이 가격은 일반적으로 1만 달러에서 5만 달러 사이입니다. 저렴하게 느껴질 텐데 1970년대 중반이라는 것을 기억하세요. 아직 인플레이션에 영향을 받지 않은 가격입니다.

3.6 주택 가곅 예측: 회귀 문제

 앞의 두 예제는 분류 문제입니다. 입력 데이터 포인트의 개별적인 레이블 하나를 예측하는 것이 목적입니다. 또 다른 종류의 머신 러닝 문제는 개별적인 레이블 대신에 연속적인 값을 예측하는 회귀(regression)입니다. 예를 들어 기상 데이터가 주어졌을 때 내일 기온을 예측하거나, 소프트웨어 명세가 주어졌을 때 소프트웨어 프로젝트가 완료될 시간을 예측하는 것입니다.

회귀와 로지스틱 회귀(logistic regression)알고리즘을 혼동하지 마세요. 로지스틱 회귀는 회귀 알고리즘이 아니라 분류 알고리즘입니다.


3.5.9 정리

 다음은 이 예제에서 배운 것들 입니다.

1) N개의 클래스로 데이터 포인트를 분류하려면 네트워크의 마지막 Dense층의 크기는 N이어야 합니다.

2) 단일 레이블, 다중 분류 문제에서는 N개의 클래스에 대한 확률 분포를 출력하기 위해 softmax 활성화 함수를 사용해야 합니다.

3) 이런 문제에는 항상 범주형 크로스엔트로피를 사용해야 합니다. 이 함수는 모델이 출력한 확률 분포와 타깃 분포 사이의 거리를 최소화합니다.

4) 다중 분류에서 레이블을 다루는 두 가지 방법이 있습니다.

    - 레이블을 범주형 인코딩(또는 원-핫 인코딩)으로 인코딩하고 categorical_crossentropy손실 함수를 사용합니다.

    - 레이블을 정수로 인코딩하고 sparse_categorical_crossentropy 손실 함수를 사용합니다.

5)많은 수의 범주를 분류할 때 중간층의 크기가 너무 작아 네트워크에 정보의 병목이 생기지 않도록 해야 합니다.

3.5.8 추가 실험

 1) 더 크거나 작은 층을 사용해 보세요. 32개의 유닛, 128개의 유닛 등

2) 여기에서 2개의 은닉 층을 사용했습니다. 1개나 3개의 은닉 층을 사용해 보세요.

3.5.7 충분히 큰 중간층을 두어야 하는 이유

 앞서 언급한 것 처럼 마지막 출력이 46차원이기 때문에 중간층의 히든 유닛이 46개보다 많이 적어선느 안 됩니다. 46차원보다 훨씬 작은 중간층(예를 들어 4차원)을 두면 정보의 병목이 어떻게 나타나는지 확인해 보겠습니다.

    model = models.Sequential()

    model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))

    model.add(layers.Dense(4, activation='relu'))

    model.add(layers.Dense(46, activation='softmax'))


    model.compile(optimizer='rmsprop',

                        loss='categorical_crossentropy',

                        metrics=['accuracy'])

    model.fit(partial_x_train,

                partial_y_train,

                epochs=20,

                batch_size=128,

                validation_data=(x_val, y_val))

검증 정확도의 최고 값은 약 71%로 8% 정도 감소되었습니다. 이런 손실의 원인 대부분은 많은 정보(클래스 46개의 분할 초평면을 복원하기에 충분한 정보)를 중간층의 저 차원 표현 공간으로 압축하려고 했기 때문입니다. 이 네트워크는 필요한 정보 대부분을 4차원 표현 안에 구겨 넣었지만 전부는 넣지 못했습니다.

2022년 7월 23일 토요일

3.5.6 레이블과 손실을 다루는 다른 방법

 앞서 언급한 것처럼 레이블을 인코딩하는 다른 방법은 다음과 같이 정수 텐서로 변환하는 것입니다.

    y_train = np.array(train_labels)

    y_test = np.array(test_labels)

이 방식을 사용하려면 손실 함수 하나만 바꾸면 됩니다. 코드 3-21에 사용된 손실 함수 categorical_crossentropy는 레이블이 범주형 인코딩되어 있을 것이라고 기대합니다. 정수 레이블을 사용할때는 sparse_categorical_crossentropy 를 사용해야 합니다.

    model.comile(optimizer='rmsprop',

                    loss='sparse_categorical_crossentropy',

                    metrics=['acc'])

이 손실 함수는 인터페이스만 다를 뿐이고 수학적으로 categorical_crossentropy와 동일합니다.