→ 셋 다 맞는 말(공통된 특성을 가지기 때문)
→ 하지만 Case by case로 머신러닝을 이해하려면 어려운 부분이 있음(워낙 다양하기 때문)
🡆 용어를 먼저 익히고 용어 간 상하관계, 군집할 수 있는 것 무엇인지 파악해 전체적인 틀 익히기

인간 → 항상 (동일한) 실수를 함: 마음이 급함, 편향된 사고, 마음이 가는 데로 결정 등 → 이를 극복하고 싶어 함 → '통계'도 이런 이유로 발전함

비용(돈&시간)의 한계 때문에 전체 모집단의 성질을 알 수 없음 → 표본을 뽑아 반대로 모집단의 성질을 알아 내기 위한 일련의 과정을 통해 통계학이 발전하게 됨
요즘은 왜 AI가 발달? → 데이터 처리 기술이 발달했기 때문!

🡆 ML/DL 프로세스가 발전한 것은 데이터를 수집하기가 용이해졌기 때문!


→ "통계학에서는 꼭 필요한 '가정' 없이 데이터를 싹 다 모아서 그걸로 패턴을 발견해 보자!"라는 것이 머신 러닝의 기조

ML
DL
자연과학, 공과 대학 등 실험을 기반으로 하는 연구는 연구노트를 사용합니다. 기존 script 코드 파일은 실험과 연구에 대한 결과를 남기기엔 메모와 시각화 기능이 약하여 cell 기반으로 연구 노트북의 형태인 Jupyter Notebook이 개발되었습니다.
conda create -n venv python=3.8conda activate venvpip install ipykernelpython -m ipykernel install --user --name=venvjupyter kernelspec listjupyter kernelspec uninstall venvJava Script Object Notation 의 약자
데이터를 표시하는 방법 중 하나
사용 이유
구조
예시
{
"name":"Jack",
"age":30,
"contactNumbers":[
{
"type":"Home",
"number":"123 123-123"
},
{
"type":"Office",
"number":"321 321-321"
}
],
"spouse":null,
"favoriteSports":[
"Football",
"Cricket"
]
}
pip install {라이브러리명}라이브러리명.__version__import pandas as pd
pd.__version__pip uninstall pandaspip uninstall pandas -y방정식을 배운 머신이는 몸무게와 키의 데이터를 획득했다. 일정하게 증가하는 패턴이 있어서 미리 몸무게를 알면 키를 알 수 있을 것이라고 생각했다.
weights = [87,81,82,92,90,61,86,66,69,69]
heights = [187,174,179,192,188,160,179,168,168,174]

중학교 1학년 때 1차 방정식을 배운 머신이는 키와 몸무게에 대한 데이터가 너무 많아서 무슨 두 점을 이어 직선을 만들지 고민 되었지만, 수 많은 점들을 관통하는 여러 개의 직선을 많이 그려보기로 했다.

머신이는 3개의 그래프를 그려보니, 아무래도 초록색, 파란색 직선보다는 빨간색 그래프가 적절한 것 같다. 하지만 이렇게 대강 직선을 그리다 보면 적절한 그래프를 찾기 어려울 것 같아 고민에 빠졌다.
머신이는 하나의 생각을 떠 올렸다. 바로 직선과 점의 간의 거리를 계산하는 것이다. 이를 Error 라고 정의하고 최소의 Error인 직선을 그리면 된다고 생각했다.

하지만 문제가 또 있었다. 선분을 기준으로 위에 있는 데이터의 거리를 계산하면 양수가 되고, 반대로 아래에 있는 것은 음수가 된다. 이 경우 모든 에러를 합치면 서로 상쇄되는 문제가 있었다. 따라서, 음수를 양수로 만들기 위해 제곱을 하는 방법이 있다는 걸 생각해 냈다.

문제는 하나 더 있었다. 나중에는 데이터를 더 수집할 예정인데, 데이터가 더 늘어날 수록(④,⑤) 에러는 자연스럽게 값이 커질 수 밖에 없는 것이다! 그래서 데이터의 갯수로 나누기로 했다. 또한 데이터가 제곱 되어 있던 것을 줄이기 위해 root를 씌우기로 했다.

머신이는 몸무게를 알면 키를 알 수 있을 것이라 생각했어요. 이를 이용해서 방정식을 세우고 용어를 정리해볼게요.
통계학과 컴퓨터 공학 두 학문을 바탕으로 발전해와서 같은 원리지만 부르는 명칭이 살짝 달라요!
→ 회귀 계수: 직선의 기울기, 편향+오차: y절편
결국 두 수식이 전달하려고 하는 의미는 같아요. 회귀 계수 혹은 가중치를 값을 알면 X가 주어졌을 때 Y를 알 수 있다는 것이죠!(→ True값은 모르지만 근사값은 알 수 있음)
우리는 편의를 위해 X의 계수는 가중치라고 지칭할게요!

몸무게와 키 데이터를 이용해서 선형회귀 식을 만들면, y = 0.86x + 109.37 이 나와요. 이 뜻은, 1kg 증가할때마다 키가 0.86 cm 증가한다는 것으로 해석 할 수 있어요.
머신이가 똑똑하게 에러를 정의한 것을 바탕으로 회귀식의 평가지표를 만들어보겠습니다. 머신이가 정리한 내용을 다시 써볼까요?
에러 = 실제 데이터 - 예측 데이터로 정의→ 수식화
1.
2.
3.
※ y값의 머리에 있는 ^는 hat이라고 하며, 예측(혹은 추정)한 수치에 표기
앞으로 만나는 숫자 예측 문제는 모델을 머신러닝이든 딥러닝이든 어떤 모델을 만들어도 위 MSE 지표를 최소화하는 방향으로 진행하고 평가합니다!
숫자를 예측하는 회귀분석에서, 선형회귀에서만 평가되는 지표가 1개 더 있어요. 그건 바로 R Square 지표입니다. R Square는 전체 모형에서 회귀선으로 설명할 수 있는 정도를 뜻합니다.
어떤 값을 “예측”한다는 건 어림짐작으로 평균값보단 예측을 잘해야한다는 것을 의미해요. 예컨대, 키의 평균 값이 176.9인데 이 값으로 모두 예측한 것보다는 잘해야겠죠?
회귀 == 숫자(y) 맞추기
↕
분류 == 범주(y=0, y=1) 맞추기


머신러닝을 쉬행하기 위한 대표적인 라이브러리인 scikit-learn과 그 외에도 자주 쓰이는 대표적 라이브러리 설치하기
scikit-learn: Python 머신러닝 라이브러리numpy: Python 고성능 수치 계산을 위한 라이브러리pandas: 테이블 형 데이터를 다룰 수 있는 라이브러리matplotlib: 대표적인 시각화 라이브러리, 그래프가 단순하고 설정 작업 많음seaborn: matplot기반의 고급 시각화 라이브러리, 상위 수준의 인터페이스를 제공sklearn.linear_model.LinearRegression : 선형회귀 모델 클래스coef_: 회귀 계수intercept: 편향(bias)fit: 데이터 학습predict: 데이터 예측import sklearn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
weights = [87,81,82,92,90,61,86,66,69,69]
heights = [187,174,179,192,188,160,179,168,168,174]
# dictionary 형태로 데이터 생성
body_df = pd.DataFrame({'height': heights, 'weight': weights})
# weight와 height 간의 산점도(scatter plot)
sns.scatterplot(data = body_df, x='weight', y='height')
plt.title('Weight vs Height')
plt.xlabel('weight(kg)')
plt.ylabel('Height(cm)')
plt.show()

→ 두 개가 선형 관계가 있음을 확인: 선형회귀를 적용할 수 있다고 판단
# 선형회귀 훈련Train(적합Fit)
from sklearn.linear_model import LinearRegression
model_lr = LinearRegression()
# DataFrame[]: Series(데이터프레임의 컬럼)
# DataFrame[[]]: DataFrame
X = body_df[['weight']]
y = body_df[['height']]
# 데이터 훈련
model_lr.fit(X=X, y=y)
w1 = model_lr.coef_[0][0]
w0 = model_lr.intercept_[0]
# print('y = {}x + {}'.format(w1.round(2), w0.round(2)))
print(f'y = {w1.round(2)}x + {w0.round(2)}')
# 실행 결과
# y = 0.86x + 109.37
※ type(model_lr)하면 sklearn.linear_model._base.LinearRegression이라고 나와야 함
※ X는 대문자, y는 소문자로 적는 게 관습이라고 함
y = 0.86x + 109.37# 예측값 만들기
body_df['pred'] = w1*body_df['weight'] + w0
# 에러
body_df['error'] = body_df['height'] - body_df['pred']
# 양수를 만들기 위해 제곱
body_df['error^2'] = body_df['error']*body_df['error']
# MSE 계산
body_df['error^2'].sum()/len(body_df)
# 실행 곃과:
# np.float64(10.152939045376309)
# 산점도 그래프에 선형식(추세선)을 만들어서 그래프로 그래기
sns.scatterplot(data=body_df, x='weight', y='height')
sns.lineplot(data=body_df, x='weight', y='pred', color='red')

# 선형회귀 모델 평가
# 회귀(숫자를 맞추는 방법): MSE(수동 계산 결과는 10)
# R Square: 평귱 대비 설명력, 값이 0이면 제일 낮고 1일수록 높은 것
# from sklearn.metrics import mean_squared_error
# from sklearn.metrics import r2_score
from sklearn.metrics import mean_squared_error, r2_score
# metrics: 평가함수 모음
# 평가함수는 공통적으로 정답(실제 true), 예측값(pred) 넣어야 함
y_true = body_df['height']
y_pred = body_df['pred']
mean_squared_error(y_true, y_pred)
# 실행 결과:
# np.float64(10.152939045376309)
r2_score(y_true, y_pred)
# 실행 결과:
# 0.8899887415172141
# 추가: 예측값(pred)을 함수로 만들 수도 있음
y_pred2 = model_lr.predict(body_df[['weight']])
y_pred2
→ 실행 결과:
array([[184.40385835],
[179.22878362],
[180.09129608],
[188.71642061],
[186.99139571],
[161.97853455],
[183.54134589],
[166.29109682],
[168.87863418],
[168.87863418]])
모르는 걸 찾을 때 공식 문서를 읽는 습관을 들이면 좋아요!
- 구글링 → 블로그
- 단점: 늘 블로그가 바뀜, 형태가 일정하지 않음
- ChatGPT LLM
- 단점: 의존하게 되면 더 이상 공부를 안함, 거짓된 정보를 전달하는 경우도 있음(hallucination)
- 공식 문서
- 장점: 일관되게 정리되어 있어 동일한 위치(경로)에 똑같은 내용이 있음
- 자격증 시험: 공식 문서만 열람할 수 있음
- 단점: 초보자에게는 읽기 어려움
help(): 인터넷 안 될 때도 쓸 수 있다는 장점
→ 아니면 mouse over했을 때 나오는 내용 읽는 것도 추천
help(sklearn)help(sklearn.linear_model.LinearRegression)
파이썬 라이브러리에 내장되어 있는 tip에 대한 데이터로 실제 회귀분석을 진행해봅시다.
식당에서 파트타임으로 일하고 있는 머신이는 이번에는 tip 데이터를 가지고 적용해보기로 했습니다. 돈을 많이 벌고 싶었던 머신이는 전체 금액(X)를 알면 받을 수 있는 팁(Y)에 대한 회귀분석을 진행해볼 예정입니다.
tips_df = sns.load_dataset('tips')
tips_df.head(3)
tips_df.head()
# 산점도 그리기
sns.scatterplot(data=tips_df, x='total_bill', y='tip')

# X: total_bill, y: tip
model_lr2 = LinearRegression()
X = tips_df[['total_bill']]
y = tips_df[['tip']]
model_lr2.fit(X, y)
# y(tip) = w1_tip*x(total_bill) + w0_tip
w1_tip = model_lr2.coef_[0][0]
w0_tip = model_lr2.intercept_[0]
print(f'y = {w1_tip.round(2)}x + {w0_tip.round(2)}')
# 실행 결과:
# y = 0.11x + 0.92
# 해석: 전체 결제 금액이 1달러 오를 때, 팁은 0.11달러 추가된다.
# scaling: 전체 결제 금액이 100달러 오를 때, 팁은 11달러 추가된다.
# 예측값 생성
y_true_tip = tips_df['tip']
y_pred_tip = model_lr2.predict(tips_df[['total_bill']])
mean_squared_error(y_true_tip, y_pred_tip)
# 실행 결과:
# np.float64(1.036019442011377)
r2_score(y_true_tip, y_pred_tip)
# 실행 결과:
# 0.45661658635167657
→ MSE는 스케일 다르면 1대 1로 비교 X 🡆 같은 데이터에서 다른 모델에 비교할 때만 사용
→ R Square는 '분야'마다 적정 기준치가 있음: 데이터가 사회·문화, 경제 쪽 통계라면 40%(0.4) 넘으면 좋다고 보기도 함
# 산점도와 선형회귀 선 그리기
tips_df['pred'] = y_pred_tip
sns.scatterplot(data=tips_df, x='total_bill', y='tip')
sns.lineplot(data=tips_df, x='total_bill', y='pred', color='red')
🡆 문제: R Square가 낮은 게 문제임 → total_bill 말고 다른 변수를 넣어보고 싶다… 하지만 어떻게?
🡆 X 변수를 여러 개 넣고 싶다! → 다중선형회귀
🡆 변수형 데이터를 어떻게 사용해야 하나?
지금까지는 X와 Y간의 데이터에 아주 간단한 단순회귀분석에 대해서만 배웠지만 실제의 데이터들은 비선형적 관계를 가지는 경우가 많습니다. 이를 위해서 X변수를 추가 할 수도, 변형할 수 도 있습니다.


머신이는 데이터 선형회귀를 훈련 시켰지만 성능이 별로 좋지 않다는 것을 알게 되었습니다. → R Square값이 0.4 정도 나왔음
그래서 성별과 같은 다른 데이터를 사용하고 싶어졌습니다. 그런데 문제는 성별 데이터는 문자형이여서 숫자로 표현할 방법이 필요해졌습니다.
# 범주형 데이터 사용하기
# Female 0, Male 1
def get_sex(x):
if x == 'Female':
return 0
else:
return 1
# apply method는 매 행에 특정한 함수를 적용한다.
tips_df['sex_en'] = tips_df['sex'].apply(get_sex)

# 모델설계도 가져오기
model_lr3 = LinearRegression()
X = tips_df[['total_bill', 'sex_en']]
y = tips_df[['tip']]
# 훈련
model_lr3.fit(X,y)
# 예측
y_pred_tip2 = model_lr3.predict(X)
y_pred_tip2[:5]
# 단순선형회귀 mse: X 변수가 전체 금액
# 다중선형회귀 mse: X 변수가 전체 금액, 성별
print('단순선형회귀', mean_squared_error(y_true_tip, y_pred_tip))
print('다중선형회귀', mean_squared_error(y_true_tip, y_pred_tip2))
# R Square
print('단순선형회귀', r2_score(y_true_tip, y_pred_tip))
print('다중선형회귀', r2_score(y_true_tip, y_pred_tip2))
→ 생각보다 성능이 좋아지지 않았음: 데이터를 살펴보지 않고 무작정 넣어서 돌렸기 때문임
🡆 사실 머신러닝 돌리기 전에 먼저 안에 있는 데이터가 어떤지 확인하고 전처리를 해서 해당 범주형 데이터가 분석을 진행할 만한지 확인하는 과정이 선행되어야 함!
sns.barplot(data=tips_df, x='sex', y='tip')

🡆 성별에 따른 Tip의 평균을 비교한 그래프 → 크게 차이가 나지 않음
🡆 전체 데이터에 대해 이러한 과정을 먼저 진행해 사전에 데이터를 확인한 후에 머신러닝 모델에 "의미가 있을 만한 것"을 넣는 게 올바른 흐름: 이 과정을 '변수 선택'이라고 함
머신러닝모델 중에 선형회귀는 이해하기 쉽고 방법도 쉬운 장점이 있지만 말 그대로 X-Y변수 간의 선형적 관계가 좋아아만 좋은 성능을 냅니다. → 선형회귀의 가정에 대해서 알아보자!

🡆 예시로 사용한 body_df의 경우 값이 0.9였고 tips_df는 0.4였음 → x, y 간 선형성이 더 있는 body_df 데이터가 값이 더 큼!(선형에 가깝다)
☞ X축:독립변수, Y축: 에러


다중공선성 문제
Weight vs Height 산점도

☞ pairplot 기능을 이용한 산점도

→ iris dataset: x값 4개 가짐
→ 같은 x값을 만나면 히스토그램을 그리고, 다른 x값을 만나면 산점도를 그림
→ petal_length와 petal_width가 강력한 선형 관계가 있음을 확인
🡆 따라서 다중공선성을 해결하려면 둘 중 하나만 가져가야 함!
☞ heatmap을 이용한 상관관계 행렬

→ 산점도를 숫자로 표현한 것
→ 선형이 크면 클수록 +1에 가까워짐(음의 선형관계일 경우 -1에 가까워짐)
→ 관계가 없으면 0
☞ PCA를 이용한 차원축소

→ 주성분 분석(Principal component analysis; PCA)
→ 변수 두 개를 써서 설명할 걸 하나의 축으로 설명할 수 있음
: 아래 [그림 1] 에서 왼쪽에 있는 2차원 데이터를 오른쪽에 있는 1차원 데이터로 최대한 특징을 살리며 차원을 낮춰주는 것

sklearn.linear_model.LinearRegression
데이터 프로세스는 위와 같아요. 이번 과정에서는 데이터 전처리, 모델링, 평가에 대해서 배울 예정이예요. 또한, 해당 방법론을 적용하기 위한 라이브러리를 연습해볼 예정입니다.