[Pandas] UnicodeDecode 에러 : utf-8 인코딩 문제

 

판다스로 read_csv를 사용해서 csv 파일을 읽을 때, 특정 문자열 때문에 에러가 발생하는 경우가 있다.

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa1 in position 22: invalid start byte

이 에러를 해결하는 방법은 encoding='CP949'을 아래와 같이 추가해주는 것이다.

df = pd.read_csv("xxx.csv", encoding='CP949')

 

[LightGBM] LGBM는 어떻게 사용할까?

 

1. Light GBM이란?

Light GBM은 트리 기반의 학습 알고리즘인 gradient boosting 방식의 프레임 워크이다.

 

2. 다른 트리 기반의 알고리즘과 무엇이 다른가?

Light GBM은 나무를 수직으로 확장한다. 반면 다른 알고리즘은 나무를 수평으로 확장한다. 따라서 기존의 알고리즘은 수평으로 확장하여 포화 트리를 만드는 방향으로 학습하는 반면 leaf-wise tree growth인 LGBM은 최대 delta loss가 증가하도록 잎의 개수를 정한다. leaf-wise알고리즘은 다른 level-wise 알고리즘보다 낮은 loss를 달성하는 경향이 있다. 데이터의 크기가 작은 경우 leaf-wise는 과적합(overfitting)되기 쉬우므로 max_depth를 줄여줘야 한다.

3. LGBM은 왜 이렇게 유명해졌나?

데이터의 크기가 커짐에 따라 빠른 결과를 내는 것도 중요해지고 있다. 그런점에서 Light GBM은 'Light'의 접두사와 같이 속도가 빠른 것이 장점이다. 메모리를 적게 차지하고 속도가 빠르다는 장점 외에도, LGBM은 결과의 정확도가 높다는 장점이 있다. 또한, GPU를 활용할 수 있기 때문에 널리 사용되고 있다.

하지만, 위에서 말했듯이 overfitting에 민감하여 데이터의 크기가 작을 경우 기존의 머신러닝 알고리즘이 더 좋을 수 있다. 경험적으로 데이터의 개수(행 수)가 10,000개 이상일 때 추천한다.

 

4. 설치하기

conda install -c conda-forge lightgbm
pip install lightgbm

Sample code

import lightgbm as lgb
train_ds = lgb.Dataset(X_train, label = y_train)
test_ds = lgb.Dataset(X_val, label = y_val)
params = {'learning_rate': 0.01,
          'max_depth': 16,
          'boosting': 'gbdt',
          'objective': 'regression',
          'metric': 'mse',
          'is_training_metric': True,
          'num_leaves': 144,
          'feature_fraction': 0.9,
          'bagging_fraction': 0.7,
          'bagging_freq': 5,
          'seed':2020}

model = lgb.train(params, train_ds, 1000, test_ds, verbose_eval=100, early_stopping_rounds=100)
y_pred=model.predict(X_val)

위의 예제는 회귀 모델을 만들기 위한 예제 코드이다. 분류 모델을 만들기 위해서는 아래와 같이 바꾸면 된다. 

  • objective를 ‘binary’로 지정
  • metric을 ‘binary_logloss’로 지정

 

5. 하이퍼파라미터

주요 파라미터

object

objective 🔗︎, options: regression, binary, multiclass...

metric

metric 🔗︎, options: mae, rmse, mape, binary_logloss, auc, cross_entropy, kullbac_leibler...

1. learning_rate

일반적으로 0.01 ~ 0.1 정도로 맞추고 다른 파라미터를 튜닝한다. 나중에 성능을 더 높일 때 learning rate를 더 줄인다.

2. num_iterations

기본값이 100인데 1000정도는 해주는게 좋다. 너무 크게하면 과적합이 발생할 수 있다.

같은 뜻으로 사용되는 옵션: num_iteration, n_iter, num_tree, num_trees, num_round, num_rounds, num_boost_round, n_estimators

3. max_depth

-1로 설정하면 제한없이 분기한다. feature가 많다면 크게 설정한다. 파라미터 설정 시 우선적으로 설정한다.

4. boosting 

부스팅 방법: 기본값은 gbdt이며 정확도가 중요할때는 딥러닝의 드랍아웃과 같은 dart를 사용한다. 샘플링을 이용하는 goss도 있다.

boosting 🔗︎, default = gbdt, options: gbdt, rf, dart, goss

gbdt : traditional Gradient Boosting Decision Tree, aliases: gbrt
rf : Random Forest, aliases: random_forest
dart : Dropouts meet Multiple Additive Regression Trees
goss : Gradient-based One-Side Sampling

5. bagging_fraction

배깅을 하기위해서 데이터를 랜덤 샘플링하여 학습에 사용한다. 비율은 0 < fraction <= 1 이며 0이 되지 않게 해야한다.

6. feature_fraction

feature_fraction이 1보다 작다면 LGBM은 매 iteration(tree)마다 다른 feature를 랜덤하게 추출하여 학습하게된다. 만약, 0.8로 값을 설정하면 매 tree를 구성할 때, feature의 80%만 랜덤하게 선택한다. 과적합을 방지하기 위해 사용할 수 있으며 학습 속도가 향상된다.

7. scale_pos_weight

클래스 불균형의 데이터 셋에서 weight를 주는 방식으로 positive를 증가시킨다. 기본값은 1이며 불균형의 정도에 따라 조절한다.

8. early_stopping_round

Validation 셋에서 평가지표가 더 이상 향상되지 않으면 학습을 정지한다. 평가지표의 향상이 n round 이상 지속되면 학습을 정지한다.

9. lambda_l1, lambda_l2

정규화를 통해 과적합을 방지할 수 있지만, 정확도를 저하시킬수도 있기 때문에 일반적으로 default 값인 0으로 둔다.

  • 더 빠른 속도
    • bagging_fraction
    • max_bin은 작게
    • save_binary를 쓰면 데이터 로딩속도가 빨라짐
    • parallel learning 사용
  • 더 높은 정확도
    • max_bin을 크게
    • num_iterations 는 크게하고 learning_rate는 작게
    • num_leaves를 크게(과적합의 원인이 될 수 있음)
    • boosting 알고리즘 'dart' 사용
  • 과적합을 줄이기
    • max_bin을 작게
    • num_leaves를 작게
    • min_data_in_leaf와 min_sum_hessian_in_leaf 사용하기

 

[이미지 및 내용 출처] 

1. https://lightgbm.readthedocs.io/en/latest/Features.html

2. https://medium.com/@pushkarmandot/https-medium-com-pushkarmandot-what-is-lightgbm-how-to-implement-it-how-to-fine-tune-the-parameters-60347819b7fc

 

[Regression] Ridge and Lasso Regression in Python (3) - Lasso


이번엔 Ridge Regression을 파이썬으로 구현해서 파라미터값에 따른 회귀식의 차이를 살펴보겠습니다.


L2와 L1 Regularization은 이전 포스팅의 내용을 참고해주세요.


1. 데이터를 생성합니다.


import numpy as np
import pandas as pd
from matplotlib.pylab import rcParams
rcParams['figure.figsize'] = 8, 5
from sklearn.linear_model import Ridge
import matplotlib.pyplot as plt

x = np.array([i*np.pi/180 for i in range(60, 300, 4)])
np.random.seed(10)
y = np.sin(x) + np.random.normal(0, 0.15, len(x))
data = pd.DataFrame(np.column_stack([x, y]), columns=['x', 'y'])
plt.plot(data['x'], data['y'], '.')
for i in range(2, 16): # power
colname = 'x_%d'%i #new var will be x_power
data[colname] = data['x']**i

2. 케이스를 구분하고 결과값을 저장할 테이블을 만듭니다.

Polynomial regression과 마찬가지로 predictors에 차수를 확장시켜 컬럼명(feature name)을 저장합니다.

파라미터값인 alpha_ridge를 케이스 별로 나눕니다.

# Initialize predictors to be set of 15 powers of x
predictors=['x']
predictors.extend(['x_%d'%i for i in range(2,16)])

# Set the different values of alpha to be tested
alpha_ridge = [1e-15, 1e-10, 1e-8, 1e-4, 1e-3,1e-2, 1, 5, 10, 20] #파라미터값인 alpha_ridge를 케이스 별로 나눕니다.

# Initialize the dataframe for storing coefficients.
col = ['rss', 'intercept'] + ['coef_x_%d'%i for i in range(1,16)]
ind = ['alpha_%.2g'%alpha_ridge[i] for i in range(0,10)]
coef_matrix_ridge = pd.DataFrame(index=ind, columns=col)

models_to_plot = {1e-15:231, 1e-10:232, 1e-4:233, 1e-3:234, 1e-2:235, 5:236}

3. Lasso regression 함수를 작성합니다.

여기서 추가로 필요한 파라미터는 alpha입니다. Ridge와 거의 같습니다.

def lasso_regression(data, predictors, alpha, models_to_plot):
# Fit the model
lassoreg= Lasso(alpha=alpha, normalize=True)
lassoreg.fit(data[predictors], data['y'])
y_pred = lassoreg.predict(data[predictors])

# Check if a plot is to be made for the entered alpha
if alpha in models_to_plot:
plt.subplot(models_to_plot[alpha])
plt.tight_layout()
plt.plot(data['x'], y_pred)
plt.plot(data['x'], data['y'], '.')
plt.title('Plot for alpha: %.3g'%alpha)

# Return the result in pre-defined format
rss = sum((y_pred-data['y'])**2)
ret = [rss]
ret.extend([lassoreg.intercept_])
ret.extend(lassoreg.coef_)
return ret

4. 결과 테이블을 계산합니다.

for i in range(10):
coef_matrix_ridge.iloc[i, ] = lasso_regression(data, predictors, alpha_ridge[i], models_to_plot)


계수를 보면 α값이 작을수록 계수값이 작습니다. Ridge와는 반대입니다. 그리고 α값이 큰 경우에 계수 값이 0이 되기도 합니다.

Lasso의 Cost function은 아래와 같습니다. 가중치의 절대값에 파라미터가 곱해져있는 형태입니다.



마찬가지로 미분을 해보면 좌극한에서는 -1, 우극한에서는 1의 기울기를 갖는데 0에서는 미분이 불가능합니다.


0에서 미분이 되지 않는 문제를 해결하는 방법인 Proximal gradient methods를 사용합니다. Sλt(x)는 Soft-thresholding operator라고 합니다.


S(x)를 x대신 w로 치환하여 아래의 g(wj)로 보면 됩니다. 꼭 람다가 λ/2가 되어야 하는 것은 아니고 그냥 λ여도 됩니다.(알고리즘의 차이인 걸로 추정됨)

즉, 미분이 안되는 미소 구간에 대해서는 가중치가 0이 된다는 뜻입니다.


미소구간을 결정하는 것은 λ이고 위의 Python 코드에서는 α입니다. 기울기가 큰 상태에서 큰 step(α)으로 기울기를 조정하는데 가중치의 크기가 +-α/2 구간으로 들어가게 되면 가중치가 0이 되어버립니다. 


또 다른 설명으로는, 가중치 제한인 s의 범위에 따른 해석입니다.

B-hat은 최소제곱자승법으로 구한 최소 지점입니다. s가 점점 커지다보면 B-hat에 도달하는데 이 지점은 파라미터가 0이되는 때입니다.

B-hat 주변의 타원은 RSS를 나타내는데 RSS와 파란색 영역이 닿는 부분이 계수값이 됩니다.




왼쪽 그림은 Lasso의 경우인데 Lasso는 어쩌다가 꼭지점에서 RSS가 최소가 될 수 있습니다. 그렇게 되면 그 B1의 가중치가 0이 될것입니다. 반면 오른쪽 그림의 Rigde는 원이기 때문에 축에서 만나지 않으므로 가중치가 0이되는 일이 없습니다.


도움이 되셨다면 공감 부탁드려요!

[Regression] Ridge and Lasso Regression in Python(2)


이번엔 Ridge Regression을 파이썬으로 구현해서 파라미터값에 따른 회귀식의 차이를 살펴보겠습니다.


L2와 L1 Regularization은 이전 포스팅의 내용을 참고해주세요.


1. 데이터를 생성합니다.


import numpy as np
import pandas as pd
from matplotlib.pylab import rcParams
rcParams['figure.figsize'] = 8, 5
from sklearn.linear_model import Ridge
import matplotlib.pyplot as plt

x = np.array([i*np.pi/180 for i in range(60, 300, 4)])
np.random.seed(10)
y = np.sin(x) + np.random.normal(0, 0.15, len(x))
data = pd.DataFrame(np.column_stack([x, y]), columns=['x', 'y'])
plt.plot(data['x'], data['y'], '.')
for i in range(2, 16): # power
colname = 'x_%d'%i #new var will be x_power
data[colname] = data['x']**i

2. 케이스를 구분하고 결과값을 저장할 테이블을 만듭니다.

Polynomial regression과 마찬가지로 predictors에 차수를 확장시켜 컬럼명(feature name)을 저장합니다.

파라미터값인 alpha_ridge를 케이스 별로 나눕니다.

# Initialize predictors to be set of 15 powers of x
predictors=['x']
predictors.extend(['x_%d'%i for i in range(2,16)])

# Set the different values of alpha to be tested
alpha_ridge = [1e-15, 1e-10, 1e-8, 1e-4, 1e-3,1e-2, 1, 5, 10, 20] #파라미터값인 alpha_ridge를 케이스 별로 나눕니다.

# Initialize the dataframe for storing coefficients.
col = ['rss', 'intercept'] + ['coef_x_%d'%i for i in range(1,16)]
ind = ['alpha_%.2g'%alpha_ridge[i] for i in range(0,10)]
coef_matrix_ridge = pd.DataFrame(index=ind, columns=col)

models_to_plot = {1e-15:231, 1e-10:232, 1e-4:233, 1e-3:234, 1e-2:235, 5:236}

3. Ridge regression 함수를 작성합니다.

여기서 추가로 필요한 파라미터는 alpha입니다.

def ridge_regression(data, predictors, alpha, models_to_plot):
# Fit the model
ridgereg = Ridge(alpha=alpha, normalize=True)
ridgereg.fit(data[predictors], data['y'])
y_pred = ridgereg.predict(data[predictors])

# Check if a plot is to be made for the entered alpha
if alpha in models_to_plot:
plt.subplot(models_to_plot[alpha])
plt.tight_layout()
plt.plot(data['x'], y_pred)
plt.plot(data['x'], data['y'], '.')
plt.title('Plot for alpha: %.3g'%alpha)

# Return the result in pre-defined format
rss = sum((y_pred-data['y'])**2)
ret = [rss]
ret.extend([ridgereg.intercept_])
ret.extend(ridgereg.coef_)
return ret

4. 결과 테이블을 계산합니다.

for i in range(10):
coef_matrix_ridge.iloc[i, ] = ridge_regression(data, predictors, alpha_ridge[i], models_to_plot)

계수를 잘 보면 α값이 작을수록 계수값이 커집니다. α값이 큰 경우 언더피팅이 발생하고 rss값이 큰 것을 알 수 있습니다.

pd.options.display.float_format = '{:,.2g}'.format
print(coef_matrix_ridge)
plt.show()

적당한 α값을 찾는 것이 중요합니다.

Ridge regression의 특징은 계수를 0으로 만들지는 않는다는 것입니다.


왜 계수가 0이 되지않는지 확인하기 위해 Cost function으로 돌아가보겠습니다.

Cost function을 최소화하는 방법 중 Gradient descent method를 생각해보겠습니다.

Cost function을 미분하면 아래와 같은 식이 나옵니다.

식을 다시 쓰면 아래와 같습니다.

wj 오른쪽을 제외하고 wj만 보면 일정한 비율로 t+1에서의 계수값이 작아진다는 것을 알 수 있습니다. 1-2λη가 계수의 크기보다 작아지면 부정확할 수 있다는 경고가 발생합니다.


즉, 계수가 %의 비율로 작아진다는 뜻입니다. 어떤 계수 값이 %로 작아진다고해도 0은 되지 않기때문에 L2 가중치 규제는 계수가 0이 되지 않습니다.

또 다른 설명으로는, 가중치 제한인 s의 범위에 따른 해석입니다.

B-hat은 최소제곱자승법으로 구한 최소 지점입니다. s가 점점 커지다보면 B-hat에 도달하는데 이 지점은 파라미터가 0이되는 때입니다.

B-hat 주변의 타원은 RSS를 나타내는데 RSS와 파란색 영역이 닿는 부분이 계수값이 됩니다.



왼쪽 그림은 Lasso의 경우인데 Lasso는 어쩌다가 꼭지점에서 RSS가 최소가 될 수 있습니다. 그렇게 되면 그 B1의 가중치가 0이 될것입니다. 반면 오른쪽 그림의 Rigde는 원이기 때문에 축에서 만나지 않으므로 가중치가 0이되는 일이 없습니다.


도움이 되셨다면 공감 부탁드려요!

[Regression] Ridge and Lasso Regression in Python(1) - Polynomial


이번에는 Ridge와 Lasso Regression을 파이썬으로 구현해보도록 하겠습니다.


1. 데이터를 생성합니다.

그리고 모델의 복잡도를 비교하기 위해 x의 차수를 높혀가며 선형 회귀식을 만들어 보려고 합니다.

rcParams는 figure의 사이즈를 지정하기 위해 사용합니다.


import numpy as np
import pandas as pd
import random
from matplotlib.pylab import rcParams
rcParams['figure.figsize'] = 8, 5
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt

x = np.array([i*np.pi/180 for i in range(60, 300, 4)])
np.random.seed(10)
y = np.sin(x) + np.random.normal(0, 0.15, len(x))
data = pd.DataFrame(np.column_stack([x, y]), columns=['x', 'y'])
plt.plot(data['x'], data['y'], '.')
for i in range(2, 16): # power
colname = 'x_%d'%i #new var will be x_power
data[colname] = data['x']**i

만들어진 데이터는 가우시안 에러를 가진 사인 곡선입니다.


2. 모델의 차수 별 계수와 절편 값을 테이블로 만들기 위해 dataframe을 만듭니다.

#Initialize a dataframe to store the results:
col = ['rss','intercept'] + ['coef_x_%d'%i for i in range(1, 16)]
ind = ['model_pow_%d'%i for i in range(1, 16)]
coef_matrix_simple = pd.DataFrame(index=ind, columns=col)

#Define the powers for which a plot is required:
models_to_plot = {1:231,3:232,6:233,9:234,12:235,15:236}

models_to_plot은 1차는 2*3 grid의 첫번째, 3차는 grid의 두번째에 띄우기 위한 Dictionary 입니다.


3. Polynomial regression을 하기위해 linear_regression 함수를 만듭니다.

predictors는 몇개의 항(차수)를 사용할지 정하여 feature 명을 저장합니다.

linreg로 차수만큼 테이블의 컬럼과 데이터를 불러와서 피팅시킵니다.

그리고 다시 training 데이터를 넣어 모델 예측값을 구합니다.


rss는 예측과 실체값의 차이 즉 MSE 입니다.

def linear_regression(data, power, models_to_plot):
# initialize predictors:
predictors=['x']
if power >= 2:
predictors.extend(['x_%d'%i for i in range(2, power+1)])
#Fit the model
linreg = LinearRegression(normalize=True)
linreg.fit(data[predictors], data['y']) # 차수만큼 테이블의 컬럼을 불러와서 피팅시킨다.
y_pred = linreg.predict(data[predictors]) # ligreg 모델에 데이터를 넣었을때 나오는 y 값

#Check if a plot is to be made for the enterted power
if power in models_to_plot:
plt.subplot(models_to_plot[power])
plt.tight_layout() # plot과 window 여백 제거
plt.plot(data['x'], y_pred)
plt.plot(data['x'], data['y'], '.')
plt.title('Plot for power: %d' % power)

#Return the result in pre-defined format
rss = sum((y_pred - data['y'])**2)
ret = [rss]
ret.extend([linreg.intercept_])
ret.extend(linreg.coef_)
return ret

아래 코드를 실행시키면 coef_matrix가 채워집니다.

for i in range(1,16):
coef_matrix_simple.iloc[i-1, 0:i+2] = linear_regression(data, power=i, models_to_plot=models_to_plot)


아래는 결과값입니다. 15차까지 다 나오지는 않았지만 차수가 높아질 수록 계수의 절대값의 크기가 커지고 모델의 복잡도가 증가합니다.

Ridge와 Lasso를 사용하여 가중치 규제를 하는 이유가 이것입니다. 계수의 절대값이 점점 커지기 때문에 가중치 값을 줄이고 모델의 복잡도를 줄일 필요가 있습니다.

가중치가 크다는 말은 무엇일까요? 큰 가중치는 그 feature를 강조한다는 뜻입니다. 하지만 가중치가 점점 커지다 보면 모델이 training data에 모두 예측하려합니다.



따라서 차수가 높아질수록 과적합 현상이 일어납니다.



도움이 되셨다면 공감 부탁드려요!


[Regression] Piecewise Regression with numpy



Piecewise Regression이란 하나의 식으로 전체 구간을 설명하기 어려울 경우 구간에 따라 모델을 다르게 쓰는 기법이다.

우선 데이터를 생성한다.


import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize

np.random.seed(0)
x = np.random.normal(0, 1, 1000) * 10
# 조건에 맞는 값을 특정 다른 값으로 변환하기
# np.where(조건, 조건에 맞을 때 값, 조건과 다른 때 값) if 문과 비슷함. 그냥 where은 조건에 맞는 인덱스 반환
y = np.where(x < -15, -2 * x + 3, np.where(x < 10, x + 48, -4 * x + 98)) + np.random.normal(0, 3, 1000)
plt.scatter(x, y, s = 5, color = u'b', marker = '.', label = 'scatter plt')

원래는 random array가 매번 바뀌지만 np.random.seed는 괄호 안의 값에 따라 동일한 랜덤 array를 생성하도록 한다. 

a = np.array([1, 2, 3, 4, 5]) 의 배열이 있을때, np.where(a < 3)을 하면 조건에 맞게 1과 2의 인덱스 값(0, 1)을 반환한다.

3개의 parameter를 이용하는 방식도 있다.

np.where(a < 3, 10, a) 를 하면 [10, 10, 3, 4, 5]를 반환한다. 즉, 조건에 맞으면 그 배열 값을 10으로 바꾸고 아니면 원래 값으로 둔다는 식이다. if 문과 비슷하다.

x와 y를 scatter plot으로 보면 아래와 같다. 


위의 데이터에 np.piecewise를 적용하기 전에 쉬운 예로 이해를 돕고자 한다.

x = np.linspace(-2.5, 2.5, 6)
print(x) # [-2.5 -1.5 -0.5 0.5 1.5 2.5]


condlist = [x < 0, x >= 0]
print(condlist) ## [array([True, True, True, False, False, False]), array([False, False, False, True, True, True,])]


t = np.piecewise(x, [x < 0, x >= 0], [lambda x: -3*x, lambda x: 3*x])
plt.plot(range(len(x)), t)

나누고자 하는 구간이 2개이면 condlist의 조건도 2개이고 2개의 array를 반환한다. 그리고 그 condlist가 첫번째 lambda와 두번째 lambda의 input으로 입력되고, True면 계산되고 False면 0을 반환하여 두 lambda 함수의 합을 최종적으로 np.piecewise의 값으로 반환한다.



하지만 우리는 위에서 0으로 두었던 분기점을 정하지 않았기 때문에 데이터에 맞춰서 최적의 분기점을 찾도록 할 것이다.

그러면 scipy.optimize의 목적함수로 쓰일 piecewise_linear 함수를 정의해야 한다. 

condlist는 3구간으로 나올수 있도록 하고(분기점의 수만큼 조건식이 필요) 그에 대응될 lambda 함수의 모양을 짠다. lambda 함수가 이어지도록 되어있는데 k1*x + b + k2*(x-x0)에서 앞의 k1*x + b 는 분기점에서의 y값(새로운 상수항)이 되므로 이렇게 쓰지 않으면 에러가 난다.

def piecewise_linear(x, x0, x1, b, k1, k2, k3):
condlist = [x < x0, (x >= x0) & (x < x1), x >= x1]
funclist = [lambda x: k1*x + b, lambda x: k1*x + b + k2*(x-x0), lambda x: k1*x + b + k2*(x-x0) + k3*(x - x1)]
return np.piecewise(x, condlist, funclist)
p , e = optimize.curve_fit(piecewise_linear, x, y)


이 과정을 거쳐 데이터에 가장 적합한(에러가 최소화되는) x0, x1, b, k1, k2, k3이 정해지고 아래와 같이 선이 그려진다.

xd = np.linspace(-30, 30, 1000)
plt.plot(x, y, "o")
plt.plot(xd, piecewise_linear(xd, *p))





[케라스(keras)] 케라스에서 텐서보드 사용하기-Tensorboard with Keras


케라스로 만든 모델을 텐서보드에서 확인하는 방법입니다.

기존에 만든 모델에 3줄만 추가해주면 됩니다. 아래 노란색 주석을 참고해주세요.


from keras.datasets import mnist
from keras.utils import to_categorical
from tensorflow.python.keras.callbacks import TensorBoard ## TensorBoard 를 import합니다.
from time import time ## Log를 만들때 사용합니다.
from keras import layers
from keras import models

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
# sp = np.shape(train_images) #(60000, 28, 28) 28x28 그림 60000장

train_images = train_images.reshape((60000, 28, 28, 1)) # <class 'numpy.ndarray'>
train_images = train_images.astype('float32') / 255 # <class 'numpy.ndarray'>
test_images = test_images.reshape((10000, 28, 28, 1))
test_images = test_images.astype('float32') / 255

train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)

model = models.Sequential() # Sequential method로 모델 구성
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1), padding='same'))
model.add(layers.MaxPooling2D(2, 2))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D(2, 2))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))

model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
print(model.summary())


tensorboard = TensorBoard(log_dir="logs/{}".format(time())) ## 이 줄과

model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=5, batch_size=64, callbacks=[tensorboard]) ## 이 줄을 추가합니다.

test_loss, test_acc = model.evaluate(test_images, test_labels)


위의 코드를 한번 실행시키고 커맨드창을 열어 텐서보드를 실행시켜줍니다. 

현재 경로로 이동하고 tensorboard --logdir=logs(로그가 저장되어 있는 폴더명)



처음에는 커맨드라인에 나온 http://컴퓨터이름:6006으로 접속했더니 페이지가 안열렸습니다.

그래서 localhost:6006으로 다시 접속하니 정상 실행됐습니다.



사용방법은 https://www.youtube.com/watch?time_continue=1255&v=eBbEDRsCmv4에 잘 나와있습니다.


[케라스(keras)] MLP regression 다층퍼셉트론으로 회귀모델 만들기



케라스를 이용해서 다층퍼셉트론으로 Neural Network 회귀 모델을 만들어보겠습니다.


모델링에 쓰인 데이터는 비행기가 이륙할 때의 속도와 무게에 따른 이륙 전 이동 거리입니다.



데이터를 보시면 선형적인 관계가 있다는 것을 알 수 있습니다.

import numpy as np
import matplotlib.pyplot as plt
from keras import models, layers
import tensorflow as tf

우선 Sequential 형태로 레이어를 쌓겠습니다.

def build_model():
model = models.Sequential()
model.add(layers.Dense(2, activation='sigmoid', input_shape=(2,)))
model.add(layers.Dense(1))
optimizer = tf.train.RMSPropOptimizer(0.001)
model.compile(optimizer=optimizer, loss='mse', metrics=['mae', 'mae'])
return model

input_shape이 2인 것은 데이터(x1, x2)가 input node에 순차적으로 들어가기 때문입니다.

activation 함수는 sigmoid를 사용했고, optimizer의 learning rate를 0.001로 맞췄습니다.


그리고 main함수를 작성합니다.


def main():
traincsvdata = np.loadtxt('trainset.csv', unpack=True, delimiter=',', skiprows=1)
num_points = len(traincsvdata[0])
print("points : ", num_points)
train_num_colum = len(traincsvdata)
train_mean = []
train_std = []
for i in range(train_num_colum):
train_mean.append(traincsvdata[i].mean())
train_std.append(traincsvdata[i].std())
traincsvdata[i] -= traincsvdata[i].mean()
traincsvdata[i] /= traincsvdata[i].std()

csv파일을 읽어들이면 300개의 행과 3개의 컬럼을 가진 데이터를 얻을 수 있습니다. 그리고 x1, x2와 y데이터를 표준화 해줍니다.

numpy의 .mean(), std() 함수를 이용해서 순서대로 연산을 합니다. 

# x_data생성
x_data = np.array([traincsvdata[0], traincsvdata[1]])
x_data = np.array(x_data).transpose()
# y_data reshape
y_data = traincsvdata[2]
y_data = np.array(y_data).transpose()

그리고 모델의 input_shape에 맞도록 행렬을 transpose 해줍니다.

model = build_model()
model.fit(x_data, y_data, epochs=2000, batch_size=50, verbose=1, shuffle=True)
w = model.get_weights()

모델을 return받아서 학습을 시작합니다. epochs는 300행짜리 데이터를 2000번 학습시키는 것이고 batch_size는 50행씩 학습시키겠다는 것입니다. verbose는 console에 학습 진행을 보여줍니다. shuffle은 True/False 차이가 없습니다.(시간 의존적 데이터가 아니므로)

그리고 layer별 weight와 bias는 다음과 같습니다.

[array([[-0.94589883,  0.15035586],  [-0.5647819 , 0.96030337]], dtype=float32), array([0.46524414, 0.03646885], dtype=float32), array([[-2.0237916], [ 3.0606623]], dtype=float32), array([-0.3549767], dtype=float32)]


학습을 끝냈으니 test 데이터와 비교해보겠습니다.


test_csv_data = np.loadtxt('testset.csv', unpack=True, delimiter=',', skiprows=1)
test_csv_data2 = np.loadtxt('testset.csv', unpack=True, delimiter=',', skiprows=1)
test_num_colum = len(test_csv_data)

#테스트셋 정규화 진행
for i in range(test_num_colum):
test_csv_data[i] -= train_mean[i]
test_csv_data[i] /= train_std[i]

test_x_data = np.array([test_csv_data[0], test_csv_data[1]])
test_x_data = np.array(test_x_data).transpose()

prediction = model.predict(test_x_data)
prediction *= train_std[2]
prediction += train_mean[2]
plt.plot(range(len(prediction)), prediction, 'k*')
plt.plot(range(len(prediction)), test_csv_data2[2], 'mo')
plt.show()

plot에 띄워 test target 데이터와 비교하려면 표준화 한 값을 원래 스케일로 돌려야합니다. 테스트 셋을 정규화 할 때 trainset의 평균, 표준편차로 정규화 했으므로 원래 스케일로 돌릴때도 같은 숫자를 이용합니다.

순서는 표준편차를 먼저 곱하고 평균을 곱해줘야합니다.


별표는 예측값이고 파란색 점은 실제값입니다. 관계가 단순해서 그런지 나름 잘 맞는 것 같습니다.

사실 모델을 단층으로 만들어도 결과는 잘 나왔습니다.
model.add(layers.Dense(1, input_shape=(2,)))

testset.csv

trainset.csv


데이터를 이용해서 선형으로도 해보시고 optimizer나 activation function도 바꿔보세요 :)



배우는 과정이라 설명이 틀렸을 수 있습니다. 이상이 있으면 댓글 남겨주세요!


도움이 되셨으면 공감 부탁드립니다!

[데이터 시각화] Matplotlib로 3D scatter plot 그리기


trainset.csv


간단한 3D scatter plot을 그려보겠습니다.

정말 간단합니다. 


간단한 설명을 추가하자면 gca는 Get current axes 입니다.

비행기의 이륙 속도, 짐의 무게를 가지고 이륙에 필요한 거리를 계산하는 예제의 시각화 부분입니다.


import matplotlib.pyplot as plt
import numpy as np


fig = plt.figure()
ax = fig.gca(projection='3d')

# Make data.
data = np.loadtxt('./trainset.csv', unpack=True, delimiter=',', skiprows=1)
X = data[0]
Y = data[1]
Z = data[2]

# Plot the surface.

# Customize the z axis.
ax.scatter(X, Y, Z)

ax.set_xlabel('Speed(km/h)')
ax.set_ylabel('Weight(ton)')
ax.set_zlabel('Distance(m)')
plt.suptitle('Takeoff distance prediction', fontsize=16)
plt.show()




데이터는 우측 상단링크로 받으실 수 있습니다.


다음 포스팅에선 신경망(Multi-Layer Perceptron)을 이용하여 비행기 이륙거리 예측을 해보겠습니다. 

[python] image processing speed comparison cv2 vs imageio


There are two way on image processing in python.

I wondered the speed using 'cv2' and 'imageio' on reading images.

I tested with 1000*667 size picture to compare their speed.



'cv2' was faster than 'imageio' in all time and the records were 32%, 39%, 29%, 44%, 49%, 40%, 42%, 45%, 34%, 40%.

The average is 39.4%.


Conclusion : Use cv2!!!




+ Recent posts