Skip to content

인공지능 컴퓨터 비전 Tensorflow 3화 – 로지스틱회기 logistic regression

titanic

Logistic Regression 이란

  • Logistric Regression = Linear Regression + classification (0, 1 사이의 확률값)
  • Target data가 0, 1이다.

Linear Regression (wx + b) -> classification (sigmoid) -> 0 ~ 1

  • – activation 함수
  • linear regression -> linear
  • Logistic Regression
  • -> sigmoid, 1 / 1+e-x
  • logistic, 1 / 1+e-(wx+b)
  • – loss 변경
  • 기존linear regression은 loss는 MSE를 사용
  • logistic에서는 binary_crossentropy 사용 (crossentropy는 다향 분류의 loss 함수)

Logistic Regression 성능평가

Confusion Matrix : 실제정답과 예측값을 비교한 매트릭스

평가지표 종류

1. Accuracy (정확도)

전체 예측건수에서 정답을 맞춘건수에 대한 비율

  • accuracy = (TP+TN)/(TP+TN+FP+FN)
  • 정확도 단점 : 데이터의 bias(편차)를 고려하지 않고 있다.
  • 예) 소수의 케이스를 알아낼때 (암, 희귀병 데이터는 편향이 크다). 편향이 있는 데이터는 정확도로 모델의 정확한 평가가 힘들다.

2. Recall (재현율) – hit rate

  • 실제 True 중에서 우리 model 이 실제로 True로 예측한 비율
  • 편차가 심한경우 recall을 사용하는게 좋다.
  • Recall = TP / (TP + FN)

3. Precision (정밀도)

  • 우리 model 이 True로 예측한 것중에 정말 True인 비율
  • Precison = TP / (TP + FP)

recall과 precision은 반비례 관계이다. 두가지 성능평가 지표를 적적히 합쳐 높은게 있다.

4. F1 score

  • F1 Score은 Precision과 Recall의 조화 평균
  • F1 Score
    = 2 * 1 / ((1/precision) + (1/recall))
    = 2 * (precison * recall)/(precision + recall)

5. ROC Curve, AUC

6. Log-loss

학습 데이터

  • – Traning Data, Validation Data, Test Data
  • – Overfit (과적합) 방지를 위해 데이터를 나눠서 테스트, 평가를 해야 함.

Logistic Regression의 가장 대표적 문제를 풀어보자.

Kaggle Titanic – Machine Learning from Disaster

https://www.kaggle.com/competitions/titanic

위의 링크에서 데이터셋을 다운 받기

import numpy as np
import pandas as pd

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.optimizers import SGD, Adam

df = pd.read_csv("train.csv")
df.head()
# passengerId : 승객번호 => 필요없는 feature
# survied : 생존여부(0: 사망, 1: 생존) => 종속변수
# Pclass : 1,2,3 (1등급이 가장 좋다. 3등급 안좋아요.) => feature
# Name : 이름 => 삭제대상
# Sex : 성별 => feature
# Age : 나이 => feature
# SibSp : 형제와 배우자 1, 0 => 가족
# Parch : 부모와 자식 => 가족
# Ticket : 티켓 번호 => 삭제대상
# Fare : 요금 => 삭제 대상
# cabvin : 객실 번호 => 삭제 대상
# Embarked : 승선한 곳 (S, C, Q) -- 지역명 - 상식적으로는 삭제대상이 맞지만... 상관관계분석을 해보면 영향을 주고 있다.

df = pd.read_csv("train.csv")
train = df
# 사용하지 않는 컬럼 제거
train.drop(['PassengerId', 'Name', 'Ticket', 'Fare', 'Cabin'], axis=1, inplace=True)
display(train)

# 성별처리 male=0, female = 1
gender_mapping = { 'male': 0, 'female': 1}
train['Sex'] = train['Sex'].map(gender_mapping)

# 가족처리
train['Family'] = train['SibSp'] + train['Parch']

train.drop(['SibSp', 'Parch'], axis=1, inplace=True)

display(train)

# Embark 결측치 처리
print(train['Embarked'].isna().sum()) # 2개 결측치가 있다.

train['Embarked'] = train['Embarked'].fillna('Q')
embarked_mapping = { 'S': 0, 'C': 1, 'Q': 2}
train['Embarked'] = train['Embarked'].map(embarked_mapping)

display(train)

train.isna().sum()
# age에 결측치가 많이 보인다.

# Age에 대한 평균값으로 결치값을 대치
train['Age'] = train['Age'].fillna(train['Age'].mean())
display(train)

# Age Binning 처리(Numerical Value -> Categorical Value)
# 정규화를 위해. 다른 수치와 차이가 많기 때문에 age에 편향이 될 수 있다. (전처리)
train.loc[train['Age'] < 8, 'Age'] = 0
train.loc[(train['Age'] >= 8) & (train['Age'] < 20), 'Age'] = 1
train.loc[(train['Age'] >= 20) & (train['Age'] < 65), 'Age'] = 2
train.loc[train['Age'] >= 65, 'Age'] = 3

display(train)

# 마지막 values를 입력하면 dataframe이 아니라 numpy array로 변환
x_data = train.drop('Survived', axis=1, inplace=False).values
t_data = train['Survived'].values.reshape(-1, 1)

model = Sequential()
model.add(Flatten(input_shape=(5,)))
model.add(Dense(units=1,
                activation='sigmoid'))
model.compile(optimizer=Adam(learning_rate=1e-2),
              loss='binary_crossentropy',
              metrics=['accuracy'])

model.fit(x_data,
          t_data,
          epochs=300,
          verbose=1,
          validation_split=0.3)

# 학습이 끝나서 모델이 만들어졌으면...
# test.csv를 이용해서 결과파일을 만들어야 합니다.
# kaggle에 제출하면 끝.
test = pd.read_csv('test.csv')
submission = pd.read_csv('gender_submission.csv')

display(test.head())
display(submission.head())

# 테스트데이터 전처리
# 사용하지 않는 column 제거
test.drop(['PassengerId', 'Name', 'Ticket', 'Fare', 'Cabin'], axis=1, inplace=True)

# 성별 처리
gender_mapping = { 'male' : 0, 'female' : 1 }
test['Sex'] = test['Sex'].map(gender_mapping)

# 가족처리
test['Family'] = test['SibSp'] + test['Parch']
test.drop(['SibSp', 'Parch'], axis=1, inplace=True)

# Embarked 결측치 처리
test['Embarked'] = test['Embarked'].fillna('Q')

# Embarked 문자를 숫자로 변환
embarked_mapping = { 'S' : 0, 'C' : 1, 'Q' : 2 }
test['Embarked'] = test['Embarked'].map(embarked_mapping)

# Age 결측치 처리
test['Age'] = test['Age'].fillna(test['Age'].mean())

# Age Binning 처리(Numerical Value -> Categorical Value)
test.loc[test['Age'] < 8, 'Age'] = 0
test.loc[(test['Age'] >= 8) & (test['Age'] < 20), 'Age'] = 1
test.loc[(test['Age'] >= 20) & (test['Age'] < 65), 'Age'] = 2
test.loc[test['Age'] >= 65, 'Age'] = 3

display(test)

predict = model.predict(test)

submission['Survived'] = predict
submission['Survived'] = submission['Survived'].astype('int')
submission.to_csv('sub.csv', index=False)
error: Content is protected !!