<Logistic Regression with Scikit-learn>
로지스틱 회귀(Logistic Regression)란?
=> Adaline model에서 Activation function을 sigmoid 함수로 쓴 회귀 모델
sigmoid 함수가 어떻게 나왔는지 알아보자
Odds(승산) : 실패 비율 대비 성공 비율
성공확률을 $ p $라 하면, $$ Odds:=\frac{p}{1-p} $$
Logit : logistic + probit
$$ Logit(L):=ln(Odds)=ln \frac{p}{1-p} $$
위의 Logit에 대해 생각해보자
어떤 input $ x $가 주어지면 그에 대한 확률 $ p $는 고정적이다
p가 최대가 되는 것이 목적이므로 Logit에 따른 p의 함수로 변환해야 한다
$$ L= ln \frac{p}{1-p} $$
$$ e^L=\frac{p}{1-p}, \;\frac{1}{e^L}=\frac{1-p}{p}=-1+\frac{1}{p} $$
$$ \frac{1}{e^L}+1=\frac{e^L+1}{e^L}=\frac{1}{p} $$
$$ \therefore p=\frac{e^L}{e^L+1}=\frac{1}{1+e^{-L}} $$
이를 선형 회귀에 대입하면,
$$ L=\sum^n_{i=1}(w^T_ix_i)+b=z $$
$$ a=\sigma(z)=\frac{1}{1+e^{-z}} $$
<Chain Rule>
특정 방식을 사용해서 Loss(L)를 a를 이용하여 계산한다
따라서 다음과 같은 미분법이 가능하다
$$ \frac{\partial L}{\partial w_j}=\frac{\partial L}{\partial a}\frac{\partial a}{\partial z}\frac{\partial z}{\partial w_j} $$
Logistic Regression에서는 Binary Cross-Entropy Loss를 Loss function으로 사용한다
$$ BCE:=-(ylog(a)+(1-y)log(1-a)) $$
따라서 각각을 미분해보면 다음과 같다,
$$ \frac{\partial L}{\partial a}=\frac{a-y}{a(1-a)} $$
$$ \frac{\partial a}{\partial z}=a(1-a) $$
$$ \frac{\partial z}{\partial w_j}=x_j $$
$$ \frac{\partial L}{\partial w_j}=\frac{a-y}{a(1-a)}\times a(1-a)\times x_j $$
$$ =x_j(a-y) $$
<Logistic Regression Gradient Descent>
class LogisticRegressionGD:
def __init__(self, eta=0.01, n_iter=50, random_state=1):
self.eta = eta
self.n_iter = n_iter
self.random_state = random_state
def fit(self, X, y):
rgen = np.random.RandomState(self.random_state)
self.w_ = rgen.normal(loc=0.0, scale=0.01, size=X.shape[1])
self.b_ = np.float_(0.)
self.losses_ = []
for i in range(self.n_iter):
net_input = self.net_input(X)
output = self.activation(net_input)
errors = (y - output)
self.w_ += self.eta * X.T.dot(errors) / X.shape[0]
self.b_ += self.eta * errors.mean()
loss = -y.dot(np.log(output)) - ((1 - y).dot(np.log(1 - output))) / X.shape[0]
self.losses_.append(loss)
return self
def net_input(self, X):
return np.dot(X, self.w_) + self.b_
def activation(self, z):
return 1. / (1. + np.exp(-np.clip(z, -250, 250)))
def predict(self, X):
return np.where(self.activation(self.net_input(X)) >= 0.5, 1, 0)
아래와 같이 X.shape[0] 으로 나누는 이유는 뭘까
self.w_ += self.eta * X.T.dot(errors) / X.shape[0]
self.b_ += self.eta * errors.mean()
loss = -y.dot(np.log(output)) - ((1 - y).dot(np.log(1 - output))) / X.shape[0]
Gradient Descent를 하는 과정에서 하나의 데이터로 업데이트하면 편향될 가능성이 크다
따라서 평균을 취해주는 것이다
다음과 같이 결과가 나온다
'AI > ML PyTorch Scikit-Learn' 카테고리의 다른 글
Ch3. SVM(Support Vector Machine) (6) | 2024.07.23 |
---|---|
Ch3. Overfitting Prevent Method (0) | 2024.07.16 |
Ch3. Scikit-learn (0) | 2024.07.08 |
Ch2. Adaline, 로스와 경사하강법(Adaline, Loss and Gradient Descent) (0) | 2024.07.02 |
Ch2. 퍼셉트론(Perceptron) (0) | 2024.06.27 |