티스토리 뷰

numerical_derivative() 함수를 모듈로 저장하여 import하여 쓰기

  • 경로 추가 방법
    • C:\my_libraryw\machine_learning_library.pynumerical_derivative()를 정의했다면, 해당 폴더의 위치를 환경 변수 PYTHONPATH에 추가해준다.
  • 동적으로 경로 추가 방법
    • sys.path.append()에 경로 삭제
    • sys는 시스템 정보에 접근할 때 사용하는 모듈이다. 리스트 형태로 되어 있으며, 모듈을 불러 올 때 해당 리스트에 등록된 경로들을 순차적으로 탐색하여 불러온다.

 

Regreesion Model과 최소 제곱법, Gradient Descent Algorithm (경사 하강법)

 

Simple Linear Regression

  • 온도에 따른 오존량 예측

  • numerical_derivative()를 사용하여 직접 회귀 모델 구현

1. Raw Data Loading
2. Data Preprocessing (데이터전처리)
3. Training Data Set
4. Simple Linear Regression
5. loss function 정의
6. 학습 종료 후 예측값을 알아오는 함수
7. 프로그램에서 필요한 변수들을 정의
8. 학습 진행
9. 그래프로 확인

Data Preprocessing (데이터전처리)

  • 결측치 처리
    • 삭제, 값을 변경, 예측해서 대체
  • 이상치 처리 (outlier)
    • 이상치를 검출하고 변경하는 작업
  • 데이터 정규화 작업
  • 학습에 필요한 컬럼을 추출, 새로 생성
# Simple Linear Repgression
# 온도에 따른 오존량 예측
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from machine_learning_library import numerical_derivative
# from my_library.machine_learning_library import numerical_derivative

# 1. Raw Data Loading
df = pd.read_csv('./data/ozone.csv')

# 2. Data Preprocessing (데이터전처리)

# 필요한 column (Temp, Ozone만 추출)
training_data = df[['Temp', 'Ozone']] 
# print(training_data.shape) # (153, 2)

# 결치값 제거 -> 리스크가 큰 방법
training_data = training_data.dropna(how='any')
# print(training_data.shape) # (116, 2)

# 3. Training Data Set
x_data = training_data['Temp'].values.reshape(-1, 1)  # 1차원 vector -> 2차원 matrix (column 하나)
t_data = training_data['Ozone'].values.reshape(-1, 1)

# 4. Simple Linear Regression
#   y = Wx + b
# 구해야 하는 W, b를 정의
W = np.random.rand(1, 1)
b = np.random.rand(1)

# 5. loss function 정의
def loss_func(x, t):
    y = np.dot(x, W) + b
    return np.mean(np.power((t-y), 2)) # 최소제곱법

# 6. 학습 종료 후 예측값을 알아오는 함수
def predict(x):
    return np.dot(x, W) + b

# 7. 프로그램에서 필요한 변수들을 정의
learning_rate = 1e-4
f = lambda x: loss_func(x_data, t_data)

# 8. 학습 진행
for step in range(30000):
    W -= learning_rate * numerical_derivative(f, W)
    b -= learning_rate * numerical_derivative(f, b)

    if step % 3000 == 0:
        # loss값은 작을 수록 좋다
        print('W : {}, b: {}, loss : {}'.format(W, b, loss_func(x_data, t_data)))

# 9. 그래프로 확인
plt.scatter(x_data, t_data)
plt.plot(x_data, np.dot(x_data, W) + b, color='r')
plt.show()

  • 그리 정확한 값이 계산되지는 않는다.

 

sklearn

  • sklearn을 이용해서 같은 데이터로 학습을 시키고 예측을 해 보자
  • sklean은 데이터분석, 머신러닝 라이브러리중 하나로, 굉장히 유명하고 효율이 좋은 라이브러리다.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import linear_model

# 1. Raw Data Loading
df = pd.read_csv('./data/ozone.csv')

# 2. Data Preprocessing (데이터전처리)
# 필요한 column (Temp, Ozone만 추출)
# 결치값 제거
training_data = df[['Temp', 'Ozone']] 
# print(training_data.shape) # (153, 2)

# 결치값 제거 -> 리스크가 큰 방법
training_data = training_data.dropna(how='any')
# print(training_data.shape) # (116, 2)

# 3. Training Data Set
x_data = training_data['Temp'].values.reshape(-1, 1)  # 1차원 vector -> 2차원 matrix (column 하나)
t_data = training_data['Ozone'].values.reshape(-1, 1)

# 4. sklearn을 이용해서 linear regression model 객체를 생성
# 아직 완성되지 않은, 학습되지 않는 모델 생성
model = linear_model.LinearRegression()

# 5. Training Data Set을 이용해서 학습 진행
model.fit(x_data, t_data)

# 6. W, b 값 알아내기
print('W : {}, b : {}'.format(model.coef_, model.intercept_))

# 7. 그래프로 확인하기
plt.scatter(x_data, t_data)
plt.plot(x_data,np.dot(x_data,model.coef_) + model.intercept_, color='r')
plt.show()

# 8. 예측하기
predict_val = model.predict([[62]]) # 온도를 이용해서 오존
print(predict_val) #  # [[3.58411393]]

  • 이런 문제가 발생한 이유는 데이터 전처리가 잘 안되서 그렇다.

  • 머신러닝에서 학습이 잘 되기 위해서는 데이터의 전처리가 필수다.

  • 결측치 처리는, 여기서는 일단 삭제 처리로 한다.

 

결측치 처리

  • 1) 이상치처리 (Outlier)
  • 2) 데이터의 정규화

이상치처리 (Outlier)

  • 이상치 (Outlier)는 속성의 값이 일반적인 값보다 편차가 큰 값을 의미.

  • 즉, 데이터 전체 패턴에서 동떨어져 있는 관측치를 지칭

  • 평균뿐만 아니라 분산에도 영향을 미치기 때문에, 데이터 전체의 안정성을 저해하는 요소.

  • 따라서, 이상치는 반드시 처리하고 검출하고 처리하는데 상당히 많은 시간이 소요되는게 일반적

  • 독립변수 (온도)에 있는 이상치 -> 지대점

  • 종속변수 (오존량)에 있는 이상치 -> outlier

 

1) Tukey Outlier

4분위값을 이용하는 이상치 검출 방식

2) Z-Score

분산, 표준편차를 이용하는 이상치 검출 방법 - 통계기반

 

 

 

1) Tukey Outlier

  • Tukey outlier를 이용하여 처리한다.
  • 우선, boxplot이라는걸 이용해서 4분위를 기준으로 한 그래프를 확인한다.
  • 4분위값을 이용하는 이상치 검출 방식

  • Boxplot을 사용하여 이상치를 분류하는 기준은 IQR value를 사용

  • IQR value = 3사분위 - 1사분위값
  • 어떤 값을 이상치로 판별하는가
    • 1사분위수 - 1.5 * IQR value보다 작은 값을 이상치로 판별
    • 3사분위수 + 1.5 * IQR value보다 큰 값을 이상치로 판별

Boxplot로 4분위수 그래프 보기

import numpy as np
import matplotlib.pyplot as plt

data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 22.1])
plt.boxplot(data)
plt.show()

boxplot

numpy로 사분위수를 구하려면 percentile() 함수를 이용한다.

import numpy as np
import matplotlib.pyplot as plt

data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 22.1])

fig = plt.figure()               # 새로운 그림 (figure)을 생성
fig_1 = fig.add_subplot(1, 2, 1)  # 1행 2열의 subplot의 위치가 1번 위치
fig_2 = fig.add_subplot(1, 2, 2)  # 1행 2열의 subplot의 위치가 2번 위치

fig_1.set_title('Original Data Boxplot')
fig_1.boxplot(data)
# plt.show()

# numpy로 사분위수를 구하려면 percentile() 함수를 이용한다.
print(np.mean(data))             # 평균 8.473333333333333
print(np.median(data))           # 중위수 - 2사분위 8.0
print(np.percentile(data, 25))   # 1사분위 4.5 - 네등분한 값의 첫번째
print(np.percentile(data, 50))   # 2사분위 8.0 - 네등분한 값의 두번째
print(np.percentile(data, 75))   # 3사분위 11.5 - 네등분한 값의 세번째
print(np.percentile(data, 100))  # 4사분위 22.1 - 네등분한 값의 네번째

# 이상치를 검출하려면 IQR value가 필요
IQR_val = np.percentile(data, 75) - np.percentile(data, 25)

upper_fense = np.percentile(data, 75) + 1.5 * IQR_val
lower_fense = np.percentile(data, 25) - 1.5 * IQR_val

print('upper_fense : {}'.format(upper_fense))
print('lowerr_fense : {}'.format(lower_fense))
# upper_fense : 22.0
# lowerr_fense : -6.0

# 데이터중에 이상치를 출력하고
# 이상치를 제거한 데이터로 boxplot을 그린다.
# boolean indexing을 이용한다.
print(data[(data > upper_fense) | (data < lower_fense)])  # [22.1]

# 이상치가 아닌 값들의 index
# print(data[(data <= upper_fense) & (data >= lower_fense)])
result_data = data[(data <= upper_fense) & (data >= lower_fense)]

fig_2.set_title('Remove Outlier Boxplot')
fig_2.boxplot(result_data)

plt.show()

이상치 제거 전/후의 boxplot

 

2) Z-Score

정규분포와 Z-score

from scipy import stats

data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 22.1])

zscore_threshold = 1.8 # zscore outlier 임계값 (일반적으로 2)
# stats.zscore(data)
print(stats.zscore(data)) 
# 데이터를 정규분포화 시킨 후, 표준편차에서 각자의 점들이 어느 위치에 있는지 나타낸다.
# [-1.40160702 -1.21405925 -1.02651147 -0.8389637  -0.65141593 -0.46386816
#  -0.27632038 -0.08877261  0.09877516  0.28632293  0.4738707   0.66141848
#   0.84896625  1.03651402  2.55565098]

# 절대값이 1.8보다 큰 boolean mask로 indexing
outliers = data[np.abs(stats.zscore(data)) > zscore_threshold]
print(outliers) # [22.1]

# invert -> outliers의 역을 구한다.
print(data[np.isin(data, outliers, invert=True)] )
# [ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14] => 이상치 22.1 제거됨

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함