안녕하세요 DA 라이언입니다. 

오늘은 가설 검증과 t-검정에 대해서 정리해보고자 합니다. 

우선 t- 검정에 대해서 정의를 살펴보면, 


t-검정은 정규분포를 따르는 하나 또는 두 모집단의 평균에 대한 가설 검정이다.

이렇게 나와 있습니다. 

즉 t-검정을 하는 이유는

내가 얻은 샘플들(예 100명의 키 데이터)의 평균이 모집단(전교생 600명)의 평균과 동일한가 ? 

를 알아보기 위해서 가설을 세우는데 기존적으로 가설을 세울때는 평균이 동일하다라고 가정을 해야 합니다.

그래서 H0 (귀무가설, 기본이되는 가설)=> 샘플100명의 평균 = 전교생의 평균 이다 라고 정해집니다.
귀무 가설을 세울 때 주의 해야하는것은 귀무가설은 내가 마음대로 설정하는 것은 아닙니다.
기본적으로 표본의 평균과 모집단의 평균이 같다 가 귀무가설이 된다. 하지만 때에 따라서는 귀무가설이 꼭 평균이 같다고 
설정되지 않을때도 있습니다. 그래서 사람들이 많이 헷갈리는데 헷갈리지 않게 아래와 같이 팁을 드리고자 합니다. 
귀무가설을 세울때 가장 생각해봐야 할것은 그 가설이 변화를 주지 않는 쪽으로 설정되어야 한다는 것입니다.

쉽게 설명해보면

  1. 고양이의 평균 수명은 20년이라고 알려져 있다 그러한지 알아보기 위해서는 귀무가설이  
         귀무가설 H0: 표본의 고양이 평균수명 = 20년 이다.
         대립가설 H1: 표본의 고양이 평균수명 ≠ 20년 이다. 
         이렇게 설정될수 있습니다. 즉 귀무가설은 평균 수명이 20년으로 설정해야 다시 평균을 찾는일 따위는 하지 않게 됩니다.
         여기서 표본이 독립표본이고, 정규분포를 따를경우
         전체 모집단을 대표하는 표본이라고 말할수 있습니다. 
        그래서 그 모집단을 대표하는 샘플 표본들이 20년정도 평균이 나온다면 우리는 과학적인 통계 근거에 의해
        "고양이의 평균 수명은 20년정도 라고 이야기 할수 있습니다."

  1. 다른 예제를 살펴보면,  피자업체에서 피자 배달 시간을 램덤하게 추출 데이터 100개를 분석하고,   
    경쟁업체의 광고 30분보다 적게 나온다 광고를 하고자 합니다. 그럴경우
    귀무가설 H0 : 우리회사 피자배달시간은 30분보다 적다. 
    대립가설 H1 : 우리회사는 피자 배달시간은 30분보다 같거나 크다  
    라고 설정할수 있고, 검정을 통해서 
    "우리 회사의 피자 배달시간은 D사보다 더 빠릅니다 " 라고 이야기해도 과학적인 이론에 기초하여 이야기했다고 할수 있습니다.

          
  1. 마지막으로  전교생이 600명인 학교에서 남학생 키와 여학생 키를 100명씩 측정해  평균이 각각 170cm 와 160cm가 나왔다고 가정해봅시다.
          이 평균의 차이가 진짜 600명의 키를 다 전수 조사해도 10cm정도 차이가 날것인지, 
          아니면 우연히 키가 남학생은 크고 여학생은 작은쪽만 조사해서 10cm정도 차이가 나는 것인지 
         평균의 차이가 이렇게 유의(의미가 있는것인지 )확인하기 하고 싶을때 가설 검증합니다. 그래서 가설 검증은 아래와 같이 할수 있습니다.
        귀무가설 H0 : 남학생 평균 키와 여학생 평균 키 차이가 없다
        대립가설 H1 : 남학생 평균 키와 여학생 평균 키 차이가 있다
        라고 설정할수 있고, 검정을 통해서 
        "100명만 조사했지만 전교생의 남학생의 평균 키는 여학생의 평균키와는 차이가 없다 "라고 증명하고 싶은 것이고, 
        이것을 좀더 유식하게 말해본다면 
        "100명만 조사했지만 전교생의 남학생의 평균 키는 여학생의 평균키보다  차이가 유의하지 않다(There is not statistical significance between two groups)
        라고 이야기 할수 있습니다. 


그럼 마지막으로 t-검정의 실제적 예시를 아래와 같이 설명해보겠습니다. 

아래는 남자 여자의 수능 점수의 차이에 대해서 확인해본 결과입니다.수능만점은 400점으로 가정합니다.

성별
표본의 수
평균점수
분산
비고
여자
50
305.25
9.81

남자
50
290.07
8.18


이런 경우 등분산 가정이 맞다고 하고 t검정을 실시하면 

method
t Value
Pr>t(p-value)
pooled
1.88
0.0321

이렇게 나왔다고 가정해봅시다. pooled 방법은 등분산 가정일경우 할수 있는 t-검정의 한 종류이며, 
t-value가 1.88 , p-value는 나왔다고 해봅시다. 
여기서 귀무가설은 H0 : 여자 평균점수은 남자 평균점수 차이가 없다 
           대립가설은 H1 : 여자 평균점수은 남자 평균점수 차이가 있다.

이것을 그림으로 그리면,  아래와 같이 나오고 , 이것은  t-검정을 한결과 p-value가 0.0321이 나왔으므로,
보통 0.05기준으로 작게 나오면 일어날 확률이 너무 작아서
신뢰구간 95% 내에서 우리는 귀무가설 H0가 성립됨을 증명되지 못한 것이고 
이걸 좀 어렵게 말하싶으시면 귀무가설을 기각한다 라고 이야기 하면 됩니다. 

따라서 우리는 이러한 검증을 거쳐서 
여자 평균점수는 남자 평균점수와 유의미한 차이가 있다고 할수 있다고 할수 있습니다.

즉 전체를 검증하지 않아도 무작위로 뽑은 50명만 검증해도 전교생의 수능 성적을 비교할수 있고, 
그 무작위로 뽑은 값에서 남녀가 차이가 나는데 이것은 다시 실험을 해도 비슷하게 나올 확률이 95%이므로 
서로 남녀 점수가 차이나는 건 의미가 있는 결과다 라고 이야기 할수 있는 것입니다. 

오늘은 가설 검증과 t -검증에 대해서 이야기 해보았습니다. 

어려운 이야기를 좀 쉽게 설명하기 위해서 노력해봤는데 그래도 어렵네요. 
잘 보시고 이해하시면 감사드리겠습니다.



안녕하세요. DA ryan 입니다. 

데이터 분석에 대한 식견을 가지려면 타인이 분석한 것도 잘 파악해볼 필요가 있습니다. 
그래서 kaggle에 open data set을 가지고 분석한 결과물들중에 괜찮은 것을 함께 알아보려고 합니다 

그래서 처음에 고른 데이터는 멜번 부동산 데이터입니다. 
멜번도 집값이 어마어마하긴 마찬가지인데 데이터를 올린 사람이 아래와 같은 사항이 궁금하다고 합니다.

메인 명제
  1. 멜번에 부동산 가격 트렌드를 파악 혹은 예측 할수 있는가?
  2. 어떤 지역을 사는것이 가장 좋은 선택이 되는것인가?
  3. 어떤 부동산이 가장 가치가 있는 부동산인가?
  4. 어디가 상대적으로 비싼지역이고 어디가 싼 지역인가?
  5. 내가 방2개가 딸린 조건의 집을 사야만 하는가?

위의 명제들에 대한 해답을 가지기 위해서 데이터 제공자는 Domain.com.au 에서 데이터공개된 내용을 다운받아 클린징을 하고 최고의
데이터 셋을 만들기 위해서 노력했다고 합니다. 

데이터셋을 클린징 했다는 이야기는 결손값 (즉 데이터 내용이 없는 것들)을 제거하고 그리고 outliner(즉 이상치, 특이하게 평균보다 멀어서 평균을 높으거니 낮추는 것이라고 생각하시면 됩니다. 트랜드를 파악하기 위해서는 단순히 모든 데이터를 다 집어 넣고 분석하는 것도 좋을수 있지만, 주로 잘 일어나지 않을 것같은 이상치값은 빼고 분석하는게 좀더 정확하게 파악될수 있습니다. 마치 각 반의 학생들의 키를 확인할 때 최홍만 선수가 끼어 있으면 평균이 확올라가므로 최홍만 선수의 키값은 빼고 계산하면 어느정도 그 반의 키  평균이 정확히 파악되는 것과 같은 문제가 됩니다. 

이렇게 데이터 클린징 작업이 끝났으면 각 데이터의 열을 파악하는 것이 중요합니다. 
즉 데이터 내의 종류를 파악해서 각각의 데이터 종류를 파악하는 것이 좋습니다. 

그래서 열을 확인해보면 

Suburb: 도시 외곽지역 이름 
Address: 주소
Rooms: 방의 갯수
Price: 호주 달러 가격

여기서 잠깐 호주 부동산 거래방법에 대한 알아볼 필요가 있습니다. 호주에서는 크게 우리가 하는 계약, 그리고 경매를 통해 부동산을 넘기는 경우가 있습니다. 부동산 경매는 우리나라에서는 부동산을 가진 사람이 보통 망한 경우에만 사용하는 경우가 빈번한데, 호주에서는 특별히 망하지 않고 보통 특정시기에는 꼭 팔아야 겠다 하고 생각되면 바로 경매에 넣는다고 합니다. 

Method: S - property sold(부동산 판매완료)
            SP - property sold prior(부동산 경매전 판매완료)
            PI - property passed in(부동산 경매 유찰됨 즉 경매에 내놓았는데 팔리지 않음)
            PN - sold prior not disclosed(경매 이전 비공개 판매완료)
            SN - sold not disclosed(비공개 판매완료)
            NB - no bid(팔리지 않으나 경매에 내놓지 않음, 역자추정)
            VB - vendor bid(경매관리인 경매 후 판매)
            W - withdrawn prior to auction(경매중 팔림)
            SA - sold after auction(경매 후 팔림)
            SS - sold after auction price not disclosed. (경매후 비공개판매)
            N/A - price or highest bid not available.

Type: br - bedroom(s) 침실만 렌트
          h - house,cottage,villa, semi,terrace(집 구매)
          u - unit, duplex(복층 구조)
          t - townhouse(타운하우스)
         dev site - development site(개발 지역, 데이터샘플내 없음)
         res - other residential(기타 )

SellerG: Real Estate Agent(부동산 중계인 이름)
Date: Date sold(거래된 날짜)
Distance: Distance from CBD( C.B.D.)(시내로 부터 떨어진 거리)



import pandas as pd
import numpy as np
%matplotlib inline
import seaborn as sns
import matplotlib.pyplot as plt
dataframe =  pd.read_csv("Melbourne_housing_extra_data.csv")
dataframe.head()  ##<-데이터 확인

dataframe["Date"] = pd.to_datetime(dataframe["Date"],dayfirst=True)
## 글자형태의 날짜 데이터를 날짜 데이터로 바꿈 , dayfirst는 영국 및 유럽국가의 중 날짜 먼저쓰는 방식인지 물어보는 것에 true를 적어준것)

len(dataframe["Date"].unique())/4
##len은 리스트 사이즈 구함, .unique() 중복 방지를 의미 . 중복되지 않은 날짜 갯수를 구하고 4로 나눔

var = dataframe[dataframe["Type"]=="h"].sort_values("Date", ascending=False).groupby("Date").std()
var
##데이터 중에 Type이 h 즉 보통 하우스 만 간추려서, Date기준으로 내림차순하여 표준편차를 구하고 그것을 화면에 출력


위와같은 화면이 나옵니다. 

count = dataframe[dataframe["Type"]=="h"].sort_values("Date", ascending=False).groupby("Date").count()
mean = dataframe[dataframe["Type"]=="h"].sort_values("Date", ascending=False).groupby("Date").mean()
#같은 형태로 날짜기준으로 수량, 평균을 구하였습니다.

mean["Price"].plot(yerr=var["Price"],ylim=(400000,1500000))
#가격의 평균값을 날짜별로 그리고, 표준편차를 그림에 표현하여 봤습니다. 




mean["Price"].plot(ylim=(1000000,1500000))
#이번에는 표준편차를 빼고 평균 가격만 날짜별로 정렬하였습니다.


이표를 보았을때는 근교지역이라도 평균 거래 금액이 1년동안 증가되는 추세가 보입니다. 
그리고 특히 2월 8월이 비수기에 속하고 연말이 성수기에 속한다고 할수도 있을 것이라 봅니다. 
하지만 5년정도의 가격 트랜드를 보아야 더 정확하게 이야기 할수 있을것 같습니다. 
이것은 그냥 1년단위므로 일단 그런정도라고 생각하면 될 듯합니다.

means = dataframe[(dataframe["Type"]=="h") & (dataframe["Distance"]<13)].dropna().sort_values("Date", ascending=False).groupby("Date").mean()
#이것은 집 형태가 h이고 시내와 거리가 13키로 이내이며, 결손값은 버린값들만 평균을 내보겠습니다.

errors = dataframe[(dataframe["Type"]=="h") & (dataframe["Distance"]<13)].dropna().sort_values("Date", ascending=False).groupby("Date").std()
#이것은 집 형태가 h이고 시내와 거리가 13키로 이내이며, 결손값은 버린값들만 표준편차을 내보겠습니다.


means["Price"].plot(yerr=errors["Price"])
# 집 형태가 h이고 시내와 거리가 13키로 이내인 집들을 날짜 기준으로 가격평균, 그리고 가격 표준편차를 그래프로 그려보았습니다.


이표를 보면 시내에서 13키로 이내인 집들의 거래 가격이 점점 높아져가고 있다고 보입니다.

pd.set_eng_float_format(accuracy=1, use_eng_prefix=True)
dataframe[(dataframe["Type"]=="h") &
          (dataframe["Distance"]<14) &
          (dataframe["Distance"]>13.7)
          #&(dataframe["Suburb"] =="Northcote")
         ].sort_values("Date", ascending=False).dropna().groupby(["Suburb","SellerG"]).mean()
# 이번에는 지역별, 부동산 중개인별 , 13.7키로 초과 14키로 미만 인 거리의 집들 가격만 평균을 내봤습니다. 다음과 같습니다.





sns.kdeplot(dataframe[(dataframe["Suburb"]=="Northcote")
         & (dataframe["Type"]=="u")
         & (dataframe["Rooms"] == 2)]["Price"])
#kdeplot은 도수분포도를 볼수 있는 그래프를 그려줍니다. 
#따라서 위의 명령어로는 지역이 Northcote이고, 집 타입이 복층형인 방2개인 집의 가격 도수분포도를 볼수 있게 됩니다.


위의 표를 보았을때 가장 많이 일어나는 가격은 60000 호주달러이고 그 기준에 따라서 표준정규 분포를 비슷하게 따른다는 것을 볼수 있게 됩니다.

sns.kdeplot(dataframe["Price"][((dataframe["Type"]=="u") &
                                (dataframe["Distance"]>3) &
                                (dataframe["Distance"]<10) &
                                (dataframe["Rooms"] > 2)#&
                                #(dataframe["Price"] < 1000000)
                               )])
#이번에는 3키로 초과 10키로 미만인 방3개이상인 집들 중 100만 호주 달러 미만의 집들의 가격분포도를 그려봅니다.

3키로 초과 10키로 미만인 방3개이상인 집들 중 100만 호주 달러 미만의 집들의 가격분포도를 보면
평균가격은  7만호주달러가 있고 그 이상으로 거래 했을 경우에는 비싸다 , 그 이하로 거래했을 경우에는 저렴하다고 이야기 할수 
있을것 같습니다. 


sns.lmplot("Distance","Price",dataframe[(dataframe["Rooms"]<=4) &
                                         (dataframe["Rooms"]> 2) &
                                        (dataframe["Type"]=="h") &
                                        (dataframe["Price"]< 1000000)
                                       ].dropna(),hue="Rooms", size=6)

#lmplot은 산포도에 직선을 그어서 추세선을 확인할수 있게 만들어 줍니다. 
#위의 코드는 보통의 집 타입에서, 가격이 100만호주달러 미만이고,
#방의 숫자가 3개와, 4개인 데이터의 가격과 거리 기준으로 산포도를 그린후에 추세선을 그려보아라는 명령어입니다.


위의 그래프는 보통의 집 타입에서, 가격이 100만호주달러 미만이고,
방의 숫자가 3개와, 4개인 데이터의 가격과 거리 기준으로 산포도를 그린후에 추세선을 그린 것입니다.

거리가 멀수록 가격이 싸지는 것은 당연한 이치이고
시내랑 가까울경우에는 방이 3개든 4개든 큰차이가 없음을 시사해줍니다.
따라서 시내 가까운곳일수록 긑은 예산으로 4개의 방을 구해봄도 괜찮을 듯 합니다.



데이터,코드 출처 사이트 :


안녕하세요.

오늘은 선형회귀 및 polynomial Regression을 이해하고 행렬을 프로그램으로 변환하는 방법에 대해서 이해해보도록 해보겠습니다.
특히 모델링이라는 말의 의미를 이 포스팅을 보시고 이해해주시면 감사하겠습니다.

이해가 안가실 것같으니 아래와 같이 python으로 그래프를 그리면서 이야기를 해보면 쉽게 이해하실수 있습니다. 


%matplotlib inline
#문서내에 그래프 출력

import numpy as np
import pylab as pl


def f(size):
    '''
    사인곡선을 적용하여 원데이터를 발생
    Returns a sample with 'size' instances without noise.
    '''
    x = np.linspace(0, 4.5, size)
    y = 2 * np.sin(x * 1.5)
    return (x,y)

def sample(size):
    '''
    원데이터에 random함수를 적용해서 사인곡선을 적용하고
    여기에 노이즈를 추가로 더하여 size수량만큼 무작위로 뽑는 함수를 만듬
    Returns a sample with 'size' instances.
    '''
    x = np.linspace(0, 4.5, size)
    y = 2 * np.sin(x * 1.5) + pl.randn(x.size)
    return (x,y)

pl.clf()
f_x, f_y = f(50)
pl.plot(f_x, f_y)
x, y = sample(50)
pl.plot(x, y, 'k.')



위와같이 파란색으로  Sin곡선을 만들어봅니다. 가로는 0~4.5, 세로는 플러스 마이너스 2 범위내에서 한 주기가 되는 sin곡선을 만들었습니다.
여기에 50개의 샘플링을 한 점을 위와같이 무작위로 찍어봅니다.
이때 이 점은 원래는 파란색 선을 따라서 나와야 하지만 error 가 각각의 점마다 더하고 빼져서 파란색선을 따르지만 거리의 편차가 있는 점을 만들었다고 생각하시면 됩니다.

이러한 곡선은 현실세계에서는 존재하지 않지만 그래도 억지로 인위적으로 만들어 본다면,
계절마다 에어콘 가격 트랜드라고 예를 들어볼수 있습니다. 즉 파란선은 에어콘 가격의 절대적인 트랜트 이며,
실제 가격은 이 트랜드를 따른다고 생각하시면 됩니다.

X가 1일때 여름이라고 가정하고 그때가 가장 높게 가격이 책정되어 팔린다고 생각하시고,
X가 3일때 겨울이라고 생각하시고 그때가 가장 낮게 가격이 책정되어 팔린다고 생각하시면 됩니다.

하지만 이 절대적인 트랜드를 각 판매처에서 따른다고 하더라도, 실제 판매처에서는 이윤을 더 붙이든 , 아니면 낮게 붙일수 있습니다.
이렇게 절대적인 트랜드 보다 높거나 낮은 실제 가격에는 각각의 가격마다 error가 들어갔다고 보시면 됩니다.


pl.clf()
x, y = sample(50)
pl.plot(x, y, 'k.')



그래서 지금부터 설명하고자 하는 variance와 bias는 위와같이 각각의 판매처가 임의로 정한 가격들(검은색점)을 보고
에어콘의 가격트랜드(위에 사라진 파란색 선)를 파악하고자 할때 고민해야하는 상황으로 가정하고, 설명하도록 하겠습니다.

그렇습니다. 위의 데이터들만 보았을때는 X축은 오른쪽으로 갈수록 시간이 지나간다고 가정하고,
Y축은 기준 가격으로부터 상대적 차이를 표현한다고 가정하더라도,
어떠한 패턴을 나타내는지 눈으로 아니면 직감적으로 파악한다는 것은 어려운 일이 아닐수가 없습니다.

패턴을 파악한다는 것은 각각의 데이터를 보고 거리에 대해서 평균을 내서 그 데이터들을 대표하는 하나의 선으로 표현하는 것을 의미하는데,
여기서 선은 직선이 될수 있고 곡선이 될수도 있습니다. 


from sklearn.linear_model import LinearRegression

def fit_polynomial(x, y, degree):
    '''
    Fits a polynomial to the input sample.
    (x,y): input sample
    degree: polynomial degree
    '''
    model = LinearRegression()
    model.fit(np.vander(x, degree + 1), y)
    return model

def apply_polynomial(model, x):
    '''
    Evaluates a linear regression model in an input sample
    model: linear regression model
    x: input sample
    '''
    degree = model.coef_.size - 1
    y = model.predict(np.vander(x, degree + 1))
    return y

model = fit_polynomial(x, y, 1)
p_y = apply_polynomial(model, x)

pl.plot(x, y, 'k.')
pl.plot(x, p_y,'g')


직선이 된다면 위와같이 그릴수 있습니다. 
위와같이 직선으로만 트랜드선을 긋는것을 1차 선형 회귀라고 합니다. 

여기서는 데이터 트랜드가 직선임을 가정하고 모델을 Y=AX+B라고 지정한후에 

원 데이터들의 각 X를 입력했을때 나오는 Y의 값과 원 데이터 값의 차이를 평균을 내서 A와 B를 정한후

가장 공평한 선을 위와 같이 긋고 ,
이것이 데이터들의 패턴을 대표한다고 이야기 할수 있습니다.

하지만 눈으로 보아도 알수 있듯이 직선은 원 데이터가 가지고 있는 패턴을 너무나 많이 생략하여서
저 선만으로 판단할경우에는 시간이 갈수록 가격은 떨어져간다고 파악하게 됩니다.

하지만 원래 의도한 가격 그래프는 sin데이터 이므로 시간에 따라 가격이 떨어지는 것을 표현한 것이 아니라 
계절에 따라 가격은 변화하지 가격이 떨어짐을 표현한 것은 아닙니다. 

따라서 직선으로만 데이터의 패턴을 파악하면, 간단하여서 좋긴 하지만, 자칫 데이터의 가지고 있는 실제 패턴을 
오해해서 이해할수 있습니다.
'
그렇다면 좀 더 구체적인 선형 회귀를 하기 위해서는 데이터의 트랜드를 직선이 아닌 곡선이라고 가정할 필요가 있습니다.
즉 1차식이 아닌 다항식이라고 규정하고 선을 그어보는 것입니다.


그전에 필수적으로 알아야 할  파이썬의  함수 np.vander로 예제를 먼저 알아보도록 하겠습니다. 

np는 numpy의 줄임말로 
윗부분에서 import numpy as np 라고 줄임말을 지정해서 np라고 사용할수 있습니다. 
import numpy as num 이라고 하면 , 우리는 num.vander라고 사용해야합니다.
우선 예제를 보도록 하겠습니다.


# This illustrates how vander function works:
x = np.array([1,2,3])
print np.vander(x, 4)

결과 : 
[[ 1 1 1 1]
 [ 8 4 2 1]
 [27 9 3 1]]

x=np.array([1,2,3])은 x1을 가로 행렬 [1,2,3]을 제작한 것이고 , 

np.vander(x, 4)는 실제로는 아래와 같이 4개의 다항식을 만들어서 x를 차례대로 입력하라는 지시를 내린 것입니다.


즉 첫번째로 x^0(X의 영 승)은 1이고 , 이것을 처음 만들고

두번째로 x^1은  두번째 만들고 기존의 1은 오른쪽으로 이동시킵니다. 

세번째 x^2은 세번째 만들고 기존 결과를 오른쪽으로 이동시키고 왼쪽에 x^2를 위치시킵니다. 

네번째 x^3은 네번째 만들고 기존 결과는 오른쪽 이동, 왼쪽에 배치 시킵니다.

그리서 아래와 같은 행렬을 만들게 되고 


결과적으로 아래와 같은 결과를 만들게되었습니다.

결과 : 
[[ 1 1 1 1]
 [ 8 4 2 1]
 [27 9 3 1]]

이것은 머신러닝이나 수치해석을 할때 굉장히 중요한 개념입니다. 

즉 여러가지 다항식을 행렬로 계산하면 계산이 깔끔할뿐만 아니라 시간도 적게 걸리는 경우가 많습니다. 

행렬로 구하지 않을 경우 for문으로 1부터 N까지 x가 변할때마다 x의 값을 세제곱, 네제곱 하는 등의 계산을 해야하는데,
이것은 프로그래밍에서 굉장히 비효율적으로 바라보는 경향이 많습니다 

따라서 데이터를 분석할때는 다항식의 계산을 행렬로 변환하여 기억하고 프로그램까지 작성할수 있다면 잘하고 있다고 스스로를 칭찬하셔도 됩니다.

다시 데이터 포인트가 4개 즉 


 일경우 다항식의 계산은 아래와같이  표현할수 있습니다. 


 

.여기서 n은 몇차 다항식 지정할 것인가 의 질문에 차수에 해당되는 숫자입니다.
즉 ,  n=2면 2차 다항식, n=3이면 3차 다항식으로 표현하여 선을 그어 볼수 있겠지요.


그럼 polynomial 다항식을 사용하는 방법을 아래와 같이 작성예제를 확인해봅니다.

# polynomial 다항식을 정의하는 함수를 작성합니다.

def fit_polynomial(x, y, degree):
    model = LinearRegression()
    model.fit(np.vander(x, degree + 1), y)
    return model

좀 상세하게 본다면 아래는 사용자가 직접 함수를 만들때 쓰는 명령어입니다. 

def fit_polynomial(x, y, degree):

def는 definition의 줄임말이고 fit_polynmial은 사용자가 지정한 함수 명입니다.
(x,y,degree)는 함수를 사용할때 필히 입력해야하는 변수를 지정해놓았습니다.

    model = LinearRegression()


위의 명령어는 model이라는 사용자 정의명에 LinearRegression()의 함수를 지정하였습니다. 
LinearRegression()은 sklearn 라는 라이브러리에 저장되어 있고

from sklearn.linear_model import LinearRegression

라고 초반에 작성하여 라이브러리를 불러냈다면 이후 사용은 언제든지 저렇게 간단하게 사용할수 있습니다.

    model.fit(np.vander(x, degree + 1), y)

마찬가지로 LinearRegression함수 안에 fit이라는 메서드 를 이미 지정되어있기 때문에 그냥 가져다 쓰기만 하면됩니다.
여기서 np.vander(x, degree + 1) 은 지정된 X를 1부터 시작해서 X의 N승까지 행렬로 표현해서 입력한 것입니다.

  return model

그리고 사용자가 지정한 모델을 반환하시면 향후 fit_polynomial(x, y, degree) 명령어만으로도 x와 y의 데이터 포인트 그리고 degree만 입력하면 

python이 알아서 polynomial regression으로 모델링을 해줍니다. 

여기서 모델링을 한다는 것은 다항식의 각각의 계수를 지정해준다는 말로 아래의 B 베타값을 계산하여 정한다는 이야기라고 생각하시면 됩니다.


def apply_polynomial(model, x):
     degree = model.coef_.size - 1
    y = model.predict(np.vander(x, degree + 1))
    return y

위의 함수는 모델링된 함수를 그래프로 그리기 편하게
X가 입력되면 모델에 의해서 
Y의 값이 자동적으로 출력되도록 함수를 작성하였습니다.

그래서 아래와 같이 8차 다항식의 모델을 만든후에 모델링후 
각각의 x값을 적용해준다면 아래와같이 모델링된 데이터패턴을 확인할수 있습니다.

model = fit_polynomial(x, y, 8)
p_y = apply_polynomial(model, x)
pl.plot(x, y, 'k.')
pl.plot(x, p_y,'g')



위와 같이 각각의 데이터를 이용해서 8차 다항식의 선형회귀 모델을 모델링 하였습니다.

여기서는 기존의 원 트랜드와 같이 sin 곡선과 유사한 패턴을 그려서 먼저번의 직선보다 좀더 정확한 데이터 패턴을 구했다고 생각하시면 됩니다.

그럼 여기까지 하고 추가적으로 다음시간에는 좀 더 자세히 분산과 bias에 대해서 알아보도록 하겠습니다.
감사합니다.

참조 사이트



+ Recent posts