ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [혼공머] 4-2. 확률적 경사 하강법
    Data Science/딥러닝 & 머신러닝 2025. 1. 11. 00:00

     

    1. 점진적인 학습

    1. 새로운 문제

    • 새로운 생선이 도착하는 대로 즉시 훈련 데이터를 제공할 수 있을까?
    • sol 1. 기존의 훈련 데이터에 새로운 데이터를 추가해 매일 다시 훈련
      • 단점 : 시간이 지날수록 데이터가 늘어나서 지속 가능 X
    • sol 2. 새로운 데이터를 추가할 때 이전 데이터를 버려서 훈련 데이터 크기 유지
      • 단점 : 데이터셋의 크기 유지, 중요한 생선 데이털르 버리면 문제 발생
    • sol3. ‘점진적 학습
      • 훈련한 모델을 버리지 않고 새로운 데이터에 대해 조금씩 더 훈련
      • 데이터 모두 유지할 필요도 없고 생선을 까먹지도 않을 것
      • 대표적으로, 확률적 경사 하강법 알고리즘을 사용한다.

    2. 경사 하강법

    1. 경사 하강법

    • 말의 뜻 : 경사를 따라 내려가는 방법 → 가장 빠른 방법은 경사가 가파른 길
    • 경사 = 기울기
    • 하강법 = 내려가는 방법
    • 경사 하강법의 목표 : 가장 가파른 경사를 따라 원하는 지점에 도달
    • 한 번에 많이 움직이면, 오히려 올라갈 수도 있다.
    • 가장 가파른 길을 찾아 내려오지만, 조금씩 내려와야 한다.

    2. 경사 하강법의 종류

    • 확률적 경사 하강법 : one sample
    • 미니배치 경사 하강법 : many sample
    • 배치 경사 하강법 : all sample

    3. 확률적 경사 하강법

    • 확률적 = 무작위하게
    • 목표 : 훈련 세트에서 랜덤하게 하나의 샘플을 골라, 가장 가파른 길을 찾는 것
    • 과정
      1. 전체 샘플을 모두 사용할 때까지 1개 골라서 내려간다.
      2. 그 다음 훈련 세트에서 또 다른 샘플 1개 선택해서 내려가는 방식
      3. 샘플을 다 사용했는데도 아직 산에 있다면 다시 처음부터 시작
      4. = 훈련 세트에 모든 샘플을 다시 채워넣고, 확률적 경사 하강법 진행
    • 여러 번의 ‘에포크’ 수행
      • 에포크 = 확률적 경사 하강법에서 훈련 세트를 한 번 모두 사용하는 과정
    • 신경망 알고리즘에서 주로 사용 : 한 번에 모든 데이터를 사용하기 어렵기 때문

    4. 미니배치 경사 하강법

    • 무작위로 샘플을 내려가는 확률적 경사 하강법이 걱정되는 경우 사용
    • 무작위로 여러 개의 샘플을 사용해 경사 하강법을 수행하는 방식

    5. 배치 경사 하강법

    • 전체 샘플을 사용해 경사 하강법을 수행하는 방식
      • 1번의 경사로를 따라 이동
      • 가장 안정적인 방식이지만 컴퓨터 자원을 너무 많이 사용

    3. 손실 함수

    1. 손실 함수

    • 정의 : 머신러닝 알고리즘이 별로인 정도(?)를 측정하는 기준
    • 작을수록 좋다.
    • 비용 함수와 손실 함수의 차이
      • 비용 함수 : 훈련 세트에 있는 모든 샘플에 대한 손실 함수의 합
      • 손실 함수 : 샘플 하나에 대한 손실을 정의

    2. 손실 함수가 연속적이어야 하는 이유

    • 분류에서의 손실 = 정답을 못 맞히는 것정확도를 손실 함수로 사용한다면 정확도가 이산적이라는 문제 발생따라서 연속적 = 미분 가능 해야 한다.
    • 정확도가 이산적 → 경사 하강법을 이용해 움직일 수 없다.

    3. 손실 함수의 종류

    • 로지스틱 손실 함수 (이진 크로스엔트로피 손실 함수)
    • 크리스엔트로피 손실 함수
    • MSE : 회귀에서 사용하는 손실 함수 ; 평균 제곱 오차

    앞으로 사용할 예시에서는

    샘플 4개의 예측 확률을 각각 0.9, 0.3, 0.2, 0.8 이라고 하자.

    샘플 4개의 타겟 값은 각각 1, 1, 0, 0 이다.

    4. 로지스틱 손실 함수

    • 이진 분류에서의 손실 함수
    • 구하는 방법
      1. ‘양성 클래스[1]’ 일 확률과 1을 곱한 후 음수를 취한다.예측이 1에 가까울수록 좋은 모델이다.따라서 양성 클래스에 대한 예측으로 바꾸어 손실을 구한다.
      2. 0.2의 예측은 타겟이 0이 되므로, 곱하면 0이 되는 문제가 있다.
    • 예측 확률에 로그 함수를 적용한다.로그 함수는 0에 가까울수록 아주 큰 음수가 된다.
    • 음수의 로그함수는 양수가 되고 손실이 양수면 이해하기 쉽다.

    5. 크로스엔트로피 손실 함수

    • 다중 분류에서 사용하는 손실 함수

    4. SGDClassifier

    1. SGDClassifier 모델

    • 확률적 경사 하강법을 제공하는 분류용 클래스
    • 객체 생성 시 지정해야 하는 매개변수 2가지
      • loss : 손실 함수의 종류
        • ‘hinge’ = 서포트 벡터 머신을 위한 손실 함수 (기본값)
        • ‘log_loss’ = 로지스틱 손실 함수
      • max_iter : 수행할 에포크 횟수 ( 전체 훈련 세트 반복 횟수)
    • 점진적 학습 가능 → partial_fit() 으로 모델 이어서 훈련
      • 호출할 때마다 1 애포크씩 이어서 훈련
    • 일정 에포크 동안 성능이 향상되지 않으면 자동으로 멈춘다.
      • tol 매개변수로 향상될 최솟값 지정 가능

    2. 데이터 준비

    fish = pd.read_csv('<https://bit.ly/fish_csv_data>')
    

    3. 훈련 데이터와 타겟 데이터 분리

    fish_input = fish[['Weight','Length','Diagonal','Height','Width']].to_numpy()
    fish_target = fish['Species'].to_numpy()
    
    from sklearn.model_selection import train_test_split
    train_input, test_input, train_target, test_target= train_test_split(fish_input, fish_target, random_state=42)

    4. 데이터 전처리

    • 훈련 세트와 테스트 세트의 특성을 표준화 전처리
    • 훈련 세트에서 학습한 통계 값으로 테스트 세트도 변환
    from sklearn.preprocessing import StandardScaler
    ss = StandardScaler()
    ss.fit(train_input)
    train_scaled = ss.transform(train_input)
    test_scaled = ss.transform(test_input)
    

    5. SGDClassifier 모델

    # 훈련
    sc = SGDClassifier(loss='log_loss', max_iter=10, random_state=42)
    sc.fit(train_scaled, train_target)
    
    # 정확도
    sc.score(train_scaled, train_target), sc.score(test_scaled, test_target)
    # (0.773109243697479, 0.775)
    
    # 이어서 훈련
    sc.partial_fit(train_scaled, train_target)
    sc.score(train_scaled, train_target), sc.score(test_scaled, test_target)
    # (0.9663865546218487, 0.925)
    

    6. 힌지 손실을 이용한 SGDClassifier 모델

    sc = SGDClassifier(loss='hinge', max_iter=100, tol = None, random_state=42)
    sc.fit(train_scaled, train_target)
    sc.score(train_scaled, train_target), sc.score(test_scaled, test_target) 
    # (0.9495798319327731, 0.925)
    

     


    5. 에포크와 과대/과소적합

    1. 확률적 경사 하강법에서의 과대/과소적합

    • 에포크 횟수가 적으면 모델이 훈련 세트 덜 학습
    • = 훈련 세트와 테스트 세트에 잘 맞지 않는 과소적합된 모델
    • 에포크 횟수가 많으면 훈련 세트에 아주 잘 맞는 모델
    • = 훈련 세트에 너무 잘 맞아 테스트 세트에서는 점수가 낮은 과대적합된 모델
    • 에포크 횟수에 따른 변화
      • 어느 순간부터 테스트 세트 점수 감소
        • 이 시점이 과대적합의 시작점

    2. 조기 종료

      • 과대적합이 시작되기 전 훈련을 멈추는 것
      • partial_fit을 이용해 에포크에 따른 정확도 나타내기
        1. 에포크마다 훈련 세트와 테스트 세트에 대한 점수 기록
        import numpy as np
        sc = SGDClassifier(loss='log_loss', max_iter=100, tol=None, random_state=42)
        train_score = []
        test_score = []
        classes = np.unique(train_target)
        
        1. 300번의 에포크 동안 partial_fit
        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))
        
        1. 300번의 에포크 동안 기록한 점수 그래프로 표시
        import matplotlib.pyplot as plt
        plt.plot(train_score) # blue
        plt.plot(test_score) # orange
        plt.xlabel('epoch')
        plt.ylabel('accuracy')
        plt.show()
        
         
      • 100 번째 에포크 이후 점수가 벌어진다 → 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)) # 0.95 print(sc.score(test_scaled, test_target)) # 0.92
      • 100번의 에포크 동안 모델 훈련

    6. 점진적 학습을 위한 확률적 경사 하강법 전체 소스 코드

    # 데이터 준비
    import pandas as pd
    import numpy as np
    
    fish = pd.read_csv('<https://bit.ly/fish_csv_data>')
    fish_input = fish[['Weight','Length','Diagonal','Height','Width']].to_numpy()
    fish_target = fish['Species'].to_numpy()
    
    # 훈련, 타겟 데이터 준비
    from sklearn.model_selection import train_test_split
    train_input, test_input, train_target, test_target= train_test_split(fish_input, fish_target, random_state=42)
    										
    # 데이터 전처리 - 표준화
    from sklearn.preprocessing import StandardScaler
    ss = StandardScaler()
    ss.fit(train_input)
    train_scaled = ss.transform(train_input)
    test_scaled = ss.transform(test_input)	
    
    # SGDClassifier - 힌지 손실함수				
    sc = SGDClassifier(loss='hinge', max_iter=100, tol = None, random_state=42)
    sc.fit(train_scaled, train_target)
    sc.score(train_scaled, train_target), sc.score(test_scaled, test_target)
    
    # SGDClassifier - 로지스틱 손실함수
    from sklearn.linear_model import SGDClassifier
    sc = SGDClassifier(loss='log', max_iter=10, random_state=42)
    sc.fit(train_scaled, train_target)
    sc.score(train_scaled, train_target), sc.score(test_scaled, test_target)
    
    # 점진적 학습
    sc.partial_fit(train_scaled, train_target)
    
    # 에포크와 과대/과소적합
    # 1. 정확도 기록
    import numpy as np
    sc = SGDClassifier(loss='log', random_state=42)
    train_score = []
    test_score = []
    classes = np.unique(train_target)
    for _ in range(0, 300):
        sc.partial_fit(train_scaled, train_target, classes=classes) # partial _fit 위해 classes
        train_score.append(sc.score(train_scaled, train_target))
        test_score.append(sc.score(test_scaled, test_target))
        
    # 2. 정확도 그래프
    import matplotlib.pyplot as plt
    plt.plot(train_score)
    plt.plot(test_score)
    plt.xlabel('epoch')
    plt.ylabel('accuracy')
    
    # 3. 더 좋은 에포크로 재훈련
    sc = SGDClassifier(loss='log', max_iter=100, tol=None, random_state=42)
    sc.fit(train_scaled, train_target)
    sc.score(train_scaled, train_target), sc.score(test_scaled, test_target)
Designed by Tistory.