ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 혼공머신 Ch 04 다양한 분류 알고리즘
    Study/머신러닝 딥러닝 2025. 9. 24. 15:45

     

    로지스틱 회귀와 확률적 경사 하강법: 모델 훈련부터 최적화까지

     

    이번 글에서는 머신러닝의 핵심 분류 알고리즘인 로지스틱 회귀와 대규모 데이터셋을 효율적으로 훈련하기 위한 확률적 경사 하강 (SGD)에 대해 종합적으로 정리합니다. 생선 품종 분류 예제를 통해 데이터를 준비하고, 모델을 훈련하며, 최적의 성능 지점을 찾아가는 전 과정을 코드와 함께 살펴보겠습니다.

     


    목차

    1. 로지스틱 회귀: 확률 기반의 분류 모델
      • 데이터 준비 및 표준화 전처리
      • 이진 분류: 두 개의 클래스 구분하기
      • 다중 분류: 여러 클래스 예측하기
    2. 확률적 경사 하강법: 점진적 학습을 통한 최적화
      • SGDClassifier 모델 소개
      • 에포크(Epoch)와 점진적 학습
      • 최적의 훈련 지점 찾기
    3. 결론

     


     

    1. 로지스틱 회귀: 확률 기반의 분류 모델

     

     

    로지스틱 회귀(Logistic Regression)는 대표적인 분류 알고리즘으로, 데이터가 특정 클래스에 속할 확률을 계산합니다. 예를 들어, 생선의 특성(무게, 길이 등)을 보고 7가지 어종 중 하나로 분류하는 문제에 사용할 수 있습니다.

    데이터 준비 및 표준화 전처리

    먼저 pandas를 사용해 CSV 파일에서 생선 데이터를 불러온 후, 모델의 입력으로 사용할 5개의 특성(Weight, Length, Diagonal, Height, Width)과 정답 값인 어종(Species)을 분리합니다. 이후 모델의 안정적인 학습을 위해 데이터를 훈련 세트와 테스트 세트로 나누고, StandardScaler를 이용해 각 특성의 스케일을 표준화합니다.

    import pandas as pd
    from sklearn.model_selection import train_test_split
    from sklearn.preprocessing import StandardScaler
    
    # 데이터 불러오기
    fish = pd.read_csv('https://bit.ly/fish_csv_data')
    
    # 입력(특성)과 타겟(어종) 데이터 분리
    fish_input = fish[['Weight','Length','Diagonal','Height','Width']]
    fish_target = fish['Species']
    
    # 훈련 세트와 테스트 세트 분리
    train_input, test_input, train_target, test_target = train_test_split(
        fish_input, fish_target, random_state=42)
    
    # 특성 표준화
    ss = StandardScaler()
    ss.fit(train_input)
    train_scaled = ss.transform(train_input)
    test_scaled = ss.transform(test_input)
    

    이진 분류: 두 개의 클래스 구분하기

    로지스틱 회귀는 선형 방정식의 출력값(z)을 시그모이드 함수(Sigmoid function)에 통과시켜 0과 1 사이의 확률값으로 변환합니다. 먼저 'Bream'과 'Smelt' 두 어종만 구분하는 이진 분류 문제를 풀어보겠습니다.

    from sklearn.linear_model import LogisticRegression
    
    # Bream과 Smelt 데이터만 선택
    bream_smelt_indexes = (train_target == 'Bream') | (train_target == 'Smelt')
    train_bream_smelt = train_scaled[bream_smelt_indexes]
    target_bream_smelt = train_target[bream_smelt_indexes]
    
    # 로지스틱 회귀 모델 훈련
    lr = LogisticRegression()
    lr.fit(train_bream_smelt, target_bream_smelt)
    
    # 훈련된 모델로 확률 예측
    # 출력: [[Bream일 확률, Smelt일 확률], ...]
    print(lr.predict_proba(train_bream_smelt[:5]))
    # 출력: ['Bream' 'Smelt']
    print(lr.classes_)
    

     

    predict_proba()는 각 클래스에 대한 확률을 반환하며, 

    decision_function()을 통해 시그모이드 함수를 통과하기 전의 z값을 직접 확인할 수도 있습니다.

     

    다중 분류: 여러 클래스 예측하기

    로지스틱 회귀는 소프트맥스 함수(Softmax function)를 사용하여 세 개 이상의 클래스를 분류하는 다중 분류도 지원합니다. 7개 어종 전체를 분류하는 모델을 훈련하고 성능을 평가해 보겠습니다. C는 규제의 강도를 조절하는 매개변수이며, 값이 작을수록 강한 규제가 적용됩니다. max_iter는 훈련 반복 횟수를 의미합니다.

     

    # C=20, max_iter=1000으로 다중 분류 모델 훈련
    lr = LogisticRegression(C=20, max_iter=1000)
    lr.fit(train_scaled, train_target)
    
    # 성능 평가
    print(lr.score(train_scaled, train_target))
    print(lr.score(test_scaled, test_target))
    
    # 5개 샘플에 대한 예측 확률
    proba = lr.predict_proba(test_scaled[:5])
    print(np.round(proba, decimals=3))
    

     

    다중 분류 모델의 계수(coef_)는 각 클래스마다 특성에 대한 가중치를 가지므로 (7, 5) 형태의 배열이 됩니다.

     


     

    2. 확률적 경사 하강법: 점진적 학습을 통한 최적화

     

     

    확률적 경사 하강법(SGD)은 대용량 데이터셋을 효율적으로 훈련시키기 위한 최적화 알고리즘입니다. 전체 데이터를 한 번에 사용하는 대신, 훈련 세트에서 무작위로 샘플 하나를 뽑아 모델을 조금씩 수정해나갑니다.

    SGDClassifier 모델 소개

    Scikit-learn의 SGDClassifier는 SGD 방식을 사용하는 분류 모델입니다. loss 매개변수를 log_loss로 설정하면 로지스틱 회귀 손실 함수를 사용하므로, 확률을 예측하는 분류 모델로 동작하게 됩니다.

     

    from sklearn.linear_model import SGDClassifier
    
    # max_iter=10으로 설정하여 10번 반복 훈련
    sc = SGDClassifier(loss='log_loss', max_iter=10, random_state=42)
    sc.fit(train_scaled, train_target)
    
    # 성능 평가
    print(sc.score(train_scaled, train_target))
    print(sc.score(test_scaled, test_target))
    

    에포크(Epoch)와 점진적 학습

    에포크(Epoch)란 전체 훈련 세트를 한 번 모두 사용하는 과정을 의미합니다. SGD는 partial_fit() 메서드를 제공하여 데이터를 조금씩 나누어 훈련하는 점진적 학습을 지원합니다. 이 메서드를 반복 호출하며 각 에포크마다 모델의 성능을 측정해 보겠습니다.

    import numpy as np
    
    sc = SGDClassifier(loss='log_loss', random_state=42)
    train_score = []
    test_score = []
    classes = np.unique(train_target)
    
    # 300번의 에포크 동안 훈련 반복
    for _ in range(0, 300):
        sc.partial_fit(train_scaled, train_target, classes=classes)
        train_score.append(sc.score(train_scaled, train_target))
        test_score.append(sc.score(test_scaled, test_target))
    

    최적의 훈련 지점 찾기

    각 에포크별 훈련 및 테스트 점수를 그래프로 그려보면, 모델이 언제 최적의 성능에 도달하고 언제  과대적합(Overfitting) 되는지 파악할 수 있습니다.

    import matplotlib.pyplot as plt
    
    # 에포크별 정확도 그래프
    plt.plot(train_score, label='train_score')
    plt.plot(test_score, label='test_score')
    plt.xlabel('epoch')
    plt.ylabel('accuracy')
    plt.legend()
    plt.show()
    

     

     

     

    그래프를 보면 약 100번째 에포크 이후부터 훈련 세트 점수는 계속 오르지만 테스트 세트 점수는 정체되거나 오히려 감소하는 경향을 보입니다. 이는 모델이 훈련 데이터에 과도하게 맞춰져 새로운 데이터에 대한 일반화 성능이 떨어지기 시작했음을 의미합니다. 따라서 100번째 에포크 근처가 최적의 훈련 지점이라고 판단할 수 있습니다. 이 지점을 max_iter 값으로 설정하여 모델을 최종 훈련합니다.

     

    # 최적의 에포크 횟수(100)로 모델 재훈련
    sc = SGDClassifier(loss='log_loss', max_iter=100, tol=None, random_state=42)
    sc.fit(train_scaled, train_target)
    
    # 최종 성능 확인
    print(sc.score(train_scaled, train_target))
    print(sc.score(test_scaled, test_target))
    

     


     

    3. 결론

     

    • 로지스틱 회귀는 클래스 분류 문제에서 각 클래스에 속할 확률을 제공하는 강력하고 해석 가능한 모델입니다.
    • 확률적 경사 하강법(SGD)은 대용량 데이터를 효율적으로 훈련시키는 최적화 기법으로, 점진적 학습을 통해 모델을 업데이트합니다.
    • 훈련 과정에서 에포크별 성능을 모니터링하면 과대적합을 방지하고 최적의 일반화 성능을 내는 모델을 만들 수 있습니다.

     

    코드 출처: 

     

    https://github.com/rickiepark/hg-mldl2/blob/main/04-1.ipynb

     

    hg-mldl2/04-1.ipynb at main · rickiepark/hg-mldl2

    <혼자 공부하는 머신러닝+딥러닝(개정판)>(한빛미디어, 2025)의 코드 저장소입니다. Contribute to rickiepark/hg-mldl2 development by creating an account on GitHub.

    github.com

    https://github.com/rickiepark/hg-mldl2/blob/main/04-2.ipynb

     

    hg-mldl2/04-2.ipynb at main · rickiepark/hg-mldl2

    <혼자 공부하는 머신러닝+딥러닝(개정판)>(한빛미디어, 2025)의 코드 저장소입니다. Contribute to rickiepark/hg-mldl2 development by creating an account on GitHub.

    github.com

     

    이미지 및 내용 출처:

     

    https://www.youtube.com/watch?v=eZoXnkQ_l4w&list=PLVsNizTWUw7E2RxZ4aspcR9vNamXccmFE&index=10

     

Designed by Tistory.