[Hands-On-Machine Learning]2장 머신러닝 프로젝트 처음부터 끝까지

YJCho·2024년 9월 16일

동아리에서 캐글을 직접 하면서 가장 먼저 들었던 의문은... "대체 EDA가 뭐지?" 라는 것이다. 제대로 된 순서도 모르고 다른 훌륭한 선두자들의 코드를 따라가면서 어영부영 따라갔었다... 순서가 좀 달라진 것 같지만 이제 드디어 제대로 된, 정석적인? 머신러닝 과정을 정리하고자 한다...할 수 있다~!

키보드 바꾸니까 할 맛난다 오예~

진행하는 주요 단계는 아래와 같다! 이걸 먼저 보고 했다면...너무 좋았을 것 같다 ㅠㅠ 핸즈온...왜 이제서야 나에게...

  1. 큰 그림을 본다
  2. 데이터를 구한다(load)
  3. EDA (탐색 및 시각화)
  4. 머신러닝 알고리즘을 위해 데이터 준비
  5. 모델 선택 및 훈련
  6. 모데 미세 튜닝
  7. 솔루션 제시
  8. 시스템 launching, monitoring, 유지보수

🔥2.1 실제 데이터로 작업하기

책에서 여러 공개 데이터 저장소를 소개해주고 있다!
나중에 직접 연습할 때 쓰면 좋을 것 같다!

유명한 공개 데이터 저장소

메타 포털 (공개 데이터 저장소가 나열되어 있는 다른 페이지)

인기 있는 공개 데이터 저장소가 나열되어 있는 다른 페이지

책에서는 StatLib 저장소에 있는 California Housing Prices 데이터를 사용했다! 교육 목적으로 사용하기 위해 범주형 특성을 추가하고 몇 가지는 제외했다고 한다.

🔥2.2 큰 그림 보기

가장 궁금했던 제목이다. 앞으로도 머신러닝 관련 프로젝트 할 때도 가장 중요하게 볼 부분이 아닐까 조심스레 예측해본다!

2.2.1 문제 정의

목적이 무엇인지 정확히 보기...!

모델을 만드는 것이 아니라 이 모델을 통해 얻을 수 있는 무언가가 있을 것이다! 이렇게 목적을 아는 것은 문제를 어떻게 구성할지, 어떤 알고리즘을 선택하고 모델 성능 평가를 어떻게 할지, 튜닝을 위해 얼마 만큼의 노력을 투여할 지 결정하기에 아주 중요한 역할을 한다!

목적을 설정하는 것은 언제나 중요한 핵심인 것 같다. 결국 목적이 있어야, 무엇이든 할 일이 정해진다!

머신러닝에 주입하는 정보를 신호(signal)이라고 한다. Claude Shannon의 정보 이론에 따라 종종 '신호'라고 부른다. 이론에 따르면 신호/잡음 비율이 높은 것이 좋다. (결국 잡음은 적어야 한다는 뜻!)

pipeline(파이프라인)

데이터 컴포넌트(component)들이 연속되어 있는 것을 데이터 파이프라인(pipeline)이라고 한다. 머신러닝 시스템은 파이프라인을 사용하는 일이 매우 흔하다. 보통 비동기적으로 작동하며, 독립적이다.

각 컴포넌트는 많은 데이터를 추출해 처리해서 그 결과를 다른 데이터 저장소로 보낸다. 따라서 컴포넌트 사이의 인터페이스는 데이터 저장소뿐이다.


캘리포니아 주택 문제의 경우, labeled된 훈련 샘플이 잇으니 지도 학습이며, 예측에 사용할 특성이 여러 개이니 다중 회귀(multiple regression)문제, 각 구역마다 하나의 값을 예측하니 단변량 회귀(univariate regression) 문제이다! 또한 데이터가 메모리에 들어갈 만큼 작기에 배치 학습이 적절하다. 데이터가 너무 크면 맵리듀스(MapReduce) 기술을 이용하면 된다!

2.2.2 성능 측정 지표 선택

회귀 문제는 보통 평균 제곱근 오차(Root Mean Square Error)를 사용한다.

RMSE(X,h)=1mi=1m(h(x)(i)y(i))2\mathrm{RMSE}\,(\mathbf{X}, h) = \sqrt{\frac{1}{m}\sum_{i=1}^{m}(h(\mathbf{x})^{(i)}-y^{(i)})^2}

이상치로 보이는 구역이 많다면
평균 절대 오차(Mean Absolute Error) = 평균 절대 편차(Mean Absolute Deviation)를 고려하기도 한다!

MAE(X,h)=1mi=1m(h(x)(i)y(i))2\mathrm{MAE}\,(\mathbf{X}, h) = \frac{1}{m}\sum_{i=1}^{m}\left|(h(\mathbf{x})^{(i)}-y^{(i)})^2 \right|

RMSE와 MAE 모두 예측값의 벡터와 타깃값의 벡터 사이의 거리를 재는 방법이다. 거리 측정엔 에는 여러 가지 norm을 사용할 수 있다!

2.2.3 가정 검사

이 부분은 qa 관련 분야 같다. 여러 가정을 나열하고 검사하는 과정이다. prompt engineering 분야로 보인다.

🔥2.3 데이터 가져오기

새로운 캐글 주제 시작하면 어김없이 했던 일을 하고 있다.
df=pd.read_csv("path") 정말 열심히 사용했던 함수다
df.head() 이것도 단골 함수였다.

df.describe(), value_counts() 등의 다양한 method가 나왔다.

테스트 세트로 훈련한 모델을 테스트 세트를 이용하여 일반화 오차를 추정하면 과대적합이 일어나면서 확실히 일반화된 모델을 얻을 수 없고, 기대한 성능을 얻을 수 없을 것이다!

이런 현상을 데이터 스누핑(data snooping) 편향이라고 한다!

🔥2.4 데이터 이해를 위한 탐색과 시각화

여러 Tip이 있길래 유용한 정보 위주로 정리했다!

  • 지리적 데이터 시각화
    → 산점도 이용! 투명도 조정하는 alpha 옵션을 이용해서 밀집도 파악 더 용이하게 할 수 있음! 여기서는 cmap으로 jet를 썼는데, 무지개색으로 기억하면 될 것 같다. 비즈니스 용으로 딱인 듯하다.

  • 상관관계 조사하기
    → 데이터셋의 크기가 크면 사용하지 못 하는 것 같다. 표준 상관계수(standard correlation coefficient, Pearson의 rr 이라고도 불림)corr() 메서드를 이용해 계산할 수 있다.

    • 상관계수는 -1부터 1까지의 범위를 가지며, 1에 가까우면 강한 양의 상관관계를 가진다는 뜻이다. 1에 가까우면 비례 관계를, -1에 가까우면 반비례 관계를 가진다. 0에 가까우면 선형적인, 즉 상관관계가 없다.

    • Tip❗판다스의 scatter_matrix를 이용해 숫자형 특성 간 산점도를 그리면 상관 관계를 살필 수 있다!❗

    • 상관 계수는 선형적인 상관관계만 측정하기에 비선형적인 관계는 잡을 수 없기에 주의해야 한다! 비선형으로 보일지라도 사실은 의미가 있는 것일 수도 있다는 것!

  • 특성 조합으로 실험하기
    → 여러 가지 조합을 만들어서 상관관계를 확인한다. 컬럼 몇 가지를 조합해서 새로운 값을 만드는 과정으로 생각하면 좋을 것 같다!

🔥2.5 머신러닝 알고리즘을 위한 데이터 준비

이 작업은 자동화해야 한다고 한다!

자동화를 해두면
✅ 데이터 변환 손쉽게 가능
✅ 프로젝트에 재사용 가능한 변환 라이브러리 점진적 구축 가능
✅ 실제 시스템에서 새 데이터 주입 전에 함수를 사용해 변환 가능
✅ 데이터 변환 쉽게 시도 가능 + 베스트 조합 찾기 가능
이렇게 다양한 장점들이 있다!

2.5.1 데이터 정제

항상 데이터에 존재하는 Nan값, 결측값을 처리하는 경우다.

해당 행 또는 열을 지우거나
누락된 값을 채우면 된다 대체(imputation)라고 한다!
dropna(), drop(), fillna() 메서드를 주로 활용한다.

사이킷런에 SimpoleImputer 클래스를 이용하면 좋다! 이 클래서는 각 특성의 중간값을 저장하기에 유용하다. 나중에 시스템이 서비스될 때 새로운 데이터에서 어떤 값이 누락될지 확신할 수 없기에 모든 수치형 특성에 imputer를 적용하는 것이 좋다.

👉 공식문서

2.5.2 텍스트와 범주형 특성 다루기

OrdinalEncoder : 카테고리를 텍스트에서 숫자로 변환해주는 메서드
❗ 이 방식의 큰 문제점은 인접한 두 값이 비슷하다고 생각한다는 점이다.

OneHotEncoder : 카테고리별 이진 특성을 만들어 해결하는 원-핫 인코딩 방식, 새로운 특성을 더미(dummy) 특성이라고 부르기도 한다!

사이킷런에서 OneHotEncoder 출력은 사이파이 희소 행렬 이다

희소 행렬 자체는 내부적으로 0이 아닌 값과 그 위치만 저장하기에 메모리 절약과 계산 속도에서 장점을 가진다. 보통 2D배열처럼 사용할 수있지만, 넘파이 배열로 바꾸려면 toarray() 메서드 호출이 필요하다

아니면 sparse_output=False 설정을 통해 일반적인 넘파이 배열을 반환하도록 할 수 있다!

categories_ : 인스턴스 변수를 사용해 카테고리 리스트 얻기 가능
get_dummies : 판다스에서 범주형 특성을 원-핫 표현으로 바꾸어줌

OneHotEncoderget_dummies와 달리 알 수 없는 카테고리를 감지하고 예외를 발생시킨다. handdle_unknown = ignore 설정을 해두면 알 수 없는 카테고리를 그냥 0으로 나타낼 수 있다!

2.5.3 특성 스케일링 변환

feature scaling
틈만나면 kaggle에서 자주 보이던 정규화가 생각난다.

모든 특성의 범위를 같게 만들어주는 방법
: min-max 스케일링, 표준화(standardization)

min-max 스케일링(=정규화 normalization)
각 특성에 대해서 0~1 범위에 들도록 값을이동, 스케일 조절

MinMaxScaler 에서 feature_range = (-1, 1)를 통해
범위 조정이 가능하다. 보통 신경망에서는 평균이 0인 -1~1 사이 범위가 선호된다고 한다!

표준화(standardization) : 항상 평균이 0
(값 - 평균) / 표준편차

특정 범위로 값을 제한하지 않기에 이상치에 영향을 덜 받는다
(정규화는 특정 범위로 줄여버리기에 이상치도 함께 줄여지는 꼴이다)

StandardScalar가 사이킷런에서 제공되고 있다.

멱법칙 분포(power law distribution)
특성 분포의 꼬리가 아주 길고 두껍다면 특성을 로그값으로 바꿔준다.
보통 population 특성이 대략적으로 멱법칙을 따른다고 한다.
오른쪽 꼬리가 두꺼운 양수 특성의 경우 특성을 제곱근으로 바꾸어 사용

버킷타이징(bucketizing)
분포를 거의 동일한 크기로 자르고, 해당하는 버킷의 인덱스로 바꾸기
ex) 각 값을 백분위로 바꾸기
거의 동일한 크기의 버킷을 사용하면 거의 균등 분포인 특성을 만들 수 있기에 추가적인 스케일링이 필요가 없다. 또한 버킷 개수로 나누어 0~1 범위를 만들수도 있다.

멀티모달 분포(multimodal distribution)
모드(mode)라 불리는 정점이 두 개 이상 나타나는 분포
→ 버킷타이징을 이용하면 도움이 된다.

→ 주요 모드에 대해 특정 모드 사이의 유사도를 나타내는 특성 추가

  • 방사 기저 함수(Radial Basis F**unction) 사용
  • 가우스 RBF가 가장 널리 사용(입력값이 고정 포인트에서 멀어질수록 출력값이 지수적으로 감소), 하이퍼파라미터 감마는 유사도 값이 감소하는 빠르기를 결정

inverse_transform()
역변환을 수행하는 함수, 스케일링 해둔 것을 돌려놓는 역할

2.5.4 사용자 정의 변환기

사용자 정의 변환, 정제 연산, 특성 결합을 위해 작성할 필요가 있음.

사이킷런은 덕 타이핑(duck typing)에 의존하기에 어떤 클래스가 특정 클래스를 상속할 필요가 없다.

2.5.5 변환 파이프라인

사이킷런은 변환을 순서대로 처리하도록 도와주는 Pipeline 클래스를 제공한다.

  • 생성자 : 연속적인 단계를 정의하는 이름/추정기 쌍(2개의 원소 가진 tuple)의 리스트 받음.
  • 이름은 (__) 이걸 포함하지 않으면서 고유하다면 어던 것도 가능
  • (__)은 하이퍼파라미터 튜닝에 사용
  • 추정기는 마지막을 제외하고 모두 변환기여야 함. 변환기, 예측기부터 다른 타입의 추정기까지 무엇이든 가능

🔥2.6 모델 선택과 훈련

- 훈련 세트에서 평가

사이킷런의 mean_squared_error()함수에서 squared = False로 지정하여 RMSE를 계산할 수 있다!

다만, 훈련세트에서만 평가하면 안 된다. 일반화를 위해 훈련에 사용하지 않은 데이터를 이용해야 한다!

- 교차 검증으로 평가

train_test_split 함수를 이용할 수도 있지만,
k-폴드 교차 검증 기능 등을 사용할 수 있다.

사이킷런의 교차 검증 기능은 scoring 매개변수에 (낮을수록 좋은) 비용 함수가 아니라 (클수록 좋은) 효용 함수를 기대한다! 그래서 RMSE의 음숫값을 출력한다.

훈련 오차가 작고 검증 오차가 높으면 과대적합이라 볼 수 있다.

🔥2.7 모델 미세 튜닝

  • 그리드 서치 (GridSearchCV)

    • 탐색하고자 하는 하이퍼파라미터와 시도해볼 값 지정
    • grid_search.best_estimator_ 속성으로 최상의 추정기 얻기 가능
  • 랜덤 서치 (RandomizedSearchCV)

    • 각 반복마다 하이퍼파라미터에 임의의 수를 대입하여 지정한 횟수만큼 평가
    • 하이퍼파라미터 값이 연속적, 또는 값이 많은데 이산적이라면 랜덤 서치는 1000번 실행하면 하이퍼파라미터마다 1000개의 다른 값 탐색
    • 그리드 서치와 달리 10개의 값을 넣는다면, 그리드 서치는 훈련이 10배 더 걸리지만, 랜덤 서치는 탐색 시간이 늘어나지 않는다!
    • 지정한 반복 횟수만큼 실행 가능
  • Scikit Learn과 그리드 서치, 랜덤 서치

    • HalvingRandomSearchCVHalvingGridSearchCV 제공
    • 작동 방식
      • 1) 반복에서 많은 하이퍼파라미터 조합(후보)이 그리드 서치나 랜덤 서치를 통해 생성, 후보들로 교차 검증을 사용해 평가
        • 반복 속도를 높이기 위해 훈련 세트의 작은 일부분에서 훈련되게 하기, 반복 횟수 줄이기 등
      • 2) 몇 번의 반복이 진행된 후 최종 후보들이 전체 자원을 사용해 평가

- 앙상블(ensemble) 방법

  • 최상의 모델을 연결하는 방법이다
  • 여러 방법에서 얻은 예측의 평균을 이용하여 예측하는 방법도 있다!

- 최상의 모델과 오차 분석

  • randomforestRegressor는 정확한 예측을 만들기 위해 각 특성의 상대적인 중요도를 알려준다
    sklearn.feature_selection.SelectFromModel 변환기는 자동으로 가장 덜 유용한 특성을 제거해 준다. feature_importances 속성을 확인하여 가장 유요한 특성을 선택한다!

- 테스트 세트로 시스템 평가

  • 어떤 경우는 오차의 점 추정(point estimate)으로 충분하지 않다
  • scipy.stats.t.interval()을 사용해 일반화 오차의 95% 신뢰 구간(confidence interval) 설정 가능
  • 하이퍼파라미터 튜닝을 많이 했다면 교차 검증을 사용해 측정한 것보다 성능이 조금 낮은 것이 보통이다. (튜닝 자체가 검증 셋에서 잘 작동하도록 맞춰둔 것이기에 그럴 수밖에 없다)

🔥2.8 론칭, 모니터링, 시스템 유지 보수

joblib 라이브러리를 이용하면 모델 저장이 가능하다!

import joblib

joblib.dump(final model, "my_model.pkl"

피클 형태로 저장해주는 것 같다.

모델은 불러올 함수, 클래스 다 불러오고 아래와 같이 load 한다.

final_model_reloaded = joblib.load("my_model.pkl")

new data = [...] # 예측을 새로 만드는 구역
predictions = final_model_reloaded.predict(new_data)

서버가 시작될 때 모델을 로드하는 것이 좋으며, REST API를 통해 모델을 올릴 수도 있다. (이 내용을 1학년 때 봐야 했는데...!!!!)

REST API를 사용하면 주 애플리케이션을 건드리지 안고 모델 업그레이드가 용이하며, load balancing할 수 있기에 규모 확장도 쉽다! 또한 웹 애플리케이션을 python이 아닌 다른 언어를 사용하는 것도 가능하다.

Google의 Vertex AI (구 구글 클라우드 AI, ML 엔진)같은 클라우드에 배포하는 방법도 있다.

배포에서 끝나는 줄 알 았는데 모니터링 코드 작성도 해야한다!

  1. 정기적으로 새로운 데이터를 수집하고 label 달기
  2. 모델을 훈련하고 hyperparameter를 자동으로 미세 튜닝하는 코드 작성, 작업에 따라 매일 또는 매주 자동으로 실행
  3. 업데이트된 test set에서 이전 모델을 평가하는 코드 작성, 성능이 감소하지 않았을 때만 모델이 배포되도록 조절! (테스트 세트의 여러 subset에서 성능 테스트할 수 있도록 하기!)

모델의 입력도 모니터링 해주어야 한다!
ex) 잘못 감지된 신호
모델의 성능이 실제로 감소하기까지 시간이 걸릴 수 있으니, 사전에 input 과정에서 잡아낸다!

마지막으로 중요한 것! 백업이다.
이전 모델로 언제든 roll back 할 수 있도록 준비해야 한다. 또한 이 과정이 되어 있으면 새로운 모델을 이전 모델과 비교하는 것도 가능하다.

🔥2.9 직접 해보기

kaggle 열심히 하자...! 고수준 알고리즘을 탐색하느라 전체 프로세스 구축을 못 하는 것보다는 서너 개의 알고리즘을 이용해서 전체 프로세스를 올바르게 구축하는 것이 좋다!

profile
호로록

0개의 댓글