본문 바로가기
혼자 공부하는 데이터 분석

7장 검증하고 예측하기

by chaechaekim 2023. 6. 11.

07-1 통계적으로 추론하기

 

모수검정이란

: 모집단에 대한 파라미터를 추정하는 방법

*파라미터: 평균, 분산 *모집단: 관심 대상이 되는 전체 데이터

*표본: 모집단에서 선택한 일부 샘플

 

표준점수 구하기

*표준점수(z 점수): 데이터가 정규분포를 따른다고 가정하고, 각 값이 평균에서 얼마나 떨어져 있는지 표준편차를 사용해 변환한 점수

*z 점수: 평균까지 거릴르 표준편차로 나눈 것

 

  • z 점수 구하기

넘파이로 먼저 표준편차와 평균 계산

import numpy as np

x = [0, 3, 5, 7, 10]

s = np.std(x) //표준편차
m = np.mean(x) //평균
z = (7 - m) / s
print(z)

 

사이파이의 stats 모듈을 임포트한 다음 zscore() 함수를 호출하여 배열 x에 대한 모든 z 점수 계산 가능

from scipy import stats

stats.zscore(x)

 

  • 누적분포 이해하기

 표준정규분포: 평균이 0이고 표준편차가 1인 정규분포

*z 점수를 사용해 전체 데이터가 어떻게 분포되어 있는지 나타낼 수 있다.

 

  • 누적분포 구하기

norm.cdf() 메서드에 평균 0을 전달하여 0까지의 비율 구하기

stats.norm.cdf(0)

*norm.cdf() 메서드: 누적된 분포 반환

 

z 점수 1 이내의 비율을 구하려면 z 점수 1까지 누적분포에서 z 점수 -1까지 누적분포를 뺀다.

stats.norm.cdf(1.0) - stats.norm.cdf(-1.0)

 

표준편차 2 이내의 비율

stats.norm.cdf(2.0) - stats.norm.cdf(-2.0)

 

90% 누적분포에 해당하는 z 점수 구하기

stats.norm.ppf(0.9)

*norm.ppf() 메서드: 전체에서 특정 비율에 해당하는 z 점수 구할 수 있다.

 

중심극한정리 알아보기

: 무작위로 샘플을 뽑아 만든 표본의 평균은 정규분포에 가깝다

 

ns_book7.csv 파일을 구글 드라이브에서 다운로드하여 판다스 데이터프레임으로 불러오기

import gdown

gdown.download('https://bit.ly/3pK7iuu', 'ns_book7.csv', quiet=False)

import pandas as pd

ns_book7 = pd.read_csv('ns_book7.csv', low_memory=False)
ns_book7.head()

 

ns_book7 데이터프레임의 '대출건수'열로 히스토그램 그리기

import matplotlib.pyplot as plt

plt.hist(ns_book7['대출건수'], bins=50)
plt.yscale('log')
plt.show()

 

  • 샘플링하기

무작위로 1,000개의 표본을 샘플링하여 각 평균을 리스트로 저장

np.random.seed(42)
sample_means = []
for _ in range(1000):
    m = ns_book7['대출건수'].sample(30).mean()
    sample_means.append(m)

*sample() 메서드 첫 번째 매개변수에는 샘플링할 개수 지정 → mean() 메서드 호출하여 샘플링 결과의 평균 계산 → 평균 sample_means 리스트에 추가 → for 문으로 1,000번 반복

 

sample_means 히스토그램 살펴보기

plt.hist(sample_means, bins=30)
plt.show()

 

  • 샘플링 크기와 정확도

sample_means 배열의 평균 확인

np.mean(sample_means) //무작위로 뽑은 표본의 통계량

 

ns_book7 데이터프레임에 있는 전체 대출건수의 평균 확인

ns_book7['대출건수'].mean() //실제 모집단의 통계량

 

샘플링 크기 20으로 낮추어 평균 계산

np.random.seed(42)
sample_means = []
for _ in range(1000):
    m = ns_book7['대출건수'].sample(20).mean()
    sample_means.append(m)
np.mean(sample_means)

*일반적으로 중심극한정리를 따르려면 샘플링의 크기가 30보다 클수록 좋다.

*30은 일종의 매직넘버 → 정규분포가 아니더라도 표본 크기가 30보다 크면 정규분포에 가까워지기 때문

 

샘플링 크기를 40으로 높여서 평균 구하기

np.random.seed(42)
sample_means = []
for _ in range(1000):
    m = ns_book7['대출건수'].sample(40).mean()
    sample_means.append(m)
np.mean(sample_means)

 

넘파이 std() 함수로 sample_means의 표준편차 구하기

np.std(sample_means)

 

전체 대출건수의 표준편차를 샘플링 개수 40의 제곱근으로 나누기

np.std(ns_book7['대출건수']) / np.sqrt(40)

→ 이렇게 구한 표본평균의 오차: 표준오차

 

모집단의 평균 범위 추정하기: 신뢰구간

*신뢰구간: 표본의 파라미터(여기에서는 평균)가 속할 것이라고 믿는 모집단의 파라미터 범위

 

주제분류번호가 '00'으로 시작하고 도서명에 '파이썬'이 포함된 행을 불리언 배열로 인덱스 python_books_index를 만들어 도서 추출

python_books_index = ns_book7['주제분류번호'].str.startswith('00') & \
                     ns_book7['도서명'].str.contains('파이썬')
python_books = ns_book7[python_books_index]
python_books.head()

 

len() 함수를 사용해 도서가 몇 권인지 확인

len(python_books)

 

파이썬 도서의 대출건수 평균 계산

python_mean = np.mean(python_books['대출건수'])
python_mean

 

남산도서관의 파이썬 도서 대출건수로 표준편차 구한 다음, 표준오차 계산

python_std = np.std(python_books['대출건수'])
python_se = python_std / np.sqrt(len(python_books))
python_se

 

95% 비율에 해당하는 z 점수를 알기 위해 norm.ppf() 메서드에 각각 0.975와 0.025 입력

stats.norm.ppf(0.975)

stats.norm.ppf(0.025)

*정규분포는 대칭이기 때문에 두 z 점수가 부호만 다르고 같다.

 

표준오차 python_se와 z 점수를 곱하여 파이썬 도서 대출건수 평균인  python_mean 데이터프레임이 속할 범위 구하기

print(python_mean-1.96*python_se, python_mean+1.96*python_se)

 

통계적 의미 확인하기: 가설검정

*가설검정: 표본에 대한 정보를 사용해 모집단의 파라미터에 대한 가정을 검정하는 것

예) 파이썬과 C++ 도서의 평균 대출건수가 같다고 가정했을 때, 파이썬과 C++ 도서의 표본을 각각  추출하여 이 가정이 맞는지 검정

영가설(귀무가설): 파이썬과 C++ 도서의 평균 대출건수가 같다.

대립가설: 파이썬과 C++ 도서의 평균 대출건수가 같지 않다.

 

*영가설: 표본 사이에 통계적으로 의미가 없다고 예상되는 가설

*대립가설: 표본 사이에 통계적인 차이가 있다는 가설

 

  • z 점수로 가설 검증하기

C++ 도서에 대한 불리언 배열의 인덱스를 만들어 cplus_books 데이터프레임 만들기

cplus_books_index = ns_book7['주제분류번호'].str.startswith('00') & \
                    ns_book7['도서명'].str.contains('C++', regex=False)
cplus_books = ns_book7[cplus_books_index]
cplus_books.head()

 

C++ 도서권수 확인

len(cplus_books)

 

C++ 평균 대출건수 확인

cplus_mean = np.mean(cplus_books['대출건수'])
cplus_mean

 

C++ 도서에 대한 표준오차 계산

cplus_se = np.std(cplus_books['대출건수'])/ np.sqrt(len(cplus_books))
cplus_se

 

가설검정 공식에 대입해서 계산

(python_mean - cplus_mean) / np.sqrt(python_se**2 + cplus_se**2)

 

계산된 z 점수를 사용해 누적분포 확인

stats.norm.cdf(2.50)

 

  • t-검정으로 가설 검증하기

*ttest_ind() 함수: t-분포인 두 표본을 비교하는 t-검정 수행

*t-분포: 정규분포와 비슷하지만, 중앙은 조금 더 낮고 꼬리가 더 두꺼운 분포

*표본의 크기가 30이하일 때 t-분포를 사용하는 것이 좋다.

*표본의 크기가 30보다 크면 t-분포는 정규분포와 매우 비슷해진다.

 

파이썬 도서와 C++ 도서의 데이터를 ttest_ind() 함수에 전달하면 t 점수와 p-값 반환

t, pvalue = stats.ttest_ind(python_books['대출건수'], cplus_books['대출건수'])
print(t, pvalue)

 

정규분포가 아닐 때 가설 검증하기: 순열검정

*순열검정: 모집단의 분포가 정규분포를 따르지 않거나 모집단의 분포를 알 수 없을 때 사용할 수 있는 방법

*모집단의 파라미터를 추정하지 않기 때문에 비모수검정 방법 중 하나이다.

*순열검정 방법

두 표본의 평균의 차이를 계산한 후 두 표본을 섞고 무작위로 두 그룹으로 나눈다. (이 때 두 그룹은 원래 표본의 크기와 동일하게 만든다.)

→ 나눈 두 그룹에서 다시 평균의 차이 계산

→ 이런 과정을 여러 번 반복해서 원래 표본의 평균 차이가 무작위로 나눈 그룹의 평균 차이보다 크거나 작은 경우를 헤아려 p-값 계산

 

  • 도서 대출건수 평균 비교하기(1): 파이썬 vs C++

두 개의 배열을 받아 평균을 구하는 statistic() 함수 만들기

def statistic(x, y):
    return np.mean(x) - np.mean(y)

 

순열검정 실행하는 permutatuion_test() 함수 구현

*permutatuion() 함수: 두 배열을 넘파이 append() 함수로 합친 후 무작위로 추출

→ 인덱스로 x_, y_ 두 그룹을 나눈 후 그룹 사이의 평균 차이 계산 → 1,000번 수행

def permutation_test(x, y):
    # 표본의 평균 차이를 계산합니다.
    obs_diff = statistic(x, y)
    # 두 표본을 합칩니다.
    all = np.append(x, y)
    diffs = []
    np.random.seed(42)
    # 순열 검정을 1000번 반복합니다.
    for _ in range(1000):
        # 전체 인덱스를 섞습니다.
        idx = np.random.permutation(len(all))
        # 랜덤하게 두 그룹으로 나눈 다음 평균 차이를 계산합니다.
        x_ = all[idx[:len(x)]]
        y_ = all[idx[len(x):]]
        diffs.append(statistic(x_, y_))
    # 원본 표본보다 작거나 큰 경우의 p-값을 계산합니다.
    less_pvalue = np.sum(diffs < obs_diff)/1000
    greater_pvalue = np.sum(diffs > obs_diff)/1000
    # 둘 중 작은 p-값을 선택해 2를 곱하여 최종 p-값을 반환합니다.
    return obs_diff, np.minimum(less_pvalue, greater_pvalue) * 2

 

파이썬 도서와 C++ 도서의 대출건수를 전달하여 순열검정 결과 확인

permutation_test(python_books['대출건수'], cplus_books['대출건수'])

 

  • 도서 대출건수 평균 비교하기(2): 파이썬 vs 자바스크립트

도서 제목에 '자바스크립트' 키워드가 들어간 행 추출

java_books_indx = ns_book7['주제분류번호'].str.startswith('00') & \
                  ns_book7['도서명'].str.contains('자바스크립트')
java_books = ns_book7[java_books_indx]
java_books.head()

 

자바스크립트의 도서권수와 평균 대출건수 확인

print(len(java_books), np.mean(java_books['대출건수']))

 

순열검정 확인

permutation_test(python_books['대출건수'], java_books['대출건수'])

 

정리

함수/메서드 기능
scipy.stats.zscore() z 점수 계산
scipy.stats.norm.cdf() 정규분포의 누적분포 비율 계산
scipy.stats.norm.ppf() cdf() 메서드와 반대로 분포의 비율을 입력하면 해당 z 점수 반환
Series.sample() 데이터프레임에서 무작위로 값 추출
scipy.stats.ttest_ind() 두 표본의 평균에 대한 t-검정 수행
scipy.stats.permutation_test() 두 표본에 대한 순열검정 수행

07-2 머신러닝으로 예측하기

 

알아두면 좋은 머신러닝 용어

*머신러닝: 컴퓨터 프로그램을 사용해 데이터에서 패턴을 학습하는 방법

→ 학습된 패턴을 사용하여 새로운 데이터에 대해 빠르고 유용한 결정 내릴 수 있다.

예) 구글 지메일의 스팸 메일 감지기: 스팸 메일과 스팸이 아닌 메일로 훈련한 다음, 예측

*머신러닝은 인공지능의 하위분야이고, 지도 학습과 비지도 학습으로 나눈다.

*사이킷런: 파이썬의 대표적인 머신러닝 패키지

 

  • 모델

*머신러닝으로 학습된 패턴을 저장하는 소프트웨어 객체 의미

*사이킷런을 사용한다면 사이킷런에 있는 어떤 클래스의 인스턱스 객체

 

  • 지도 학습과 비지도 학습

*지도 학습: 데이터에 있는 각 샘플에 대한 정답(타깃)을 알고 있는 경우

*입력(input): 타깃을 맞추기 위해 모델이 재료로 사용하는 데이터

→ 입력과 타깃이 들어있는 데이터를 사용해 어떤 머신러닝 모델을 훈련한 후, 타깃을 모르는 새로운 입력에 모델을 적용하여 타깃을 예측

 

비지고 학습: 입력 데이터는 있지만 타깃이 없는 경우

 

모델 훈련하기

*일반적으로 훈련 데이터가 테스트 데이터보다 크다.(보통 테스트 데이터는 전체 데이터의 20~25% 정도를 사용)

 

  • 훈련 세트와 테스트 세트로 나누기

ns_book7 데이터를 다운로드하고 데이터프레임으로 불러오기

import gdown

gdown.download('https://bit.ly/3pK7iuu', 'ns_book7.csv', quiet=False)

import pandas as pd

ns_book7 = pd.read_csv('ns_book7.csv', low_memory=False)
ns_book7.head()

 

train_test_split() 함수를 임포트한 다음 ns_book7 데이터를 훈련 세트와 테스트 세트로 나누기

from sklearn.model_selection import train_test_split

train_set, test_set = train_test_split(ns_book7, random_state=42)

* train_test_split() 함수는 기본적으로 입력된 데이터를 무작위로 섞은 후 75%를 훈련 세트로, 25%를 테스트 세트로 나눈다.

*분할된 훈련 세트와 테스트 세트를 리스트로 반환하기 때문에 리스트 개수에 맞는 변수를 왼쪽에 나열하여 반환되는 값 각각 저장 가능

 

반환된 훈련 세트와 테스트 세트를 저장한 train_set, test_set 크기 확인

print(len(train_set), len(test_set))

 

train_set에서 '도서권수'열과 '대출건수'열을 각각 X-train와 y_train 변수에 저장하고 크기 확인

X_train = train_set[['도서권수']]
y_train = train_set['대출건수']

print(X_train.shape, y_train.shape)

*'도서권수'열 하나를 리스트로 감싸서 입력 X-train을 만들었다.

*특성: 2차원 배열인 입력은 행 방향으로 샘플이 나열되고 열 방향으로 샘플의 속성이 나열

 

  • 선형 회귀 모델 훈련하기

선형 회귀 알고리즘인 LinearRegression 클래스의 객체 lr을 만들고 이 객체의 fit() 메서드를 호출하며 모델 훈련

→ fit() 메서드를 호출할 때 앞서 만들었던 입력 X-train와 타깃 y_train을 전달

from sklearn.linear_model import LinearRegression

lr = LinearRegression()
lr.fit(X_train, y_train)

 

훈련된 모델을 평가하기: 결정계수

X_test와 y_test를 만들어 score()메서드 호출

X_test = test_set[['도서권수']]
y_test = test_set['대출건수']

lr.score(X_test, y_test)

 

y_train을 입력으로 사용해 모델 훈련

*y_train은 시리즈 객체이므로 fit() 메서드의 입력으로 사용하려면 2차원 배열 형태여야 한다.

→ to_frame() 메서드를 사용해 데이터프레임으로 만든다.

lr.fit(y_train.to_frame(), y_train)
lr.score(y_test.to_frame(), y_test)

 

연속적인 값 예측하기: 선형 회귀

*선형 회귀: 선형 함수를 사용해 모델을 만드는 알고리즘

*y = ax + b

*x는 입력, y는 타깃, 입력에 기울기 a를 곱하고 y축과 만나는 절편 b를 더하여 예측을 만드는 것

 

lr 객체의 coef_ 속성과 intercept_ 속성에 학습된 기울기와 절편 각각 저장

print(lr.coef_, lr.intercept_)

→ 기울기는 1이고 절편은 0에 가까운 매우 작은 음수: y = x + 0

 

카테고리 예측하기: 로지스틱 회귀

*회귀: 지도 학습 중에서 타깃이 실수인 문제

*이진 분류: 2개의 카테고리로 분류

*다중 분류: 3개 이상의 카테고리로 분류

*클래스: 분류 알고리즘에서 타깃 카테고리

*일반적으로 이진 분류의 타깃은 0 또는 1이다.

*음성 클래스: 0일 때

*양성 클래스: 1일 때

*로지스틱 회귀: 선형 회귀처럼 선형 함수를 사용하지만, 예측을 만들기 전에 로지스틱 함수 거친다.

 

  • 로지스틱 회귀 모델 훈련하기

도서권수로 대출건수가 평균보다 높은지 아닌지 예측하는 이진 분류 문제

borrow_mean = ns_book7['대출건수'].mean()
y_train_c = y_train > borrow_mean
y_test_c = y_test > borrow_mean

 

사이킷런의 linear_model 모듈에 있는 LogisticRegression 클래스를 임포트하여 훈련 세트로 fit() 메서드 호출

→ 테스트 세트로 score() 메서드 호출

from sklearn.linear_model import LogisticRegression

logr = LogisticRegression()
logr.fit(X_train, y_train_c)
logr.score(X_test, y_test_c)

*사이킷런의 분류 모델의 경우 score() 메서드가 출력하는 점수는 정확도이다.

*정확도: 입력 데이터 중 정답을 맞힌 비율

 

  • 양성 클래스와 음성 클래스 분포 확인하기

시리즈 객체인 y_test_c에서 value_counts() 메서드를 호출

y_test_c.value_counts()

 

DummyClassifier()를 사용해 score() 메서드 결과 확인

from sklearn.dummy import DummyClassifier

dc = DummyClassifier()
dc.fit(X_train, y_train_c)
dc.score(X_test, y_test_c)

*사이킷런은 가장 많은 클래스로 무조건 예측을 수행하는 더미 모델 제공

*회귀일 경우 DummyRegressor 모델이 있으며 무조건 타깃의 평균을 예측

*분류일 경우 DummyClassifier 모델이 기본적으로 가장 많은 클래스 예측

 

정리

함수/메서드 기능
sklearn.model_selection.train_test_split() 입력된 데이터를 훈련 세트와 테스트 세트로 나눈다.
sklearn.linear_model.LinearRegression 선형 회귀 수행
LinearRegression.fit() 모델 훈련
LinearRegression.score() 모델의 성능 평가
LinearRegression.predict() 샘플에 대한 예측 만들기
sklearn.linear_model.LogisticRegression 로지스틱 회귀 수행
sklearn.dummy.DummyClassifier 입력값을 고려하는 대신 타깃에서 다수의 클래스를 예측으로 사용

 

'혼자 공부하는 데이터 분석' 카테고리의 다른 글

6장 복잡한 데이터 표현하기  (0) 2023.06.08
5장 데이터 시각화하기  (1) 2023.05.29
4장 데이터 요약하기  (0) 2023.05.29
3장 데이터 정제하기  (0) 2023.05.22
2장 데이터 수집하기  (0) 2023.05.14

댓글