🔍 머신러닝 3일차!
📝 어제에 이어서 데이터 전처리
📌 변수 추가
- 분석에 의미가 있다고 판단되는 변수를 추가한다.
# 데이터 확인
data['Name']
# Title 변수 추가
data['Title'] = data['Name'].str.extract('([A-Za-z]+)\.') # [a-zA-Z] : 알파벳 모두
#추출대상에 공백을 포함하지 않아서 공백은 나오지 않는다.
# Title 확인
data['Title']
# 확인
data['Title'].value_counts()
# 중요 호칭외에는 Others로 변경.
main_tit = ['Mr','Miss','Mrs','Master']
data.loc[data['Title'].isin(main_tit)==False,'Title'] = 'Others'
# 확인
data['Title'].value_counts()
💡 정규표현식 : 특정한 조건의 문자를 '검색'하거나 '치환'하는 과정을 매우 간편하게 처리하기 위한 수단
✔ df.Name.str.extract(' ([a-zA-Z]+)\.')
# Dot(.) 메타 문자는 줄바꿈 문자인 \n을 제외한 모든 문자와 매치됨
-extract함수 안에 있는 정규식에서는 중괄호 ([a-zA-Z]+)부분이 추출된다.
-띄어쓰기로 시작해 모든 알파벳이 포함된 문자열을 한 번이상 반복하다가 dot(.)으로 마무리하는 문자열이다.
따라서 Mr,Miss 등 영어 호칭이 추출된다.
✔ df.Name.str.contains('(Mr)')
- Mr가 포함된 행 확인
- str.contains()를 통해 지정한 문자열이 포함되어 있는지 확인할 수 있다.
- 검색 문자열이 포함되어 있는 경우에는 True, 아닌 경우에는 False를 반환한다.
✔ r'(day)'
- day가 포함된 모든 문자열을 의미.
💡 DataFrame.isin(values)
- isin메서드는 DataFrame객체의 각 요소가 values값과 일치하는지 여부를 bool형식으로 반환한다.
- Series일 경우 : Index가 일치해야 한다.
- DataFrame일 경우 : Index와 열 레이블이 일치해야 한다.
- Dict일 경우 : key는 열 레이블이다.
📌 Age 결측치를 중앙값으로 채우기
# 결측치 확인
data.isna().sum()
# Age 결측치를 중앙값으로 채우기 1
data['Age'].fillna(data["Age"].median(), inplace=True)
# Age 결측치를 중앙값으로 채우기 2
age_median=data["Age"].median()
data['Age'].fillna(age_median, inplace=True)
📌 Age 결측치를 Title별 중앙값으로 채우기
# 결측치 확인
data.isna().sum()
# Age 결측치를 Title 별 중앙값으로 채우기
# data.groupby(by='Title',as_index=False)[['Age']].median()
# groupby 수정
age_median = data.groupby(by='Title')['Age'].transform('median')
data['Age'].fillna(age_median, inplace=True)
💡 df.transform( ' 함수 ' ): 함수를 df에 적용하는 메서드
💡 결측치의 타입은 실수(float)
💡 결측치 채우기의 경우 Series(시리즈)로 채우려면 행수가 데이터프레임과 같은 시리즈를 주어야한다.
📌 train_test_split() 함수 내의 매개변수 stratify
# 모듈 불러오기
from sklearn.model_selection import train_test_split
# 7:3으로 분리
x_train, x_test, y_train, y_test = train_test_split(x,y,
test_size=0.3,
stratify=y,
#y값 기준으로 균등하게 분할되게끔 .
random_state=1)
💡 train_test_split() 함수 내의 매개변수 stratify
- 테스트 세트의 갯수가 훈련 세트에 비해 터무니 없이 작을 때 샘플링 편향이 발생할 수 있음.
- 그것을 방지하기 위해 train_test_split()함수 내에 stratify 매개변수에 타깃 데이터(y)를 전달하면 클래스 비율에 맞게 데이터를 나누게 됨.
- 쉽게 말하면 그냥 골고루 비율 맞춰서 데이터 잘 나눠주는 옵션이다 정도로 이해하면 된다.
- stratify에 대한 결과는 classification_report에서 확인할 수 있다.
- KT Aivle 단체카톡 민초단님
📌 precision_score
# 모듈 불러오기
from sklearn.metrics import precision_score
# 성능 평가
print(precision_score(y_test,y_pred))
# 1에 대한 precision이었다.이게 기본값평균이 아니었다.
print(precision_score(y_test,y_pred, average=None))
# 평균을 내지말라고 하면 P와 N 두개 다 보여준다.
print(precision_score(y_test,y_pred, average='macro')) # 산술평균
print(precision_score(y_test,y_pred, average='weighted'))# 가중평균
print(precision_score(y_test,y_pred, average='binary'))
# average의 기본값 => binary(p의 값을 보여줌)
❓오류) Target is multiclass but average='binary'. 에 대한 해결법
💡 average 매개변수 정리
- None = 평균을 내지말고 각각의 값 P,N 둘 다 표시
- macro = 산술평균
- weighted = 가중평균
- binary = 기본값(P의 값을 보여줌)
- 위 average 매개변수는 Precision_score뿐만 아니라, recall_score와 f1_score에도 동일하게 적용됨.
- iris데이터는 단순한 데이터이므로 Precision_score, recall_score, f1_score의 값이 동일하게 나올 수도 있다.
💡precision_score 함수의 average 매개변수는 multiclass classification 문제에서만 사용 가능한 값들만 사용 가능합니다. 오류 메시지에서도 알 수 있듯이 'binary' 값은 multiclass 문제에서는 사용할 수 없습니다. 따라서 다른 값을 사용하셔야 합니다. 'micro', 'macro', 'weighted' 등이 사용 가능합니다.
기본적으로 파라미터 average는 binary, 즉 이진 분류로 default가 되어 있기 때문에 파라미터 값을 따로 설정해주어야 합니다. 사용될 수 있는 파라미터 값은 다음과 같습니다.
- micro : 각각의 TP, FN, FP, TN 값들을 모두 합친 Total TP, FN, FP, TN 값들을 이용해 계산
- macro : 각각의 클래스에 따라 TP, FN, FP, TN 값들을 이용해서 평가지표를 계산한 후 그 값들의 평균을 사용
- weighted : 각 클래스에 해당하는 data 개수에 가중치를 주어 평균을 구하는 것
어떤 옵션을 선택할 지는 문제의 특성에 따라 다르며, 가장 적합한 옵션을 선택해야 합니다.
- 너굴안내님의 precision_score 함수 오류에 대한 1:1 문의 튜터님의 답변
📕 기본 알고리즘 (이론)
성능은 기본적으로 앙상블 알고리즘이 제일 좋다.
하지만 기본적으로 알고리즘을 알고 있어야 한다.
📌Linear Regression (선형 회귀)
- 회귀 : 평균으로 돌아가려는 경향
- X 값이 0 일 때, Y 값을 Y절편이라고 한다.
- 데이터는 다양한 형태를 가질 것이며 최선의 직선(오차제곱의 합이 가장 작은 값)을 긋기가 쉽지 않음
(오차제곱의 합이 가장 작은 값: SSE, MSE, MAE이 가장 작은 값)
- 선형 회귀의 목적은 최선의 직선을 찾는 것.
- 최적의 회귀모델은 전체 데이터의 오차 합이 최소가 되는 모델을 의미함.
- 결국 오차 합이 최소가 되는 가중치 w1과 편향 w0을 찾는 것을 의미함.
- 독립변수 개수로 회귀분석을 단순 회귀와 다중 회귀로 분류
📌 단순회귀
- 독립변수 하나와 종속변수 하나가 일대일 대응 관계를 갖는 선형 회귀
- x값 하나만으로 y값을 설명할 수 있는 경우
ex) 행복지수(y = 종속변수)가 연수입(x = 독립변수)만으로 결정됨.
- 회귀식: hat_y = w0 + w₁x₁
- 반복학습을 통해서 최선의 가중치(w₁)와 편향(w0)을 찾음.
# 모델 학습 후 회귀 계수 확인 가능
print(model.coef_) # 가중치(기울기)
print(model.intercept_) # 편향(절편)
이를 회귀식으로 표현하면
y = 편향절편 + 가중치 * x
단순회귀는 이 값만 주어진다면 회귀선을 시각화하여 그릴 수 있다.
📌 다중회귀
- 여러 독립변수가 종속변수에 영향을 미치는 선형 회귀
- y값을 설명하기 위해서는 여러개의 x값이 필요한 경우
ex) 여러요인들(x = 독립변수들)에 의해 보스턴 지역 집 값(y = 종속변수)이 결정됨.
- 회귀식: hat_y = w0 + w₁x₁+w₂x₂+w₃x₃+···+wnxn
- 각 독립변수의 최선의 가중치(w₁, w₂ ,w₃···)와 편향(w0)을 찾음
# 모델 학습 후 회귀 계수 확인 가능
print(list(x_train[features]))
print(model.coef_) # 가중치(기울기)
print(model.intercept_) # 편향(절편)
이를 회귀식으로 표현하면
y = 편향절편 + 가중치w₁ * x₁ + 가중치w₂ * x₂ + 가중치w₃ * x₃
다중회귀는 이 값이 주어진다고 하더라도 회귀선을 시각화하여 그릴 수 없다.
시각화에 너무 집중하지 말자.
💾 선형회귀 실습(익히기 03_01_선형회귀(Cars데이터))
# speed, dist 관계 산점도
plt.scatter(x='speed', y='dist', data=data)
plt.xlabel('Speed(mph)')
plt.ylabel('Dist(ft)')
plt.show()
📌모델링
# 1단계: 불러오기
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, r2_score
# 선형회귀에서는 평가지표를 mae와 r2 이 두개를 보자
# MSA,RMSA,MAE 다 봐도 되지만 너무 많잖아
# accuracy는 분류모델이지 회귀모델이 아니다. 여기서 나오면 안돼!!
# 2단계: 선언하기
model = LinearRegression()
# 3단계: 학습하기
model.fit(x_train,y_train)
# 4단계: 예측하기
y_pred=model.predict(x_test)
# 5단계: 평가하기
print('MAE :', mean_absolute_error(y_test, y_pred))
print('R2 :', r2_score(y_test, y_pred))
📌 회귀계수를 살펴보자
# 회귀계수 확인
print(model.coef_) #가중치(기울기)
print(model.intercept_) # 편향(절편)
Distance = 3.91 × Speed -16.37
📌 기타 선형회귀
# y=ax+b
a = model.coef_
b = model.intercept_
# speed 에 들어갈 적당한 X값이 필요
speed = np.array([x_train.min(), x_train.max()])
# 선형회귀식
dist = speed * a + b
# 산점도
plt.scatter(x_train, y_train) # 학습데이터 산점도
plt.scatter(x_test, y_test) # 테스트데이터 y=실제값 산점도
plt.scatter(x_test, y_pred) # 테스트데이터 y=예측값 산점도
# y_pred값은 직선상에 놓여있다.
# 회귀선 (학습데이터에 대해서 최선의 직선, 따라서 최적의 회귀선이 아닐수도 있음.)
plt.plot(speed, dist, color='r')
# 학습데이터의 평균값
plt.axhline(y_train.mean(), color='r', linestyle='--')
# 확인
plt.show()
📌 시각화
plt.plot(y_test.values, label='Actual')
plt.plot(y_pred, label='Predicted')
plt.legend()
plt.ylabel('Dist(ft)')
plt.show()
💾 LinearRegression 실습
📌단순 회귀(실습_03_01_ 선형회귀(Happy 데이터))
✔ 모델링
# 1단계: 불러오기
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, r2_score
# 2단계: 선언하기
model = LinearRegression()
# 3단계: 학습하기
model.fit(x_train,y_train)
# 4단계: 예측하기
y_pred= model.predict(x_test)
# 5단계: 평가하기
print('MAE:',mean_absolute_error(y_test,y_pred))
print('R2:',r2_score(y_test,y_pred))
# r2_score 대신에 model.score(x_test,y_test) 해도 R2나옴
model.score(x_test,y_test) # 회귀일 때는 R2, 분류일 때는 Accuracy가 나옴
# 회귀계수 확인
print(model.coef_)
print(model.intercept_)
# 예측값, 실제값 시각화
plt.plot(y_test.values, label='Actual')
plt.plot(y_pred, label='Predicted')
plt.legend()
plt.ylabel('happiness')
plt.show()
happiness = 0.72 × income + 0.16
📌 다중회귀(실습_03_02_ 선형회귀(Carseats 데이터)
✔ 데이터 준비(전처리 과정)
# target 확인
target='Sales'
# 데이터 분리
x=data.drop(target, axis = 1)
y=data.loc[:, target]
# 데이터 확인
data.info()
# 가변수화 대상: ShelveLoc, Education, Urban, US
cols=['ShelveLoc', 'Education', 'Urban', 'US']
#Education 교육수준으로 가변수화 대상
# 가변수화
x= pd.get_dummies(x, columns=cols, drop_first=True)
# data가 아니라 x를 가변수화하는 것을 잊지 말자!
# 확인
x.head() # data가 아니라 x를 확인하는 것을 잊지 말자!
# 모듈 불러오기
from sklearn.model_selection import train_test_split
# 데이터 분리
x_train, x_test, y_train, y_test = train_test_split(x,y,test_size=0.3, random_state=1)
# x_train, y_train, x_test, y_test라고 적으면 절대 안됨!!
# 여기서 object 형식의 값이 있으면 안됨.
# 확인
x_train.info()
✔ 모델링
# 1단계: 불러오기
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, r2_score
# 2단계: 선언하기
model = LinearRegression()
# 학습 전 데이터 제대로 분리했는지 확인
print(x_train.shape, y_train.shape)
print(x_test.shape, y_test.shape)
# 3단계: 학습하기
model.fit(x_train,y_train)
# 4단계: 예측하기
y_pred = model.predict(x_test)
# 5단계: 평가하기
print('MAE:', mean_absolute_error(y_test,y_pred))
print('R2:', r2_score(y_test,y_pred))
# 회귀계수 확인(칼럼이름까지 같이 출력)
print(list(x))
print(model.coef_)
print(model.intercept_)
💡 LinearRegression는 선언하기 과정에서 튜닝이 안된다.(괄호안에 넣을 수 있는 값이 없다.)
따라서 전처리 과정에서 이상치 제거나 성능에 방해되는 컬럼을 제거하는 것도 고려해보아야한다.
✔ 가중치
# 가중치 데이터프레임 만들기
tmp = pd.DataFrame()
tmp['feature']= list(x)
# list(x)를 써도 되고, x.columns를 써도 된다.
tmp['weight']=model.coef_
tmp.sort_values(by='weight',ascending=True,inplace=True)
# barh라서 아래에서부터 시작된다.
# 가중치 시각화
plt.figure(figsize=(5,5))
plt.barh(tmp['feature'],tmp['weight'])
plt.show()
# 무조건 가중치가 크다고 그 변수가 가장 중요한 값은 아니다.
# 표준화나 정규화를 해야한다.
✔ 시각화
# 예측값, 실젯값 시각화
plt.plot(y_test.values, label='Actual')
plt.title('comparison btw test-pred')
plt.plot(y_pred, label='Predicted')
plt.legend()
plt.ylabel('Sales')
plt.show()
📕 KNN (K-Nearest Neighbor) : 회귀와 분류에 모두 사용가능
- k 최근접 이웃
- 회귀와 분류에 사용되는 매우 간단한 지도학습 알고리즘
- 다른 알고리즘에 비해 이해하기 쉽지만, 연산 속도가 느림
⭐ k값의 중요성
-k(탐색하는 이웃 개수)에 따라 데이터를 다르게 예측할 수도 있음
- k값에 따라 예측 값이 달라지므로 적절한 k값을 찾는 것이 중요(기본값 = 5 = 이웃의 개수)
- 일반적으로.
-k를 1로 설정 안함 → 이웃 하나로 현재 데이터를 판단하기에는 너무 편향된 정보
-k를 홀수로 설정 → 짝수인 경우 과반수 이상의 이웃이 나오지 않을 수 있음
- 검증 데이터로 가장 정확도가 높은 k를 찾아 KNN알고리즘의 k로 사용
💡 맨하튼 거리는 유클리드 거리보다 항상 크거나 같다.
📌Scaling 스케일링 작업
- KNN모델 성능을 높이기 위해서는 스케일링 작업을 진행해야한다.
- 모든 데이터가 같은 범위의 데이터를 가질 때 좋은 성능을 보여준다.- 스케일링 여부에 따라 KNN 모델 성능이 달라질 수 있음을 꼭 기억해야한다.
💾 kNN(k-Nearest Neighbor) 실습
💡 결측치 처리
- 시계열 데이터이므로 선형보간법으로 채운다.
df. interpolate(method='linear', inplace=True)
# 결측치 확인
data.isnull().sum()
# 결측치 채우기
data.interpolate(method='linear', inplace=True)
# interpolate에서 매개변수를 method='linear'로 줘서 선형보간
# 확인
data.isnull().sum()
`interpolate`는 결측치(missing values)를 보간(interpolation)하여 데이터를 대체하는 방법.
판다스(Pandas)에서는 `interpolate` 메서드를 사용하여 시계열(time-series) 데이터나 연속적인 수치 데이터에서 우리는 일종의 연속성있는 패턴을 발견할 수 있는데 이를 결측치를 채우는데 사용한다. `interpolate` 메서드는 다양한 방법으로 보간(Interpolation)을 통해 앞,뒤 값을 통하여 유추하여 좀 더 스마트하게 결측치(NaN)를 채워줄 수 있도록 매개변수를 제공한다.
참고(Reference) - Pandas 공식 도큐먼트
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.interpolate.html
pandas.DataFrame.interpolate — pandas 1.5.3 documentation
‘nearest’, ‘zero’, ‘slinear’, ‘quadratic’, ‘cubic’, ‘spline’, ‘barycentric’, ‘polynomial’: Passed to scipy.interpolate.interp1d. These methods use the numerical values of the index. Both ‘polynomial’ and ‘spline’ req
pandas.pydata.org
📌 정규화 작업
- 방법1: 공식 사용 => 결과: 데이터프레임형태로 열이름 있음.
# 학습데이터에서 최댓값, 최솟값 구하기
x_max = x_train.max()
x_min = x_train.min()
# 정규화
x_train = (x_train - x_min)/(x_max - x_min)
x_test = (x_test - x_min)/(x_max - x_min)
# 정규화하기 전으로 되돌려놓을 수 없음
# 확인
x_train.describe()
x_test.describe() # 최대값이 1을 넘었다고 해도 어쩔 수 없다.
- 방법2: 함수 사용=> 결과: 배열형태로 열이름 사라져버림.
x_train.head(5)
# 모듈 불러오기
from sklearn.preprocessing import MinMaxScaler
# 정규화
scaler=MinMaxScaler()
scaler.fit(x_train) # x_train(학습데이터)에서 최소값, 최대값을 학습(확인)해!!
x_train = scaler.transform(x_train) # 그 사실을 가지고 x_train을 정규화해
x_test = scaler.transform(x_test) # 그 사실을 가지고 x_test를 정규화해
# 결과가 배열이 됨(열 이름이 사라짐)
x_train[:5]
# 정규화하기 전으로 되돌려놓을 수 있는 장점
scaler.inverse_transform(x_train)[:5]
# 소수점까지 되돌려놓을 수는 없음
# 칼럼까지 되돌려놓을 수는 없음
✔ 모델링
# 1단계: 불러오기
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_absolute_error, r2_score
# 2단계: 선언하기
model = KNeighborsRegressor()
# 3단계: 학습하기
model.fit(x_train, y_train)
# 4단계 예측하기
y_pred = model.predict(x_test)
# 5단계: 평가하기
print('MAE:',mean_absolute_error(y_test,y_pred))
print('R2:',r2_score(y_test,y_pred))
💡 2단계 선언하기에서 model = KNeighborsRegressor(n_neighbors=5)를 넣어주면
k값을 선언해준 것.
- k값에 따라 예측 값이 달라지므로 적절한 k값을 찾는 것이 중요
(n_neighbors = 기본값 = 5 = 이웃의 개수)
- k가 클수록 가장 단순한 모델이 된다.
( k가 1일 때 가장 복잡한 모델이다.)
( k값은 많아야 5 ~ 10 사이이다. 10도 너무 많음)
✔ 시각화
# 예측값, 실젯값 시각화
plt.plot(y_test.values, label='Actual')
plt.plot(y_pred, label='Predicted')
plt.legend()
plt.ylabel('Ozone')
plt.show()
💡가변수화한 값은 0,1 밖에 없다. (범주값이 0과 1사이의 연속값으로 바뀐 것)
따라서 가변수화한 값은 정규화를 해도 되고 안해도 된다.
가변수화한 값을 정규화한다면 정수에서 실수(float)형태가 된다.
💡 가장 단순한 모델 => 평균
kNN은 k개의 이웃에게 물어서 평균을 내는 것.
데이터의 개수와 k값의 개수가 같다면 k값은 평균이다.
따라서 KNN은 K값이 클수록 단순해진다.
💡 평가(미래,test)데이터가 현재(학습,train)데이터에 영향을 못 미친다.
따라서, Scaling 스케일링(정규화 - 거리에 대한 고려와 표준화)는 무조건 학습데이터와 평가데이터를 분리한 후에 Scaling 스케일링 해야한다.
💡 미래의 데이터(평가데이터)는 1보다 클 수도 있고 음수가 될 수도 있다.
미래의 데이터(평가데이터)는 0과 1을 벗어날 수 있다. => 이상치(Outlier)
💡 함수 = function = x에 대한 y대응값
= 직선을 수식화한 것 = 직선을 표현한 수식
💡스케일링의 종류
1. 표준화
- 표준화는 분포의 범위가 다양할 때, 분포를 비교하기 위한 (특히 정규분포) 방법.
- 표준화를 거치면 z-score가 된다.
- 모든 분포가 평균은 0, 표준편차는 1이 되므로 분포에 대한 비교가 가능해진다.
2. 정규화
- 모든 feature(변수)를 0과 1 사이 값으로 변환하는 방식.
- 이상치 제거가 선행되어야한다.
- 이상치가 존재할 경우, 성능이 저하된다.
표준화와 정규화의 차이점
- 표준화는 이상치와 상관없이 분포를 그대로 유지해준다.
- 반면에 정규화는 값의 범위를 0에서 1로 맞춰야하기 때문에 이상치에 따라서 분포가 좀 더 압축된다.
따라서, 이상치가 큰 경우 표준화가 적절하고, 이상치가 작은 경우 대체로 정규화를 사용한다.
우리는 수업시간에 표준화가 아닌 정규화를 사용할 것이다.
'KT AIVLE School 3기 > 머신러닝' 카테고리의 다른 글
KT Ailvle DX트랙 29일차 (0) | 2023.03.14 |
---|---|
KT Aivle DX 트랙 27일차 (0) | 2023.03.11 |
KT Aivle DX 트랙 26일차 (0) | 2023.03.09 |
KT Avile DX트랙 24일차 (0) | 2023.03.07 |
KT Aivle DX트랙 23일차 (0) | 2023.03.06 |