ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [혼공머] 4-1. 로지스틱 회귀
    Data Science/딥러닝 & 머신러닝 2025. 1. 10. 23:55

    1. 럭키백의 확률

    1. 배경

    • 기간 한정 럭키백을 런칭 : 7개의 생선이 들어간다.
    • 럭키백에 포함된 생선의 확률을 알려줄 것이다.
    • → 어떻게 생선의 확률을 구할 수 있을까?
    • 사용할 데이터 : 생선의 길이, 높이, 두께, 대각선 길이, 무게

    2. 데이터 불러오기

    import pandas as pd
    fish = pd.read_csv('<https://bit.ly/fish_csv_data>')
    print(pd.unique(fish['Species']))
    # ['Bream' 'Roach' 'Whitefish' 'Parkki' 'Perch' 'Pike' 'Smelt']
    

    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)
    										
    from sklearn.preprocessing import StandardScaler
    ss = StandardScaler()
    ss.fit(train_input)
    train_scaled = ss.transform(train_input)
    test_scaled = ss.transform(test_input)

    4. K-NeighborsClassifier로 확률 예측

    from sklearn.neighbors import KNeighborsClassifier
    kn = KNeighborsClassifier(n_neighbors=3)
    kn.fit(train_scaled, train_target)
    kn.score(train_scaled, train_target), kn.score(test_scaled, test_target)
    # (0.8907563025210085, 0.85)
    
    • classes_ : 다중 분류에서의 타겟값 확인
    • predict_proba : 클래스별 확률값 출력조금 더 구체적인 확률이 필요하다.
    kn.classes_
    # array(['Bream', 'Parkki', 'Perch', 'Pike', 'Roach', 'Smelt', 'Whitefish'],
          dtype=object)    
          
    kn.predict_proba(test_scaled[:3])
    # array([[0., 0., 1., 0., 0., 0., 0.],
    #       [0., 0., 0., 0., 0., 1., 0.],
    #       [0., 0., 0., 1., 0., 0., 0.]])

     


    2. 로지스틱 회귀와 시그모이드 함수

    1. 로지스틱 회귀

    • 선형회귀와 동일하지만, 분류 모델
    • 다중회귀(독립변수 여러개)의 선형 방정식과 동일a, b, c, d, e : 가중치 or 계수 / z : 어떤 값도 가능함

    2. 시그모이드 함수 (로지스틱 함수)

    • 배경 : 로지스틱 회귀에서 z가 [0, 1] 의 확률 값을 갖도록 변경할 필요가 있다.
      • z 가 아주 큰 음수라면 0
      • z가 아주 큰 양수라면 1
    • 시그모이드 함수의 형태수식 = 시그모이드 함수 → 그래프 만들기
    • 확률값의 범위 내에 있고, z가 무한하게 크면 1, 무한하게 작으면 0을 가진다.
    import numpy as np
    import matplotlib.pyplot as plt
    
    z = np.arange(-5, 5, 0.1)
    phi = 1 / (1 + np.exp(-z))
    plt.plot(z, phi)
    plt.xlabel('z')
    plt.ylabel('phi')
    plt.show()

    3. 로지스틱 회귀로 이중 분류 수행하기

    1. 클래스 구분

    • 0.5 초과 시 양성 클래스 [1]
    • 0.5 미만 시 음성 클래스 [0]
    • → 도미와 빙어를 구분해보자.

    2. 불리언 인덱싱

    • True, False 값을 전달해 행을 선택하는 것
    char_arr = np.array(['A', 'B', 'C', 'D', 'E']) 
    print(char_arr[[True, False, True, False, False]]) # ['A' 'C']

    3. 불리언 인덱싱을 이용한 Bream과 Smelt 구분

    • 도미와 빙어만 True를 전달하면 된다.
    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]
    

    4. 로지스틱 회귀 모델

    # 훈련
    from sklearn.linear_model import LogisticRegression
    lr = LogisticRegression()
    lr.fit(train_bream_smelt, target_bream_smelt)
    
    # 예측
    print(lr.predict(train_bream_smelt[:5])) # ['Bream' 'Smelt' 'Bream' 'Bream' 'Bream'] 
    
    # 음성 클래스와 양성 클래스의 확률
    print(lr.predict_proba(train_bream_smelt[:5]))
    # [[0.99759855 0.00240145]
    # [0.02735183 0.97264817]
    # [0.99486072 0.00513928]
    # [0.98584202 0.01415798]
    # [0.99767269 0.00232731]]
    

    5. 로지스틱 회귀 모델의 속성

    • classes_ : 음성 클래스와 양성 클래스 확인
      • 사이킷런에서는 타겟값을 알파벳 순으로 정렬, 0 1 순서
      print(lr.classes_) # ['Bream' 'Smelt'] -> Smelt가 양성
      
    • coef_, intercept_
    print(lr.coef_, lr.intercept_)
    # [[-0.4037798 -0.57620209 -0.66280298 -1.01290277 -0.73168947]] [-2.16155132]
    • decision_function : logisticRegression 모델로 z 값 계산하기
      decisions = lr.decision_function(train_bream_smelt[:5])
      print(decisions)
      # [-6.02927744  3.57123907 -5.26568906 -4.24321775 -6.0607117 ]
      ​
      • z 값을 시그모이드 함수에 넣으면 확률을 얻을 수 있다.
        from scipy.special import expit
        print(expit(decisions))
        # [0.00240145 0.97264817 0.00513928 0.01415798 0.00232731]
        ​

    4. 로지스틱 회귀와 소프트맥스 함수

    1. 소프트맥스 함수

    • 여러 개의 선형 방정식의 출력값을 0 ~ 1 사이로 압축하고 전체 합이 1이 되도록 만든다.
    • ↔ sigmoid 는 1개의 선형 방정식에 대해 압축한다.
    • 계산 방식
      • class 개수만큼 z 를 구하고, 지수함수에 넣어 더한다.
      • e^zi를 e_sum으로 나눈다.모두 더하면 분자 = 분모 → 1

    5. 로지스틱 회귀로 다중 분류 수행하기

    1. LogisticRegression으로 다중 분류

    • LogisticRegression 클래스로 7개의 생선을 분류하자.
    • max_iter 매개변수 : 반복 횟수 지정 b/c LogisticRegression은 반복적인 알고리즘을 사용
    • C 매개변수 : LogisticRegression에서 규제를 제어
      • 작을수록 규제가 크다.
      • 기본값은 1

    2. LogisticRegression 모델

    # 훈련
    lr = LogisticRegression(C=20, max_iter=1000)
    lr.fit(train_scaled, train_target)
    print(lr.score(train_scaled, train_target) # 0.93
    print(lr.score(test_scaled, test_target)) # 0.92
    
    # 예측
    print(lr.predict(test_scaled[:5]))
    # ['Perch' 'Smelt' 'Pike' 'Roach' 'Perch']
    
    # 확률
    proba = lr.predict_proba(test_scaled[:5])
    print(np.round(proba, decimals=3))
    # [[0.    0.014 **0.841** 0.    0.136 0.007 0.003]
    # [0.    0.003 0.044 0.    0.007 0.946 0.   ]
    # [0.    0.    0.034 0.935 0.015 0.016 0.   ]
    # [0.011 0.034 0.306 0.007 0.567 0.    0.076]
    # [0.    0.    0.904 0.002 0.089 0.002 0.001]]
    

    가장 높은 확률을 예측 클래스로.

    3. 로지스틱 회귀 모델의 속성

    • classes_ 속성
    • 다중 분류의 선형 방정식 - coef_ 와 intercept_coef 의 행이 7개, 열이 5개 → 열 = 특성가장 높은 z값을 출력하는 클래스가 예측 클래스
    • → 행 7개 = z를 일곱 개 계산 : 클래스마다 z값을 하나씩 계산
    • print(lr.coef_.shape, lr.intercept_.shape) # (7, 5) (7,)
    • decision_function() 으로 z 각각 구하기
    print(lr.classes_) # ['Bream' 'Parkki' 'Perch' 'Pike' 'Roach' 'Smelt' 'Whitefish']
    decision = lr.decision_function(test_scaled[:5])
    print(np.round(decisions, decimals=3))
    # [[ -6.498   1.032   5.164  -2.729   3.339   0.327  -0.634]
    # [-10.859   1.927   4.771  -2.398   2.978   7.841  -4.26 ]
    # [ -4.335  -6.233   3.174   6.487   2.358   2.421  -3.872]
    # [ -0.683   0.453   2.647  -1.187   3.265  -5.753   1.259]
    # [ -6.397  -1.993   5.816  -0.11    3.503  -0.112  -0.707]]
    
    • z 값을 소프트맥스 함수에 넣으면 확률을 얻을 수 있다.
      • softmax 함수
        • axis =1 : 각 샘플(행)에 대해 소프트맥스르 게산
      from scipy.special import expit
      proba = softmax(decisions, axis=1)
      print(np.round(proba, decimals=3))
      # [[0.    0.014 0.841 0.    0.136 0.007 0.003]
      # [0.    0.003 0.044 0.    0.007 0.946 0.   ]
      # [0.    0.    0.034 0.935 0.015 0.016 0.   ]
      # [0.011 0.034 0.306 0.007 0.567 0.    0.076]
      # [0.    0.    0.904 0.002 0.089 0.002 0.001]]
      

    6. 로지스틱 회귀로 확률 예측 전체 소스 코드

    # 사용할 전체 데이터 준비
    import pandas as pd
    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)
    
    # K-Neighbors를 이용한 다중 분류
    from sklearn.neighbors import KNeighborsClassifier
    kn = KNeighborsClassifier(n_neighbors=3)
    kn.fit(train_scaled, train_target)
    kn.score(train_scaled, train_target), kn.score(test_scaled, test_target)
    kn.predict(test_scaled[:5])
    kn.predict_proba(test_scaled[:3])
    
    # 로지스틱 회귀를 이용한 이중 분류 + sigmoid
    bream_smelt_indexes = (train_target == 'Bream') | (train_target == 'Smelt') # boolean
    train_bream_smelt = train_scaled[bream_smelt_indexes] # boolean indexing
    target_bream_smelt = train_target[bream_smelt_indexes] # boolean indexing
    
    from sklearn.linear_model import LogisticRegression
    lr = LogisticRegression()
    lr.fit(train_bream_smelt, target_bream_smelt)
    
    lr.predict(train_bream_smelt[:5])
    lr.predict_proba(train_bream_smelt[:5])
    lr.coef_, lr.intercept_
    
    decisions = lr.decision_function(train_bream_smelt[:5])
    from scipy.special import expit
    print(expit(decisions))
    
    # 로지스틱 회귀를 이용한 다중 분류 + softmax
    lr = LogisticRegression(C=20, max_iter=1000)
    lr.fit(train_scaled, train_target)
    lr.score(train_scaled, train_target), lr.score(test_scaled, test_target)
    lr.predict(test_scaled[:5])
    lr.decision_function(test_scaled[:5])
    
    import numpy as np
    decision = lr.decision_function(test_scaled[:5])
    print(np.round(decision, decimals=2))
    from scipy.special import softmax
    proba = softmax(decision, axis = 1)
    print(np.round(proba, decimals=3))
    

     

Designed by Tistory.