728x90

오늘 아침일찍 저감장치 장착하기 하기 위해서 가산쪽 공업사를 방문했습니다 ㅎㅎ

집에 돌아 오니까 10시라서 넉넉하게 주간에 배운 내용을 간단하게 복습했습니다

짧은 시간에 많은 걸 배우다 보니까 조금 헷갈리는 부분이 있었습니다

 

이제 3월 말이라서 그런지 불안감이 커집니다 ㅠ 30살이라서 

마치 시한부 마냥 시간이 갈수록 갑갑하게 느껴집니다

 

걱정과 생각이 많아서 남은시간에는 쉬었어요 

운동도 갔다오고~ 산책도 하고 ~

 

무튼, 다음주 부터는 시계열 알고리즘을 배웁니다 

총 63강 정도 되서 대략 2주 정도 걸릴것같습니다:D

 

그러면 다음주 월요일에 알고리즘 내용을 가지고 다시 돌아 오겠습니다

 

728x90
728x90

*본 내용은 시계열데이터 강의 내용 중 일부분을 요약한 내용입니다

 

 

저번 포스팅에 이어서 조건수를 줄이기 위한 다중공선성(Multicollinearity) 제거를 포스팅하겠습니다.

  • 독립변수가 다른 독립변수의 조합으로 표현될 경우 다중공선성이 발생
  • 독립변수끼리 서로 상관관계가 있을경우 발생
  • 독립변수의 공분산 행렬(Covariance Matrix) 벡터공간(Vector Space)의 차원과 독립변수의 차원이 같지 않는 경우(Full Rank가 아니다)

 

다중공선성 제거 방법 2가지(VIF,PCA)

1.VIF(Variance Inflation Factor): 종속성이 높은 X들을 선택하는 방법

각 변수에 대해서 회귀분석을 실시합니다. 아래처럼 X1이라는 변수는 다른 변수의 선형결합으로 표현이 될수 있을지를 계산한게됩니다. 만일 R^2값이 크다면 X1는 다른 변수에 의해 표현이 되는 것이므로 제거 대상에 해당됩니다.

X1= aX2+bX3

 

이런 방법을 통해 모든 변수를 회귀분석을 통해 종속성이 높은 X들을 찾아냅니다.

 

위 VIF 공식에서 R^2이 클수록 VIF값도 커집니다.

 

#효과적인 X들을 VIF 방법을 통해 추출하기
from statsmodels.stats.outliers_influence import variance_inflation_factor
vif = pd.DataFrame()

#i번째 x들을 다른 x들로 회귀분석
#높을수록 선형결합으로 표현 될수 있으며 이는 종속성이 있는 변수이다.
vif['VIF_Factor']= [[variance_inflation_factor(X_train_feRS.values, i) for i in range(X_train_feRS.shape[1])]

vif['Feature'] = X_train_feRS.columns
vif.sort_values(by='VIF_Factor', ascending=True)

 

실습으로 사용방법 확인

# extract effective features using variance inflation factor
vif = pd.DataFrame()
vif['VIF_Factor'] = [variance_inflation_factor(X_train_feRS.values, i) 
                     for i in range(X_train_feRS.shape[1])]
vif['Feature'] = X_train_feRS.columns
vif.sort_values(by='VIF_Factor', ascending=True)['Feature'][:10].values


array(['count_diff', 'holiday', 'count_seasonal', 'Day', 'windspeed',
       'Quater_ver2', 'Hour', 'weather', 'Quater_Dummy_2', 'DayofWeek'],
      dtype=object)
  • 몇개의 변수를 사용했을때 성능이 가장 좋을지는 모르기 때문에 모든 경우의 수를 실행해 봐야 한다
  • 아래 결과는 순서 VIF가 낮은 순으로 정렬 후 12개 변수를 사용했을때 결과입니다. 

 

 

  • 정화도는 0.864로 기존보다 정확도가 내려갔습니다
  • windspeed를 제외한 모두가 종속변수에 영향을 주고 있으며 계수값도 이전에 비하면 현실성 있는 수치를 보입니다.
  • Kurtosis가 6.022로 정규분포로 더욱 근사한 모양을 띠고 있으며 왜도 값도 줄어 들었음을 확인할수 있습니다
  • cond.No가 1,530으로 기존 34,000보다 확연히 감소 했습니다. 조건수의 감소는 독립변수들간의 상관성 감소를 뜻합니다.

 

 

2.PCA(Principal Component Analysis)

X1~X10까지의 10개 변수를 PCA 실행하면 X1^ ~X10^ 변수에 완전히 새로운 값이 채워지게 됩니다.

이 값은 기존의 변수들 값과 어떠한 연관성이 없습니다. 따라서 이 새 값은 서로 독립적으로 생기게끔 생성되었으므로 모델에 적용하면 되지만 단점은 완전히 새 값이 나오므로 어떤 의미를 가지고 있는지에 대한 재해석이 필요합니.

강의 실습에서는 VIF만을 실습했기때문에 따로 소스는 없습니다.

 

 

 

 

 

 

 

 

*정상성프로세스 이해하기

시계열이 정상성이다 라는 뜻은 시간의 흐름에 따라 "통계적 특성(Statistical Properties)"이 변하지 않는것이다.

  • 통계적 특성(Statistical Properties): 주로 평균(Mean)과 분산(Variance)/공분산(Covariance)를 얘기하지만 이를 포함한 모든 분포적 특성을 총칭함

시간 흐름에 따라 평균,분산,자기상관(autocorr), 공분산 등 통계적 특성이 변하지 않는다라는건 아래 녹색 그래프와 같은 의미이다. 평균을 낼때는 Frequency 기준으로 계산하면 같은 값이 나온다. 이외에 빨간색 그래프는 왼쪽부터 평균이 변하는 그래프, 중간 그래프는 분산이 일정치 않은 그래프, 맨 오른쪽 그래프는 평균과 분산은 일정한데 시점별로 짤랐을때는 자기상관이 있는 경우이다.  

시계열 데이터에서 정상성이 왜 필요한 것일까?녹색 그래프 처럼 값이 일정하면 좋은 점은 무엇일까?

 

예를들어서 설명하면 한 회사의 매출액을 예측하고자 합니다. 매출액은 -값도 나올수 있으므로 그 범위는 +무한대, -무한대 입니다. 매출액이 유리천장이 있는 게 아니기 때문에 한계란 없습니다. 그러면 예측을 하는 입장에서는 이 무한대 범위에서 예측을 하면 틀릴확률이 높습니다. 그러면 Y값인 매출액을 점유율로 우회해서 표현하게되면 0~1사이의 확률값으로 표현이 되고 범위가 정해졌으므로 틀릴확률이 크게 줄어들게 됩니다. 점유율을 예측 후 이를 매출액으로 다시 변환하면 되는것이죠

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90
728x90

*본 내용은 시계열데이터 강의 내용 중 일부분을 요약한 내용입니다

 

 

이전에 올렸던 포스팅은 test 데이터를 알고 있을 경우에 FE를 진행하여 모델을 돌렸습니다. test 할 데이터에 대해서 FE를 했으므로 R^2 값이 1.0이 나왔습니다. 하지만 현실에서는 test할 데이터를 모릅니다. 미래가 어떻게 변할지는 그 누구도 모르기 때문입니다. 따라서 현실에 있을법한 test 데이터를 만들고자 합니다. 1-step 방법을 사용해서 미래 데이터 패턴을 예측하는 방법도 있지만 현 실습에서는 간단하게 진행했습니다

 

2011,2012년도 두 연도가 있는 자전거 수요 데이터에서, 현 실습에서는 2011년 데이터 패턴을 그대로 2012년도 데이터패턴에 적용했습니다. 여기에 모델을 적용한 후 스케일링 전처리 작업을 수행했습니다. 좀더 세부적인 교육 내용은 아래에 간단하게 적었습니다

 

현실성을 반영한 데이터패턴

# Test 기간의 FE데이터를 알 수 있을까? 2가지 방법소개
# 1) 과거 패턴이 반복될 것이다
# 2) 하나씩 예측하며 업데이트
'''
현재 데이터 그래프와 미래 데아터 그래프는 다르다. 이를 각각 어떻게 FE를 진행하는가?
이상적으로 가장 적합한 방법은 test 부분 영역은 아무도 모르는 영역이다-> 추정하는게 현실적으로 맞다
어떻게 추정하는가? train값으로 바로 t번재 테스트 값을 추정하고, 추정된 값을 포함한 값으로 t+1번째 값 추정 하는식 

위 방법은 복잡하므로 좀더 간단한 방법으로 실습을 진행한다.
train에서 보인 패턴이 test에도 반복될거라는 가장 하에 진행
이렇게 되면 급작스러운 패턴 변화 때문에 다소 이질감이 생길수 있다.
2011 일년치를 가져와서 덜 이질감 있도록 2012년 적용
'''

 

len(raw_fe.loc['2012-01-01':'2012-12-31', 'count_trend'])
8784

len(raw_fe.loc['2011-01-01':'2011-12-31', 'count_trend'])
8760

# 2011년도 count_trend를 2012년 count_trend에 덮어 씌울려고 시도하면 에러가 발생
길이가 24개 차이가 나기 때문이다. 현재 시간 단위는 H이므로 
24시간=> 윤달인 2월29일 데이터가 2011년도에는 없었던 것
 

 

#2월29일을 제외한 나머지 날짜를 대입
raw_fe.loc['2012-01-01':'2012-02-29', 'count_trend']=raw_fe.loc['2011-01-01':'2011-02-28', 'count_trend']
raw_fe.loc['2012-03-01':'2012-12-31', 'count_trend']=raw_fe.loc['2011-03-01':'2011-12-31', 'count_trend']

#2011-02-29데이터 만들기
step= (raw_fe['2011-03-01 00:00:00','count_trend']-raw_fe.loc['2011-02-28 23:00:00','count_trend'])/25
step_value=np.arange(raw_fe.loc['2011-02-28 23:00:00','count_trend']+step, raw_fe.loc['2011-03-01 00:00:00','count_trend'], step) 
step_value= step_value[:24]
raw_fe.loc['2012-02-29','count_trend']=step_value

raw_fe.loc['2012-02-28 22:00:00':'2012-03-01 02:00:00', 'count_trend']

 

 

raw_fe['count_trend'].plot()

 

  • 2011년도와 같은 count_trend를 가지게 되었다

 

함수로 정의하기

def feature_engineering_year_duplicated(raw, target):
    raw_fe = raw.copy()
    for col in target:
        raw_fe.loc['2012-01-01':'2012-02-28', col] = raw.loc['2011-01-01':'2011-02-28', col].values
        raw_fe.loc['2012-03-01':'2012-12-31', col] = raw.loc['2011-03-01':'2011-12-31', col].values
        step = (raw.loc['2011-03-01 00:00:00', col] - raw.loc['2011-02-28 23:00:00', col])/25
        step_value = np.arange(raw.loc['2011-02-28 23:00:00', col]+step, raw.loc['2011-03-01 00:00:00', col], step)
        step_value = step_value[:24]
        raw_fe.loc['2012-02-29', col] = step_value
    return raw_fe
target = ['count_trend', 'count_seasonal', 'count_Day', 'count_Week', 'count_diff']
raw_fe = feature_engineering_year_duplicated(raw_fe, target)

 

Lag값 새로 정의하기

# calculation of lag data from Y
X_test_fe['count_lag1'] = Y_test_fe.shift(1).values # Y_test_fe.shift(1)값으로 새로 채우기 (현재는 train lag값이 들어가 있음)
X_test_fe['count_lag1'].fillna(method='bfill', inplace=True) #nan 값 채워주기
X_test_fe['count_lag2'] = Y_test_fe.shift(2).values
X_test_fe['count_lag2'].fillna(method='bfill', inplace=True)
X_test_fe['count_lag2']


DateTime
2012-07-01 00:00:00   149.00
2012-07-01 01:00:00   149.00
2012-07-01 02:00:00   149.00
2012-07-01 03:00:00    93.00
2012-07-01 04:00:00    90.00
                       ...  
2012-12-31 19:00:00   164.00
2012-12-31 20:00:00   122.00
2012-12-31 21:00:00   119.00
2012-12-31 22:00:00    89.00
2012-12-31 23:00:00    90.00
Freq: H, Name: count_lag2, Length: 4416, dtype: float64

 

현실성을 반영한 코드 요약

### Functionalize
### duplicate previous year values to next one
def feature_engineering_year_duplicated(raw, target):
    raw_fe = raw.copy()
    for col in target:
        raw_fe.loc['2012-01-01':'2012-02-28', col] = raw.loc['2011-01-01':'2011-02-28', col].values
        raw_fe.loc['2012-03-01':'2012-12-31', col] = raw.loc['2011-03-01':'2011-12-31', col].values
        step = (raw.loc['2011-03-01 00:00:00', col] - raw.loc['2011-02-28 23:00:00', col])/25
        step_value = np.arange(raw.loc['2011-02-28 23:00:00', col]+step, raw.loc['2011-03-01 00:00:00', col], step)
        step_value = step_value[:24]
        raw_fe.loc['2012-02-29', col] = step_value
    return raw_fe
# target = ['count_trend', 'count_seasonal', 'count_Day', 'count_Week', 'count_diff']
# raw_fe = feature_engineering_year_duplicated(raw_fe, target)

### modify lagged values of X_test
def feature_engineering_lag_modified(Y_test, X_test, target):
    X_test_lm = X_test.copy()
    for col in target:
        X_test_lm[col] = Y_test.shift(1).values
        X_test_lm[col].fillna(method='bfill', inplace=True)
        X_test_lm[col] = Y_test.shift(2).values
        X_test_lm[col].fillna(method='bfill', inplace=True)
    return X_test_lm
# target = ['count_lag1', 'count_lag2']
# X_test_fe = feature_engineering_lag_modified(Y_test_fe, X_test_fe, target)

 

#현실성 반영한 모델 실행하기

# Data Loading
# location = 'https://raw.githubusercontent.com/cheonbi/DataScience/master/Data/Bike_Sharing_Demand_Full.csv'
location = './Data/BikeSharingDemand/Bike_Sharing_Demand_Full.csv'
raw_all = pd.read_csv(location)

# Feature Engineering
raw_fe = feature_engineering(raw_all)
### Reality ###
target = ['count_trend', 'count_seasonal', 'count_Day', 'count_Week', 'count_diff']
raw_feR = feature_engineering_year_duplicated(raw_fe, target)
###############

# Data Split
# Confirm of input and output
Y_colname = ['count']
X_remove = ['datetime', 'DateTime', 'temp_group', 'casual', 'registered']
X_colname = [x for x in raw_fe.columns if x not in Y_colname+X_remove]
X_train_feR, X_test_feR, Y_train_feR, Y_test_feR = datasplit_ts(raw_feR, Y_colname, X_colname, '2012-07-01')
### Reality_lag ###
target = ['count_lag1', 'count_lag2']
X_test_feR = feature_engineering_lag_modified(Y_test_feR, X_test_feR, target)
###############

# Applying Base Model
fit_reg1_feR = sm.OLS(Y_train_feR, X_train_feR).fit()
display(fit_reg1_feR.summary())
pred_tr_reg1_feR = fit_reg1_feR.predict(X_train_feR).values
pred_te_reg1_feR = fit_reg1_feR.predict(X_test_feR).values

# Evaluation
Score_reg1_feR, Resid_tr_reg1_feR, Resid_te_reg1_feR = evaluation_trte(Y_train_feR, pred_tr_reg1_feR,
                                                                   Y_test_feR, pred_te_reg1_feR, graph_on=True)
display(Score_reg1_feR)

# Error Analysis
error_analysis(Resid_tr_reg1_feR, ['Error'], X_train_feR, graph_on=True)
'''
R값이 0.9이며 유의한 변수가 25개로써 기존에 2개보다 많아졌음을 확인
Durbin-Watson도 2근방으로 다가 가면서 자기상관이 상당히 줄어들었으며
Kurtosis도 정규분포에 가까워짐

조건수는 현실 반영 전 모델과 비교 시 34,000 -> 32,000 감소를 보임
이는 독립변수가 그 전보다는 생겼다는 의미이다.
t검정을 봐도 유의한 변수들이 많이 생겼음을 확인할수있다. 조건수 수치를 보고 설명변수의 상태를 
파악할수 있다.
'''

 

 

 

 

Scaling

본 내용 설명에 앞서 condition number에 대해서 설명을 하자면 예측 정확성 향상을 위해서는 두가지 방향이 있는데

1) Train 정확도 증가+ Test 정확도 증가 

2) Train <<< Test  조건수(Condition Number) 감소

 

2번에서 train 의 정확성 보다는 test의 정확성을 더 중시한다는 의미입니다. test 정확성을 높이기 위해서는 조건수의 감소가 일어나야 합니다.  x들의 특징에서 조건수를 추출하는데 이 값이 낮을수록 2번처럼 이상적수치가 나올수 있습니다. 

 

조건수는 𝑒𝑖𝑔𝑒𝑛𝑣𝑎𝑙𝑢𝑒의 최대값,최소값의 비율을 나타냅니다. X라는 설명변수들이 서로 독립적이면 𝑒𝑖𝑔𝑒𝑛𝑣𝑎𝑙𝑢e

값들은 서로 비슷한 수치를 보입니다. 반대로 종속변수가 많을수록 두 𝑒𝑖𝑔𝑒𝑛𝑣𝑎𝑙𝑢𝑒 값은 차이가 커집니다.       

ex) 𝜆1=1, 𝜆2=100

 

따라서 조건수를 줄이기 위해서는 설명변수안에 서로 독립적이여야 Test 예측 성능을 올릴수 있습니다. 

 

*조건수를 감소하는 방법 3가지

1) 변수들의 단위차이로 숫자의 스케일들이 크게 다른 경우, 스케일링(Scaling)으로 해결 가능
2) 독립변수들 간에 상관관계가 높은 "다중공선성" 존재할 경우,
Variance Inflation Factor(VIF)나 Principal Component Analysis(PCA)를 통한 변수선별로 해결 가능
3) 독립변수들 간 의존성이 높은 변수들에 패널티를 부여하는 정규화(Resularization)로 해결 가능

 

 

Scaling

숫자가 큰 변수가 그렇지 않는 변수들보다 크게 관여될수가 있으므로 값 조정은 필수다.

 

총 4가지 방법이 있습니다

1) Standard Scaler

스케일링 후의 분포의 모양은 각기 다르다(정규분포애 근사한 형태를 띈다)

2) Min-Max Scaler(𝑋𝑖𝑡𝑚𝑖𝑛(𝑋𝑖)/𝑚𝑎𝑥(𝑋𝑖)𝑚𝑖𝑛(𝑋𝑖))

본래 분포모양을 그대로 가져가면서 범위는 동일하게 적용한다
표편이 매우 작을때 효과적, 왜일까? 
표편이 작다는 건 데이터들이 모여 있다는 뜻 -> 이상치가 없다 
이상치가 있다면 표편이 커지게 된다.
극단치 때문에 비율이 왜곡된다  
이러한 문제점을 해결하고자 Robust Scaler 사용

3) Robust Scaler(𝑋𝑖𝑡𝑄1(𝑋𝑖)/𝑄3(𝑋𝑖)𝑄1(𝑋𝑖))

25%~75% 데이터를 가지고 Min-Max Scaler 공식과 동일하게 적용

 

4) Normalizer

각 변수(Feature)를 전체 𝑛n개 모든 변수들의 크기들로 나누어서 변환(by Cartesian Coordinates)
각 변수들의 값은 원점으로부터 반지름 1만큼 떨어진 범위 내로 변환한다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90
728x90

*본 내용은 시계열데이터 강의 내용 중 일부분을 요약한 내용입니다

 

 

모델 성능 평가 후 개선 할 점이 있는지, 모델이 신뢰성이 있는 것인지를 파악하기 위해서 잔차진단을 합니다. 

총 네가지 스텝으로 구성되어있습니다.

 

1. 정상성 테스트 

 정상성이란 시간의 흐름에 따라 통계적 특성이 변하지 않는다. 즉, 시계열이 정상성이다.

 통계적 특성: 주로 평균(Mean)과 분산(Variance)/공분산(Covariance)를 얘기하지만 이를 포함한 모든 분포적 특성을 총칭합니다.

 

2. 정규분포 테스트(normality Test)

3. 자기상관 테스트(Autocorrelation Test)

4. 등분산성 테스트(Homoscedasticity)

 

잔차진단 결과 백색잡음이면 패턴을 잘 추출 했다는 의미 입니다. 

즉, 찾아낼 패턴을 다 찾은 의미인데, 그렇지 못한 경우에는 시각화 그래프가 어떠한 추세를 보인다던가 정규분포을 따르지 않는다 던가, 분산이 일정치 않고 뒤죽박죽 튄다 던가 하는 등 판별기준이 있습니다. 실습코드는 아래에 있습니다

 

백색잡음

백색잡음(White Noise)는 2가지의 속성을 만족해야 하며 하나라도 만족하지 못하면 모델이 개선의 여지가 있음을 의미합니다. 무작위한 진동 패턴(fx가 y에 최대한 근접할때 생긴다)

 

1. 잔차들은 정규분포이고, 평균 0과 일정한 분산을 가진다.

정규분포인지 아닌지를 알수 있는 방법은 시각화와 검정통계량 2가지가 있다.

*시각화: 잔차들의 값을 빈도체크하여 시각화를 할때 정규분포 모양을 따르는지 확인할수 있다.

*검정통계량 Shapiro-Wilk Test 외에 여러 방법이 존재, 유의확률을 통해 의사결정을 하여 정규분포인지를 판별(4.6.2 교육자료)

 

2. 잔차들이 시간의 흐름에 따라 상관성이 없어야 한다.

아무 잔차 2개의 시점을 뽑았을때, 이 둘의 corr은 0이여야 한다. corr=0은 서로 관련성이 없으므로 독립이라는 뜻이다.  

자기상관함수(Autocorrelation Fundtion)

한 변수 내에 다른 시간 축에 대한 데이터 상관성 분석합니다. 시간 흐름에 따라 상관성이 존재하는지를 알아 볼때 사용됩니다.

특정 변수를 lag값을 취한 뒤 corr이 있는지 계산하며 아래 그래프의 파란색 실선 범위 안에 있으면 자기상관은 없다고 판별합니다. 파란색 실선은 유의수준과 같은 역할을 합니다

 

 

  정리 차원에서 회귀분석 가정들 살펴보기(모두 만족시 패턴을 잘 뽑아낸 경우이다)

  • 종속변수와 독립변수 간에 선형서의 관계를 가져야 한다
  • 독립변수들 간에 서로 독립이어야 한다
  • 잔차의 분포가 정규분포이어야 한다
  • 잔차들이 서로 독립적으로 움직여야 한다
  • 잔차들의 분산이 서로 같아야 한다

 

#잔차와 실제 잔차 인덱스=> 시간으로 확인하든 인덱스로 확인하든 순서는 보존가능해진다=> 공부 필요
Resid_tr_reg1['Rownum'] = Resid_tr_reg1.reset_index().index

#시각화 작업

# Stationarity(Trend) Analysis: 정상성 시각화
sns.set(palette='muted', color_codes=True, font_scale=2)
sns.implot(x='RowNum', y='Error', data=Resid_tr_reg1.iloc[1:], fit_reg='True', size=5.2,
                 aspect=2, ci=99, sharey='True')
                 
# Normal Distribution Analysis_정규분포 시각화
figure, axes = plt.subplots(figsize=(12,8))
sns.displot(Resid_tr_reg1['Error'], norm_hist='True', fit=stats.norm)

## Lag Analysis
'''
x축: 잔차의 오리지널 값
y축: 1시점 이동된 시점
이 두개 시점의 correlation 값들을 표현
선형성 모양의 상관성이 있어 보인다.
2.4.2의 백색잡음이 되기 위한 조건은 어떠한 시점 두개를 뽑아도 corr이 0이여야 한다
하지만 아래 그래프를 통해, corr이 시점에 따라 변화 하고 있으므로 백색잡음이 아니다.
'''
figure, axes = plt.subplots(1,4, figsize=(12,3))
pd.plotting.lag_plot(Resid_tr_reg1['Error'], lag=1, ax=axes[0])
pd.plotting.lag_plot(Resid_tr_reg1['Error'], lag=5, ax=axes[1])
pd.plotting.lag_plot(Resid_tr_reg1['Error'], lag=10, ax=axes[2])
pd.plotting.lag_plot(Resid_tr_reg1['Error'], lag=50, ax=axes[3])

# Autocorrelation Analysis_자기상관 시각화
figure , axes = plt.subplots(2,1, figsize=(12,5))

'''
lags=100: 100 lag를 그려서 수치를 알려준다
y축: corr
0번째가 1인 이유: et와 자기자신 et의 상관성 이기 때문에 1이다.
밑면에 회색그림자:유의수준 범주, 이 값을 벗어난 만큼 자기상관이 있다고 판별하고
이 범주 안에 있다면 자기상관은 0이다.(없다고 판별) 
'''

figure = sm.graphics.tsa.plot_acf(Resid_reg1['Error'], lag =100, use_vlines=True, ax=axes[0])
figure = sm.graphics.tsa.plot_pacf(Resid_reg1['Error'], lags=100, ues__vlines=True, ax=axes[1])

#검정통계량 작업

# Error Analysis(Statistics)
# Checking Stationarity
# Null Hypothesis(대중 주장): The Time-series is non-stationalry
#adfuller: ADF 정상성테스트

stationarity = pd.Series(sm.tsa.stattools.adfuller(Resid_reg1['Error'])[0:4],
index=['Test Statistics', 'p-value', 'Used Lag', 'Used Observations'])
for key , value in sm.tsa.stattools.adfuller(Resid_tr_reg1['Error'])[4].items(): #각 p_value마다의 통계량
	Stationarity['Critial Value(%s)'%key]=value
Stationarity['Maximum Information Criteria'] = sm.tsa.stattools.adfuller(Resid_tr_reg1['Error'])[5]
Stationarity = pd.DataFrame(Stationarity, columns=['Stationarity'])


# Checking of Normality(정규분포 테스트)
# Null Hypothesis(대중 주장): The residuals are normally distributed
Normality= pd.DataFrame([stats.shapiro(Resid_tr_reg1['Error'])], index=['Normality'], columns=['Test Statistics','p-value']).T


# Checking for Autocorrelation
# Null Hypothesis: Autocorrelation is absent = 자기상관은 없다 
Autocorrelation = pd.concat([pd.DataFrame(sm.stats.diagnostic.acorr_ljungbox(Resid_tr_reg1['Error'], lags=[1,5,10,50])[0], columns=['Test Statistics']),
                             pd.DataFrame(sm.stats.diagnostic.acorr_ljungbox(Resid_tr_reg1['Error'], lags=[1,5,10,50])[1], columns=['p-value'])], axis=1).T
Autocorrelation.columns = ['Autocorr(lag1)', 'Autocorr(lag5)', 'Autocorr(lag10)', 'Autocorr(lag50)']
Autocorrelation.columns = ['Autocorr(lag1)', 'Autocorr(lag5)', 'Autocorr(lag10)', 'Autocorr(lag50)']


# Checking Heteroscedasticity(등분산성)
# Null Hypothesis: Error terms are homoscedastic(등분산이다)
# 입력form이 array로 넣어야 하므로 X_train.values
#two-sided: 크냐,작냐,같냐 구분하는 방식
# Alternative: 가설의 방향
Heteroscedasticity = pd.DataFrame([sm.stats.diagnostic.het_goldfeldquandt(Resid_tr_reg1['Error'], X_train.values, alternative='two-sided')],
                                  index=['Heteroscedasticity'], columns=['Test Statistics', 'p-value', 'Alternative']).T
Error_Analysis = pd.concat([Stationarity, Normality, Autocorrelation, Heteroscedasticity], join='outer', axis=1)

#row 순서 정렬
Error_Analysis = Error_Analysis.loc[['Test Statistics', 'p-value', 'Alternative', 'Used Lag', 'Used Observations',
                                     'Critical Value(1%)', 'Critical Value(5%)', 'Critical Value(10%)',
                                     'Maximum Information Criteria'],:]






 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90
728x90

*본 내용은 시계열데이터 강의 내용 중 일부분을 요약한 내용입니다

 

 

 회귀모델을 적용 후 R-squared,F-분포, t검정 등의 결과가 일관성이 없을때 믿어야 할건 데이터 라는 것이다.

일관성이 없다고 효과없는 데이터를 무작정 삭제 하는게 아니라, 시각화를 통해서 종속변수에 영향을 주는 데이터인지 아닌지를 판단해야한다. 

 

모델적용

fit_reg1 = sm.OLS(Y_train, X_train).fit()
display(fit_reg1.summmary())
pred_tr_reg1 = fit_reg1.predict(X_train).values
pred_te_reg1 = fit_reg1.predict(X_test).values
'''
*R-squared
 평균치 ybar 보다 적합이 좋은지 나쁜지를 나타낸다 
 1.00은 모드예측값이 실제값과 모두 동일함을 의미한다

*F-statistic(F검정)
 유의확률이 0.00으로 유의수준보다 작으므로, 이 모델링은 효과가 있다.
 모든 계수가 효과가 있다

*t 검정
 count_diff, count_lag1를 제외하곤 모두 영향력이 없다
 F검정에는 모든 계수가 효과 있다고 했는데? 이상함을 감지 해야한다

*잔차 보기
 정규분포의 Kurtosis(첨도)는 3이다.
 현 Kurtosis는 13078.751, 일반 첨도보다 훨씬 꼬리가 두터운 형태

*정규분포의 Skew(왜도)는 0이다.
 현 Skew는 -114.255, negative 형태 (오른쪽 쏠림), 상당히 벗어난 값

*회귀분석 지표가 많은 이유는 모든 결과가 일관성 있을때 까지 시도하라는 의미
*지속적인 튜닝이 필요
*회귀분석은 값만 출력하고, 쓸지 말지는 사람이 선택한다. 따라서 합리적인 근거를 토대로
 사용여부를 결정한다. 근거의 대표적인 도구가 시각화이다.
 믿어야 할건 알고리즘이 아니라 데이터이다.
'''

 

  • 위 결과에 대한 해석은 실습의 주석처리로 되어있습니다
  • 일관성 없는 데이터에 대해서 시각화를 통해 정확한 정보를 얻어낸다
  • 이상적인 그림은 모델 적용하기 전 시각화를 통해 변수에 대한 정보를 파악하는게 맞다

 

시각화

# histogram plot
raw_fe.hist(bins=20, grid=True, figsize=(16,12)) #x를 몇개 그룹으로 나눌것이가: bins
plt.show()
'''
count와 비슷한 분포가 상관관계가 높고, 유의하다고 나올 가능성이 높다
y분포와 비슷하게 만드는 것이 예측에 도움이 될것
'''

 

# box plot_계절별 각 수요 관계 파악
raw_fe.boxplot(column='count', by='season', grid=True, figsize=(12,5))
plt.ylim(0,1000)
raw_fe.boxplot(column='registered', by='season', grid=True, figsize=(12,5))
plt.ylim(0,1000)
raw_fe.boxplot(column='casual', by='season', grid=True, figsize=(12,5))
plt.ylim(0,1000)
'''
만일 계절의 y분포 네개가 똑같다면 어떨까?
계절에 의한 count 변화는 없다는 의미이며 계절변수가 쓸모 없다는 것
계절별로 패턴이 많이 달라야 예측에 도움이 된다.
'''

 

 

 

# box plot_휴일,평일과 수요(count) 관계 파악
raw_fe.boxplot(column='count', by='holiday', grid=True, figsize=(12,5))
plt.ylim(0,1000)

raw_fe.boxplot(column='count', by='workingday', grid=True, figsize=(12,5))
plt.ylim(0,1000)

'''
휴일과 평일 비교하는 그래프에서, 평일에 수요가 훨씬 많음을 알수있다
분포가 다르고 해석되는 것에 차이가 있으므로 y분포에 도움이 될수 있다.
'''

 

 

raw_fe[raw_fe.holiday==0].boxplot(columns = 'count', by ='Hour', grid=True, figsize=(12,5))
plt.show()
raw_fe[raw_fe.holiday ==1].boxplot(columns='count', by ='Hour', grid=True, figsize=(12,5))
plt.show()
'''
두 분포간의 차이가 있으며 개별 분포를 봐도 count값 분포가 다르므로 y에 효과가 있음을 추론가능
'''

 

 

 

# scatter plot for some group
#temp를 추가해서 삼차원 그래프
raw_fe[raw_fe.workingday == 0].plot.scatter(y='count', x='Hour', c='temp', grid=True, figsize=(12,5), colormap='viridis')
plt.show()
raw_fe[raw_fe.workingday == 1].plot.scatter(y='count', x='Hour', c='temp', grid=True, figsize=(12,5), colormap='viridis')
plt.show()

'''
temp도 두 그래프의 분포가 다르므로 영향을 줄거라는 걸 추론 할수있다.
'''

 

 

# box plot example_날씨에 따른 수요 변화
raw_fe.boxplot(column='count', by='weather', grid=True, figsize=(12,5))
plt.ylim(0,1000)
raw_fe.boxplot(column='registered', by='weather', grid=True, figsize=(12,5))
plt.ylim(0,1000)
raw_fe.boxplot(column='casual', by='weather', grid=True, figsize=(12,5))
plt.ylim(0,1000)
'''
날씨에 따른 count 변화가 보인다.
'''

 

 

# box plot example_년도에 따른 수요 변화
raw_fe.boxplot(column='count', by='Year', grid=True, figsize=(12,5))
plt.show()
'''
년도에 따른 수요가 다르다는 걸 알수 있다. y에 영향을 준다
'''

 

 

# box plot example_월에 따른 수요 변화 
raw_fe.boxplot(column='count', by='Month', grid=True, figsize=(12,5))
plt.show()

 

 

 

 

#독립변수간의 상관관계를 파악하기 위한 시각화
#상관관계를 추정하는게 알고리즘의 목표
pd.plotting.scatter_matrix(raw_fe, figsize=(18,18), diagonal='kde')
plt.show()

 

  • 색깔이 짙을수록 관계성이 강하다는 의미

 

 

 

# selecting of columns from correlation tables
#y값과 x들 간의 상관관계 보기
'''
아래 값이 회귀분석 결과에 나온 계수값과 비슷한지 비교해봐야 한다
유사하지 않기 때문에 t검정이 유의하지 않다고 한것이다. 
count_lag2 회귀분석결과를 비교해도 다름을 알수있다.
'''
raw_fe.corr().iloc[:,8:11]

 

 

 

# correlation table example
raw_fe.corr().iloc[0:8,8:11].style.background_gradient().set_precision(2).set_properties(**{'font-size': '15pt'})

 

 

 

검증지표 방향

R-squared(R^2):추정된 (선형)모형이 주어진 데이터에 잘 적합된 정도, 계량경제학에서는 모델에 의해 설명되는 데이터 분산의 정도(퍼센트)

 

R-squared는 기준이 ybar이다. 이는 다른 mse,mae와 차이점이다.
-> 평균적으로 추정된 값보다 얼만큼 잘 적합이 되었는지 확인
    최소값은 마이너스 무한대이다.

 

 

 

Mean Absolute Error(MAE): 각 데이터의 단위를 보존하는 성능지표
단위보존 ? mse와 비교하면 알수있다.

 

Mean Squared Error(MSE): 가장 많이 사용되며 큰 오차에 패널티(Penalty)를 높게 부여하는 성능지표

mse는 실제값-예측값의 제곱이므로, 0보다 작은값은 더 작게, 1보다 큰 값은 더 크게 만들고 애초에 y값 자체의 스케일이 클수도, 작을수도 있다. 

 

mae는 절대값으로 이뤄져 있기 때문에 작은 값이 더 작게, 큰 값은 더 크게 계산되지 않는다
즉, mae는 y스케일을 그대로 보존할수 있다.

 

 

 

Summary

  • Squared 가 들어간 평가지표는, 이상치 하나만 있어도 오차가 제곱이 된다. 훨씬큰 오차가 반영됨
    따라서 이상치가 있다면 yes로 표기된 평가지표를 쓰기를 추천

 

 

편향, 분산 상충관계

 

*bias를 보는건 train학습이 잘되었는지(과적합인지 아닌지) 확인할때 본다
편향이 작다면 정확성가 높고 (오버핏팅)
편향이 크다면 정확성이 낮다 (언더핏팅)

 

*분산을 보는건  test 데이터에 대해서 정확성이 안정적으로 나올지 아닐지를 확인할때 본다
분산이 작다면 다른 데이터로 예측시 적은 변동 예상
분산이 크다면 다른 데이터로 예측시 많은 변동 예상

 

*이둘의 관계그래프를 보면 모델이 복잡할수록 값이 증가한다.
왜일까? 모델이 복잡할수록 train 데이터에 과적합이 되고(bias 증가), 새로운 test 데이터가 들어올때
어디로 튈지 모르게 되므로 분산값이 커진다.(variance 증가)

분산과 편향을 둘다 줄여야 오류가 작아진다

728x90
728x90

*본 내용은 시계열데이터 강의 내용 중 일부분을 요약한 내용입니다

 

시계열 변수 추출 7종

Feature Engineering 통해  새 변수를 창출

추가된 새 변수가 무조건 종속변수에 영향을 못 줄수도 있다

예로들어 광고비 1,2,3,4(백만원 단위),  GDP 1,2,3,4(조 단위) 변수가 있을때 컴퓨터는 이 두 변수를 같은 것으로 취급한다

 

1. 빈도(Frequency): 계절성 패턴(seasonality)이 나타나기 전까지의 데이터 갯수(사람이 정함)

사람이 정하는 것은 데이터를 년단위로 짜를건지, 시간단위로 짜를 건지 등 을 말한다

예로들어 한 컬럼의 데이터가 2019,2020,2021 있을때, 사람은 연도라는 걸 알지만 컴퓨터는 지정하지 않으면 모르므로 

년도라고 지정 해줘야 한다

 

다만, 데이터를 분석할때 년도,월,일 등 분해 해서 알아봐야 한다-> 어떤 변수가 종속변수에 영향을 줄지는 해보지 않곤 모른다. 이 분해 과정에서 생기는 nan는 여러 방법으로 채울수가 있다.

nan 채우는 방법's

*빈도를 먼저 설정 시 장점

 Freq를 만일 년도로 설정하고 월,일 등으로 날짜를 분해할때, 중간에 누락된 공백을 찾아서 nan로 넣어주고, 분석자는   nan를 채워주면 중간에 빠짐없이 데이터를 채울수 있다

 ex) 2020-03-29~ 2021-03-29 데이터에서 일별로 분해 시, 본 데이터에서 누락된  2020-09-21 데이터가 nan로 채워지   게 된다. 이를 위 method로 해결

 

 

2.추세(Trend): 시계열이 시간에 따라 증가, 감소 또는 일정 수준을 유지하는 경우

 

3.계절성(Seasonality): 규칙적인 기간 동안에 나타나는 패턴을 말합니다. 연간,월간,일간,시간 등 반복되는 규칙만 존재한다면 계절성으로 불립니다.

 

4.주기(Cycle): 일정하지 않은 빈도로 발생하는 패턴

현실 데이터는 계절성과 주기의 명확한 구분이 어렵다(혼재 되어 있는 경우가 많다)

영업 환경이나 전략 변화에 의하여 나타나는 경우가 많다. 

 

5.시계열 분해(추세/계절성/잔차): 본래 데이터를 추세,계절성,잔차로 분해가 가능하다

본래데이터(observed)= 추세(trend) + 계절성(seasonal)+ 잔차(residual) 

 

6.더미변수(Dummy variables): 이진수(0 또는 1)의 형태로 변수를 생성하는 것으로 휴일,이벤트,캠페인 등을 생성 가능

1. 더미변수를 하지 않았을때 의미

Y=ax가 있을때 Y는 매출, X는 계절(봄,여름,가을,겨울 )

a 계수가 3이라고 한다면 계절이 바뀔때마다 3씩 매출에 영향을 준다 로 해석가능하다

즉, 계절이 변할때 마다 매출이 어떻게 변하는지를 알고자 할때 더미 변수를 하지 않고 사용하는게 적합하다

 

2. 더미변수를 사용하고자 할때 의미

각 계절별로 '따로따로' 매출에 얼마큼 영향을 주는지 알고자 할때 쓰인다

 

7.지연값(Lagged values): 변수의 지연된 값을 독립변수로 반영하는 것으로,ARIMA/VAR/NNAR 등이 활용

ex) 광고비를 투입한 시점부터 매출에 영향을 준 걸까? 라는 의문점에서부터 시작된다
즉 영향을 주고 받는 시간 차이가 발생한다. 

★위 이론 내용을 토대로 실습 진행

Dataset: BikeSharingDemand

 

Import

# Ignore the warnings
import warnings 
# warnings.filterwarnings('always') #항상 경고문이 뜨게 한다
warnings.filterwarnings('ignore') # 경고 뜨지 않게 설정

# System related and data input controls
import os

# Data manipulation and visualization
import pandas as pd
pd.options.display.float_format = '{:,.2f}'.format #options클래스 안에 display 안에 float_format
pd.options.display.max_rows = 10 #전체데이터에서 row data 앞에 5개, 뒤에 5개 만 보이게 함
pd.options.display.max_columns = 20
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# Modeling algorithms
# General
import statsmodels.api as sm
from scipy import stats

# Model selection
from sklearn.model_selection import train_test_split

# Evaluation metrics
# for regression
from sklearn.metrics import mean_squared_log_error, mean_squared_error, r2_score, mean_absolute_error

 

#데이터 불러오기

location = './Data/BikeSharingDemand/Bike_Sharing_Demand_Full.csv' #맨 앞에 . 점은 동일한 위치 라는 의미
raw_all = pd.read_csv(location)
raw_all

 

 

 Feature Engineering: 데이터에서 시계열패턴 추출하기

 Feature engineering 하기 전/후 비교하기 위해서 non_feature_engineering을 추가해여 생성합니다
 
 def non_feature_engineering(raw):
 	raw_nfe= raw.copy()
    
    #객체 타입인 datatime 변수를 datetime 타입으로 변경
    if 'datetime' in raw_nfe.columns:
    	raw_nfe['datetime'] = pd.to_datetime(raw_nfe['datetime'])
        raw_nfe['DateTime]= pd.to_datetime(raw_nfe['datetime']) #인덱스로 적용
   	if raw_nfe.index.dtype=='int64':
    	raw_nfe.set_index('DateTime', inplace=True)
        
        #bring back
        #if raw_nfe.dtype !='int64':
        #	raw_nfe.reset_index(drop=False, inplace=True)
        
        #시간 단위로 시간 축 설정후 결측치는 forward fill
        raw_nfe = raw_nfe.asfreq('H', method ='ffill')
        return raw_nfe
        
def feature_engineering(raw):
	raw_fe=raw.copy()
    if 'datetime' in raw_fe.columns:
    	raw_fe['datetime'] = pd.to_datetime(raw_fe['datetime'])
        raw_fe['DateTime]= pd.to_datetime(raw_fe['datetime']) #인덱스로 적용
   	if raw_fe.index.dtype=='int64':
    	raw_fe.set_index('DateTime', inplace=True)
        
        #시간 단위로 시간 축 설정후 결측치는 forward fill
        raw_fe = raw_fe.asfreq('H', method ='ffill')
        
        #시계열 분해_추세
        result= sm.tsa.seasal_decompose(raw_fe['count'], model ='additive')
        Y_trend = pd.DataFrame(result.trend)
        Y_trend.fillna(method='ffill', inplace=True)
        Y_trend.fillna(method='bfill', inplace=True)
        Y_trend.columns = ['count_trend']
        
        #시계열 분해_계절성
        Y_seasonal = pd.DataFrame(result.seasonal)
        Y_seasonal.fillna(method='ffill', inplace=True)
        Y_seasonal.fillna(method='bfill', inplace=True)
        Y_seasonal.columns = ['count_seasonal']
        
        #원본과 합치기
        pd.concat([raw_fe, Y_trend,Y_seasonal], axis=1).isnull().sum()
        if 'count_trend' not in raw_fe.columns:
        	raw_fe = pd.concat([raw_fe, Y_trend, Y_seasonal], axis=1)
            
        #이동평균으로 일별, 주별 count 생성    
        Y_count_Day = raw_fe[['count']].rolling(24).mean() 
        Y_count_Day.fillna(method='ffill', inplace=True)
        Y_count_Day.fillna(method='bfill', inplace=True)
        Y_count_Day.columns = ['count_Day']
        Y_count_Week = raw_fe[['count']].rolling(24*7).mean()
        Y_count_Week.fillna(method='ffill', inplace=True)
        Y_count_Week.fillna(method='bfill', inplace=True)
        Y_count_Week.columns = ['count_Week']
        
        #원본과 합치기
        if 'count_Day' not in raw_fe.columns:
          raw_fe = pd.concat([raw_fe, Y_count_Day], axis=1)
        if 'count_Week' not in raw_fe.columns:
          raw_fe = pd.concat([raw_fe, Y_count_Week], axis=1)
        
        Y_diff = raw_fe[['count']].diff()
        Y_diff.fillna(method='ffill', inplace=True)
        Y_diff.fillna(method='bfill', inplace=True)
        Y_diff.columns = ['count_diff']
        if 'count_diff' not in raw_fe.columns:
        	raw_fe=pd.concat([raw_fe,Y_diff],axis=1)
            
        #날짜 변수 생성
        raw_fe['temp_group'] = pd.cut(raw_fe['temp'], 10)
        raw_fe['Year'] = raw_fe.datetime.dt.year
        raw_fe['Quater'] = raw_fe.datetime.dt.quater
        raw_fe['Quater_ver2'] = raw_fe.datetime.dt.quater+(raw_fe.Year- raw_fe.min())*4
        raw_fe['Month'] =raw_fe.datetime.dt.Month
        raw_fe['Day'] = raw_fe.datetime.dt.day
        raw_fe['Hour'] = raw_fe.datetime.dt.hour
        raw_fe['DayofWeek'] = raw_fe.datetime.dt.dayofweek      
        
        #지연값 변수 생성
        raw_fe['count_lag1'] = raw_fe['count'].shift(1)
        raw_fe['count_lag2'] = raw_fe['count'].shift(2)
        raw_fe['count_lag1'].fillna(method='bfill', inplace=True)
        raw_fe['count_lag2'].fillna(method='bfill', inplace=True)  
        
        if 'Quater' in raw_fe.columns:
        	if 'Quater_Dummy' not in raw_fe.columns:
            	raw_fe = pd.concat([raw_fe, pd.get_dummies(raw_fe['Quater], prefix='Quater_Dummy', drop_first=True)], axis=1)
                del raw_fe['Quater']
        return raw_fe
                
        
        

 

 

 

데이터 분리

시계열 데이터는 분리할때 시간축이 반드시 있어야 한다. 

기존에 알고 있는 train_test_split, k-fold 등 분리 방법은 비시계열 데이터 분리 방법으로써 시간차원 없다

시계열데이터에 위 방법을 사용하면 시간개념이 사라지므로 1스텝 교차검사,2스텝 교차검사 분리 방법을 사용해야한다.

1-step 교차검사

하얀 점들이 예측해야할 test 미래 시기이다. 시간 단위로 index가 구성되어 있으므로 

하얀점들 각각이 2021-03-15 09:00, 2021-03-15 10:00, 2021-03-15 11:00 ~~~ 로 구성되어 있을것이다. 

시계열데이터는 각 시기를 예측해야한다. 비시계열은 아래처럼 test를 한 곳에 뭉쳐서 성능값이 하나 나온다

만일 90%라고 나와도, 가까운 미래 정확도가  98%나오고 먼 미래 일수록 그 정확도가 떨어진다. 이 수치를 종합해서 90%라고 해도 시계열 데이터 입장에서는 신뢰할수 없는 성능 수치이다.

그래서 각 시기별로 각각 정확도를 구하고, 정확도를 구한 시기는 train으로 들어간다. 

 

 

★위에 이론 내용을 토대로 실습 진행

실습은 시계열데이터지만 전통적인 데이터분리 방법을 적용했다(강의 구성이 그렇게 되어있다...)

 

### Data split of cross sectional
def datasplit_cs(raw, Y_colname, X_colname, test_size, random_seed=123):
	X_train, X_test, Y_train, Y_test = train_test_split(raw[X_colname], raw[Y_colname], test_size=test_size, random_state=random_seed)
    print('X_train:', X_train.shape, 'Y_train:', Y_train.shape)
    print('X_test:', X_test.shape, 'Y_test:', Y_test.shape)
    return X_train, X_test, Y_train, Y_test
    
### Data split of time series => 특정 날짜를 기준으로 나눈다
def datasplit_ts(raw, Y_colname, X_colname, criteria):
	raw_train = raw.loc[raw.index < criteria,:]
    raw_test = raw.loc[raw.index >= criteria,:]
    Y_train = raw_train[Y_colname]
    X_train = raw_train[X_colname]
    Y_test = raw_test[Y_colname]
    X_test = raw_test[X_colname]
    print('Train_size:', raw_train.shape, 'Test_size:', raw_test.shape)
    print('X_train:', X_train.shape, 'Y_train:', Y_train.shape)
    print('X_test:', X_test.shape, 'Y_test:', Y_test.shape)
    return X_train, X_test, Y_train, Y_test
    
Y_colname =['count']

#중복되는 count & 문자형 변수
X_remove = ['datetime', 'DateTime', 'temp_group', 'casual', 'registered']
X_colname= [col for col in raw_fe.columns if col not in Y_colname+X_remove] 
X_train, X_test, Y_train, Y_test = datasplit_ts(raw_fe, Y_colname, X_colname, '2012-07-01')
728x90
728x90

처음시작부터 기하학적 변환까지 진행했습니다

Opencv로 프로젝트를 진행해 보지 않아서 인지

완전히 머리로 들어 왔다는 느낌이 없습니다 

 

그래서 복습할때는 외우려 하기 보다는 이해 위주로 진행합니다

다음에 Opencv 써야 할 때가 온다면 실습내용과 책이 있으니까 금방 적용할수 있지 않을까 생각합니다

 

요즘 생각이 많아져서 학습에 제대로 집중이 안되네요 

내가 하고 있는게 맞는 방향인지, 제대로 컬리큘럼을 계획한건지 자신감도 떨어지고 있습니다

 

3월달 들어오면서 부터 그런것 같습니다 

하... 

 

일단 내일은 쉬고 월요일에는 시계열데이터 공부하도록 하겠습니다~

728x90
728x90

*본 내용은 시계열데이터 강의 내용 중 일부분을 정리 요약한 내용입니다

 

 

현실의 데이터 분석

  • 현실의 데이터 분석은 2단계인 데이터 분석이 아니라 1단계, 문제 정의/기획이 가장 중요하다
  • 어떻게 정의 하느냐에 따라 독립,종속 변수가 달라지므로 데이터 분석의 방향이 결정되기 때문이다.
  • 문제 정의 단계는 끊임없이 진화/변경하여 업데이트를 해야한다

 

데이터 관점에 따른 분류

  • 횡단면 데이터: 어느 한 시점에서 여러 변수들이 있는 데이터
  • 시계열 데이터: 여러개의 시점과 특정한 변수가 있는 데이터
  • 시계열 횡단면 데이터: 여러시점과 변수들이 함께 있는 데이터
  • 패널데이터: 꽉차 있는 시계열 횡단면 데이터
  • Tick: 초 보다 작은 시간단위(high Frequency)

 

* raw data의 2가지 타입

1. Log: 시간 순으로 데이터를 쌓은 것(정렬 개념이 아닌 특정시간에 따라 쌓는 개념

ex) 센서에서 나오는 정보를 차곡차곡 쌓아 가는 형식

 

2. Tabel: 특정한 형태로 가공된 것(정렬되거나 groupby 등)

ex) 주로 경연대회에서 제공해주는 데이터가 Tabel에 속하는 것같다

 

 

통계 기본 용어

1. 왜도(Skewness): 평균을 중심으로 좌우 데이터가 편향 되어 있는 정도를 표현 

 

왜도가 왜 필요한가?

A와 B반의 키를 비교해볼때, 두 반 모두 키 평균과 퍼져있는 정도, 즉 분산이 같다고 가정합니다.

하지만 분포를 보면 그 양상은 다를수 있습니다. A반은 키가 매우 작은 학생 몇명때문에 평균이 177이고

B반은 키가 매우 큰 학생이 몇몇 존재 해서 평균이 177이 되었습니다. 아래 그림에서 교차하는 점이 

177일때 왼쪽이 A반이고 오른쪽이 B반 이라면 이해하기가 쉬워집니다.

두 반 모두 평균과 분산은 같지만 우리는 각기 다른 인사이트를 얻을수 있기 때문에 왜도가 필요합니다

  • 질 좋은 빅데이터란 stew가 없는 데이터입니다
  • 특정한 샘플만을 통해 분석을 실행한다면 치우침(bias)은 생길수 밖에 없습니다
  • 따라서 데이터 분석 시 이러한 함정에 빠지지 않도록 유의해야합니다

 

 

2. 첨도(Kurtosis): 분포의 뾰족함 정도

 

첨도가 왜 필요한가?

뾰족할수록 중심으로 몰리게 되는 분포가 만들어 집니다. 이는 양 끝 사이드가 0으로 빨리 수렴이 됩니다.

그래서 이상치가 거의 존재 하지 않을 가능성이 커집니다. 반면 첨도<0 인경우 분포를 보면

양끝 사이드가 두텁게 형성되어 있습니다. 이때 저만의 예시를 들자면 가운데 몰리는 부분을 일반적인 사람, 평범한 사람이라고 말하고 양 끝사이드에 있는 사람은 독창적이며 남들이 가지 않는 길을 걷는 사람이라고 이해했습니다

 

아마존의 경영전략은 A~Z까지 모든 물건을 판다는 전략입니다. 그래서 독창적인 사람이 요구하는 특이한 물건도 판매를 하게 됩니다. 따라서 아마존에게는 이 첨도의 분포를 통해 인사이트를 고객에 대한 특징과 인사이트를 얻을수 있습니다

 

 

3. 상관관계: A변수의 변화와 B변수의 변화방향의 (선형적)유사성으로 표준화된 공분산이라고도 함

상관관계는 왜 있는 것인가?

인과관계를 규명하지 못하기 때문에 대신 상관관계를 사용하는 것입니다.

강의에서 예로 든 것을 말하자면 여름이 되면 아이스크림 매출은 증가합니다. 또한 여름이 되면 익사자 수가 증가합니다.

그렇다면 여름이 원인이고 결과가 아이스크림 매출 증대, 익사자의 수 증가 인가요? 여름을 어느날부터 여름이라고 정의하는건 신의 영역이므로 인과관계 규명이 불가능 해집니다. 따라서 아이스크림 매출과 익사자의 수 사이에 어떤 상관정도가 있는지를 대신 알아보는 것입니다.

=> 아이스크림 매출이 증가하면 익사자 수가 증가한다 라는 상관관계 정보를 얻을 수는 있습니다.

 

 

가설검정

중심극한정리: 전체 모집단에서 여러 번 Sample을 추출해라. 그리고 Sample마다 평균을 구해라.
이 평균들의 분포는 정규분포이며 전체 모집단의 평균으로 수렴한다.

(개인적으로 위 강의자료 설명이 다른 교재에서 어렵게 설명한 것보다 직관적으로 알기 쉽고 좋은 설명이라고 생각합니다)

 

검정통계량:대립가설(나의주장)과 귀무가설(대중주장)을 비교하기 위한 검증(Evaluation)지표값, 일명 "점추정"

위 점추정을 한번이 아니라 여러번 구하면 점추정1~점추정2 라는 특정한 구간이 생기는데 이를

신뢰구간 또는 구간추정 이라고도 합니다.

 

 

유의수준: 귀무가설(대중주장)이 참이라는 전제 하에, 대립가설(나의주장)이 참이라고 "오판"할 최대 확률

ex) 유의 수준 5%라는 것은.. 

A와 B가 달리기 시합을 합니다. 대중들은 실력의 차이가 없다고 주장하고, 나의 주장은 a가 더 빠르다고 주장하고 있습니다. 이때 둘다 실력의 차이가 없다는 전제 하에 100번 시합중 95번은 무승부(실력 차이가 없다)이고, 5번은 a가 이길때(나의 주장이 증명된것) 이 5번이 유의 수준이 됩니다.  

 

 

유의확률: 귀무가설(대중주장)이 참이라는 전제 하에, 대립가설(나의주장)이 관찰될 확률

ex) 유의수준을 5번으로 정했습니다. 이때 만일 a선수가 5번이 아니라 극단적으로 한 20번 이겼다고 가정합니다.

그러면 80번은 무승부인데 이중에 20번은 a 선수가 이기게 되므로 나의 주장(a선수가 더 잘한다)의 신뢰가 급상승 하게됩니다. 로또도 확률이 희박하듯이 20번까지 이길 확률도 크지 않을 것이기에 1%라 가정합니다.

1%를 분포 상에서 보자면 5%보다 오른쪽에 위치해 있습니다. 희박한 확률이 당첨이 된것입니다.

따라서 만일 유의확률이 유의수준보다 더 낮게 나오면 희박한 확률을 뚫고 나온 것이므로 나의 주장(대립가설)이 채택이 되고 반대로 유의 확률이 유의수준보다 크면 대중 주장이 채택됩니다. 

 

 

학습방향과 알고리즘

각 알고리즘을 바라볼때의 관점을 3가지로 나눈다면 아래와 같습니다

1) 문제가 어디에 속하는지 -> "분석기획(가설/방향)" 가능
2) 알고리즘마다 입력은 무엇인지 -> "데이터전처리(준비)" 가능
3) 알고리즘마다 출력은 무엇인지 -> "결과해석(설명/검증)" 가능

 

알고리즘의 쓰임을 제대로 파악해야 적재적소의 알고리즘을 선택할수 있으며 선택된 알고리즘이 어떤 입력을 요구(전처리에 영향을준다) 하는지와 출력은 무엇을 주는지를 꼭!!! 알아야 한다.

 

 

Time-series Learning는 '주로' 어떤 알고리즘에서 많이 쓰이는가

1. Regression Algorithms(OLSR, Linear Regression, Logistic Regression,Stepwise Regression,MARS, LOESS)
2. Regularization Algorithms(Ridge, LASSO, Elastic Net, LARS)
3. Clustering Algorithms(k-Means,k-Medians, Expectation Maximisation, Hierarchical Clustering)

 

 

데이터 분석에서 설명력은 뭘 뜻하는 걸까?

결론부터 말하자면 아래 표와 같다

설명력과 정확도는 반비례 관계

설명력: 결과 값에 대한 해석, 가설검정이 가능한 구간 추정으로써 가설검정의 결과를 통해 의사결정할수 있는 내용이 포함되는 것들을 설명력이 있다고 표현 (어떠한 변수때문에 종속변수가 영향을 받는지 설명이 가능하다)

 

반면 주로 점추정으로 설명하는 것들은 설명력이 떨어진다
-> 결과가 왜 이렇게 나왔는지에 대한 설명이 부족

 

회귀식에서는 아래 그림처럼 구간추정이 있으므로 유의수준과 유의확률이라는 개념이 통합니다.

이는 어떤 변수가 종속변수에 영향을 끼치는가 아닌가 하는 설명이 가능합니다

하지만 가장 설명력이 떨어지는 딥러닝은 구간 추정이라는 결과가 없습니다

단지 신경망을 통해 얻어진 결과만을 출력합니다. 이는 설명력이 떨어지며 왜 이런 결과가 나왔는지 증명할 길이 현재는 없다는 의미가 됩니다.

 

 

여기까지가 1일차 요약한 내용입니다. 처음에 현실적인 데이터 분석을 들으면서 

뭔가.. 허탈?하다고 해야 할까요 정말 밑도 끝도 없이 프로젝트가 시작되는 구나 라는 생각이 들더라구요

두루뭉실한 말 한마디로 시작해서 분석이 가능하도록 구체적인 명제로 정의 하기 까지의 과정이 만만치 않음을 확인했습니다. :O 

 

내일은 토요일입니다. 일단 계획대로 Opencv 복습을 나갈 생각입니답 

728x90

+ Recent posts