[캐글로 시작하는 머신러닝, 딥러닝] 8. 머신러닝
👉🏻 지난시간에 딥러닝 돌린 결과
강사님
나
🧩 시각적으로 살펴보기
- 모델 학습 시킬 때 history변수에 넣었음
강사님 ver
- 강사님 그래프 기준에서 15번 넘어가면 별 차이가 없음
- validation을 통해 중간중간 점검해보니 튀는 구간이 있지만 전반적으로 낮은 수준으로 유지됨
왜 강사님과 다른 결과가 나왔을까?
딥러닝 모델의 결과가 다르게 나올 수 있는 이유는 여러 가지가 있을 수 있습니다. 다음은 가능한 원인 몇 가지입니다:
- 랜덤 초기화 (Random Initialization): 딥러닝 모델은 초기 가중치를 랜덤으로 설정하고 학습을 시작합니다. 따라서 같은 코드와 데이터를 사용하더라도 모델이 다르게 초기화되면 결과가 다를 수 있습니다.
- 하드웨어 차이: 학습 중인 하드웨어 환경이나 GPU의 성능 차이도 결과에 영향을 미칠 수 있습니다. GPU의 종류, 메모리 크기 등을 확인해보세요.
- 데이터 전처리의 차이: 데이터 전처리 과정에서 실수가 있을 수 있습니다. 데이터를 정규화하거나 다르게 처리한 경우 결과에 영향을 줄 수 있습니다.
- 하이퍼파라미터 튜닝: 학습률, 배치 크기, 에포크 수 등의 하이퍼파라미터를 다르게 설정한 경우 결과가 달라질 수 있습니다.
- 버전 차이: 사용하는 딥러닝 프레임워크나 라이브러리의 버전이 다르면 결과가 달라질 수 있습니다. 코드의 호환성을 확인하세요.
- 데이터 분할의 차이: 학습 데이터와 검증 데이터를 나누는 방식이나 비율이 다를 경우 결과가 달라질 수 있습니다.
🧩 예측하기
- 모형을 학습한 뒤 테스트데이터로 예측
- 우리가 만든 모형을 가지고 test데이터에 있는 독립변수들에 있는 데이터로 예측
👉🏻 머신러닝
- 앞서 해본 딥러닝은 사람이 학습하는 방법을 흉내낸, 인공 신경망 기반의 기계학습
- 딥러닝도 머신러닝의 일종
- 머신러닝은 기계학습인데, 인공신경망 기반이 아니라 별도의 알고리즘을 통해 기계가 학습하는 것
🧩 RMSE
- 각 모형을 돌렸을 때 실제값과 예측값의 정확도를 비교하는 방법 중 RMSE를 통해서 모형을 평가
- 라이브러리도 존재함
- MSE: 실제값과 예측값 간의 차이를 나타냄
- 여기에 루트를 씌우면 RMSE
- 함수를 통해 RMSE 계산
- np.sqr(): 넘파이의 루트 명령어
- mse를 통해 모형이 예측한 값과 실제 값을 비교하고 거기에 np.sqr로 루트를 씌운 값을 리턴
- 1039가 나왔다
- RMSE가 높다는 것은 실제 값과 예측값 간의 차이가 크다는 것.. 즉 좋지 않은 모델임
- 어디부터 잘못된걸까..
- 강사님은 277
- RMSE가 낮을 수록 좋다
🧩 랜덤 포레스트
- 딥러닝을 통해서 똑똑한 모형 하나를 만들었음
- Forest = 숲
- 수천개의 똑똑한 모형보다 약간 부족한 여러가지 모형을 만들어서 그 모형들의 값을
- 평균내거나
- 투표를 하거나
- 등의 방법으로 성능을 높임
- 앙상블 기법이 적용됨
- 병렬로, 한꺼번에 모형을 만듦
- 여러가지 옵션이 있고 아무것도 안 넣어도 돌아가긴 함
- 우리는 n_estimator
- 약한 모형 100개를 가지고 평균을 내달라
- 매번 돌릴 때 마다 값이 다르면 안되니까 random_state지정
- rf 모형을 돌리는데 훈련용 데이터 독립변수와 훈련용 데이터 종속변수(자전거 이용객수)
- 결과값을 rf_result에
- RMSE 함수를 통해 RMSE값을 계산
- 딥러닝으로 돌렸을 때 보다 높아짐
- 성능이 떨어지는 것
- 데이터 전처리 등이 영향을 주기 때문에 딥러닝이 반드시 좋다는 의미는 아님
🧩 XG부스터
- 부스팅 계열 모형은 순차적으로, 앞서 만든 모형의 성능 등을 참고하여 뒤의 모형이 만들어진다
- XGB, Light GBM, Gradiant Boost ...
- 자전거 이용객 수를 알아보고 싶은 것이니 Regressor
- 만약 자전거를 탄다 안 탄다의 분류 문제라면 Classifier
- 모형은 100개
- 똑같이 randomstate 지정
- 랜덤포레스트보다 연산 속도가 빠르다
- 랜덤포레스트보다 성능이 떨어진다
- 파라미터의 영향을 많이 받기 때문에 최적의 파라미터를 찾아가야한다
🧩 Light GBM
- 더 안 좋아졌음
- 실제 업무를 하다 보면, 파라미터를 잘 맞추고 전처리를 잘 하면 Light GBM과 XGBooster가 RandomForest보다 조금 더 높게 나온다
✏️ 더 알아본 내용
💡 RMSE
RMSE는 Root Mean Square Error의 약자로, 회귀 모델의 예측 값과 실제 값 간의 차이를 나타내는 평가 지표입니다. 이는 모델이 얼마나 정확하게 예측하는지를 측정하는 데 사용됩니다.
RMSE는 다음과 같은 단계로 계산됩니다:
- 각 데이터 포인트에서 실제 값과 모델의 예측 값 간의 차이를 계산합니다.
- 이 차이를 제곱합니다.
- 모든 차이의 제곱 값을 평균합니다.
- 이 평균값의 제곱근을 취합니다.
수학적으로는 다음과 같이 표현됩니다:
- 은 데이터 포인트의 개수입니다.
- 는 실제 값이고, 는 모델의 예측 값입니다.
RMSE는 예측 값과 실제 값 간의 차이를 표준화된 방법으로 나타내며, 값이 작을수록 모델의 예측이 더 정확하다고 볼 수 있습니다.
이것은 주로 회귀 모델의 성능을 평가하는 데 사용되며, 예측 값과 실제 값 간의 오차를 측정하여 모델의 예측 정확도를 판단하는 데 도움이 됩니다.
💡 랜덤포레스트
랜덤 포레스트(Random Forest)는 머신러닝의 앙상블(Ensemble) 기법 중 하나로, 여러 개의 의사 결정 트리(Decision Tree)를 조합하여 강력한 모델을 형성하는 알고리즘입니다. 랜덤 포레스트는 분류 및 회귀 문제에 모두 사용될 수 있습니다.
기본 아이디어:
- 의사 결정 트리의 앙상블:
- 랜덤 포레스트는 여러 개의 의사 결정 트리를 만들어 그들의 예측을 결합합니다. 이렇게 여러 트리를 조합하는 것을 앙상블 학습이라고 합니다.
- 부트스트랩 샘플링:
- 각 트리는 원본 데이터에서 무작위로 선택된 부트스트랩 샘플(복원추출)을 기반으로 학습합니다. 이는 중복을 허용하여 샘플링하는 것을 의미합니다.
- 랜덤 특성 선택:
- 각 트리가 분할할 때, 무작위로 선택한 특성의 부분 집합을 사용합니다. 이는 각 트리가 다양한 특성을 고려하여 학습하도록 합니다.
- 다수결 또는 평균:
- 분류 문제의 경우 각 트리의 결과를 다수결 투표로, 회귀 문제의 경우 평균으로 결합하여 최종 예측을 수행합니다.
주요 특징:
- 앙상블 효과:
- 여러 트리를 결합함으로써 일반적으로 단일 의사 결정 트리보다 안정적이고 강력한 모델을 형성할 수 있습니다.
- 과대적합 감소:
- 부트스트랩 샘플링과 무작위 특성 선택을 통해 각 트리는 다양한 측면에서 학습하므로, 과대적합을 줄이는 효과가 있습니다.
- 높은 성능:
- 랜덤 포레스트는 다양성과 병렬 처리의 이점을 활용하여 많은 데이터셋과 다양한 문제에 대해 높은 성능을 보이는 경향이 있습니다.
- 특성 중요도:
- 각 트리의 분할에서 사용되는 특성의 중요도를 평가하여, 어떤 특성이 모델에서 중요한 역할을 하는지 확인할 수 있습니다.
랜덤 포레스트는 특히 데이터셋이 크거나 다양한 특성을 갖는 경우에 효과적이며, 많은 실제 응용 분야에서 널리 사용되고 있습니다.
💡 XG부스터
XGBoost(Extreme Gradient Boosting)는 그래디언트 부스팅 알고리즘의 일종으로, 트리 기반의 앙상블 학습 방법입니다. 주로 구조화된 데이터(표 형식의 데이터)에 대한 예측 및 분류 작업에 사용되며, 많은 데이터 과학 대회에서 우승한 경험이 있는 강력한 머신 러닝 알고리즘 중 하나입니다.
기본 아이디어:
- 부스팅(Boosting):
- XGBoost는 여러 개의 약한 학습기(weak learner)인 결정 트리를 조합하여 강력한 모델을 형성합니다. 이를 부스팅이라고 하며, 이전 트리의 오차를 보완하는 새로운 트리를 만들어 나갑니다.
- 그래디언트 부스팅:
- 그래디언트 부스팅은 이전 트리의 예측 값과 실제 값 사이의 잔차(오차)에 대해 새로운 트리를 학습시킵니다. 이는 기울기(그래디언트)를 이용하여 오차를 최소화하는 방향으로 학습하는 것을 의미합니다.
- 규제와 정규화:
- XGBoost는 트리의 복잡성을 제어하기 위해 L1(Lasso) 및 L2(Ridge) 규제를 사용하고, 트리의 깊이를 제한하여 과적합을 방지합니다.
- 특성 중요도:
- 각 트리의 분할에서 사용된 특성의 중요도를 계산하여, 어떤 특성이 모델에서 중요한 역할을 하는지 확인할 수 있습니다.
주요 특징:
- 속도와 효율성:
- XGBoost는 효율적인 그래디언트 부스팅 구현으로 속도가 빠르며, 대용량 데이터셋에서도 잘 동작합니다.
- 병렬 처리와 분산 학습:
- 다양한 병렬 처리 기능을 지원하며, 분산 컴퓨팅 환경에서 효율적으로 학습할 수 있습니다.
- 자동 가지치기:
- 트리의 가지를 자동으로 가지치기하여 불필요한 가지를 제거함으로써 모델의 일반화 성능을 향상시킵니다.
XGBoost는 많은 데이터 과학 및 기계 학습 경연 대회에서 상위 성적을 기록하며, 다양한 응용 분야에서 널리 사용되는 알고리즘 중 하나입니다.
💡 Light GBM
Light GBM은 그래디언트 부스팅 알고리즘 중 하나로, 고성능 및 분산 학습을 목표로 하는 경량화된 부스팅 프레임워크입니다. Light GBM은 특히 대용량 데이터셋과 다양한 특성을 갖는 데이터에 대해 빠른 학습 속도와 높은 성능을 제공합니다.
주요 특징:
- 리프 중심 트리 분할:
- Light GBM은 트리의 리프 노드를 중심으로 트리를 성장시키는 방식을 사용합니다. 이는 특정 특성의 값에 기초하여 리프 노드를 분할하는 효과적인 방법을 제공합니다.
- 카테고리형 특성 지원:
- 카테고리형 데이터를 효율적으로 다룰 수 있는 기능을 제공하며, 원-핫 인코딩이나 라벨 인코딩을 필요로 하지 않습니다.
- 병렬 및 분산 학습:
- Light GBM은 데이터 병렬 처리와 히스토그램 기반의 분산 학습을 지원하여 대규모 데이터셋에서도 빠른 학습이 가능합니다.
- 리프 중심의 가지치기:
- 리프 중심 트리 성장 방법은 자연스럽게 가지치기를 수행하며, 불필요한 분기를 줄이고 모델의 일반화 성능을 향상시킵니다.
- 고성능 및 메모리 효율성:
- Light GBM은 작은 메모리 사용량과 빠른 학습 속도를 가집니다. 이는 히스토그램 기반의 특성 분할과 정형화된 특성으로 인한 효율성에 기인합니다.
사용 예시:
import lightgbm as lgb
# 데이터 준비
train_data = lgb.Dataset(train_X, label=train_y)
# 모델 학습
params = {'objective': 'binary', 'metric': 'binary_error', 'boosting_type': 'gbdt'}
model = lgb.train(params, train_data, num_boost_round=100)
# 예측
predictions = model.predict(test_X)
Light GBM은 파이썬에서 사용하기 쉽고, 다양한 하이퍼파라미터 튜닝 옵션을 제공하여 모델을 최적화할 수 있습니다. 특히 대용량의 데이터셋이나 다양한 특성을 다루어야 하는 경우에 유용한 머신러닝 알고리즘입니다.
💡 강사님과 똑같이 하면 에러가 나서 에러가 안 나는 방향으로 코드를 바꾼 것이 몇가지 있는데
그게 영향을 준 것 같아 매우 찝찝하다
일단 ChatGPT에게 물어본 결과는 다음과 같다
강사님과 당신의 코드 중에서 차이를 확인해봤습니다. 각 부분이 RMSE에 어떤 영향을 미칠 수 있는지 살펴보겠습니다.
- 이상치 처리 코드의 차이:
- 강사님 코드: df_out = df[~df.groupby('hour')['cnt'].apply(is_outliers)]
- 당신의 코드: df_out = df.groupby('hour').apply(lambda x: x[~is_outliers(x['cnt'])]).reset_index(drop=True)
강사님의 코드는 그룹별로 이상치(outliers)를 제거하고 해당 데이터프레임을 유지합니다. 당신의 코드는 그룹별로 이상치를 제거한 결과를 다시 데이터프레임으로 만들고, 그 결과를 하나의 데이터프레임으로 결합합니다. 이는 모델이 학습하는 데이터의 패턴을 다르게 만들 수 있습니다. - 데이터 타입 및 값 범위 처리 차이:
- 강사님 코드: history = model.fit(x_train, y_train, epochs=50, batch_size=1, validation_split=0.1, callbacks=[early_stopping])
- 당신의 코드: x_train_np = x_train.values.astype('float32'), y_train_np = y_train.values.astype('float32'), history = model.fit(x_train_np, y_train_np, epochs=50, batch_size=1, validation_split=0.1, callbacks=[early_stopping])
강사님의 코드는 데이터프레임을 그대로 사용하여 모델을 학습시킵니다. 당신의 코드는 데이터프레임을 넘파이 배열로 변환하여 사용합니다. 데이터를 넘파이 배열로 변환하면 모델이 학습하는 과정에서 값의 범위나 데이터 타입의 변화가 있을 수 있습니다. 이로 인해 모델이 데이터를 다르게 인식할 가능성이 있습니다. - 테스트 데이터 예측 부분의 차이:
- 강사님 코드: y_predict = model.predict(x_test)
- 당신의 코드: x_test = x_test.astype('float32'), y_predict = model.predict(x_test)
당신의 코드는 테스트 데이터의 데이터 타입을 변경한 후에 예측을 수행합니다. 이는 모델이 테스트 데이터에 대해 예측을 할 때 입력 데이터의 형태에 변화를 주는데, 이는 모델의 예측 결과에 영향을 줄 수 있습니다.
위의 세 가지 부분 중에서 모델의 성능에 영향을 미치는 정확한 이유는 데이터와 모델의 세부사항에 따라 다를 수 있습니다. 그래서 각 부분을 하나씩 검토하고 비교하여 RMSE 차이의 원인을 찾아내는 것이 중요합니다.
이렇게 각 코드의 차이를 확인해본 결과, 이상치 처리 및 데이터 타입 변환의 차이가 모델의 학습과 예측에 영향을 미칠 가능성이 있습니다. 각 부분을 변경하지 않으면서도 원하는 결과를 얻기 위해 코드를 수정하는 것이 중요하다
출처: https://youtu.be/OTf1-cE962E?si=7Z3arFx6bGzGPSyM