기본 콘텐츠로 건너뛰기

통계관련 함수와 메서드 사전

A B C d E F G H I K L M N O P Q R S T U V W Z A statsmodels.ap.stats.anova_lm(x) statsmodels.formula.api.ols 에 의해 생성되는 모형 즉, 클래스 인스턴스(x)를 인수로 받아 anova를 실행합니다. np.argsort(x, axis=-1, kind=None) 객체 x를 정렬할 경우 각 값에 대응하는 인덱스를 반환합니다. Axis는 기준 축을 지정하기 위한 매개변수로서 정렬의 방향을 조정할 수 있음(-1은 기본값으로 마지막 축) pandas.Series.autocorr(lag=1) lag에 전달한 지연수에 따른 값들 사이의 자기상관을 계산 B scipy.stats.bernoulli(x, p) 베르누이분포에 관련된 통계량을 계산하기 위한 클래스를 생성합니다. x: 랜덤변수 p: 단일 시행에서의 확률 scipy.stats.binom(x, n, p) 이항분포에 관련된 통계량을 계산하기 위한 클래스를 생성합니다. x: 랜덤변수 n: 총 시행횟수 p: 단일 시행에서의 확률 C scipy.stats.chi2.pdf(x, df, loc=0, scale=1) 카이제곱분포의 확률밀도함수를 계산 $$f(x, k) =\frac{1}{2^{\frac{k}{2}−1}Γ(\frac{k}{2})}x^{k−1}\exp\left(−\frac{x^2}{2}\right)$$ x: 확률변수 df: 자유도 pd.concat(objs, axis=0, join=’outer’, …) 두 개이상의 객체를 결합한 새로운 객체를 반환. objs: Series, DataFrame 객체. Axis=0은 행단위 즉, 열 방향으로 결합, Axis=1은 열단위 즉, 행 방향으

경사하강법(Descent Gradient)

내용

경사하강법(Descent Gradient)

경사하강법이란?

최소자승법은 공식화된 계산식에 의해 결정된 회귀계수를 적용합니다. 이에 반면에 경사하강법은 수치적으로 모델을 최적화하는 과정에서 회귀계수를 산출합니다.

식 1의 선형회귀모형은 독립변수(x)와 종속변수(y)의 사이의 다음의 선형식을 만족하는 최적의 회귀계수를 결정하는 것입니다.

$$\begin{align}\tag{1}&y=xW\\&W:\text{회귀계수(가중치)}\end{align}$$

예를 들어 다음의 자료는 y=2x를 만족하는 인위적으로 생성한 데이터입니다.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import sympy as sp
x=np.arange(0, 10).reshape(-1,1)
y=x*2
x.shape, y.shape
((10, 1), (10, 1))
np.c_[x, y]
array([[ 0,  0],
           [ 1,  2],
           [ 2,  4],
           [ 3,  6],
           [ 4,  8],
           [ 5, 10],
           [ 6, 12],
           [ 7, 14],
           [ 8, 16],
           [ 9, 18]])

역으로 위 자료의 선형회귀 모델을 생성한다고 할 경우 y=xw로부터 식 2와 같이 계산되는 mse가 최소가 되는 방식으로 W를 결정해야 합니다.

$$\begin{align}\tag{2}\text{mse}&=\frac{\sum^n_{i=1}(\hat{y}-y)^2}{n}\\&=\frac{\sum^n_{i=1}(xW-y)^2}{n} \end{align}$$

W를 임의적으로 적용할 경우 mse의 변화는 그림 1과 같이 2차 곡선의 형태를 나타냅니다.

plt.figure(dpi=100)
coef=np.linspace(-7, 11, 1000)#회귀계수의 변화
mse=[np.sum((x*i-y)**2)/len(y) for i in coef]
plt.plot(rng, mse)
plt.xlabel("Coeff(W)", size="14")
plt.ylabel("MSE", size="14")
plt.show()
그림 1. 회귀계수의 변화에 따른 MSE의 변화.

경사하강법 알고리즘

최소자승법의 경우는 mse의 최소값이 되는 지점에서 회귀계수를 결정하지만 경사하강법의 경우는 임의적으로 지정한 회귀계수의 초기값으로부터 이 값의 변화에 의해 도달하는 mse의 최소로 되는 지점을 발견하며 그 지점에서 회귀계수를 결정하는 방법입니다. 이 방법은 수치해석에 의한 것으로 최소자승법의 여러 전제조건에서 자유로운 분석 방법입니다.

이 방법은 다음의 과정으로 이루어집니다.

  1. 초기 회귀모형 생성(회귀계수, 편차를 지정합니다.)
  2. 그 모형에 대한 MSE를 계산합니다. 이것은 모형에 대한 비용함수(cost function) 또는 손실함수(loss function)이라고 합니다.
  3. 회귀계수에 대해 비용함수 변화율을 고려하여 새로운 계수를 계산합니다.
  4. 비용함수가 극소점에 도달할 때까지 또는 변화가 없을 때까지 1 ∼ 3번 과정을 반복합니다. 이 과정을 최적화(optimization)라 합니다.

그림 2에서 나타낸 것과 같이 회귀 계수에 대한 비용 변화율은 미분, $\displaystyle \frac{d(cost)}{dw}$,으로 계산됩니다. 회귀 계수에 대해 이 결과를 다시 고려하는 과정을 반복하여 최적화된 값을 도출합니다.

np.random.seed(1)
x=np.linspace(-4, 4, 100)
y0=0.5*x
w=np.random.rand(1)
mse=np.sum((w*x-0.2-y0)**2)/len(x)
dmse_x=np.sum(2*(w*x-0.2-y0)*w)/len(x)
mset=[float(mse)]
wt=[float(w)]
for i in range(20):
    w=w-0.03*np.sum(2*(w*x-0.2-y0)*w)/len(x)
    wt.append(float(w))
    mset.append(float(np.sum((w*x-0.2-y0)**2)/len(x)))

plt.figure(dpi=100)
plt.scatter(wt, mset, color="red")
plt.plot(wt, mset, label="Cost Function")
plt.legend(loc="best")
plt.xlabel("Weight(W)", size=12, weight='bold')
plt.ylabel("Cost(mse)", size=12, weight='bold')
plt.annotate('w', xy=(wt[4]+0.01, mset[4]), xytext=(wt[1]+0.01, mset[1]), arrowprops=dict(facecolor='navy', width=1))
plt.text(0.44, 0.070, r"$\mathbf{w=w-\eta \frac{d(cost)}{dx}}$")
plt.show()
그림 2. 비용함수를 사용한 회귀계수의 최적화.
η: 학습률(learning rate)

위 과정을 경사하강법(Gradient Descent)이라고 하며 그 알고리즘을 수식으로 전개하면 다음과 같습니다(식 5.3 ∼ 7). 그림 2에서 나타낸 것과 같이 초기의 w, b를 랜덤하게 지정하는 것으로 시작하며 w, b를 감소시키면서 손실(loss)의 변화를 확인합니다. 그러한 변화 동안 최소의 손실이 생성되는 지점에서 w, b를 모수로 하여 모형을 설정합니다.

식 3은 경사하강법의 기본 특성치인 비용함수를 나타낸 것입니다.

$$\begin{align}\tag{3}&\epsilon=\hat{y}-y \\&\begin{aligned}\text{cost}&=\frac{\sum^n_{i=1}(\epsilon)^2}{n}\\&=\frac{\epsilon^T \cdot \epsilon}{n} \end{aligned}\\ &\epsilon: \text{error} \end{align}$$

가중치의 수정을 위해 비용함수는 식 4와 같이 각 가중치들과 편차에 의해 미분됩니다.

$$\begin{align}\tag{4}\text{cost}&=\frac{\sum^n_{i=1}(\hat{y}-y)^2}{n}\\&=\frac{\sum^n_{i=1}(wx-b-y)^2}{n}\frac{d(cost)}{dw}\\&=\frac{\sum^n_{i=1}2(wx-b-y)x}{n}\frac{d(cost)}{db}\\&=\frac{\sum^n_{i=1}2(wx-b-y)}{n} \end{align}$$

식 4에서 비용함수의 미분 결과를 행렬연산으로 나타내면 식 5와 같습니다.

$$\begin{align}\tag{5}\frac{d(cost)}{dw}&=\frac{2(wx-b-y)x}{n}\\&=\left(2 \times \begin{bmatrix}\epsilon_1&\epsilon_2&\cdots&\epsilon_n\end{bmatrix} \cdot \begin{bmatrix}x_1\\x_2\\ \vdots\\x_n\end{bmatrix}\right)\frac{1}{n}\\\frac{d(cost)}{db}&=\frac{2(wx-b-y)}{n}\\&=\left(2 \times \begin{bmatrix}\epsilon_1&\epsilon_2&\cdots&\epsilon_n\end{bmatrix} \cdot \begin{bmatrix}1\\1\\\vdots\\1\end{bmatrix}\right)\frac{1}{n} \end{align}$$

식 5의 두 계산은 식 6과 같이 결합하여 나타낼 수 있습니다.

$$\begin{equation}\tag{6}d(cost)=\left(2 \times \begin{bmatrix}\epsilon_1&\epsilon_2&\cdots&\epsilon_n\end{bmatrix} \cdot \begin{bmatrix}x_1&1\\x_2&1\\\vdots&\vdots\\x_n&1\end{bmatrix}\right) \frac{1}{n}\end{equation}$$

식 6의 결과에 의한 각 가중치들과 편차의 개선 과정을 최적화(optimization)이라 하며 식 7과 같이 이루어집니다.

$$\begin{align}\tag{7}&w= w- \varUpsilon \frac{d(cost)}{dw} & \varUpsilon : \text{학습률(learning rate)} \end{align}$$

그림 5와 같이 최적화 과정은 각 가중치의 미분 결과에 의존됩니다. 즉, 그 결과가 크다면 최적화의 단계 간 간격이 증가하여 극소점을 발견할 확률이 매우 낮아집니다. 이를 방지하기 위해 최적화 단계의 간격(최적화 속도)을 조절할 필요가 있습니다. 그 조절인자를 학습률(learning rate, η)라고 합니다. 이러한 최적화 과정을 학습(train)과정이라하며 이 과정을 통해 회귀계수가 결정됩니다. 그러나 학습률은 학습과정의 시작과 함께 지정되는 변수입니다. 학습률과 같이 과정의 시작에 지정되는 변수를 초매개변수(hyper-parameter)라고 합니다.

예)
  단순한 예로 y=2x를 따르는 자료에 대해 경사하강법을 적용하여 회귀계수 2를 산출해 봅니다.

x0 1 2 3 4 5 6 7 8 9
y0 2 4 6 8 10 12 14 16 18

선형모델에 편차항을 첨가하기 위해 독립변수에 1로 이루어진 새로운 변수를 첨가해야 합니다.

x=np.arange(0, 10)
x1=np.c_[np.ones(10), x]
x1
array([[1., 0.],
           [1., 1.],
           [1., 2.],
           [1., 3.],
           [1., 4.],
           [1., 5.],
           [1., 6.],
           [1., 7.],
           [1., 8.],
           [1., 9.]])
y=np.array([2*i for i in x])
y
array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])

임의로 회귀계수와 편차의 초기값을 지정합니다.

np.random.seed(0)
param=np.random.rand(2,1)
param
array([[0.5488135 ],
           [0.71518937]])

최초로 생성한 모델에 의해 추정값을 계산합니다.

$$\begin{bmatrix}y_1\\y_2\\\vdots\\ y_n \end{bmatrix}=\begin{bmatrix}1&x_1\\1&x_2\\\vdots\\ 1&x_n \end{bmatrix}\begin{bmatrix}0.5488135\\0.71518937\end{bmatrix}$$
#추정값
pre=np.dot(x1, param)
pre
array([[0.5488135 ],
           [1.26400287],
           [1.97919224],
           [2.6943816 ],
           [3.40957097],
           [4.12476034],
           [4.8399497 ],
           [5.55513907],
           [6.27032843],
           [6.9855178 ]])
#오차
error=pre-y.reshape(-1,1)
error
array([[  0.5488135 ],
           [ -0.73599713],
           [ -2.02080776],
           [ -3.3056184 ],
           [ -4.59042903],
           [ -5.87523966],
           [ -7.1600503 ],
           [ -8.44486093],
           [ -9.72967157],
           [-11.0144822 ]])

위에서 산출한 오차를 기반으로 비용 즉, mse를 계산합니다.

cost=np.dot(error.T, error)/len(y)
cost
array([[41.00114681]])

$\displaystyle \frac{d(\text{cost})}{dw}$와 $\displaystyle\frac{d(\text{cost})}{db}$ 를 계산합니다.

grad=2*np.dot(error.T,x1)/len(error)
grad
array([[-10.46566869, -68.29488458]])

위의 미분된 값과 학습률을 고려하여 회귀계수와 편차를 업데이트 합니다.

param=param-0.01*grad.reshape(-1,1)
param
array([[0.65347019],
           [1.39813821]])

sklearn 패키지의 SGDRegressor()클래스는 위의 과정을 모두 수행합니다. 이 클래스에 의한 생성된 모델을 .fit(x, y) 메소드로 데이타에 적합시키고 결정계수는 .score(x, y) 메소드로 확인할 수 있습니다. 이 메소드에 전달되는 독립변수(x)는 2차원 numpy 배열객체, 반응변수(y)는 1차원 벡터이어야 합니다. 또한 회귀계수와 편차는 각각 .coef_, .intercept_ 속성으로 계산할 수 있습니다.

x
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
from sklearn.linear_model import SGDRegressor
x2=x.reshape(-1,1)
reg=SGDRegressor(max_iter=1000, tol=1e-3, learning_rate='constant', eta0=0.01)
reg1=reg.fit(x2, y)
print(f'scroe:{np.around(reg1.score(x2, y),4)}, coef:{np.around(reg1.coef_,4)}, intercept:{np.around(reg1.intercept_,4)}')
scroe:0.9996, coef:[1.9651], intercept:[0.2208]


 다음 금융자료로부터 1일전의 설명변수에의한 당일 kodex 반도체의 주가를 추정하기 위한 회귀모델을 구축해 봅니다.

설명변수 코스피지수(kos), 삼성전자(samE), sk하닉스(skny), ,kodex 반도체(ksemi)의 시가, 고가, 저가, 종가, 거래량의 1일간 변화율, 달러대 환율(kd)의 종가
반응변수kodex 반도체(ksemi)의 시가, 고가, 저가, 종가

다음 코드로 자료를 호출하고 각 자료의 Volume의 일간변화율을 DataFrame.pct_change() 메소드를 적용하여 계산합니다.

import FinanceDataReader as fdr
st=pd.Timestamp(2021,3, 1)
et=pd.Timestamp(2022, 3, 3)
nme={"kos":"KS11", 'sam':'005930', 'skny':'000660','ksemi':'091160'}  
nme2={'kd':"USD/KRW"}
daOri={ }
for i, j in zip(nme.keys(), nme.values()):
    x=fdr.DataReader(j,st, et)
    x2=x[["Open","High","Low","Close"]]
    x3=x["Volume"].pct_change()*100 #Volume의 일간변화율
    daOri[i]=pd.concat([x2, x3], axis=1)
    daOri[i].columns=[i+ k for k in daOri[i].columns] #열이름 수정
daOri['kos'].head(2) 
kosOpen kosHigh kosLow kosClose kosVolume
Date
2021-03-02 3021.68 3096.50 3020.74 3043.87 NaN
2021-03-03 3041.20 3083.04 3029.37 3082.99 28.0

환율자료의 경우 위에서 호출한 자료와 구성에서 차이가 있습니다. 그러므로 별도로 호출하여 위 사전(dictionary)개체 daOri에 결합합니다.

daOri['kd']=fdr.DataReader(nme2['kd'],st, et)["Close"]
daOri['kd'].head(2)
Date
    2021-03-01    1113.33
    2021-03-02    1125.01
    Name: Close, dtype: float64

pd.concat() 함수를 작용하여 위의 객체 daOri를 DataFrame으로 전환하고 자료에 포함되어 있는 결측치 NaN을 삭제하여 자료를 정제합니다.DataFrame.dropna() 메소드를 적용합니다.

da=pd.DataFrame()
for i in daOri.keys():
    da=pd.concat([da, daOri[i]], axis=1)
da=da.dropna()
da.head(2).iloc[:,:4]
kosOpen kosHigh kosLow kosClose
Date
2021-03-03 3041.20 3083.04 3029.37 3082.99
2021-03-04 3076.88 3076.88 3022.54 3043.49

설명변수는 반응변수보다 1일 앞선 값들이라는 기준으로 설명과 반응변수를 분리합니다. 반응변수는 'ksemiClose'입니다.

ind=da.iloc[:-1, :].values
de= da['ksemiClose'][1:].values
new=da.iloc[-1,:].values
de[:10]
array([35792., 35488., 34560., 34216., 33712., 34615., 35388., 35114.,
           36341., 36450.])

위에서 생성된 자료의 각 변수의 스케일(Scale)에 차이가 있으므로 표준화를 진행합니다. 최종 추정치 역시 표준화된 자료이므로 다시 원래의 스케일로 환원하기 위해서 표준화에 사용된 평균과 표준편차의 자료가 필요합니다. sklearn.preprocessing.StandardScaler() 클래스를 적용합니다.

from sklearn.preprocessing import StandardScaler
indScaler=StandardScaler().fit(ind)
deScaler=StandardScaler().fit(de.reshape(-1,1))
XNorm=indScaler.transform(ind)
yNorm=deScaler.transform(de.reshape(-1,1))
newNorm=indScaler.transform(new.reshape(1,-1))
newNorm
array([[-2.11123117, -2.11530059, -1.96686745, -1.96493631,  0.66249176,
            -1.29919369, -1.24298305, -1.15764714, -1.11639629,  0.06325032,
             0.58655059,  0.58900825,  0.67240477,  0.69696735, -0.02196599,
            -0.16329146, -0.1660803 ,  0.00832936,  0.00550933,  0.16539065,
             1.57722766]])

SGDregressor() 클래스를 적용하여 회귀모델을 구현하고 그 모델에 의한 최종 추정치를 계산합니다.

from sklearn.linear_model import SGDRegressor
reg=SGDRegressor(alpha=0.01, max_iter=10000,tol=1e-5, learning_rate='invscaling')
reg1=reg.fit(XNorm, yNorm.ravel())
print(f'score:{np.around(reg1.score(XNorm, yNorm.ravel()), 4)}\ncoef:{np.around(reg1.coef_, 4)}\nindent intercept:{np.around(reg1.intercept_, 4)}')
score:0.9219
    coef:[-0.0207  0.0131  0.0109  0.0398 -0.0283 -0.0919 -0.038  -0.0247  0.0221
     -0.0008 -0.006   0.026   0.0402  0.0577 -0.0296  0.1024  0.2254  0.2581
      0.3595  0.028  -0.0381]
    indent intercept:[0.]
pre=reg1.predict(newNorm)
pre1=deScaler.inverse_transform(pre.reshape(-1,1))
pre1
array([[36503.10866093]])

위 모델에 의한 오차가 정규분포에 부합여부를 판단하고 신뢰구간을 결정할 수 있습니다.

from scipy import stats
err=de.reshape(-1,1)-deScaler.inverse_transform(reg1.predict(XNorm).reshape(-1,1))
stat=stats.probplot(np.array(err).ravel(), plot=plt)[1]
print(f'회귀계수: {np.around(stat[0], 2)}, 편차: {np.around(stat[1], 2)}, 결정계수: {np.around(stat[2], 2)}')
회귀계수: 561.95, 편차: -0.08, 결정계수: 1.0

위 결과에 의하면 이 모델에 의해 생성된 오차는 정규성을 가지고 있으므로 t분포로 신뢰구간을 추정할 수 있습니다. 이 자료의 경우 전체 샘플 수는 260개 이상으로 t분포 대신 정규분포를 적용합니다. 유의수준 0.05에서 오차의 신뢰구간을 위에서 산출한 추정치에 적용하여 추정치의 신뢰구간을 계산합니다.

ci=stats.norm.interval(0.95, err.mean(), pd.DataFrame(err).sem(ddof=ind.shape[1]))
print(f'하한: {np.around(ci[0], 3)}, 상한 :{np.around(ci[1], 3)}')
 하한: [-72.608], 상한 :[72.439]
np.around(pd.DataFrame(np.r_[pre1+ci[0], pre1, pre1+ci[1]], index=['하한','평균', '상한']),0)
0
하한 36431.0
평균 36503.0
상한 36576.0

위 모델은 ksemiClose를 반응변수로 한 것입니다. 반응변수를 ksemi의 다른 변수들로 전환하기 위해서 위 과정 중 설명변수와 반응변수 분리 단계를 수정하고 나머지 과정은 동일하게 실행됩니다. 이를 위해 다음과 같이 코드를 변형시킬 수 있습니다.

score=[]
Pre=pd.DataFrame()
for i in ['ksemiOpen','ksemiHigh','ksemiLow','ksemiClose']:
    ind=da.iloc[:-1, :].values
    de= da[i][1:].values
    new=da.iloc[-1,:].values
    indScaler=StandardScaler().fit(ind)
    
    deScaler=StandardScaler().fit(de.reshape(-1,1))
    XNorm=indScaler.transform(ind)
    yNorm=deScaler.transform(de.reshape(-1,1))
    newNorm=indScaler.transform(new.reshape(1,-1))
    
    mod=SGDRegressor(alpha=0.01, max_iter=10000, tol=1e-5, 
    learning_rate='invscaling').fit(XNorm, yNorm.ravel())
    score.append(np.around(reg.score(XNorm, yNorm.ravel()), 3))
    pre=reg1.predict(newNorm)
    pre1=deScaler.inverse_transform(pre.reshape(-1,1))
    ci=stats.norm.interval(0.95, err.mean(), pd.DataFrame(err).sem(ddof=ind.shape[1]))
    re=pd.DataFrame(np.r_[pre1+ci[0], pre1, pre1+ci[1]], index=['하한','평균', '상한'])
    Pre=pd.concat([Pre, re], axis=1)
Pre=np.around(Pre, 0)
Pre.columns=['Open',"High",'Low',"Close"]
Pre
Open High Low Close
하한 36471.0 36768.0 36102.0 36431.0
평균 36543.0 36841.0 36174.0 36503.0
상한 36616.0 36914.0 36247.0 36576.0

댓글

이 블로그의 인기 게시물

matplotlib의 그래프 종류

1. 산포도(scatter plot) plt.scatter(x, y) >>> import matplotlib.pyplot as plt >>> import numpy as np >>> data=np.random.rand(1024, 2) >>> data[:3, :] >>> plt.scatter(data[:,0], data[:,1]) >>> plt.show() 2. 막대그래프(bar chart) plt.bar(x, hight, width, align='center') 매개변수중 width에 인수를 전달하여 막대의 두께를 조절할 수 있다. 또한 align의 인수는 'center'와 'edge' 이다. 기본값은 'center'이다. 이 값은 x축의 레이블이 막대의 중간에 위치(center) 또는 왼쪽 가장자리에 위치(edge)시킨다. 코드에서 np.random.randint 는 특정한 범위내에서 지정한 갯수의 랜덤수를 생성 np.unique(배열, retrun_counts=False, axis=None) : 객체 내의 중복되지 않은 수들을 반환한다. return_counts=True이면 각 수에 대한 빈도수를 반환한다. axis를 통해 행(1), 열(0)을 선택한다. >>> x=np.random.randint(1, 6, size=100) >>> uni,count=np.unique(x, return_counts=True) >>> uni array([1, 2, 3, 4, 5]) >>> count array([25, 17, 23, 16, 19], dtype=int64) >>> plt.bar(uni, count) >>> plt.show() 위의 막대그래프의 막대의

유사변환과 대각화

내용 유사변환 유사행렬의 특성 대각화(Diagonalization) 유사변환(Similarity transformation) 유사변환 n×n 차원의 정방 행렬 A, B 그리고 가역 행렬 P 사이에 식 1의 관계가 성립하면 행렬 A와 B는 유사하다고 하며 이 변환을 유사 변환 (similarity transformation)이라고 합니다. $$\begin{equation}\tag{1} A = PBP^{-1} \Leftrightarrow P^{-1}AP = B \end{equation}$$ 식 1의 유사 변환은 다음과 같이 고유값을 적용하여 특성 방정식 형태로 정리할 수 있습니다. $$\begin{align} B - \lambda I &= P^{-1}AP – \lambda P^{-1}P\\ &= P^{-1}(AP – \lambda P)\\ &= P^{-1}(A - \lambda I)P \end{align}$$ 위 식의 행렬식은 다음과 같이 정리됩니다. $$\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)\\ &= \t

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$$ 실수