정규화(Normalization) - 데이터(training data set)가 가진 sacle이 심하게 차이가 나는 경우 학습이 잘 이루어지지 않아요! → scale을 맞추어주는 작업이 필요 → Normalization(있는 그대로의 숫자를 가지고 판단을 하는 게 아닌 의미를 가지고 판단, 척도, 중요도를 비율적으로 잡아줌)
집의 가격 방의 개수 1~ 20 1 ~ 10
집의 월별 연식 1~ 240 1~ 240 (20년)
Normalization의 2가지 방식
Min Max Normalization
Z-score Normalization(표준화, standardization )
가장 일반화된 Normalization 방식은 Min Max Normalization이에요.
모든 특성(feature, ex) 온도, 습도, 태양광 등등)에 대해 최솟값 0과 최댓값 1 사이의 값으로 변환(scaling) 시켜주는 것이에요
.
편하고 쉬운 대표적 정규화 방법이에요. 하지만 기본적으로 최대 최솟값을 사용하기 때문에 이상치가 들어가 있으면 전체 데이터가 망가져요. → 이상치에 상당히 민감해서 이상치 처리가 선행되어야 해요.
Z-score Normalization
변환시킨 값은 평균을 빼기 때문에 음수, -값이 나올 수 있어요. 표준편차는 분산의 제곱 근이기에 양수예요.
그리고 동일한 척도가 아니기 때문에 0~ 1 사이 값이 아니에요!
평균과 표준편차를 이용하기 때문에 이상치에 덜 민감해요. → 이상치에 상대적으로 관대해요.
sklearn은 자체적으로 Normalization 작업이 진행돼요! 그래서 python 코드랑 동일한 결과를 내지 못했어요!
위의 두 가지 방식을 python 코드로 알아보아요!!
일단 reset
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import linear_model
from scipy import stats #z scoe 값 계산해주는 함수
from sklearn.preprocessing import MinMaxScaler # preprocessing 전처리 관련 모듈 중에 MinMaxScaler 호출
## 그래프##
fig = plt.figure() # 도화지를 나눠요
fig_python = fig.add_subplot(1,2,1) # 1행 2열 첫 번째 subplot 영역 추가
fig_sklearn = fig.add_subplot(1,2,2) # 1행 2열 오른쪽
fig_python.set_title('Using python') # 제목
fig_sklearn.set_title('Using sklearn')
###
# 1. 수치 미분을 수행할 함수
def numerical_derivative(f, x):
# f : 미분을 하려고 하는 함수
# x : 모든 독립변수의 값을 포함하고 있는 ndarray(차원에 무관하게 처리할 수 있어야 해요!)
delta_x = 1e-4
derivative_x = np.zeros_like(x)
it = np.nditer(x, flags=['multi_index'])
while not it.finished:
idx = it.multi_index
tmp = x[idx]
# 중앙 차분으로 수치 미분하는 식 : (f(x + delta_x) - f(x-delta_x)) / 2 * delta_x
x[idx] = tmp + delta_x
fx_plus_deltax = f(x)
x[idx] = tmp - delta_x
fx_minus_deltax = f(x)
derivative_x[idx] = (fx_plus_deltax - fx_minus_deltax) / (2 * delta_x)
x[idx] = tmp
it.iternext()
return derivative_x
############################
# Raw Data Loading (정제되지 않는 수집한 데이터 불러오기)
df = pd.read_csv('./data/ozone/ozone.csv', sep=',')
training_data_set = df[['Temp','Ozone']] #fancy indexing, # 독립변수가 1개 'Temp' 종속변수 'Ozone'
# display(training_data_set.head())
# 1. 결치값부터 처리해야 해요!
# 상대적으로 데이터가 적고 데이터가 많을 때는 지우는 게 최적이지만 그 외에는 데이터의 손실이 발생해요!
# 그다음 대안은 다른 값으로 대치, 보정해줘요! 일단은 지우고 진행할게요.
training_data = training_data_set.dropna(how='any') # any는 NaN 포함된 행 다 지워요.
display(training_data) # 116 rows × 2 columns
# 2. 이상치를 처리해야 해요. 지대점(온도) 날리고 outlier(오존) 날릴 거예요.
# 일반적으로 이상치라고 하는 것은 Label(종속변수)에 대한 이상치를 outlier라고 해요.
# 입력데이터, 독립변수에도 이상치(지대점)가 개념이 존재해요
#지대점 - 독립변수의 이상치를 지대점이라고 합니다.
# 현재 데이터 기준으로 이상치를 판단, 전체를 보고 이상치를 판단하는 거랑 하나가 띄어진 상태에서 이상치 처리하는 것은 다른 결과가 나와요.
# 지대점(x축) 포함? 불포함 이상치에 대한 기준점 handling 선택
# 이상치 처리 2.0으로 잡으면 정규분포로 봤을 때 97.7% 이상의 극단이기에 1.8 정도로 잡을게요!
# 기준점(threshold)
zscore_threshold = 1.8
# Temp(온도)에 대한 이상치(지대점) 처리
# np.abs(stats.zscore(training_data['Temp'])) > zscore_threshold
# 절대값 abs로 바꿔 1.8에 대한 비교 연산을 해서 Mask 생성
# False 는 크지 않기 때문에 지대 값이 아니에요!
outlier = training_data['Temp'][np.abs(stats.zscore(training_data['Temp'])) > zscore_threshold]
#True 부분만 찾아내요
print(outlier) # 지대점
#7 59
#14 58
#17 57
#20 59
#119 97
#121 96
#Name: Temp, dtype: int64
#training_data.loc[~(training_data['Temp'].isin(outlier))]
# ~ 은 not의 의미 각각의 isin 값이 안에 있니? 논리 값을 역으로 False 지대점
training_data = training_data.loc[~(training_data['Temp'].isin(outlier))]
#Ozone에 대한 이상치(outlier) 처리
outlier = training_data['Ozone'][np.abs(stats.zscore(training_data['Ozone'])) > zscore_threshold]
training_data = training_data.loc[~(training_data['Ozone'].isin(outlier))]
display(training_data) # 103 rows × 2 columns
# 3. 정규화(Normalization) - Min Max Normalization
temp_max = training_data['Temp'].max()
print(temp_max) # 94
temp_min = training_data['Temp'].min()
print(temp_min) # 61
tmp = temp_max - temp_min # 분모
(training_data['Temp']- temp_min) / tmp
#0 0.181818
#1 0.333333
#2 0.393939
#3 0.030303
#5 0.151515
...
#147 0.060606
#148 0.272727
#150 0.424242
#151 0.454545
#152 0.212121
#Name: Temp, Length: 103, dtype: float64
이렇게 해도 돼요!
하지만 학습용 Data Set을 만들어 봐요.
# 3. 정규화(Normalization) - Min Max Normalization
# scaling 작업을 수행하는 객체를 하나 생성(입력값 처리 , Label처리 총 두 개 생성)
scaler_x = MinMaxScaler() #입력값('Temp'에 대한 min max scaling class객체
scaler_y = MinMaxScaler()
scaler_x.fit(training_data['Temp'].values.reshape(-1,1)) #데이터 개수, 최대, 최소 같은 값들이 scaler에 저장
#온도에대한 data를 2차원 형태로 fit 해줘요.아직은 정보가 없어요.
# 컬럼이 정해져 있기때문에 행을 세지 않고 -1을 써요.
scaler_y.fit(training_data['Ozone'].values.reshape(-1,1)) # scaler_y에도 적용
# scaling 할때는 transform 함수를 이용해요
training_data['Temp'] = scaler_x.transform(training_data['Temp'].values.reshape(-1,1))
#원래 데이터 날리고 변환된 데이터 가져요
training_data['Ozone'] = scaler_y.transform(training_data['Ozone'].values.reshape(-1,1))
display(training_data)
#Training Data Set
x_data = training_data['Temp'].values.reshape(-1,1)
t_data = training_data['Ozone'].values.reshape(-1,1)
# Weight & bias를 정의
W = np.random.rand(1,1)
b = np.random.rand(1)
def predict(x): #python 으로 구현한 linear모델 예측함수
return np.dot(x,W) + b # y = Wx + b
def loss_func(input_obj): # 편미분 함수 [W의 값, b의 값], 1행1열 1차원 ndarray
input_w = input_obj[0].reshape(-1,1) # 행렬곱연산을 수행해야 하니까 2차원으로 표현
input_b = input_obj[1]
# 평균제곱오차를 구해야 해요! => loss함수의 값.
y = np.dot(x_data,input_w) + input_b # 입력값에 대해 현재 W와 b를 이용한 예측치 계산
return np.mean(np.power((t_data-y),2))
learning_rate = 1e-4#ㅣoss값을 보고 조절해야하는 값
# 반복학습을 진행해야해요.
for step in range(300000):
input_param = np.concatenate((W.ravel(), b.ravel()), axis=0)
# def loss_func(input_obj)로 들어가야하기때문에 1차원으로 연결
result_derivative = learning_rate * numerical_derivative(loss_func,input_param)
W = W - result_derivative[0].reshape(-1,1)
b = b - result_derivative[1]
if step % 30000 == 0:
print('loss : {}'.format(loss_func(input_param)) # loss : 0.028423382676837344
# 학습이 끝났으니 Prediction을 해 보아요!
# print(predict([[62]])) # [[48.74690939]] ???? 많이 이상해요!!! ㅡㅜ 당연히 이상한거예요!
scaled_predict_data = scaler_x.transform([[62]])
print(scaled_predict_data)
scaled_result = predict(scaled_predict_data) ## [[-0.02019973]] ?? 이게 최종 예측값인가요??
# y에 대해서 원래값으로 복구해야해요!
print(scaler_y.inverse_transform(scaled_result)) ##[[2.12142534]]
# sklearn을 이용한 구현
df = pd.read_csv('./data/ozone/ozone.csv', sep=',')
training_data_set = df[['Temp', 'Ozone']]
# display(training_data_set.head())
# 1. 결치값부터 처리해야 해요!
training_data = training_data_set.dropna(how='any')
# 2. 이상치를 처리해야 해요!
zscore_threshold = 1.8
# Temp에 대한 이상치(지대점) 처리 - 지대점 : 독립변수의 이상치를 지대점이라고 합니다.
outlier = training_data['Temp'][np.abs(stats.zscore(training_data['Temp'])) > zscore_threshold]
# print(outlier) # 지대점
training_data = training_data.loc[~(training_data['Temp'].isin(outlier))] # 110 rows × 2 columns
# Ozone에 대한 이상치(outlier) 처리
outlier = training_data['Ozone'][np.abs(stats.zscore(training_data['Ozone'])) > zscore_threshold]
training_data = training_data.loc[~(training_data['Ozone'].isin(outlier))]
model = linear_model.LinearRegression()
model.fit(training_data['Temp'].values.reshape(-1,1),
training_data['Ozone'].values.reshape(-1,1))
result = model.predict([[62]]) # [[3.58411393]]
print(result)
## 그래프를 그려보아요!
#################################
fig = plt.figure()
fig_python = fig.add_subplot(1,2,1)
fig_sklearn = fig.add_subplot(1,2,2)
fig_python.set_title('Using Python')
fig_sklearn.set_title('Using sklearn')
#################################
fig_python.scatter(x_data,t_data)
fig_python.plot(x_data, x_data*W.ravel() + b, color='r')
fig_sklearn.scatter(training_data['Temp'].values,
training_data['Ozone'].values)
fig_sklearn.plot(training_data['Temp'].values,
training_data['Temp'].values*model.coef_.ravel() + model.intercept_, color='g')
#coef_ 가중치 , intercept_ 편향
fig.tight_layout()
plt.show()
'머신러닝 딥러닝' 카테고리의 다른 글
0901 TensorFlow (0) | 2021.09.01 |
---|---|
0831 MultipleLlinear Regression (0) | 2021.08.31 |
0830 linear regression 데이터 전처리 (0) | 2021.08.30 |
0827Machine Learning에서Linear Regression (0) | 2021.08.27 |
0826 회귀(regression ) (0) | 2021.08.26 |
댓글