728x90

지난 포스팅에 이어서 오늘은 모델링을 만들어 봤습니다. 

#그리드 서치
models = [
    ('ridge', lm.Ridge()),
    ('lasso', lm.Lasso()),
    ('elastic', lm.ElasticNet()),
    ('LassoLars', lm.LassoLars()),
    ('LogisticRegression', lm.LogisticRegression()),
    ('SGDRegressor', lm.SGDRegressor()),
    ('Perceptron', lm.Perceptron(n_jobs=-1)),
    ('xgboost', xgb.XGBRegressor()),
    ('lgb', lgb.LGBMRegressor()),
    ('knn', KNeighborsRegressor(n_jobs = -1) ),
    ('rf', RandomForestRegressor(n_jobs = -1)),
    ('dt',  DecisionTreeRegressor()),
    ('ada', AdaBoostRegressor())
]

params = {
    'ridge': {
        'alpha': [0.01, 0.1, 1.0, 10, 100],
        'fit_intercept': [True, False],
        'normalize': [True, False],
    },
    'lasso': {
        'alpha': [0.1, 1.0, 10],
        'fit_intercept': [True, False],
        'normalize': [True, False],
    },
    'elastic': {
        'alpha': [0.1, 1.0, 10],
        'normalize': [True, False],
        'fit_intercept': [True, False],
    },
    'LassoLars': {
        'alpha': [0.1, 1.0, 10],
        'normalize': [True, False],
        'fit_intercept': [True, False],
    },
    'LogisticRegression': {
        'penalty': ['l1', 'l2'],
        'C': [0.01,0.1, 1.0, 10,100],
        'fit_intercept': [True, False],
    },
    'SGDRegressor': {
        'penalty': ['l1', 'l2'],
        'alpha': [0.001, 0.01, 0.1, 1.0, 10, 100],
        'fit_intercept': [True, False],
    },
    'Perceptron' :{
        'penalty': ['None', 'l1', 'l2'],
        'alpha': [0.001, 0.01, 0.1, 1.0, 10, 100],
        'fit_intercept': [True, False]
    },
    'xgboost': {
        "gamma": uniform(0, 0.5).rvs(3),
        "max_depth": range(2, 7), 
        "n_estimators": [100,200,300] 
    },
    'lgb': {
        "gamma": uniform(0, 0.5).rvs(3),
        "max_depth": range(2, 7), 
        "n_estimators": [100,200,300] 
    },
    'knn': {
        "n_neighbors": range(2,7),
        },
    'rf': {
        "max_depth": range(2, 5),
        "min_samples_split": range(2, 5),
        "min_samples_leaf": range(2, 5), 
        "n_estimators": [100,200,300],
        },
    'dt': {
        "max_depth": range(2, 5),
        "min_samples_split": range(2, 5),
        "min_samples_leaf": range(2, 5), 
        },
    'ada': {
        "n_estimators": [40,50,60]
    }
}

best_model, best_mae = None, float('inf')
x_columns = ['hour','hour_bef_temperature','hour_bef_precipitation']
for model_name, model in models:
    param_grid = params[model_name]
    grid = GridSearchCV(model, cv=5, n_jobs=-1, param_grid=param_grid)
    grid = grid.fit(X_train[x_columns], y_train)

    model = grid.best_estimator_
    predictions = model.predict(X_test[x_columns])
    mae = mean_absolute_error(y_test, predictions)

    print(model_name, mae)

    if mae < best_mae:
        best_mae=mae
        best_model = model
ridge 40.31602129541864
lasso 40.30855653538877
elastic 41.252566307860604
LassoLars 40.30853364226131
LogisticRegression 51.55936073059361
SGDRegressor 40.257925028487605
Perceptron 93.32876712328768
[10:07:54] WARNING: /workspace/src/objective/regression_obj.cu:152: reg:linear is now deprecated in favor of reg:squarederror.
xgboost 27.404816101675163
lgb 27.910991375973378
knn 27.974885844748858
rf 30.92272982406107
dt 32.59905879619483
ada 34.54503408876004

 

가장 좋은 성능을 보인 xgboost로 test 데이터 predict 제출한 결과, 

 

37.03 점수를 받았습니다. 참고로 리더보드 1등 점수는 29.31입니다.

53점을 받은 pred는 모든 변수를 넣은 결과 입니다. VIF와 xgb의 feature 중요도를 본 경과 변수 세 개만 이용해도 될것 같아서 변수의 수 만 조절했는데 53->37로 성능이 좋아졌습니다. 

 

위에 해당하는 모델 말고도 CV를 기반한 스태킹 코드를 미리 짜놨는데, 스태킹을 해도 성능이 획기적으로 줄어 들것같진 않더라구요. 그래서 스케일링도 해보고, 이것저것 시도 중입니다. 

 

변수가 한정적이라서 어떻게 뭘 더 해야할지 고민 중입니다. 타켓값의 분포를 보면 계절성은 있어 보였습니다. 

 

그래서 계절성 성분을 뽑아서 변수로 넣을 고민 중에 있습니다. 받은 데이터 시간순으로 되어 있지 않아서 이를 어떻게 적용할지 감이 확 오진 않더라구요.

 

target 분포가 정규분포가 아니면 log을 사용해볼려고 했는데, 그래프상 약간 왼쪽으로 치우친 것 같지만 통계량 결과 정규분포라고 나왔어요, log를 씌운 것과 비교 했을때 그닥 차이가 없어 보여서 제외 시켰습니다 .ㅠ

 

앞서 언급한 스케일링도, 하기 전/후의 성능이 고만고만했습니다. 종류별로 다 돌려 봤는데 거의 비슷했습니다. 

구글링하면서 다른 분들은 어떻게 했는지 찾아 보고 있는데, 저와는 데이터 자체가 달라서 인사이트를 얻기가 쉽진 않았어요 

 

많이 알수록 많은 걸 볼수 있는데 이럴때면 참 갈길이 멀구나 생각이 드네요 ㅎㅎ;

728x90
728x90

저번 포스팅까지는 하나의 데이터에 대한 학습과정을 공부했습니다. 이번 시간부터는 미니배치 즉, 여러개 샘플을 가지고 학습을 시키는 방법에 대해 공부한 내용을 포스팅하겠습니다. 2가지로 나눠서 진행할 예정입니다.

 

1. 두개의 sample에 대해서 cost function을 이용한 업데이트 방법

2. vector notation을 이용한 방법 (n개의 미니배치가 있을 경우의 업데이트 방법)

 

*실습링크

2021.09.04 - [실습 note] - 딥러닝 수학 실습과제 모음 9~12

 

딥러닝 수학 실습과제 모음 9~12

실습파일이 없는 줄 알았는데 있더라구요 그래서 쌓여 있는 실습을 진행했습니다. 각 구분선에 따라 이론내용과 실습을 분리했습니다. 순서는 맨 위부터 아래 순입니다. 2021.08.19 - [Data 일기] - 20

ghdrldud329.tistory.com

 

1. 두개의 sample에 대해서 cost function을 이용한 업데이트 방법

Loss 값들을 모두 평균내는 cost 부분을 미분하면 1/n이다. 만일 2개의 x data가 있다고 한다면 2개의 Loss값이 나오고 1/2씩 값을 가져와서 cost를 계산하게 된다. 이해를 돕기 위해 아래 그림을 참고해보자.

각 구해진 Loss 값에서 1/2씩 전달되어 cost가 만들어진다. backward 일때도 같은 원리로 과정을 거치게 된다.

데이터가 하나일때와 다른점은 1/2이 추가 된것 뿐이다. 미분은 내가 어느정도 영향을 끼쳤는지를 볼때 사용된다. forward 할때 1/2씩 각 loss값에서 cost로 전달이 되었고, 이를 다시 backward를 진행할 땐 내가 주었던 1/2을 "다시 받는 것이다." cost의 backward는 "공평하게 값을 나눈다."

다음으로 추가적인 핵심 부분은 아래 그림과 같다.

현재 th1,th0 두개가 있을 경우 backward의 진행을 살펴보고 있다. 초록색 수식을 보면 th1,th0 각각에 할당되는 값을 볼수있다. 두개 모두 "1" 이다. 즉, 앞전에 진행된 값을 "그대로" th1,th0에 전달하게 되는 것이다. 파란색 수식을 보면 값이 같다는 걸 알수 있다. 딱 여기까지가 bias term이 cost에 얼마나 영향을 주었는지를 알기 위해 편미분 값을 구한 것이다. 참고로 위 그림에서 검정색 글씨 th1이 두개가 있는데 왼쪽에 있는 것이 th1, 뒤에 있는 것이 th0이다.(강의 자료 오류)

정리를 하게 되면 아래와 같다.

각각 어떤 X data sample을 뽑느냐에 따라 수식은 같지만 값이 완전히 달라질수 있다. 이를 명심해야한다. cost는 각각 다른 이 두개를 섞어 주면 되는 것이다. 아래 수식을 통해 확인해 보자.

최종 수식의 의미를 본다면 "각각의 Loss을 더한 뒤 1/n만큼 나눈다" 이다. 이는 cost와 같은 의미이다.

th1, th0 각각의 평균값이 cost 값으로 이용이 된다. cost를 사용하게 되면 데이터들의 "전반적인 특성"을 반영하다 보니까 개별의 gradient 특성을 파악하는데 힘들수가 있게 된다. (배치 사이즈를 작게 하면 해결가능하다) 반면 얻는 장점은 튀는 값들을 surpress 해줌으로써 안정적인 학습을 가능케 한다.

 

 

2. vector notation을 이용한 방법 (n개의 미니배치가 있을 경우의 업데이트 방법)

x가 n개가 있을때 이를 jacobian metrices로 아래처럼 표현할수 있다.

n개에 대한 함수에 대해서 각각 th1의 편미분 값을 구할수 있다. 다른 편미분 값들도 보자면 아래처럼 표현할수 있겠다.

위는 벡터 function에 대한 벡터 독립변수의 편미분값을 구하는 과정이다. 행과열이 n개이므로 n*n 매트릭스가 된다. 위 내용 중 th1,th0으로 가는 편미분 값은 1이기 때문에 앞서 받았던 편미분을 그대로 전달 한다고 배웠다. 그때와 지금 다른 점은 매트릭스라는 형태이다. 항등행렬을 곱하므로써 자기 자신을 그대로 전달하는 역할을 하게 된다. th0도 마찬가지고 편미분 값이 모두 1로 나옴으로써 앞서 계산된 편미분 값을 그대로 받게된다. plus_node의 특징이다.

마이너스에 대해서 편미분을 구하게 되기 때문에 값이 모두 마이너스로 계산되는 특징을 가진다.

스칼라 fuuction에 대해서 벡터에 대한 미분을 해준다는게 특징이다.

앞으로 강의에서는 해당 수식들을 vec(편미분)으로 표현 해줌으로써 vector 표현을 변경하였다. 이를 활용하여 어떻게 backward가 진행되는지 자세한 과정은 생략하도록 한다.

정리를 하게 되면 아래와 같다.

Implementation

기존과 달라진 점은 vector로 연산이 된다는 점 이외에는 배웠던 내용과 같으므로 자세한 설명은 생략해도 될것같다.

8개씩 나뉜 평균값 cost를 사용하므로 위 그림처럼 부드러운 곡선을 나타내며 학습이 진행된다.

728x90
728x90

저번 포스팅에서 언급했던 결측치 문제를 오늘 해결했습니다. 결과만 보면 이렇게 간단한데 그 과정을 알기까지가 힘드네요. 아래가 해결한 코드입니다.

def nan_fill(dataset):
  #결측치가 있는 컬럼
  nan_columns = [col for col in dataset.iloc[:,2:-1].columns.to_list() if col!='hour_bef_precipitation']

  #for 문을 통해 결측치를 각 시간대별 평균값으로 대체
  for col in nan_columns:
    hour_mean_value = dataset.groupby('hour').mean()[col]
    hour_mean_value.fillna(hour_mean_value.mean(),inplace=True) #회귀를 통해서 값 채우기 시도

    for nan_hour in dataset[dataset[col].isna()]['hour'].unique():
      
      #nan index 구하기
      index= dataset[dataset[col].isna()].loc[dataset['hour']==nan_hour,col].index

      #채우기 
      for idx in index:
        dataset.loc[idx, col] = hour_mean_value[nan_hour]

  #hour_bef_precipitation 결측치 삭제
  dataset.dropna(inplace=True)
  print(dataset.isna().sum())
  return dataset
train =  nan_fill(train)
test= nan_fill(test)
id                        0
hour                      0
hour_bef_temperature      0
hour_bef_precipitation    0
hour_bef_windspeed        0
hour_bef_humidity         0
hour_bef_visibility       0
hour_bef_ozone            0
hour_bef_pm10             0
hour_bef_pm2.5            0
count                     0
dtype: int64
id                        0
hour                      0
hour_bef_temperature      0
hour_bef_precipitation    0
hour_bef_windspeed        0
hour_bef_humidity         0
hour_bef_visibility       0
hour_bef_ozone            0
hour_bef_pm10             0
hour_bef_pm2.5            0

 

위 함수를 통해 각 시간별 평균값을 대체값으로 활용할수 있었습니다. 

 

VIF를 통해 다중공선성을 확인해 봤습니다. 

한 시간전 온도가 다중공선성이 있는 걸로 계산 되었습니다. 온도가 타켓변수와 상관성이 높게 나왔기 때문에 무작정 제거 하기 보다는 상관성과 모델링 비교를 통해서 결정해야 할것같습니다.

 

다음시간에는 FE에 대해 좀더 색다른 방법은 없는지 조사해 보면서 진도 나갈것같습니다.

728x90
728x90

이틀 전 부터 따릉이 수요예측 프로젝트를 시작했습니다. 깜빡하고 당일에 업로드를 하지 않아서 지금 몰아서 적성하게 되었습니다.

 

일단 간단하게 EDA는 진행했고 전처리 과정을 진행 중입니다. 그런데 몇 시간 동안 매달려 해결 되지 않은 문제가 있어서 정체 되었습니다 

 

본 데이터는 위와 같이 되어 있습니다. 결측치가 많습니다. 일괄적으로 bfill을 사용하려고 했으나 hour가 뒤죽박죽이라서 적용하지 못했습니다. 각 시간대 별 평균 값을 넣어 볼려고 아래처럼 시도를 했습니다.

 

위 코드를 실행해도 결측치가 그대로여서 이것저것 실험해 본 결과, fillna 같은 경우는 위 처럼 train[train 블라블라] 와 같은 필터? 조회형식으로는 채워지지 않는다는 걸 알게 되었습니다. train.fillna() 혹은 train['column'].fillna() 형식으로 해야 적용이 되더라구요. 그래서 현재는 결측치를 어떻게 하면 될까 고민 중에 있습니다.

 

진도가 진행되면 그때 또 다시 진도 내용을 업로드 해보겠습니다.

 

 

 

 

728x90
728x90

실습파일이 없는 줄 알았는데 있더라구요 그래서 쌓여 있는 실습을 진행했습니다.

각 구분선에 따라 이론내용과 실습을 분리했습니다. 순서는 맨 위부터 아래 순입니다.

 

 

2021.08.19 - [Data 일기] - 2021-08-19(딥러닝수학9_Loss function & Gradient Descent)

 

2021-08-19(딥러닝수학9_Loss function & Gradient Descent)

1.Single-variate Linear Regression (y= ax+b) -딥러닝 수학 1~8까지는 y =theta*x에 대한 내용을 학습했다. 지금부터는 y= theta1*x+theta0에 대한 학습을 진행한다. 오늘은 그 중에 Loss function의 변화와 그..

ghdrldud329.tistory.com

PA_04_06 Learning with Cost.ipynb
2.70MB
PA_04_01 Gradient Descent Method.ipynb
0.17MB


 

 

2021.08.24 - [Data 일기] - 2021-08-24(딥러닝 수학10_Cost function & Feature Scaling)

 

2021-08-24(딥러닝 수학10_Cost function & Feature Scaling)

저번 시간까지 배웠던 V 형태의 loss function들을 어떻게 합쳐서 cost function으로 만드는지와 합쳐졌을때 이상적인 학습이 어떤 모습을 보일지 자세히 알아본다. 1. Cost function 두개 data sample에 대해서

ghdrldud329.tistory.com

PA_04_02 Loss Function with Contour Plot.ipynb
1.50MB
PA_04_03 GDM with Contour Plots.ipynb
2.94MB
PA_04_04 Learning with Dataset.ipynb
7.66MB
PA_04_05 Contour Plot of Cost Function.ipynb
6.05MB
PA_04_06 Learning with Cost.ipynb
2.70MB


 

 

2021.08.26 - [Data 일기] - 2021-08-26(딥러닝 수학 11_mini batch & for one sample-Theory)

 

2021-08-26(딥러닝 수학 11_mini batch & for one sample-Theory)

1. mini batch 3번의 iteration 학습 과정을 보려 봤을 때, 각 cost function에 projection 방향으로 다가가고 있다. interation 돌릴 때마다 cost function이 달라진다는 점 헷갈리지 말아야 한다. 계속 intera..

ghdrldud329.tistory.com

PA_04_07 SVLR for One Sample.ipynb
0.66MB


 

 

2021.09.08 - [Data 일기] - 2021-09-08(딥러닝 수학 12_ for Several Samples Theory & Implementation)

 

2021-09-08(딥러닝 수학 12_ for Several Samples Theory & Implementation)

저번 포스팅까지는 하나의 데이터에 대한 학습과정을 공부했습니다. 이번 시간부터는 미니배치 즉, 여러개 샘플을 가지고 학습을 시키는 방법에 대해 공부한 내용을 포스팅하겠습니다. 2가지로

ghdrldud329.tistory.com

PA_04_08 SVLR for Several Samples.ipynb
0.27MB

 

728x90

'실습 note' 카테고리의 다른 글

CNN 실습 모음  (0) 2021.10.05
딥러닝 수학 1~7 실습과제 모음  (0) 2021.08.13
Mask-RCNN 실습모음(2021-07-29~02)  (0) 2021.08.02
EfficientDet 실습모음(2021-07-27~28)  (0) 2021.07.27
YOLO 실습 모음  (0) 2021.07.21
728x90

저번 포스팅 딥러닝 수학10에 이어서 포스팅 하겠습니다.

*실습링크

2021.09.04 - [실습 note] - 딥러닝 수학 실습과제 모음 9~12

 

딥러닝 수학 실습과제 모음 9~12

실습파일이 없는 줄 알았는데 있더라구요 그래서 쌓여 있는 실습을 진행했습니다. 각 구분선에 따라 이론내용과 실습을 분리했습니다. 순서는 맨 위부터 아래 순입니다. 2021.08.19 - [Data 일기] - 20

ghdrldud329.tistory.com

 

1. mini batch

3번의 iteration 학습 과정을 보려 봤을 때, 각 cost function에 projection 방향으로 다가가고 있다. interation 돌릴 때마다 cost function이 달라진다는 점 헷갈리지 말아야 한다.

계속 interation 학습과정을 보면 가장 왼쪽의 cost function의 기울기가 급하게 그러져 있다. 즉, 입력 데이터의 크기가 크다는 점을 뜻하게 되고, X 값이 크면 Gradient도 크게 계산되기 때문에 껑충 뛰는 모습을 볼 수 있다. 반대로 가운데 그림의 기울기는 x축과 평행할수록 x의 값이 작아지며 또한 학습 속도가 느리게 된다는 걸 저번 시간에 배웠었다. 따라서 가운데 그림의 학습 속도가 갑자기 느려졌음을 알 수 있다.

빨간색 크로스 되는 지점이 본래의 Opimal point이다. 노이즈가 있기 때문에 빨간색 교차점과 다소 떨어진 곳에 Opimal point가 생긴 것이다. 가장 오른쪽 그림을 보면 빨간색 교차점에 도달했을 때 학습을 멈췄어야 했지만 노이즈가 포함된 optimal point 때문에 아래 방향으로 학습된 걸 볼 수 있다. 만일 노이즈가 더 컸더라면 교차점과의 거리가 더 멀어지기 때문에 결국 학습이 되지 않는다.

batch size 2일 때보다는 전체적으로 안정적인 모습을 가지고 있다. batch size가 커지면서 평균적인 위치를 나타내기 때문에 상대적으로 안정적이다.

32로 설정 시, 위처럼 거의 동글동글한 모양을 취한다. 또한 noise의 효과도 거의 사라졌기 때문에 교차점과 optimal point의 위치가 비슷하게 위치해 있다. 하지만 실제 딥러닝에서 32를 적용하기란 문제가 있다. '복잡한 함수'를 만들지 못하게 된다. 동글동글하게 만들어지는 함수를 추구하기 때문에 적당히 batch size를 줄여 줘야 data sample들에 맞는 gradient를 반영할 수 있다.

noise 효과가 거의 없다시피 학습이 이뤄지고 있는데 실제 딥러닝에서는 noise가 오버 핏팅을 방지 역할을 하기 때문에 noise가 아~주 없는 것도 문제가 될 수 있다.

 

 

 

2. for one sample-Theory

노드들을 활용하여 이론을 정리하는 시간을 가져본다. 하나의 sample에 대해서 진행하기 때문에 cost가 아니라 loss의 forward, backward이다..

bias term을 추가하면 위처럼 표현할 수 있겠다. back propagation은 어떻게 되는지 아래 그림을 통해 알아본다.

bias인 theta0도 학습 대상이기 때문에 BP를 해줘야 한다. Z1과 theta0에 대한 미분 값이 각각 1씩 나왔으므로 위 식처럼 계산이 된다.

실제 숫자를 넣어서 어떻게 적용되는지 알아보자.

노이즈가 없는 dataset y=x+1이 있다고 가정했을 때, 초기값은 각각 0.1로 설정한다. 그럴 때의 Gradient가 그림처럼 표현이 가능한데, 이 gradient의 특징이 data에 따라서 어떻게 변화하는지 확인해 본다.

(1,2)을 넣었을 때 theta0,1의 값이 같고 norm이 5.09이다. x=1이라는 것 theta 0,1이 같은 비율로 학습이 된다는 의미이다. 또한 -3.6 값이 둘 다 값으므로 y=x 방향과 평행하다는 것이다(y=-x와도 평행할 수도 있다) 학습이 균등하게 갈 수 있는 이유가 이 때문이다.

(2,3) 일 경우엔 theta1의 편미분 값이 크게 증가함에 따라 norm길이도 5.09에 비해서 크게 증가했다. 즉 벡터의 길이가 길어졌다는 뜻이며 이는 곧 크게 학습이 되었다는 것과 연결된다.

x가 더욱 증가함에 따라 norm도 증가를 하게 되고, theta1에 지배적인 학습이 이뤄지므로 theta0은 천천히 학습하게 된다.

반대로 X에 1보다 작은 값들을 넣게 되면 어떻게 변하는지 한 번에 보도록 한다.

X값이 점점 줄어들수록 norm길이도 줄어들게 된다.

정리를 하게 되면 X가 1보다 크면 클수록 norm의 길이도 커지기 때문에 지그재그로 학습될 가능성이 크다. 이렇게 되면 norm길이가 커서 학습도 무조건 빨리된다는 보장이 없는 것이다. 지그재그로 이동하기 때문에 학습이 더욱 느려질 수 있다.

반대로, 1보다 작으면 지그재그로 이동하는 건 없지만 norm길이가 짧기 때문에 학습이 굼벵이처럼 느리게 진행된다.

그래서 x=1일 때, 즉 y=x or y=-x 대칭일 때 어느 한쪽으로 쏠리지 않고 공평하게 학습이 이뤄진다(학습되는 비율이 같으므로)

 

 

3. for one sample Implementation

앞서 배운 one sample Theory를 직접 코드를 통해 구현해 보는 시간을 갖도록 한다.

실습을 위해서 y=5x+2의 dataset을 생성해 준다.

각 과정에 맞는 노드를 정의해준다.

 

 

파라미터를 설정한 후 그간의 실습에서 했던 내용과 동일하게 forward, backward를 진행한다. dth1은 x라는 term이 추가로 붙는다는 사실을 잊지 말아야 한다.

 

 

y=5x+2에서 만들어진 데이터를 가지고 th1, th0을 학습한 그래프이다. th1, th0가 각각 5와 2에 잘 수렴되고 있다. 학습 시 이용된 데이터는 평균이 아닌 각각의 데이터를 이용했으므로 loss가 위 그림처럼 파동이 생기면서 학습이 진행된다. 설명을 추가하자면, 큰 데이터가 뽑히면 큰 loss가 생기고 작은 데이터로 학습하면 작은 loss가 생기기 때문에 loss 그래프가 커졌다 작아졌다 반복하면서 학습된다.

이번엔 다양한 input data가 들어왔을 때 어떻게 학습이 되는지 그래프를 통해 알아본다.

 

 

가장 이상적인 상태인 standard normal 분포를 가지고 학습을 시킬 때 모습이다. 즉, th1, th0가 "공평하게" 학습이 진행된다.

 

 

평균인 높아지면 x값이 증가한다는 뜻이다. 이는 즉 학습 시 th1에 지배적으로 학습이 된다는 것이다. 지난 포스팅에서 x값이 커질수록 loss function이 아래처럼 수직에 가까워진다. 그래서 th1이 th0보다 더 빨리 학습이 진행된다.

x의 값이 더 높아지면 th1에 대해서 더욱 지배적인 학습이 이뤄진다. 반면 th0은 아주 천천히 학습이 된다.

 

 

반면 x값이 1보다 작은 값일 땐, th0이 th1보다 빠른 학습을 보인다. 엄밀히 말하자면 th0 학습 속도가 빨라지는게 아니라 th1 학습속도가 느려지는 것이다. 왜냐하면 th1의 gradient 식에서 -2*x*lr*(y-y^), 즉 x가 곱해지기 때문이다. 소수점을 곱하면 당연히 업데이트 양 또한 줄어들기 마련이다. 그래서 무지개색 그래프를 보면 th0가 먼저 학습되기 때문에 기울기보다는 위아래 위치가 업데이트에 따라 먼저 변하게 되는 것이다.

728x90
728x90

https://colab.research.google.com/drive/1eesj-6EBRPpZn6AebXDIOhdULzh7x_BU?hl=ko 

 

Google Colaboratory Notebook

Run, share, and edit Python notebooks

colab.research.google.com

 

Mask Detection을 수행해 봤습니다. dataset은 캐글에서 받았습니다.

아래 그림은 유튜브 영상 중 일부를 편집하여 모델로 돌린 결과로써 threshold 0.1로 설정했음을 알려드립니다. 

 

dataset이 좀 더 많고 다양하다면 지금의 성능보다 훨씬 좋아 질것 같습니다. 자세한 내용은 위 링크에서 보실수 있습니다.

 

 

 

728x90
728x90

저번 딥러닝 수학9에서 배웠던 V 형태의 loss function들을 어떻게 합쳐서 cost function으로 만드는지와 합쳐졌을때 이상적인 학습이 어떤 모습을 보일지 자세히 알아본다.

 

*실습링크

2021.09.04 - [실습 note] - 딥러닝 수학 실습과제 모음 9~12

 

딥러닝 수학 실습과제 모음 9~12

실습파일이 없는 줄 알았는데 있더라구요 그래서 쌓여 있는 실습을 진행했습니다. 각 구분선에 따라 이론내용과 실습을 분리했습니다. 순서는 맨 위부터 아래 순입니다. 2021.08.19 - [Data 일기] - 20

ghdrldud329.tistory.com

 

1. Cost function

두개 data sample에 대해서 각각 loss function이 왼쪽과 같이 그러져 있다. 이 두개의 loss function을 평균내서 cost function의 contour plot을 그리면 오른쪽 처럼 동글 동글한 모양을 가지게 된다. 이 contour plot은 theta0,1이 균일하게 학습되므로 가장 이상적인 모습이다. 그래서 우리가 해야 할건 여기서 정해진다. 어떤 데이터 이건 모두 평균내서 최대한 오른쪽 contour plot 처럼 동글동글한 모양을 가지도록 해야 학습에 유리하다는 것이다. 이해를 돕기 위해 다른 data sample의 cost function을 보도록 하자

X 절대값 2의 data sample들이 있을때 loss function은 왼쪽처럼 표현이 가능하고 cost function의 contour plot은 오른쪽처럼 위 아래가 쭉 늘어진 형태를 보인다. 즉, 절대값에 따라서 cost function의 모양이 결정된다.

1보다 작은 x 절대값일 경우엔 위 예시 처럼 양쪽으로 늘어진 형태를 취한다. 이번엔 여러 data sample에 대해서 보도록 해보자.

해당 data sample들은 contour plot이 최대한 동글동글하게 만들도록 해준다. loss function들을 보면 가운데를 기준으로 왼쪽과 오르쪽이 완벽하게 대칭이다. 반대로 대칭 아닐수록 동글동글한 contour plot을 만들지 못한다는 것을 알수 있겠다. 아래 내용들을 통해 좀다 자세히 정리를 해본다.

 

 

*동글동글한 contour plot을 만들기 위한 조건 2가지

1. 좌우대칭

각각 3개씩 data sample들을 가지고 있는 loss function들이다. 이 두개의 data sample들은 양수와 음수로 나뉘면서도 x의 절대값이 같다는 특징을 가진다. 이 두개를 평균내서 cost function을 그리면 완벽한 동글한 모양은 아니지만 적어도 왼쪽, 오른쪽을 같게 만들 수가 있다. 그래서 우리가 data set을 만들때 각 feature들이 0을 기준으로 대칭하도록 만들어야 한다.

현실적으로 완벽한 대칭은 만들지 못하지만 최소한 x1 = 2 가 있다면 x2 = -1 정도 있어야 한쪽으로 치우칠 모양이 최대한 동그한 모양으로 만들수 있게 된다.

미니배치 8개를 뽑을때, 그 안에는 양수 4개, 음수 4개 균일하게 있어야 최대한 동글동글한 contour plot을 만들어 낼수 있다.

data sample들을 수집했는데 0을 기준으로 분포가 되어 있지 않다면 억지로 옮길 필요가 있다.(만일 평균 170을 기준으로 분포가 형성되었다면 각각의 loss function은 양수 있을 뿐더러 값이 워낙 크기 때문에 weight만 학습 될것이다. 따라서 0을 기준으로 양수와 음수를 조화롭게 scaling 해줘야 한다.)

정리하면 평균을 0으로 맞춰주는 이유는 동글동글한 contour plot을 만들기 위함이다.

 

 

2. 대각을 기준으로 대칭만들기

X절대값이 1보다 클수록 Y축과 평행을 이루려고 한다. 반대로 X 절대값이 0에 가까울수록 X축과 평행을 이루려고 한다.

여기서 관건은 0<X절대값<1 범위에 만족하는 대각선을 기준으로 좌우 대칭을 만드는게 가장 이상적이다.

위 두개의 데이터에 대한 loss function을 합치게되면 두 loss function 가운데에 cost function이 생기지 않는다. 절대값 X가 일단 1보다 크게 되면 1보다 작은 값이 하나만으로는 상쇄시키기 어렵다(왜 상쇄를 해야할까? 위에서 말했듯이 대각선을 기준으로 좌우 대칭을 만들어야 하기 때문이다.) 다시말해서 X = 0.5의 loss function만 가지고는 X= 2의 loss function을 대각선으로 만들지 못한다. 대각선 이라 함은 y= x, or y= -x 이다. 대각선이 양쪽을 으로 대칭적으로 있어야 동글동글한 밥그릇 모양의 cost function을 만들수 있다. 그러면 학습 시 theta들이 골고루 균등하게 학습이 가능해진다.

 

기존 dataset 은 y= x+1에서 나왔는데 이 두개를 합치니까 x의 기울기가 1보다 커졌다는 얘기다. 절대값 X값이 큰 loss function이 cost function을 만들때 지배적인 영향력을 끼친다.

0.5 -> 0.2로 더 줄여봐도 오른쪽 그림의 기울기가 1보다 크다. 그래서 단순하게 1대1로 대응을 시킬수 없다. 해결법은 간단하다. 한개로 부족하면 여러개를 대응시키면 된다.

1보다 큰 값이 한개가 있고 (1.2)는 거의 영향력이 없다. 결국 0.1 과 0.2 이 두개가 2를 상쇄시키기 위해 달라붙은 것이다. 오른쪽 그림을 보면 완벽하진 않지만 기울기가 1과 가까워 졌음을 알수있다. 정리하면 절대값이 1보다 큰게 하나가 있으면 1보다 작은 X값들이 여러개 있어야 y=-x에 대칭인 것들을 만들수 있다.

동글 동글한 모양을 갖기 위해서는 y=x, y=-x 서로 대칭인 것들이 필요하고, 절대값 x가 1보다 큰 값들은 적어야 하며 반대로 0보다 작은 x값들은 상대적으로 더 많아야한다.

이것들을 따르는 분포가 있는데 이를 정규분포라 한다. 특히 표준정규분포는 완벽한 대칭을 이루면서 절대값 자체가 1보다 큰 값들이 적다. 그렇기때문에 dataset가 표준정규분포를 따르게 된다면 가장 이상적인 동글동글한 모양의 contour plot이 만들어진다.

많은 데이터들이 정규분포를 따른다. 그러면 이 정규분포를 잘 조절 해줘서 표준정규분포로 만들어만 준다면 딥러닝 학습에 유리하게 된다. 정규분포에서 표준 정규분포로 바꾸는 방법은 나중에 뒤에서 배우게 된다.

표준정규분포를 따르는 데이터 16개를 cost function으로 그리게 되면 상당히 동글동글한 모양을 가지고 있다.

이번엔 y=x방향쪽으로 쏠리게 되었는데, 그 이유는 음수 절대값에서 큰수가 나온 것을 loss function을 통해 확실히 알수가 있다. 0보다 낮은 값들과 상쇄해서 오른쪽과 같은 cost function이 만들어 진것이다.

이번엔 반대로 y = -x 방향쪽으로 살짝 지배적인 모습을 보인다. 이렇게 위 예시처럼 완벽한 동글동글한 모습은 아니지만 이러한 작업 자체가 상당히 딥러닝 학습에 큰 효과를 가져와준다.

loss function을 가지고 학습 시키면 지그재그로 이쁘지 않게 학습이 되는데, 이를 cost function으로 바꾸면 대체로 동글동글한 contour plot이므로 theta0,1이 균일하고 부드럽게 학습이 된다.

평균이 0이고 표편이 1인 분포가 있을때 왼쪽처럼 이쁜 밥그릇 모양을 가진다. 하지만 정규분포라고 해서 다 이와 같은 모습을 보이지 않는다.

평균이10이고 표편이 동일하게 1이라고 할지언정 뽑히는 X 값 자체가 10 언저리 이므로 cost function이 왼쪽처럼 만들어 진다. 즉, 정규분포라 할지라도 평균값을 0에 꼭 반드시 맞춰줘야 한다. 그래야지 좌우 대칭이 맞춰지기 떄문이다.(양수 음수 골고루 나오게끔)

그러면 평균이 0이고, 표편을 1보다 작게 만들면 어떻게 될까? 1보다 큰 값이 적어지게 되고 0에 가까운 값들이 너무 많아지게 되므로 기울기가 x축과 평행한 cost function이 만들어 지게 된다. 따라서 어느 한 곳으로 치우치지 않은 y= x, y= -x 즉, 대각선을 취할때가 가장 좋은 균형을 가진다.

 

 

 

2. Feature Scaling

Feature Scaling 식을 통해서 평균은 0, 표준편차는 1로 표준정규분포를 만들수 있다.

 

 

*평균은 같고 표편만 다를경우

파란색이 평균이 0, 표편이 10인 본래의 dataset이다. Feature scaling을 해주면 표준편차 10을 나눴기 때문에 초록색으로 변하게 된다. 원래 가지고 있던 dataset과는 다른 dataaset을 가지게 된다.

 

 

*평균은 다르고 표편은 같을 경우

Feature Scaling해주면 평균이 0으로 변화했기 때문에 왼쪽 그림처럼 다른 dataset를 갖게 된다.

 

 

*평균,표편 모두 다른경우

본래 dataset은 평균이 10이고 표편도 10정도라고 했을때 왼쪽 그림의 파란색처럼 dataa의 분포를 볼수 있겠다. 여기에 Feature scaling을 해주게 되면 표편 10으로 나눴기 때문에 기울기가 달라지고, 평균도 0으로 변경됨에 따라 이동하게 된다. 여기서 유의할 점이 있다. 자세한 내용은 아래를 통해 알아보자.

feature Scaling한 dataset을 가지고 학습을 진행하여 predictor를 생성했다고 하자. 이제 새로운 data을 가지고 predictor를 이용하여 예측값을 구하고자 넣는 행위는 틀렸다고 볼수 있다. 앞서 말했듯이 Feature scaling을 하게 되면 전혀 다른 dataset을 가진다. 즉, 분포가 기존의 data와는 다른 dataset이 만들어 지기 때문에 바로 다이렉트로 넣지 못하고, new data도 FS을 통해 같은 dataset으로 만들어 준 뒤, predictor를 이용해야 한다.

 

dataset 처음 수집할때 중요한 점이 있다. dataset을 대충, 적당하게 수집해서 FS 적용 후 predictor를 만들게 되면, 이 predictor는 본래 dataset에서 빠졌던 data를 잘 예측하지 못하게 된다. 즉, '너는 dataset에 없었으니까 나는 널 예측 못한다' 로 정리 할수 있겠다. 그래서 dataset을 최대한 많이 확보해야 한다.

평균:0, 표편:10 인 왼쪽 loss function(16개 data)과 오른쪽 FS을 진행 후 loss function이다. 왼쪽보다는 골고루 흩어 졌기 때문에 그나마 원에 가깝게 cost function을 만들수 있을 것이다. 아래 그림을 통해 자세히 보도록 하자.

양쪽의 cost function 모양이 다르다는 걸 확인 할수 있다. 오른쪽은 y=-x방향쪽으로 쏠려 있다. 즉 1보다 큰 절대값x가 지배적이라는 걸 알수 있다. 학습의 유리함을 보자면 당연히 오른쪽 Cost function이 그나마 theta들을 균등하게 학습할 기회를 주게 된다.

728x90

+ Recent posts