본문 바로가기
AI/머신러닝

[머신러닝] 로지스틱

by snow_white 2022. 4. 16.

Logistic Regression

  • 선형 회귀 방식을 이용한 이진 분류 (binary classification)알고리즘
  • 우리가 분류해야 하는 class가 두 개
  • 분류 레이블 : 0 or 1
  • 0~1 범위를 예측 결과로 갖는 모델 필요
    • 가설 결과에 Sigmoid 함수 적용
  • Logistic, sigmoid 함수 
    • S자 모양의 함수
    • Logistic, sigmoid 함수
    •  e^(-z) ⇒ np.exp(-z) 사용
    • 𝑧 값을 0과 1사이의 값으로 바꾸는 함수

 

 

Sigmoid 함수 원리

11=111=1인데, 분모 1에다 0보다 크거나 같은 어떤 수를 더 하면 그 결과는 1 보다 클 수 없다.

분모에 더 할 값은 𝑒^-𝑧, 이 값은 어떤 𝑧가 주어져도 0보다 작아 지지 않는다.

𝑒^-𝑧는 𝑧의 값이 크면 클 수록 0에 가까운 작은 수가 되고 𝑧z값이 작으면 무한대에 가까운 큰 수가 된다

따라서 𝑧의 값이 크면 𝑒^-𝑧의 값이 작아져서 1/1+𝑒^-𝑧의 값은 1에 가까워 지고 그 반대는 0에 가까워 진다.

  • sklearn API
    • sklearn.linear_model.LogisticRegression

 

Sigmoid 함수 그리기

# 이진 분류에 쓰이는 sigmoid
import numpy as np
import matplotlib.pyplot as plt
# e는 np.exp()로 
def sigmoid(z):
    return 1 / (1+np.exp(-z))
plt.figure(figsize=(10, 7))

x = np.arange(-10, 10)
y = sigmoid(x)

plt.plot(x, y)
plt.show()

 

로지스틱 회귀 실습

plt.figure(figsize=(8,6))
x = np.array([1,2,3,4,5,6,7,8,9,11,13])
y = np.array([0,0,0,0,0,0,0,1,1,1,1])

plt.scatter(x,y)
plt.show()

 

 

⇒ 이 그래프는 linear로 예측할 수 없으므로 부득이 하게 아래와 같이 표현해야 함

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.linear_model import LinearRegression
from sklearn.metrics import accuracy_score

model = LinearRegression()
model.fit(x.reshape(-1,1),y)
pred = model.predict(x.reshape(-1,1))

plt.figure(figsize=(8,6))
plt.scatter(x,y)
plt.plot(x, pred, c ='r')
plt.show()

 

linear regression을 가미한 rogistic regression이다!

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

model = LogisticRegression()
model.fit(x.reshape(-1,1),y)
pred = model.predict(x.reshape(-1,1))

plt.figure(figsize=(8,6))
plt.scatter(x,y)
plt.plot(x, pred, c ='r')
plt.show()

 

정확도 예측

아래 두 표현 동일

#정확도
(pred==y).mean() # 1.0
accuracy_score(pred, y) # 1.0

 

로지스틱 회귀 실습 : 위스콘신 유방암 환자 데이터

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.model_selection import train_test_split

from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_breast_cancer

# 데이터셋 로드
cancer = load_breast_cancer()

# 데이터 프레임 
df = pd.DataFrame(cancer['data'], columns=cancer['feature_names']) # data안에는 feature만 들어감!
df['target'] = cancer['target']
df

암 0, 정상 1

이런 데이터는 nomalization보다 standardization 성능이 더 높다.

# standardization

scaler = StandardScaler()
scaled = scaler.fit_transform(df.drop('target',axis=1)) # target만 뺀 데이터 넣어야 함

# 데스트 분할하기
x_train, x_test, y_train, y_test = train_test_split(scaled, df['target'], random_state=10)

# 모델 생성 LogisticRegression 모델생성 / 학습하고 / 예측하기
model = LinearRegression()
model.fit(x_train, y_train)
# 예측
pred = model.predict(x_test)
#정확도 측정
accuracy_score(pred, y_test) # 0.958041958041958

분류 모델 평가지표 Accuracy = 예측결과가 동일한 데이타 건수 / 전체 예측 데이타 건수

  1. 직접 확인y_test 결과와 predict 결과를 서로 비교해보면 100% 일치하고 있지 않은 부분들이 두군데 보인다. 직접 확인..
  2. 사용자 함수 정의y_test, predict 이 2개의 변수를 비교해서 성능을 측정할수 있다. 아래는 함수를 이용해서 성능평가 함수를 직접 구현해서 만든것임.
  3. score() 라이브러리 사용accuracy_score 함수를 이용해서 성능측정 한다. from sklearn.metrics import accuracy_score Confusion Matrix
  4. 정밀도(Precision)
  5. 재현율(Recall)
  6. F1 Score

 

Accuracy

직접확인

pred = model.predict(x_test)
pred
'''
array([0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0,
       1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
       1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0,
       1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0,
       1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
       1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
       0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0])
'''
y_test
'''
172    0
553    1
374    1
370    0
419    1
      ..
545    1
161    0
434    1
59     1
164    0
Name: target, Length: 143, dtype: int32
'''
# zip : 두개의 리스트값을 병렬적으로 추출하는 기능
# 2)
y_tuple=list(zip(y_test, pred))
y_tuple
'''
[(0, 0),
 (1, 1),
 (1, 1),
 (0, 0),
 (1, 1),
 (1, 1),
 (1, 1),
.
.
.
'''

 

사용자함수 정의

count = 0
for a,b in y_tuple:
    if not a==b:
        count = count+1
        print('unmatched : (y_test, pred)=(',a,',',b,')')  
print('UnMatched Target',count,'개')
'''
unmatched : (y_test, pred)=( 0 , 1 )
unmatched : (y_test, pred)=( 1 , 0 )
unmatched : (y_test, pred)=( 0 , 1 )
unmatched : (y_test, pred)=( 1 , 0 )
unmatched : (y_test, pred)=( 1 , 0 )
unmatched : (y_test, pred)=( 1 , 0 )
UnMatched Target 6 개
'''
len(y_test) # 143

 

accuracy_score 함수사용

# accuracy = accuracy_score(y_test, pred)
accuracy = accuracy_score(pred,y_test)
print(accuracy) # 0.958041958041958

 

오차 행렬 (Confusion Matrix)

성능지표에서 잘 활용되는 있는 오차행렬은 학습된 분류모델이 예측을 수행하면서 얼마나 헷갈리고(Confusion) 있는지도 잘 보여주는 지표이다.

 

아래 코드의 결과를 보면 a와 b의 오차 행렬 결과로 아래 두 가지 특징을 보인다.

  1. cherry를 apple로 잘못 예측
  2. cherry를 banana로 잘못 예측
from sklearn.metrics import confusion_matrix
from IPython.display import Image
# 샘플데이타
y_true=[2,0,2,2,0,1]
y_pred=[0,0,2,2,0,2]
confusion_matrix(y_true, y_pred)
'''
array([[2, 0, 0],
       [0, 0, 1],
       [1, 0, 2]], dtype=int64)
'''
a = ['cherry','apple','apple','banana','cherry'] #Label
b = ['banana','apple','apple','banana','apple'] #Predict
confusion_matrix(a, b) # 라벨 a 먼저, 그 다음 데이터 b 순서
'''
array([[2, 0, 0],
       [0, 1, 0],
       [1, 1, 0]], dtype=int64)
'''
a = ['cherry','apple','apple','banana','cherry'] #Label
b = ['banana','apple','apple','banana','apple'] #Predict
confusion_matrix(a, b) # 라벨 a 먼저, 그 다음 데이터 b 순서
'''
array([[2, 0, 0],
       [0, 1, 0],
       [1, 1, 0]], dtype=int64)
'''

 

실제 데이터 적용

cm = confusion_matrix(y_test, pred)
cm
''' 이차원 배열 구조
array([[50,  2],
       [ 4, 87]], dtype=int64)
'''
cm = pd.DataFrame(confusion_matrix(y_test, pred), columns=cancer['target_names'],
                                                index = cancer['target_names']
                 )
cm

 

import seaborn as sns

plt.figure(figsize=(6,5))
sns.heatmap(cm, annot=True, annot_kws={'size':20}, cmap='Blues')
plt.xlabel('Predict', fontsize=20)
plt.xlabel('Actual', fontsize=20)

 

위의 2 표시 되는 곳으로 표시한 곳이 암인데 정상으로 예측했기 때문에 더 위험하다. 

위의 경우를 잡아내는 것이 recall 이라고 한다.

 

 

 

Accuracy와 함께 사용되는 보조 지표로서 재현율인 Recall 과 정밀도인 Precision 두 가지 서로 trade off 관계이기 때문에 둘을 종합적으로 판단하는 f1score를 사용한다.

 

Accuracy

보조지표 두 가지

분류 문제에서 정확도와 재현율을 ~하는 것이 가장 중요

  • Recall (재현율)
    • 가로 방향 (암, 정상 순서)
    • 암 환자가 원래는 52가 나아야 하는데 50명밖에 안 나옴, 2명은 정상으로 오진단
    진단에서는 검출률, 재현율(recall)이 중요하다! 특히 암 recall 부분 윗 부분이 중요하다.
  • Precision (정밀도)
    • 세로 방향 (암, 정상 순서)
    • 정상인데 암으로 4명을 예측함, 따라서 암진단에서는 precision이 별로 중요하지 않다.

댓글