TIL 48:論理回帰


🙄 ろんりかいふく


ろんりかいふく

  • データに最適な信号関数を見つけます:
  • しんごうかんすう

  • S(x)=11+e−xS(x)=\frac{1}{1+e^{-x}}S(x)=1+e−x1​
  • 無条件0と1の間の結果
  • eeeは2.718の正数
  • である.
  • S(∞)=11+e−∞=11+0=1S(\infty)=\frac{1}{1+e^{-\infty}}=\frac{1}{1+0}=1S(∞)=1+e−∞1​=1+01​=1
  • S(−∞)=11+e∞=11+∞=0S(-\infty)=\frac{1}{1+e^{\infty}}=\frac{1}{1+\infty}=0S(−∞)=1+e∞1​=1+∞1​=0
  • xxxxは非常に時間が0に近いが、xxxは非常に大きい場合は1に近い.
  • の1回目の関数の結果は小さくなるか大きくなる可能性があるため、分類
  • には適していない.
  • 線形回帰は1つの例外データの仮定関数に敏感である
  • 信号関数は異常データに大きな影響を及ぼさない
  • 0と1の間の連続値であるため、ローズ分類ではなくローズ回帰
  • である
  • 主な報告関数のリンゴ値は0.5より大きいか0.5より小さいか、分類
  • 🙄 仮定関数


    仮定関数

  • 特定データの入力変数を受信と、予測対象変数の関数
  • が生成する.
    次に,
  • の線形回帰に用いる仮定関数を開発し,Logistic回帰の仮定関数
  • とする.
    gggで
  • ,hhでgestic回帰仮定関数を表す
    θ\thetaθ = [θ0θ1θ2..θn]\begin{bmatrix}\theta_0\\\theta_1\\\theta_2\\.\\.\\\theta_n\end{bmatrix}⎣⎢⎢⎢⎢⎢⎢⎢⎡​θ0​θ1​θ2​..θn​​⎦⎥⎥⎥⎥⎥⎥⎥⎤​
    xxx = [1x1x2..xn]\begin{bmatrix}1\\x_1\\x_2\\.\\.\\x_n\end{bmatrix}⎣⎢⎢⎢⎢⎢⎢⎢⎡​1x1​x2​..xn​​⎦⎥⎥⎥⎥⎥⎥⎥⎤​
    gθ(x)=θ0x0+θ1x1+θ2x2+...θnxng_\theta(x)=\theta_0x_0+\theta_1x_1+\theta_2x_2+...\theta_nx_ngθ​(x)=θ0​x0​+θ1​x1​+θ2​x2​+...θn​xn​
    gθ(x)=θTxg_\theta(x)=\theta^Txgθ​(x)=θTx
    hθ(x)=11+e−gθ(x)h_\theta(x)=\frac{1}{1+e^{-g_\theta(x)}}hθ​(x)=1+e−gθ​(x)1​
    hθ(x)=11+e−θTxh_\theta(x)=\frac{1}{1+e^{-\theta^Tx}}hθ​(x)=1+e−θTx1​
  • の線形回帰で用いる仮定関数gggの出力を信号関数とする入力
  • とする.
  • 出力0から1の間の任意の数
  • .

    🙄 そんしつかんすう


    ログロス(log-loss,クロスエントロピー)


    ログ損失
  • はログ関数によって決定されるため、ログ損失
  • 損失関数を使用して仮定関数を評価し、
  • データに適した仮定関数を見つけます.
    logloss(hθ(x),y)={−log⁡(hθ(x))y=1−log⁡(1−hθ(x))y=0logloss(h_\theta(x), y) =\begin{cases} -\log(h_\theta(x)) &\text{y=1}\\-\log(1-h_\theta(x)) &\text{y=0}\end{cases}logloss(hθ​(x),y)={−log(hθ​(x))−log(1−hθ​(x))​y=1y=0​
  • 単行は次のように表される.
    logloss(hθ(x),y)=−ylog⁡(hθ(x))−(1−y)log⁡(1−hθ(x))logloss(h_\theta(x),y)=-y\log(h_\theta(x))-(1-y)\log(1-h_\theta(x))logloss(hθ​(x),y)=−ylog(hθ​(x))−(1−y)log(1−hθ​(x))

  • ログ損失は、実際のOutputyyyが1と0に分けられます.

  • yyyが1の場合、予測値が1に近づくほど損失は0に近づき、遠くなるほど損失は急峻になる

  • yyyが0の場合は正反対
  • ログ損失関数

  • の目標は、データ毎の損失評価後、平均損失
  • である.
  • J(θ)=1m∑i=1m[(logloss(hθ(x),y))]J(\theta)=\frac{1}{m}\sum_{i=1}^m[(logloss(h_\theta(x),y))]J(θ)=m1​∑i=1m​[(logloss(hθ​(x),y))]
  • J(θ)=1m∑i=1m[−y(i)log⁡(hθ(x(i)))−(1−y(i))log⁡(1−hθ(x(i)))]J(\theta)=\frac{1}{m}\sum_{i=1}^m[-y^{(i)}\log(h_\theta(x^{(i)}))-(1-y^{(i)})\log(1-h_\theta(x^{(i)}))]J(θ)=m1​∑i=1m​[−y(i)log(hθ​(x(i)))−(1−y(i))log(1−hθ​(x(i)))]
  • θ\thetaθ 損失関数の入力はθ\thetaθ
  • 🙄 けいしゃこうかほう


    けいしゃこうかほう

  • は関数と損失関数が異なると仮定するが,傾斜降下法を用いた方法は線形回帰と同じ
  • である.
  • θ\thetaθ すべての値を0に指定するか、またはすべてを
  • にランダムに指定します.
  • θ0\theta_0θ0​, θ1\theta_1θ1​, θ2\theta_2θ仮に2、3つあるとしたら
    θ0=θ0−α∂∂θ0J(θ)\theta_0=\theta_0-\alpha\frac{\partial}{\partial\theta_0}J(\theta)θ0​=θ0​−α∂θ0​∂​J(θ)
    θ1=θ1−α∂∂θ1J(θ)\theta_1=\theta_1-\alpha\frac{\partial}{\partial\theta_1}J(\theta)θ1​=θ1​−α∂θ1​∂​J(θ)
    θ2=θ2−α∂∂θ2J(θ)\theta_2=\theta_2-\alpha\frac{\partial}{\partial\theta_2}J(\theta)θ2​=θ2​−α∂θ2​∂​J(θ)
  • 損失関数を偏微分し、学習率αに従来のθ\thetaθ減算
  • 所有θ\thetaθ更新は、
  • の傾斜降下と言える
  • の違いは損失関数JJJJが異なることである
  • しかし、偏微分を行うと、線形回帰と同じ式が得られる.
    θj=θj−α1m∑i=1m(hθ(x(i))−y(i))∗xj(i)\theta_j=\theta_j-\alpha\frac{1}{m}\sum_{i=1}^m (h_\theta(x^{(i)})-y^{(i)})*x_j^{(i)}θj​=θj​−αm1​∑i=1m​(hθ​(x(i))−y(i))∗xj(i)​
  • の線形回帰とほぼ同じであるが,唯一異なるのは仮定関数hhhh
  • である.
  • 線形回帰仮定関数は一次関数であり、論理回帰仮定関数は信号関数
  • である.
  • hhに信号関数を導入するθ\thetaθ 更新値
  • 簡略傾斜降下法

  • θ=θ−α1m(XT∗error)\theta=\theta-\alpha\frac{1}{m}(X^T*error)θ=θ−αm1​(XT∗error)
  • 傾斜降下法の実施

    import numpy as np
    
    def sigmoid(x):
        """시그모이드 함수"""
        return 1 / (1 + np.exp(-x))
        
        
    def prediction(X, theta):
        """로지스틱 회귀 가정 함수"""
        return sigmoid(X @ theta)
        
    
    def gradient_descent(X, theta, y, iterations, alpha):
        """로지스틱 회귀 경사 하강 알고리즘"""
        m = len(X) 
        
        for _ in range(iterations):
            error = prediction(X, theta) - y
            theta = theta - alpha / m * X.T @ error 
        return theta
        
        
    # 입력 변수
    hours_studied = np.array([0.2, 0.3, 0.7, 1, 1.3, 1.8, 2, 2.1, 2.2, 3, 4, 4.2, 4, 4.7, 5.0, 5.9])  # 공부 시간 (단위: 100시간)
    gpa_rank = np.array([0.9, 0.95, 0.8, 0.82, 0.7, 0.6, 0.55, 0.67, 0.4, 0.3, 0.2, 0.2, 0.15, 0.18, 0.15, 0.05]) # 학년 내신 (백분률)
    number_of_tries = np.array([1, 2, 2, 2, 4, 2, 2, 2, 3, 3, 3, 3, 2, 4, 1, 2])  # 시험 응시 횟수
    
    # 목표 변수
    passed = np.array([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1])  # 시험 통과 여부 (0: 탈락, 1:통과)
    
    # 설계 행렬 X 정의
    X = np.array([
        np.ones(16),
        hours_studied,
        gpa_rank,
        number_of_tries
    ]).T
    
    # 입력 변수 y 정의
    y = passed
    
    theta = [0, 0, 0, 0]  # 파라미터 초기값 설정
    theta = gradient_descent(X, theta, y, 300, 0.1)  # 경사 하강법을 사용해서 최적의 파라미터를 찾는다
    theta
    
    
    # array([-1.35280508,  1.61640725, -1.83666046, -0.60286277])

    🙄 せいそくほうていしき


    正規方程式

  • 線形回帰は損失関数Jのみならずθ\thetaθ
  • ロギス回帰では損失関数JJJJ(ログ損失)が下に突き出ている場合は,傾斜降下法を用いると常に最適であるθ\thetaθ
  • しかしJJJの偏微分元素は線形ではなく、θ\thetaθeeeに含まれる指数には、指数に含まれる式を一次式で表すことはできず、単純なマトリクス演算で最小点
  • を見つけることはできない.

    🙄 scikit-learn回帰ロジック

    # 필요한 라이브러리 import
    from sklearn import datasets
    from sklearn.model_selection import train_test_split
    from sklearn.linear_model import LogisticRegression
    
    import pandas as pd  
    
    wine_data = datasets.load_wine()
    """ 데이터 셋을 살펴보는 코드
    print(wine_data.DESCR)
    """
    
    # 입력 변수를 사용하기 편하게 pandas dataframe으로 변환
    X = pd.DataFrame(wine_data.data, columns=wine_data.feature_names)
    
    # 목표 변수를 사용하기 편하게 pandas dataframe으로 변환
    y = pd.DataFrame(wine_data.target, columns=['Y/N'])
    
    # 데이터 분리
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 5)
    
    # 경고 메시지가 나오지 않게 학습시키기 전 아래 코드 한 줄 추가하기
    y_train = y_train.values.ravel()
    
    logistic_model = LogisticRegression(solver = 'saga', max_iter = 7500)
    
    # 모델 학습
    logistic_model.fit(X_train, y_train)
    
    # y값 예측
    y_test_predict = logistic_model.predict(X_test)
    
    # 테스트 코드
    score = logistic_model.score(X_test, y_test)
    y_test_predict, score
    
    
    # (array([0, 1, 0, 0, 2, 2, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0,
    #        1, 1, 1, 0, 1, 2, 0, 1, 1, 0, 0, 0, 2]), 0.72222222222222221)