기본 콘텐츠로 건너뛰기

벡터와 행렬에 관련된 그림들

회귀분석을 위한 주가데이터 만들기2_ DataForRegressionS

포스트 DayInInterRetStockS()의 클래스를 소개하는 글에서 원 일일주가데이터로 부터 새로운 변수들을 생성하여 새로운 객체를 만들었습니다.
그 결과를 바탕으로 회귀분석을 위한 데이터 생성을 계속해 보면 다음과 같습니다. 
이전의 데이터 경향으로 새로운 값을 예측하는 것이 회귀분석의 기본방향이라면 위에서 생성된 데이터들 중에 예측에 사용되는 변수들(독립변수)과 예측을 위한 변수(반응변수)를 구분해야 겠지요.
이전에 생성한 객체의 변수명은 다음과 같습니다. 
>>> da.columns
Index(['Open', 'High', 'Low', 'Close', 'Volume', 'Close:Open:ret',
       'Close:High:ret', 'Close:Low:ret', 'Open:intRet', 'High:intRet',
       'Low:intRet', 'Close:intRet', 'Volume:intRet', 'olag', 'hlag', 'llag',
       'clag', 'vlag'],
      dtype='object')
위의 변수들 중에 반응변수의 대상은 'Open', 'High', 'Low', 'Close'중의 하나의 변수가 될 것입니다. 
예로서 Close를 반응변수로 한다면 나머지 변수들은 독립변수가 됩니다. 독립과 반응변수는 날들로 모형의 설계는 
'당일까지의 독립변수들의 성격들로 다음날의 반응변수를 예측'
으로 구축할 것입니다. 
이러한 구축을 위해 먼저 독립변수들과 반응변수를 구분하고 이 두 대상의 날짜를 다르게 하여 한 행에 위치시켜야 합니다. 
또한 데이터 구축 후 분석을 위해 sklearn 패키지의 함수들을 사용할 것입니다. 이 함수들의 인수들은 np.array 객체가 대상이 됩니다. 데이터는 모두 동일한 형식으로 반환됩니다. 
아래 함수에서 독립변수들은 표준화됩니다. 이것은 각 변수들 간의 scale의 차이로 효과를 제거하기 위한 것으로 별도의 함수를 만들어 사용해도 되지만 sklearn에거 제공하는 함수를 사용하는 것이 편리합니다. 그러므로 다음과 같이 관련된 모듈을 부착합니다. 

>>> from sklearn import preprocessing, cross_validation, svm

def DataRegS1(da, deCol, stdize=1, shiftD=1):
        d_lag=da.shift(shiftD)
        if type(deCol) !=str:
            deCol=d_lag.columns[deCol]
        d=pd.concat([d_lag.drop([deCol], axis=1), da[deCol]],axis=1)
        d=d.dropna()
        ind=np.array(d.drop([deCol], axis=1))
        de=np.array(d[deCol])
        new=da.drop([deCol], axis=1).ix[len(da)-1,:]
        if stdize==0:
            ind=ind
            new=new
        else:
            ind=preprocessing.scale(ind)
            ind1_mu=np.mean(ind, axis=0)
            ind1_sd=np.array([np.std(ind[:,i]) for i in range(ind.shape[1])])   
            new=np.array((new-ind1_mu)/ind1_sd)
        return(ind, de, new) 

반환되는 결과는 독립변수(ind), 반응변수(de), 최종적으로 사용되는 변수(new) 입니다. 
new는 원 자료의 마지막 행입니다. 

>>> cpind, cpde, cpnew=DataRegS1(da, 3)
>>> cpind[:2,:]
array([[-1.9438624 , -2.0539455 , -1.97377112, -0.34551834, -0.04362155,
         0.48868343, -0.36767019, -0.7867308 , -1.11823123, -0.202969  ,
        -0.13116804, -0.78078135, -1.39300768, -1.33736073, -1.4881869 ,
        -1.4835275 ,  0.33076086],
       [-2.13940978, -2.2486958 , -2.21829566,  0.30033078, -0.27026372,
         0.16433956, -0.51126002, -0.67611283, -0.69818054, -0.92970837,
        -0.90124321,  0.44802125, -1.58394452, -1.58412679, -1.45874598,
        -1.47638189, -0.15688456]])

>>> cpde[:2,]
array([16405, 16340], dtype=int64)

>>> cpnew 
array([  1.74300000e+04,   1.74850000e+04,   1.68400000e+04,
         1.59008480e+07,  -3.38496845e+00,  -3.68887618e+00,
         2.60999799e-16,  -4.00000000e-01,  -1.04697227e+00,
        -3.71640938e+00,  -3.88127854e+00,   2.50238248e+02,
         1.75800000e+04,   1.76300000e+04,   1.74850000e+04,
         1.75850000e+04,   5.32917100e+06])

회귀분석을 위한 데이터가 생성되었습니다. 

다음으로 위 함수에서 사용한 데이터 da를 사용하여 이전에 사용한 bootstrap 방법을 적용하여 데이터 수를 증가시켜 회귀분석을 위한 데이터를 생성하는 함수를 만들어 봅니다. 이 함수는 이전에 작성한 mkbtsSampleS()(bootstrap 방법 참조, 위 링크된 포스트)과 위 DataRegS1()와의 결합으로 실행될 수 있습니다.
DataRegS1() 함수에서 사용된 pd.shift(number)는 데이터프레임 형태의 데이터에서 지정된 수 만큼 행을 아래로(양수), 위로(음수) 이동시킵니다. 
다음을 볼까요?
>>> x=np.random.randint(0, 10, 10).reshape(5,2)
>>> x=pd.DataFrame(x)
>>> x
   0  1
0  4  8
1  5  8
2  1  7
3  3  8
4  6  9
>>> x.shift(1)
     0    1
0  NaN  NaN
1  4.0  8.0
2  5.0  8.0
3  1.0  7.0
4  3.0  8.0

>>> x.shift(-1)
     0    1
0  5.0  8.0
1  1.0  7.0
2  3.0  8.0
3  6.0  9.0
4  NaN  NaN

이 함수를 사용하여 분석에 대응되는 독립변수들과 반응변수를 한 행에 정리한 후 이들의resampling의 bootstrap 방법 즉,  mkbtsSampleS()를 적용합니다. 그 적용후에 DataRegS1에 그 결과를 적용합니다. 다음과 같이 class를 생성하여 사용합니다.

1. 클래스 BtsDataRegS에 사용할 객체를 전달하여 클래스 객체를 생성합니다.
2. 클래스 객체에 반응변수로 사용할 열 번호 또는 열 이름을 전달하여 독립변수들과 반응변수간의 날짜를 변경시켜 분석을 위한 데이터 형태로 만듭니다. 이 과정에서 반응변수는 생성된 데이터셋의 마지막 열에 위치하게 됩니다.
3. bootstrap 방법을 적용하여 샘플의 수를 증가시킵니다.
4. 3번에서 생성된 데이터를 독립변수와 반응변수, 그리고 최종적으로 사용하게 될 독립변수들을 생성합니다. 이 과정에서 독립변수들의 표준화를 적용할 수 있습니다.

class BtsDataRegS:
    def __init__(self, da):
        self.da=da
    def MkIndDeS(self, deCol, shiftD=1):
        self.deCol=deCol
        d_lag=self.da.shift(shiftD)
        if type(self.deCol) !=str:
            self.deCol=d_lag.columns[self.deCol]
        d=pd.concat([d_lag.drop([self.deCol], axis=1), self.da[self.deCol]],axis=1)
        self.d=d.dropna()
        return(self.d)
    def MkbtsS(self, smpN=10, repN=500):
        n=len(self.d)
        spId=np.random.choice(n, size=smpN, replace=True)
        sample=np.array(np.mean(self.d.iloc[spId,:], 0)).reshape(1,self.d.shape[1])
        for i in range(repN+1):
            spId=np.random.choice(n, size=smpN, replace=True)
            sp=np.array(np.mean(self.d.iloc[spId,:], 0)).reshape(1,self.d.shape[1])
            sample=np.r_[sample,sp]
        self.sample=sample
        return(self.sample)
    def MkData(self,stdize=1):
        ind=self.sample[:, :(self.sample.shape[1]-1)]
        self.de=self.sample[:, (self.sample.shape[1]-1)]
        new=self.da.drop([self.deCol], axis=1).iloc[len(self.da)-1,:]
        if stdize==0:
            self.ind=ind
            self.new=new
        else:
            self.ind=preprocessing.scale(ind)
            daS=preprocessing.scale(self.da.drop(["Close"], axis=1))
            self.new=daS[(daS.shape[0]-1),:]
        return(self.ind, self.de, self.new)

위 클래스를 적용하기 위해 위에서 생성된 데이터 da의 마지막 5행을 사용합니다.
>>> trg=da.tail(5)
>>> test=BtsDataRegS(trg)
>>> inde=test.MkIndDeS(3)
>>> sm=test.MkbtsS()
>>> ind, de, new=test.MkData()
>>> new.shape
(17,)
>>> ind.shape
(502, 17)
>>> de.shape
(502,)

위에서 생성된 cpde와 500회 반복한 샘플 de, 1000회 반복한 샘플의 정규성을 확인하여 보면 다음과 같습니다. (그래프 작성을 위한 사용자 정의 함수 histNormalplotS)
먼저 bootstrap을 적용하지 않은 경우;
(0.98360045319196987, 1.3322215876321926e-42)
 상관계수와 상관분석의 p-value가 결과로 반환됩니다. 
500회 반복한 샘플;

(0.98502701750103172, 0.0)
1000회 반복한 샘플;


(0.99757571983444615, 0.0)
반복회수가 증가할 수록 정규성의 부합정도가 증가됨을 알 수 있습니다.
이는 회귀분석의 기본 가정 즉, 반응변수가 정규분포에 부합한다는 것을 만족시키는 것입니다. 이 가정은 분석자 입장에서 데이터의 모수를 아는 상태에 이루어지므로 분석 결과를 적용하는 합리적 근거가 됩니다. 

댓글

이 블로그의 인기 게시물

[Linear Algebra] 유사변환(Similarity transformation)

유사변환(Similarity transformation) n×n 차원의 정방 행렬 A, B 그리고 가역 행렬 P 사이에 식 1의 관계가 성립하면 행렬 A와 B는 유사행렬(similarity matrix)이 되며 행렬 A를 가역행렬 P와 B로 분해하는 것을 유사 변환(similarity transformation) 이라고 합니다. $$\tag{1} A = PBP^{-1} \Leftrightarrow P^{-1}AP = B $$ 식 2는 식 1의 양변에 B의 고유값을 고려한 것입니다. \begin{align}\tag{식 2} B - \lambda I &= P^{-1}AP – \lambda P^{-1}P\\ &= P^{-1}(AP – \lambda P)\\ &= P^{-1}(A - \lambda I)P \end{align} 식 2의 행렬식은 식 3과 같이 정리됩니다. \begin{align} &\begin{aligned}\textsf{det}(B - \lambda I ) & = \textsf{det}(P^{-1}(AP – \lambda P))\\ &= \textsf{det}(P^{-1}) \textsf{det}((A – \lambda I)) \textsf{det}(P)\\ &= \textsf{det}(P^{-1}) \textsf{det}(P) \textsf{det}((A – \lambda I))\\ &= \textsf{det}(A – \lambda I)\end{aligned}\\ &\begin{aligned}\because \; \textsf{det}(P^{-1}) \textsf{det}(P) &= \textsf{det}(P^{-1}P)\\ &= \textsf{det}(I)\end{aligned}\end{align} 유사행렬의 특성 유사행렬인 두 정방행렬 A와 B는 'A ~ B' 와 같...

[sympy] Sympy객체의 표현을 위한 함수들

Sympy객체의 표현을 위한 함수들 General simplify(x): 식 x(sympy 객체)를 간단히 정리 합니다. import numpy as np from sympy import * x=symbols("x") a=sin(x)**2+cos(x)**2 a $\sin^{2}{\left(x \right)} + \cos^{2}{\left(x \right)}$ simplify(a) 1 simplify(b) $\frac{x^{3} + x^{2} - x - 1}{x^{2} + 2 x + 1}$ simplify(b) x - 1 c=gamma(x)/gamma(x-2) c $\frac{\Gamma\left(x\right)}{\Gamma\left(x - 2\right)}$ simplify(c) $\displaystyle \left(x - 2\right) \left(x - 1\right)$ 위의 예들 중 객체 c의 감마함수(gamma(x))는 확률분포 등 여러 부분에서 사용되는 표현식으로 다음과 같이 정의 됩니다. 감마함수는 음이 아닌 정수를 제외한 모든 수에서 정의됩니다. 식 1과 같이 자연수에서 감마함수는 factorial(!), 부동소수(양의 실수)인 경우 적분을 적용하여 계산합니다. $$\tag{식 1}\Gamma(n) =\begin{cases}(n-1)!& n:\text{자연수}\\\int^\infty_0x^{n-1}e^{-x}\,dx& n:\text{부동소수}\end{cases}$$ x=symbols('x') gamma(x).subs(x,4) $\displaystyle 6$ factorial 계산은 math.factorial() 함수를 사용할 수 있습니다. import math math.factorial(3) 6 a=gamma(x).subs(x,4.5) a.evalf(3) 11.6 simpilfy() 함수의 알고리즘은 식에서 공통사항을 찾아 정리하...

sympy.solvers로 방정식해 구하기

sympy.solvers로 방정식해 구하기 대수 방정식을 해를 계산하기 위해 다음 함수를 사용합니다. sympy.solvers.solve(f, *symbols, **flags) f=0, 즉 동차방정식에 대해 지정한 변수의 해를 계산 f : 식 또는 함수 symbols: 식의 해를 계산하기 위한 변수, 변수가 하나인 경우는 생략가능(자동으로 인식) flags: 계산 또는 결과의 방식을 지정하기 위한 인수들 dict=True: {x:3, y:1}같이 사전형식, 기본값 = False set=True :{(x,3),(y,1)}같이 집합형식, 기본값 = False ratioal=True : 실수를 유리수로 반환, 기본값 = False positive=True: 해들 중에 양수만을 반환, 기본값 = False 예 $x^2=1$의 해를 결정합니다. solve() 함수에 적용하기 위해서는 다음과 같이 식의 한쪽이 0이 되는 형태인 동차식으로 구성되어야 합니다. $$x^2-1=0$$ import numpy as np from sympy import * x = symbols('x') solve(x**2-1, x) [-1, 1] 위 식은 계산 과정은 다음과 같습니다. $$\begin{aligned}x^2-1=0 \rightarrow (x+1)(x-1)=0 \\ x=1 \; \text{or}\; -1\end{aligned}$$ 예 $x^4=1$의 해를 결정합니다. solve() 함수의 인수 set=True를 지정하였으므로 결과는 집합(set)형으로 반환됩니다. eq=x**4-1 solve(eq, set=True) ([x], {(-1,), (-I,), (1,), (I,)}) 위의 경우 I는 복소수입니다.즉 위 결과의 과정은 다음과 같습니다. $$x^4-1=(x^2+1)(x+1)(x-1)=0 \rightarrow x=\pm \sqrt{-1}, \; \pm 1=\pm i,\; \pm1$$ 실수...