본문 바로가기

KHUDA/homework study

CHAPTHER 4 - 5

최적의 선 구하기

다음 두 가지 방법을 이용해 주어진 데이터에 맞는 최적의 선 구하기.

[1]

import numpy as np
# 데이터
x = 2 * np.random.rand(100, 1)
y = 4 + 3 * x + np.random.randn(100, 1)

 
numpy 의 np.random.randint vs rand/randn
 
- np. random.seed: seed를 통한 난수 생성
 
- np.random.randint: 균일 분포의 정수 난수 1개 생성
- np.random.rand: 0부터 1사이의 균일 분포에서 난수 matrix array 생성
- np. random.randn 가우시안 표준 정규 분포에서 난수 matrix array 생성
 
- np.random.shuffle: 기존의 데이터의 순서 바꾸기
- np.random.choice: 기존의 데이터에서 sampling
- np.unique: 데이터에서 중복된 값을 제거하고 중복되지 않는 값의 리스트를 출력
- np.bincount: 발생하지 않은 사건에 대해서도 카운트를 해준다.
 
np.random.randint: 모두(시작, n-1) 사이의 랜덥숫자 1개 뽑기
 
ex) np.random.randint(6) # 0부터 5까지 랜덤한 숫자 1개
 
np.random.rand(m,n): 0~1의 균일분포 표준정규분포 난수를 matrix array(m,n) 생성

np.random.randn(m,n): 평균0, 표준편차 1의 가우시안 표준정규분포 난수를 matrix array(m,n) 생성

 

[2]
# 시각화
import matplotlib.pyplot as plt
plt.scatter(x, y);

1. 공식 이용

[1]

mean_x = np.mean((x))
mean_y = np.mean((y))

def top(xmean_xymean_y):
  t = 0
  for i in range(len(x)):
    multiple = (x[i]-mean_x) * (y[i]-mean_y)
    t = t + multiple

  return t

def bottom(xmean_x):
  bo = 0
  for i in range(len(x)):
    bo = bo + (x[i] - mean_x)**2
  
  return bo

a = top(x, mean_x, y, mean_y)/ bottom(x, mean_x)
b = mean_y - (mean_x * a)

print(a)
print(b)

*주의*
np.mean(sum(x)) 와 np.mean(x)는 다르다.
np.mean(sum(x)) 이거는 그냥 리스트 x의 모든 값들의 합만 반환해줌.

2. 경사하강법 이용

[1]

# your code
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

model = Sequential()
model.add(Dense(1, input_dim=1,activation='linear'))
model.compile(optimizer = 'sgd', loss = 'mse')
model.fit(x,y,epochs=2000)

plt.scatter(x,y)
plt.plot(x, model.predict(x),'r')
plt.show()
 
[2]
 
print(model.get_weights()[0])
print(model.get_weights()[1])

.get_weights() 함수
 
- model.get_weights[1]: 입력층과 은닉층을 연결하는 가중치
- model.get_weights[2]: 은닉층의 바이어스
- model.get_weights[3]: 은닉층과 출력층을 연결하는 가중치
- model.get_weights[4]: 출력층의 바이어스

[1]
 
import numpy as np
mx = np.mean(x)
my = np.mean(y)
divisor = sum([(i-mx)**2 for i in x])

def top(xmxymy):
    d=0
    for i in range(len(x)):
        d+=(x[i] - mx) * (y[i] - my)
    return d

dividend = top(x, mx, y, my)

w= dividend / divisor
b = my-(mx*w)

print(f"Weight: {w}")
print(f"Bias: {b}")

[2]

 

from tensorflow import keras

model = keras.models.Sequential([
    keras.layers.Dense(1, activation="linear")
])

model.compile(loss="mse", optimizer="sgd")

model.fit(x,y, epochs=1000, verbose=0)
 
print(model.layers[0].get_weights()[0])
print(model.layers[0].get_weights()[1])

f - string?

- f와 {}만 알면 된다. 문자열 맨 앞에 f를 붙여주고, 중괄호 안에 직접 변수 이름이나 출력하고 싶은것을 넣으면 된다.

ex) f'문자열{변수}문자열'

 

verbose

- 함수 수행시 발생하는 상세한 정보들을 표준 출력으로 자세히 내보낼 것인가를 나타냅니다. 보통 0은 출력하지 않고, 1은 자세히, 2는 함축적인 정보만 출력하는 형태로 되어있습니다.

선형회귀

선형 회귀를 이용해 캘리포니아 지역의 집 값을 예측하는 문제

  • 교재의 tensorflow 기반 모델 대신 sklearn library를 이용해 간단한 코드로 선형 회귀를 구현할 수 있습니다. 6장 실습 내용과 아래 링크를 참고해 간단한 회귀 문제를 풀어봅시다.
 

sklearn.linear_model.LinearRegression

Examples using sklearn.linear_model.LinearRegression: Principal Component Regression vs Partial Least Squares Regression Principal Component Regression vs Partial Least Squares Regression Plot indi...

scikit-learn.org

1. 데이터 로드

from sklearn.datasets import fetch_california_housing
import pandas as pd
import warnings
warnings.filterwarnings('ignore')

housing = fetch_california_housing()
housing_dt = housing.data #독립변수
target = housing.target #종속변수

df = pd.DataFrame(housing_dt, columns=housing.feature_names)
df['price'] = target

warnings 라이브러리로 경고 메시지 무시하기

- 파이썬에서 경고 메시지를 무시하고 싶을 때

import warnings
warnings.filterwarnings('ignore')

sklearn.datasets 활용법

- data 는 학습해야 할 feed(좋은 정보를 모아 독자들에게 전달하는 행위 또는 그러한 것)용 데이터를 의미합니다.

- target은 label 데이터 이며, 예측해야 할 (class) 데이터 입니다.

- target_names 는 0, 1, 2와 같이 숫자로 된 데이터들의 원 이름입니다.

- DESCR은 description입니다. 데이터 셋에 대한 설명을 제공합니다.

- feature_names는 제공되는 (feed되는) 데이터 셋의 column 명으로 이해하시면 됩니다.

- filename은 datasets을 다운로드 받은 경로를 return 합니다.

 

2. 데이터 EDA

EDA(탐색적 데이터 분석)는 데이터를 분석하고 결과를 내는 과정에 있어서 지속적으로 해당 데이터에 대한 '탐색과 이해'를 기본으로 가져야 한다는 것을 의미한다.

print(df.head())
print(df.shape)
print(df.info())
print(df.isnull().sum())
import matplotlib.pyplot as plt
from pandas.plotting import scatter_matrix

scatter_matrix(df, alpha=0.5, figsize = (16, 16), diagonal = 'hist')
plt.show()
import seaborn as sns
plt.figure(figsize = (12, 12)) 
df_corr = df.corr(method = 'pearson')
sns.heatmap(df_corr, xticklabels = df.columns, yticklabels=df.columns, cmap = 'RdBu_r', annot=True)
plt.show()

Pandas 불러온 데이터 살펴보기

- .columns: 해당 데이터프레임을 구성하는 컬럼명을 확인할 수 있습니다.

- .head(): 불러온 데이터 상위 5개의 행을 출력합니다. (+ 괄호 안에 원하는 숫자를 넣으면 그 숫자만큼 행을 출력합니다.)

- .tail(): 하위 5개의 행을 출력합니다. (+ 괄호 안에 원하는 숫자를 넣으면 그 숫자만큼 행을 출력합니다.)

- .shape: 데이터의 (행, 열) 크기를 확인할 수 있습니다.

- .info(): 데이터에 대한 전반적인 정보를 나타냅니다. df를 구성하는 행과 열의 크기, 칼럼명, 컬럼을 구성하는 값의 자료형등을 출력해줍니다.

- .describe(): 데이터의 컬렴별 요약 통계량을 나타냅니다. 또한 mean(), max(), median()등 개별 함수를 사용하여 통계량을 계산할 수도 있습니다.

- .value_counts(): 개별 컬럼 내에 각각의 값이 나온 횟수를 셀 수 있습니다. (normalize 옵션을 사용하면 % 로도 표현이 가능합니다.)

- .unique(): 개별 컬럼 내에 유일한 값을 확인할 수 있습니다.

 

DataFrame 결측값 여부 확인, 결측값 개수

: Python pandas에서는 결측값을 'NaN' 으로 표기하며, 'None'도 결측값으로 인식합니다.

- .isnull(): 관측치가 결측이면 True, 결측이 아니면 False의 boollean 값을 반환합니다. (.notnull() 은 정반대)

- .isnull().sum(): 칼럼별 결측값 개수 구하기.

 

pandas.plotting.scatter_matrix

: 산점도 행렬이라고 하는데 다변량 데이터에서 각 변수 간 관계를 산포도로 그려줍니다. 대각선에 그려지는 그래프는 density plot과 histogram만 가능합니다.

Parameters

  frame:DataFrame

  alpha:float, optional (적용된 투명도의 양입니다.)

  figsize:(float,float), optional (인치 단위의 튜플 (너비, 높이)입니다.)

  ax : Matplotlib 축 객체, 선택 사항

  grid:bool, optional (이것을 True로 설정하면 그리드가 표시됩니다.)

  diagonal:{‘hist’, ‘kde’} (커널 밀도 추정 또는 대각선의 히스토그램 플롯에 대해 'kde'와 'hist' 중에서 선택합니다.)

  marker:str, optional (Matplotlib 마커 유형, 기본값 '.'.)

  density_kwds:keywords (커널 밀도 추정 플롯에 전달할 키워드 인수입니다.)

  hist_kwds:keywords (hist 함수에 전달할 키워드 인수입니다.)

  range_padding : float, 기본값 0.05 ((x_max-x_min) 또는 (y_max-y_min)에 대한 x 및 y 축 범위의 상대적 확장.)

  **kwargs (분산 함수에 전달할 키워드 인수입니다.)

Returns

  numpy.ndarray (산점도 행렬입니다.)

KDE란?

: 커널함수를 이용한 밀도추정(얻어진 데이터들의 분포로부터 원래 변수의 확률 분포 특성을 추정 하고자 하는 것. 즉 변수 x가 a라는 변수를 가질 확률을 추정하는 것) 방법의 하나

hist란?

: 도수분포표를 그래프로 나타낸 것.

 

상관계수 (corr / corrwith)

: corr메서드는 각 열 간의 상관 계수를 반환하는 메서드입니다.
  corrwith메서드는 두 DataFrame객체의 동일한 행/열 간의 상관 계수를 반환하는 메서드입니다.
  상관계수 산정 방식에는 피어슨 상관계수, 켄달-타우 상관계수, 스피어먼 상관계수를 사용합니다.

피어슨 상관계수

: 두 변수 간의 선형 상관관계를 계량화 한 수치입니다. 코시-슈바르츠 부등식에 의해 +1과 -1사이의 값을 가집니다. +1의 경우 완벽한 양의 선형 상관 관계, -1의 경우 완벽한 음의 상관관계, 0의 경우 선형 상관관계를 갖지 않습니다.

켄달-타우 상관계수

: 두 변수들간의 순위를 비교해서 연관성을 계산하는 방식입니다.

스피어먼 상관계수

: 두 변수의 순위 값 사이의 피어슨 상관 계수와 같습니다. 즉, 순서척도가 적용되는 경우에는 스피어먼 상관계수가, 간격척도가 적용되는 경우에는 피어슨 상관계수가 적용됩니다.

사용법

- df.corr(method='pearson', min_periods=1)
  method : {pearson / kendall / spearman} 적용할 상관계수 방식입니다.
  min_periods : 유효한 결과를 얻기위한 최소 값의 수 입니다. (피어슨, 스피어먼만 사용가능)

- df.corrwith(other, axis=0, drop=False, method='pearson')
  other : 동일한 이름의 행/열을 비교할 다른 객체입니다.
  axis : {0 : index / 1 : columns} 비교할 축 입니다. 기본적으로 0으로 인덱스끼리 비교합니다.
  drop : 동일한 이름의 행/열이 없을경우 NaN을 출력하는데, 이를 출력하지 않을지 여부입니다.
  method : {pearson / kendall / spearman} 적용할 상관계수 방식입니다.

 

heatmap

: heatmap은 열을 의미하는 heat와 지도를 뜻하는 map을 합친 단어이다. 데이터들의 배열을 색상으로 표현해주는 그래프이다.

heatmap 기본 문법

- df # 데이터

- vmin = 100 # 최솟값

- vmax = 700 # 최댓값

- cbar = True # colorbar의 유무

- center = 400 # 중앙값 선정

- linewidths = 0.5 # cell 사이에 선을 집어 넣는다.

- annot = True, fmt = 'd' # 각 cell의 값 표기 유무, 그 값의 데이터 타입 설정

- cmap = 'Blues' # 히트맵의 색을 설정한다.

- xticklabels =  # 좌표축의 x축 눈금 레이블을 설정합니다.

- yticklabels =  # 좌표축의 y축 눈금 레이블을 설정합니다.

 

3. 데이터 분할 (8:2)

from sklearn.model_selection import train_test_split
x = df.iloc[:, :-1].values
y = df['price'].values

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, random_state=1)
print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)

sklearn의 train_test_split() 사용법

Parameter

from sklearn.model_selection import train_test_split

train_test_split(arrays, test_size, train_size, random_state, shuffle, stratify)

 

arrays : 분할시킬 데이터를 입력 (Python list, Numpy array, Pandas dataframe 등..)

test_size : 테스트 데이터셋의 비율(float)이나 갯수(int) (default = 0.25)

train_size : 학습 데이터셋의 비율(float)이나 갯수(int) (default = test_size의 나머지)

random_state : 데이터 분할시 셔플이 이루어지는데 이를 위한 시드값(시드값이 똑같으면 생성된 난수도 같음) (int나 RandomState로 입력)

shuffle : 셔플여부설정 (default = True)

stratify : 지정한 Data의 비율을 유지한다. 예를 들어, Label Set인 Y가 25%의 0과 75%의 1로 이루어진 Binary Set일 때, stratify=Y로 설정하면 나누어진 데이터셋들도 0과 1을 각각 25%, 75%로 유지한 채 분할된다.

 

iloc 사용방법

: iloc는 integer location의 약어로, 데이터 프레임의 행이나 칼럼의 순서를 나타내는 정수로 특정 값을 추출해오는 방법이다. loc는 칼럼명을 직접 적거나 특정 조건식을 써줌으로써 사람이 읽기 좋은 방법으로 데이터에 접근하는 방법이었다면, iloc는 컴퓨터가 읽기 좋은 방법으로 데이터가 있는 위치에 접근한다고 생각하면 쉬울 것이다.

 

- df.iloc[행 인덱스, 열 인덱스]

 

4. scaling

from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
x_train_scaled = scaler.fit_transform(x_train)
x_test_scaled = scaler.transform(x_test)

MinMaxScaler

- 표준화 = StandardScaler

- 정규화 = MinMaxScaler

: 모든 값을 0 ~ 1 사이의 값으로 바꾸는 것이다. 음수도 예외 없이 다 바꾼다.

  => (X - (X의 최솟값)) / (X의 최댓값 - X의 최솟값)

 

데이터 스케일링( 반드시 필요한 전처리 과정!)

:모델을 학습시키기에 앞서 데이터 전처리는 꼭 필요하다. 특성별로 값의 범위가 다 다르기 때문에 어떤 특성은 값이 너무 작고 어떤 특성은 값이 너무 크다면 알고리즘 학습 시 0으로 수렴하거나 무한으로 발산해버리면서 원하는 결과값이 나오지 않을 수 있다.

 

데이터 스케일링의 종류

1. StandardScaler

평균=0, 표준편차=1로 조정해서 모든 특성이 같은 크기를 갖게 한다.

 

2. MinMaxScaler

최대값=1, 최소값=0으로 조정, 아웃라이어에 취약

 

3. RobustScaler

중앙값=0, IQR(1분위~3분위값)=1로 조정, 아웃라이어 영향을 최소화하며 정규분포보다 더 넓게 분포

 

4. MaxAbsScaler

0을 기준으로 절대값이 가장 큰 수가 1 또는 -1이 되도록 조정, 양수 데이터로만 구성된 데이터셋에서는 아웃라이어에 민감

 

데이터 스케일링을 하는 이유가 아웃라이어의 영향을 최소화하는 것이기 때문에 보통은 이상치 영향을 가장 적게 받는 StandardScaler 혹은 RobustScaler를 주로 사용한다. 모두 사이킷런에서 모듈을 제공한다.

 

fit_transform()과 transform()의 차이

:스케일링을 할 때 꼭 사용하는게 fit_transform(), fit(), transform()메서드이다. fit_transform()은 말그대로 fit()과 transform()을 한번에 처리할 수 있게 하는 메서드인데 조심해야 하는 것은 테스트 데이터에는 fit_transform()메서드를 쓰면 안된다. fit()은 데이터를 학습시키는 메서드이고 transform()은 실제로 학습시킨 것을 적용하는 메서드이다.

 

from sklearn.preprocessing import StandardScaler

 

#scaler정의

scaler = StandardScaler()

 

#train data에 scaler를 fit

scaler.fit(X_train)

 

#train data 변환

X_train_scaled = scaler.transform(X_train)

 

#test data 변환

X_test_scaled = scaler.transform(X_test)

 

1. scaler 생성

2. 학습 데이터에 대해 fit

3. 학습 데이터에 대해 transform

4. 학습데이터를 스케일링한 scaler로 테스트 데이터도 transform (fit은 하지 않음!)

 

 

학습 데이터에 fit 한 설정을 그대로 test set에도 적용하는 것이다.

이때 주의할 점은 test set에는 fit이나 fit_transform 메서드를 절대 쓰면 안된다는거!

 

 

만약 test set에도 fit을 해버리면 sclaer가 기존에 학습 데이터에 fit한 기준을 다 무시하고 테스트 데이터에 새로운 mean, variance값을 얻으면서 테스트 데이터까지 학습해버린다. 테스트 데이터는 검증을 위해 남겨둔 셋이기 때문에 반드시 주의해야 한다.

 

 

만약 fit_transform()메서드를 쓴다면 코드는 아래와 같다. fit_transform을 사용하는 것과 fit을 하고 transform을 하는거는 아주 약간의 미세한 성능 차이는 있지만 더 효율적이다.

X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = sclaer.transform(X_test)

 

추가로 train_test_split을 하기 전에 미리 전처리를 해주고 train, test분리를 해줘도 무방하다.

 

5. 모델 적합

from sklearn.linear_model import LinearRegression

model = LinearRegression()
model.fit(x_train_scaled, y_train)

6. 테스트셋 예측

+ 주의 + 

y_predict = model.predict(x_test)

이렇게 해버리면 test 데이터 셋이 정규화가 안되어있기에 예측이 제대로 되지 않는다.

 

7. 성능 평가

from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

mae = mean_absolute_error(y_test, y_predict)
mse = mean_squared_error(y_test, y_predict)
rmse = np.sqrt(mse)
r2 = r2_score(y_test, y_predict)

print('MAE: {0: .5f}'.format(mae))
print('MSE: {0: .5f}'.format(mse))
print('RMSE: {0: .5f}'.format(rmse))
print('R2: {0: .5f}'.format(r2))

[Machine Learning] 회귀모델의 평가지표 - MSE, MAE, RMSE, R2, OLS (최소자승법; Ordinary Least Squares) (tistory.com)

 

[Machine Learning] 회귀모델의 평가지표 - MSE, MAE, RMSE, R2, OLS (최소자승법; Ordinary Least Squares)

회귀모델을 평가하는 평가지표들(evaluation metrics) MSE (Mean Squared Error) =np.mean(np.square((y_true - y_pred))) MAE (Mean absolute error) =np.mean(np.abs((y_true - y_pred))) RMSE (Root Mean Squared Error) =np.sqrt(MSE(y_true, y_pred)) R-sq

kimmaadata.tistory.com

[Python] 성능 측정 지표 :: MAE, MSE, RMSE, MAPE, MPE, MSLE (tistory.com)

 

[Python] 성능 측정 지표 :: MAE, MSE, RMSE, MAPE, MPE, MSLE

1. MAE (Mean Absolute Error) - 실제 값과 예측 값의 차이(Error)를 절대값으로 변환해 평균화 - MAE는 에러에 절대값을 취하기 때문에 에러의 크기 그대로 반영된다. 그러므로 예측 결과물의 에러가 10이

mizykk.tistory.com

참고.