들어가며
어제에 이어서 데이터 전처리와 시각화를 마친 후 간단한 모델을 학습시켜보는 머신러닝 기초를 다뤄보았다. 기억나는 만큼 복기해보자.
타이타닉 데이터 셋 활용
오류 수정
어제 수업 중에 타이타닉 데이터 셋을 활용해서 상관계수를 구하려다가 예상하지 못한 오류가 발생했었다.
`could not convert string to float`라는 오류였는데, 교수님께서 말씀하시길 버전 업데이트에 따른 오류라고 설명해주셨다. 문자열을 실수형으로 변환하지 못한다는 메시지였기 때문에 `select_dtypes()`를 사용해서 `include`에 `int`, `float`, `bool` 자료형을 지정해줌으로써 `string` 값을 제외시켜주었다. 의도한 결과는 다음과 같다.
# 오류 could not convert string to float -> string 값 제외
titanic2 = titanic.select_dtypes(include=[int, float, bool])
print(titanic2)
print(titanic2.shape)
titanic_corr = titanic2.corr(method='pearson')
print(titanic_corr)
print(titanic_corr.shape)
성인남자였을 때의 생존률과 운임요금에 따른 생존률의 각 상관계수를 구한 결과이다. 0에 가까울 수록 관계가 낮고, -1이나 1과 가까울 수록 관계가 높다.
print(f"성인남자의 생존률 : {titanic['survived'].corr(titanic['adult_male'])}") # -0.5570800422053259
print(f"운임요금의 생존률 : {titanic['survived'].corr(titanic['fare'])}") # 0.2573065223849622
다음은 히트맵으로 각 속성 간의 상관관계를 나타낸 것이다. 여기서 나이의 값이 문제가 되는데, 각 나잇대 간 값의 크기가 커서 bias가 매우 커질 수 있기 때문에 그 차이를 줄여야 한다. 따라서 각 나이대에 맞게 0부터 7까지 값을 할당해주었다. 재할당된 나이 값은 `age2`라는 새로운 변수에 저장해주었고, 성별도 남자는 1, 여자는 0으로 값을 수정해줬다. 가족의 수는 `형재자매와 배우자 수 + 함께 탑승한 부모, 자녀 수 + 자기자신(1)`으로 계산했다. 자기자신과의 상관관계는 1로 표시된다.
# heat_map : 열로써 상관관계를 봄, 빨간색일수록 서로 연관관계가 크다.
# 나잇 대 문제가 발생 10, 20, 30, 40, 50, 60, 70 -> 값이 커서 bias가 매우 커짐
def category_age(x:int) -> int: # 파라미터 자료형 명시, 반환 자료형 명시
if x < 10: return 0
elif x < 20: return 1
elif x < 30: return 2
elif x < 40: return 3
elif x < 50: return 4
elif x < 60: return 5
elif x < 70: return 6
else: return 7
# age를 가져와서 나이에 따른 category_age반환 값을 할당
titanic['age2'] = titanic['age'].apply(category_age) # 콜백 함수
# 성별을 숫자형태로 변환
titanic['sex'] = titanic['sex'].map({'male':1, 'female':0})
# sibsp: 동반한 형재자매와 배우자 수, parch : 함게 탑승한 부모, 자녀 수 총합, [+ 1:자기 자신]
titanic['family'] = titanic['sibsp'] + titanic['parch'] + 1
titanic.to_csv('NewTitanic.csv', index=False)
heat_map = titanic[['survived', 'sex', 'age2', 'family', 'pclass', 'fare']]
color_map = plt.cm.RdBu
sns.heatmap(heat_map.astype(float).corr(), linewidths=0.2,
vmax=1.0, square=True, cmap=color_map, linecolor='white',
annot=True, annot_kws={'size': 8})
plt.show()
선형 회귀 (Linear Regression)
선형 회귀란 알려진 다른 관련 데이터 값을 사용하여 알 수 없는 데이터의 값을 예측하는 데이터 분석기법이다. 아래는 간단한 선형 회귀 예제이다.
`fit()`메서드로 X와 y를 집어넣어 모델을 학습시킨다. `score()`는 모델의 성능을 평가하여 수치로 나타내주고, `coef_`는 x의 계수 즉, 그래프 기울기를 계산하여 나타낸다. `intercept_`는 절편을 나타낸다. 아래 예제에서는 `y = 1.25X + 2.75` 이라는 일차함수를 얻어냈다. 따라서 `predict()`메서드를 이용하여 X에 지정한 값을 식에 대입하면 그 값은 예측값이 된다. 아래 그래프를 보면 빨간 점들(입/출력 데이터)에 근접한 일차함수` y = 1.25X + 2.75 ` 그래프를 확인할 수 있다.
import matplotlib.pyplot as plt
from sklearn import linear_model
reg = linear_model.LinearRegression()
X = [[0], [1], [2],] # 입력 데이터
y = [3, 3.5, 5.5,] # 출력 : 정답, 레이블, 타겟 | y = wx^T + b -> 직선의 방적식
# 학습을 시킨다. fit()
reg.fit(X=X, y=y) # 모델을 학습시키는 함수
print(reg.score(X=X, y=y)) # 0.8928... -> 학습된 모델의 성능 평가
print(reg.coef_) # [1.25] -> x의 계수 (기울기)
print(reg.intercept_) # 2.750000 (절편)
print(reg.predict(X=[[5]])) # X에 5를 넣었을 때 예상 결과값
plt.scatter(x=X, y=y, color='red') # 빨간 점으로 표현
# plt.show()
y_predict = reg.predict(X=X) # x값에 따른 예측된 y값
plt.plot(X, y_predict, color='blue', linewidth=2)
plt.show()
로지스틱 회귀(Logistic Regression)
로지스틱 회귀란 일종의 확률 모델로서 독립 변수의 선형 결합을 이용하여 사건의 발생 가능성을 예측하는 데 사용되는 기법이다.
와인 데이터셋 활용
와인 데이터 셋을 활용하여 학습용 데이터와 테스트용 데이터를 추출한 후, 추출한 데이터를 바탕으로 로지스틱 회귀 모델을 학습시키는 과정이다.
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
# 데이터 셋 확인
wine = pd.read_csv(filepath_or_buffer="wine_csv_data.csv")
print(wine)
print(wine.head())
print(wine.shape)
print(wine.info())
# 지정한 속성을 numpy 배열 형태로 변환
data = wine[['alcohol', 'sugar', 'pH']].to_numpy() # 데이터
print(data)
print(data.shape)
target = wine['class'].to_numpy()
print(target) # 정답 (0과 1)
print(target.shape)
# 학습용 데이터와 테스트용 데이터로 분할(20%를 테스트 데이터로 사용)
(X_train, X_test, y_train, y_test) = train_test_split(data, target, test_size=0.2)
lr = LogisticRegression() # 로지스틱 회귀 모델 초기화
lr.fit(X=X_train, y=y_train)
print(lr.score(X=X_train, y=y_train)) # 0.777948816624976
print(lr.score(X=X_test, y=y_test)) # 0.7823076923076923
print(lr.coef_) # [[ 0.45818783 0.35160024 -3.99271497]]
print(lr.intercept_) # [7.88640625]
# weight 값 찾는 것이 중요
# 1. 다량의 데이터의 개수
# 2. 정규화
# 3. 규제화 norm
# 4. 데이터 증감
# 훈련데이터 : 테스트데이터 = 8:2 or 7:3
# cost function : 비용함수-뭔가를 하기위한 손해(미분)
# 학습 데이터는 반드시 2차원 배열이어야 함
붓꽃 데이터 셋을 활용한 머신러닝
붓꽃의 데이터 셋은 딕셔너리 형태로 되어있다. 키값 중 `data`의 value를 추출한 후 학습모델을 로지스틱 회귀 모델로 선택한다. 그리고 이 데이터를 학습용 데이터와 테스트용 데이터로 분할한다. 훈련 데이터는 전체의 80%로 사용했다. Weight와 Bias를 모두 구한 후 예측 성능 수치는 약 93%로 측정됐다. 또한 그래프에서 4개의 데이터 중 1개가 틀린 것을 확인할 수 있다.
from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from matplotlib import pyplot as plt
import numpy as np
# 붓꽃 데이터 셋 확인
iris = load_iris()
print(iris)
print(type(iris)) # shape안됨 : dictionary타입
print(iris.data) # data의 값 부분
print(type(iris.data)) # data의 값 부분은 넘파이 array타입
print((iris.data).shape)
# 붓꽃 데이터의 data 값부분 확인
data = iris.data
target = iris.target
print(target)
print(type(target))
print(target.shape)
# 학습용 데이터와 테스트용 데이터 분할
(X_train, X_test, y_train, y_test) = train_test_split(data, target, train_size=0.8)
print(X_train.shape)
print(X_test.shape)
# 머신러닝 모델 선택하기
regression = LinearRegression() # 생성자 호출
# 훈련 시키기
regression.fit(X_train, y_train)
print(f'Weight : {regression.coef_}') # x의 계수 [-0.08035508 -0.04461079 0.17601326 0.68920722]
print(f'Bias : {regression.intercept_}') # y절편 0.10834226231241928
print(regression.score(X_train, y_train)) # 훈련했을 때 맞춘 점수 %수치 0.933782629865521
# 예측 해보기 (X_test 사용하기)
y_predicts = regression.predict(X=X_test)
print(y_predicts)
print(y_predicts.shape)
# 정답 비교
print(y_test) # 정답표 출력
print(np.round(y_predicts).astype(int))
# 그래프 출력
rounded_y_predicts = np.round(y_predicts).astype(int)
plt.plot(rounded_y_predicts, y_test, 'b.') # 1개 틀림
plt.show()
당뇨병 데이터 셋 활용
당뇨병 데이터 셋에서 `bmi`만 추려낸 후 체질량지수 데이터와 함께 학습용 데이터, 테스트용 데이터로 분할하는 과정이다. 그래프를 그리는 과정은 다음시간에 마저 해보도록 하자.
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn import datasets
from sklearn.model_selection import train_test_split
# 당뇨병 데이터 가져오기
diabetes_X, diabetes_y = datasets.load_diabetes(return_X_y=True)
print(diabetes_X)
print(diabetes_X.shape)
print(diabetes_y)
print(diabetes_y.shape)
# bmi만 추려내서 2차원 배열로 만들기. bmi 특징의 인덱스가 2이다.
bmi = diabetes_X[:, np.newaxis, 2] # 축 생성
print(bmi)
print(bmi.shape)
# 학습용 데이터와 테스트용 데이터 분할
(X_train, X_test, y_train, y_test) = train_test_split(bmi, diabetes_y, test_size=0.2)
print(X_train)
print(X_train.shape)
print(X_test)
print(X_test.shape)
마무리
널리 쓰이는 데이터 셋이 라이브러리에 내장되어 있어서 매우 간편하게 데이터 셋을 활용할 수 있었던 점이 정말 편했다. 예측모델 그래프에 입출력 데이터가 근접해질수록 뿌듯함도 더해지는 것 같다.
'ABC부트캠프 테크노트' 카테고리의 다른 글
[21일차] ABC부트캠프 : ESG포럼 & 세미나3 (0) | 2024.08.02 |
---|---|
[20일차] ABC부트캠프 : 머신러닝2 (0) | 2024.07.31 |
[18일차] ABC부트캠프 : 머신러닝 - 라이브러리 기초 (0) | 2024.07.29 |
[17일차] ABC부트캠프 : 건양대 메디컬 캠퍼스 견학 (0) | 2024.07.26 |
[16일차] ABC부트캠프 : 데이터 분석 팀 프로젝트(2/2) (0) | 2024.07.25 |