Skip to content

인공지능 컴퓨터 비전 tensorflow 쪼개기 1화

elderly man thinking while looking at a chessboard

Tensorflow 2.x 소개

  • Tensorflow 2.x 부터 Keras 기반의 API 로 변경되어 구현이 쉬워졌다.
  • 모델의 그림을 그린 후, 코드로 변경한다.
  • Keras는 다양한 모델을 제공한다 (Sequential, functional api 등)
  • Layer라는 것이 존재하여 model 과 layer를 조합하여 구현 가능하다.

데이터 전처리

  • 결측치 처리
    – deletion (데이터 양이 많은 경우 (10만건) 삭제가 좋다)
    – imputation (데이터 양이 적을 경우 : 보정 (평균, 최대, 최소, 중위 등))
  • 이상치 처리 (정상적인 범위가 아닌값 : deletion, inputation)
  • 정규화

해당 파일은 아래 링크에서 다운로드 가능

# tensorflow로 linear regression 구현하기
import pandas as pd
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Flatten, Dense
from tensorflow.keras.optimizers import SGD

# 정규화 추가
from sklearn.preprocessing import MinMaxScaler

pf = pd.read_csv('dataset/ozone.csv')
training_data = df[['Ozone', 'Temp']]
display(training_data)
training_data = training_data.dropna(how='any')
display(training_data)

x_data = training_data['Temp'].values.reshape(-1,1)
t_data = training_data['Ozone'].values.reshape(-1,1)

keras_model = Sequential()
keras_model.add(Flatten(input_shape=(1,)))
output_layer = Dense(units=1, activation='linear')
keras_model.add(output_layer)
keras_model.compile(optimizer=SGD(learning_rate=1e-2),
                    loss='mse')

# 정규화진행
scaler_x = MinMaxScaler()
scaler_t = MinMaxScaler()

scaler_x.fit(x_data)
scaler_t.fit(t_data)

x_data_norm = scaler_x.transform(x_data)
t_data_norm = scaler_t.transform(t_data)

keras_model.fit(x_data_norm, t_data_norm, epochs=2000, verbose=0)

predict_data = np.array([[62]])
predict_data_norm = scaler_x.transform(predict_data)
keras_predict = keras_model.predict(predict_data_norm)

# input 데이터가 0~1값으로 normalization 되었기 때문에 원래대로 복원 한다.
result = scaler_t.inverse_transform(keras_predict)

weights, bias = output_layer.get_weights()
plt.scatter(x_data_norm, t_data_norm)
plt.plot(t_data_norm, t_data_norm * weights + bias, color='r')

정규화를 안하면 sklearn과 tensorflow의 훈련 결과 같이 다르다.

sklearn에서는 내부적으로 input 데이터를 정규화 하는것으로 보인다.

위의 코드 까지는 정규화만 진행함

위의 그래프에서 보면, 선에서 많이 떨어진 점들이 보인다. 이상치를 검출하여 제외 해야 한다.

  • 이상치 검출방법
    – Variance (정규분포)
    – Likelihood (베이즈 정리)
    – Density (카이제곱 분포)
    – Clustering
    Tukey’s Fence (터키펜스) : 사분위에 근거를 두고 있고 boxplot을 이용해서 도식적으로 검출
    Z-Score 이용

Tuckey’s Fence를 이용한 이상치 검출

  • boxplot 기준으로 1Q, 3Q에서 IQR value * 1.5 보다 낮거나 높으면 이상치로 본다.
  • IQR value = 3Q – 1Q
  • upper_fence = 3Q + IQR * 1.5
  • lower_fence = 1Q – IQR * 1.5
# 이상치 제거
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 임의로 이상치 데이터가 포함된 데이터를 생성
data = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,25,30])

fig = plt.figure()
fig_1 = fig.add_subplot(1,2,1) # 1행 2열 중에 1번째로 추가
fig_2 = fig.add_subplot(1,2,2) # 1행 2열 중에 2번째로 추가
fig_1.set_title("Origian Data - Box Plot")
fig_1.boxplot(data)

print(np.percentile(data, 25)) # 1사분위
print(np.percentile(data, 50)) # 2사분위
print(np.percentile(data, 75)) # 3사분위

# IQR value = 3사분위값 - 1사분위값
iqr_value = np.percentile(data, 75) - np.percentile(data, 25)
print(iqr_value)

upper_fence = np.percentile(data, 75) + iqr_value * 1.5
lower_fence = np.percentile(data, 25) - iqr_value * 1.5

print(upper_fence)
print(lower_fence)
result_data = data[(data <= upper_fence) & (data >= lower_fence)]

fig_2.set_title("Outlier Data Removed")
fig_2.boxplot(result_data)
print(result_data)
fig.tight_layout()

plt.show()

scipy를 이용한 이상치 제거 (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 outliers 임계값 (2.0이하가 optimal)

# outliers 출력.
outliers = data[(np.abs(stats.zscore(data)) > zscore_threshold)]
print(outliers)    # [22.1]

# 이상치 제거한 결과
print(data[np.isin(data,outliers, invert=True)])
# [ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10. 11. 12. 13. 14.]

tensorflow로 ozone데이터 예측 하기

# 온도에 따른 Ozone량 예측
# 데이터 전처리
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import linear_model
from sklearn.preprocessing import MinMaxScaler
from scipy import stats
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.optimizers import SGD

# 데이터 위치는 본인의 파일 위치
df = pd.read_csv('dataset/ozone.csv')
display(df)

# 데이터 전처리
# 1. 결측치 삭제
# 2. 이상치 삭제
# 3. 정규화(MinMaxScaling)

training_data = df[['Temp', 'Ozone']]

# 결측치 삭제
training_data = training_data.dropna(how='any')
display(training_data)

# 이상치 삭제
zscore_threshold = 1.8
outliers = training_data['Ozone'][(np.abs(stats.zscore(training_data['Ozone'])) > zscore_threshold)]
print(outliers)
training_data = training_data.loc[~training_data['Ozone'].isin(outliers)]
print(training_data)

# 정규화 시작
x_data = training_data['Temp'].values.reshape(-1, 1)
t_data = training_data['Ozone'].values.reshape(-1, 1)

scaler_x = MinMaxScaler()
scaler_t = MinMaxScaler()

scaler_x.fit(x_data)
scaler_t.fit(t_data)

x_data_norm = scaler_x.transform(x_data)
t_data_norm = scaler_t.transform(t_data)

# sklearn으로 예측하기
sklearn_model = linear_model.LinearRegression()
# sklearn은 내부적으로 데이터를 normalization 진행
sklearn_model.fit(x_data, t_data)
sklearn_model.predict([[62]])

# keras로 예측하기 (normalization 진행해야 한다)
keras_model = Sequential()
keras_model.add(Flatten(input_shape=(1,)))

output_layer = Dense(units=1, activation='linear')
keras_model.add(output_layer)
# learning_rate가 다르면 결과가 sklearn과 달라진다.
keras_model.compile(optimizer=SGD(learning_rate=1e-2),
                                  loss='mse')

keras_model.fit(x_data_norm,
                t_data_norm,
                epochs=2000,
                verbose=0)

predict_data = np.array([[62]])
predict_data_norm = scaler_x.transform(predict_data)
result_norm = keras_model.predict(predict_data_norm)
result = scaler_t.inverse_transform(result_norm)
print(result)

다음 포스트에서 계속

error: Content is protected !!