인공지능/공부

고급 인공지능 활용 - 기말 고사 정리

이게될까 2024. 4. 14. 01:01
728x90
728x90

9주차 나이브 베이즈

나이브 베이즈 베이즈 정리를 적용한 조건부 확률 기반의 분류 모델

조건부 확률 – A가 일어났을 때 B가 일어날 확률

스팸 필터링을 위한 대표적인 모델, 딥러닝보다 간단한 방법으로 자연어 처리원할 때 사용

수식 P(A|B) =P(B|A) * P(A) / P(B)

P(A|B) – 사후확률, b가 발생했을 때 a가 발생할 확률

P(A) – 사전확률, B의 발생유무와 관련 없이 기본적으로 A가 발생할 확률

P(B|A) – 우도 Likelihood 혹은 가능도라고도 부름, A가 발생했을 때, B가 발생할 확률

P(B)- 전체에서 B가 발생할 확률

사전 확률로 사후 확률을 예측하는 조건부 확률을 기반으로 한다.

사후 확률 사건 A B가 있을 때, 사건 A가 발생한 상황에서 사건 B가 발생할 확률

사전 확률 사건 A와 상관없이 사건 B가 발생할 확률

베이즈 정리 두 확률 변수의 사전 확률과 사후확률 사이의 관계를 나타내는 정리, 사후 확률을 구할 때 쓰임

장점 비교적 간단한 알고리즘이라 속도가 빠르고, 적은 훈련 셋으로도 잘 예측한다.

단점 모든 독립 변수가 각각 독립적임을 전제로 하는데 이는 장점이자 단점이다. 실제로 독립 변수들이 모두 독립적이라면 다른 알고리즘보다 우수할 수 있지만, 실제 데이터에서 그런 경우가 많지 않기 때문에 단점이다.

나이브 베이즈 모델을 활용하여 스팸 여부를 판단하라.

1문제정의 2라이브러리 및 데이터 불러오기, 데이터 확인하기

전처리 3특수기호 제거하기 4불용어(의미없는 언어) 제거하기 5목표 컬럼 형태 변경하기 6카운트 기반으로 벡터화하기

7모델링 예측하기

 

 

시작하기 위해 사전으로 불러올 것들

from google.colab import drive

drive.mount('/content/drive')

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

import seaborn as sns

 

data = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/spam.csv')

data['target'].unique() #고유값 확인

특수기호 제거

import string 

sample_string = data['text'].loc[0]

new_string = []

for i in sample_string:

  if i not in string.punctuation:

    new_string.append(i)

new_string = ''.join(new_string)

이걸 함수로 만들기

def remove_punc(x):

  new_string=[]

  for i in x:

      if i not in string.punctuation:

            new_string.append(i)

  new_string = ''.join(new_string)

  return new_string

data['text'] = data['text'].apply(remove_punc)

함수를 각각의 행에 다 적용하는 방법

 

불용어(의미  없는 단어) 제거하기

1문자열을 단어 단위 리스트로 변환함 2불용어가 아니면 소문자로 저장함

3한 문자열로 합침 4모든 문자열에 대하여 반복해 적용함(문자열>리스트>리스트>문자열 과정)

import nltk

nltk.download('stopwords') #불용어 목록 다운로드

from nltk.corpus import stopwords

new_string = []

for i in sample_string.split(): # 단어 단위로 쪼개기

  if i.lower() not in stopwords.words('english'): 

    new_string.append(i.lower()) # 소문자로 바꾸기

new_string = ' '.join(new_string) # 공백을 넣어 문장으로 만들기

new_string

이제 이걸 함수로 만들기

def stop_words(x):

  new_string = []

  for i in x.split():

    if i.lower() not in stopwords.words('english'):

      new_string.append(i.lower())

  new_string = ' '.join(new_string)

  return new_string

 

data['text'] = data['text'].apply(stop_words)

data['text']

불용어 처리 완료했으니 목표 컬럼 형태로 변경하기(목표 컬럼: 문자 형식 데이터>문자를 숫자로 변형한다)

data['target'] = data['target'].map({'spam': 1, 'ham': 0}) # 1대1 매핑

data['target'] #문자를 숫자로 바꿔서 연산하는 경우 뛰어난 성능을 보여준다

나이브 베이즈 활용 분야

1.     각 독립변수들이 모두 독립적이고 그 중요도가 비슷할 때 유용하다

2.     자연어 처리(NLP)에서 간단하지만 좋은 성능을 보여준다

3.     범주 형태의 변수가 많을 때 적합하다.

나이브 베이즈의 핵심 용어

1.     사후확률: 사건 AB가 있을 때, 사건 A가 발생한 상황에서 사건 B가 발생할 확률

2.     사전확률: 사건 A와 상관없이 사건 B가 발생할 확률

베이즈 정리: 두 확률 변수의 사전확률과 사후확률 사이의 관계를 나타내는 정리로, 사후 확률을 구할 때 쓰인다.

전처리(카운트 기반 벡터화): 문자를 개수 기반으로 벡터화

1.     데이터에 있는 모든 단어를 확인해 컬럼으로 삼음

2.     각 문장마다 출현한 단어 수를 확인함

3.     각 단어에 대한 인덱스를 부여함

4.     변환된 데이터는 아래와 같은 포맷으로 각 행마다 해당 인덱스의 단어가 몇 번 나타났는지를 표시한다. 출현하지 않은 단어의 인덱스는 포함하지 않음

 

모델링 및 예측/평가하기: 혼동 행렬(confusion matrix)

맞춘 것과 못 맞춘 것을 모두 구하고 (맞춘 경우)/(전체 경우)로 정확도를 구할 수 있다.

  예측값
0 1
실제값 0 음성을 음성으로 판단(TN) 양성을 음성으로 판단(FP)1종 오류
1 양성을 음성으로 판단(FN)2종 오류 양성을 양성으로 판단(TP)

1종 오류(음성을 양성으로 예측) False positive 2종 오류(양성을 음성으로 판단) False Negative             이 둘은 중요도가 다를 수 있다. (암예측과 같은 경우 양성이 훨씬 중요하다 2종 오류, 거짓 오류)

x = data['text']

y = data['target']

from sklearn.feature_extraction.text import CountVectorizer

cv = CountVectorizer()

cv.fit(x) # 단어와 인덱스(숫자) 1 대 1 매핑

x = cv.transform(x)

 

이제 학습셋 나눠서 학습시키기

from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=100)

from sklearn.naive_bayes import MultinomialNB  #다항 분포 알고리즘

model = MultinomialNB()

model.fit(x_train, y_train)

pred = model.predict(x_test)

예측값 혼동행렬 진행

from sklearn.metrics import accuracy_score, confusion_matrix # 혼동 행렬

accuracy_score(y_test, pred) # 정확도 확인

print(confusion_matrix(y_test, pred)) # 혼동 행렬 표로 보기

sns.heatmap(confusion_matrix(y_test, pred), annot=True, fmt='.0f') # 보기 쉽게 그림으로


10주차 결정트리 decision Tree

결정 트리 관측값과 목표값을 연결시켜주는 예측모델(나무모양 데이터분류)

수많은 트리 기반 모델의 기본 모델이 되는 중요 모델

선형모델 트리모델
각 변수에 대한 기울기 값들을 최적하 하여 모델을 만들어 나감 각 변수의 특정 지점을 기준으로 데이터를 분류해가며 예측 모델을 만듦
Ex) 남자/여자로 나눠서 각 목푯값 평균치를 나눔

트리 모델의 장점

1.     Non-Parametric Model 데이터에 대한 가정이 없는 모델

선형 모델정규분포에 대한 가정이나 독립변수와 종속변수의 선형관계 등을 가정으로 하는 모델

결정 트리-데이터에 대한 가정이 없으므로 어디에나 자유롭게 결정할 수 있음

2.     아웃라이어에 영향을 거의 받지 않음(기준점에 따라 분류하기 때문)

3.     시각화에 굉장히 탁월함 트리 그래프를 통해 직관적으로 이해 및 설명 가능

트리 모델의 단점

1.     오버 피팅트리가 무한정 깊어지면 오버피팅 문제를 야기할 수 있음

2.     예측력이 떨어짐 앞으로 배울 발전된 트리 기반 모델들에 비하면 예측력이 떨어짐

결정트리 특정 변수에 대한 특정 기준값으로 데이터를 계속 분류해가면서 유사한 그룹으로 묶어내어 예측값을 만드는 알고리즘

변수 선정과 기준점을 정하는 것이 중요, 각 상황에서 최적의 번수와 기준점을 찾아내야 한다.

노드 : 결정트리 다이어그램에서 보이는 각 박스

순도 : 한 노드 안에 여러 종류가 아닌 한 종류의 목표값만 있는 상태에 대한 지표

지니 인덱스와 교차 엔트로피를 평가하여 분류함

사과 2 복숭아 2: 1 –[0.5^2+0.5^2]=0.5, 사과1 복숭아3: 1-[0.25^2+0.75^2]=0.375 복숭아4 : 0

노드가 한쪽 아이템으로 완전히 분류된 경우 지니 인덱스가 0이며, 순도가 높다고 평가

옵션을 넣으면 교차 엔트로피로 사용가능 최대값은 1, 최소값은 0, 지니 인덱스 대신 활용 가능

회귀 결정 트리: 회귀는 연속형 변수를 대상으로 MSE를 평가 기준으로 이용함

- MSE를 구하며, 결정 트리 회귀는 가장 낮은 MSE 값이 나오도록 노드를 분류해나감.

- MSE는 사이킷런의 결정 트리 모델에서 기본값으로 설정된 평가 기준임

- 필요에 따라 매개변수를 이용하여 MSE 대신 MAEPoisson 등으로 설정할 수도 있음

MSE: 실젯값(y)과 예측값(오른쪽 노드에서 y의 평균)의 차이에 대한 계산 (차이의 제곱 평균)

예측력과 설명력: 반비례 관계이다. (복잡한 모델은 설명하긴 어려워도 예측은 잘한다.)

예측력: 모델 학습을 통해 얼마나 좋은 예측치를 보여주는 지를 의미함

설명력: 학습된 모델을 얼마나 쉽게 해석할 수 있는지를 의미함

결정트리와 회귀분석은 상대적으로 해석이 쉬어 설명력이 높지만 예측이 낮다

앙상블 기법과 인공 신경망과 같은 복잡한 알고리즘은 예측력은 높지만 해석이 어렵다.

특정 질병의 발병률에 대한 예측 모델: 발병률을 높이거나 억제하는 중요한 요인을 밝히는 설명력이 좋은 알고리즘이 적합하다.

사기 거래 예측 모델: 요인보다 더 정확하게 사기거래를 잡아내야 함=예측력이 높은 알고리즘

결정트리 실습 1. 문제정의 2. 라이브러리 및 데이터 불러오기, 데이터 확인하기

전처리 3. 범주형 데이터 4. 결측치 처리 및 더미 변수 변환 5. 모델링 예측하기

 

from google.colab import drive

drive.mount('/content/drive')

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

import seaborn as sns

 

data = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/salary.csv', skipinitialspace = True) # 빈칸 자동 제거

data.info() # 데이터 타입 확인 문자로 구성된 범주형 범수 많은 것 확인

data.describe() # 숫자인 변수만 보여준다. 오브젝트 형이 많다 보니 보여주는 것이 많지 않다.

data.describe(include = 'all') # 모든 변수들이 다 나온다. 3줄이 추가 되어 나온다. unique : 종류, top: 제일 많은 종류, freq:top의 개수

data['class'] = data['class'].map({'<=50K': 0, '>50K': 1}) # 범주형 데이터 처리

 

for i in data.columns: #모든 데이터의 범주형 데이터 확인하는 방법

  print(i, data[i].dtype)

obj_list = [] 

for i in data.columns: # 오브젝트형 변수의 이름 뽑기

  if data[i].dtype == 'object':

    obj_list.append(i)

for i in obj_list: # 변수의 데이터들이 너무 다양하면 원핫 인코딩으로 해결하기 어려울 수 있음

  print(i, data[i].nunique()) # 더미 변수를 사용하면 그 만큼의 변이 생기니까 잘 생각해야됨

for i in obj_list: 

  if data[i].nunique() >= 10: # 종류가 너무 많은 데이터들 보여주기

    print(i, data[i].nunique())

data['education'].value_counts() # 고유값의 빈도를 보여준다 이미 선형화가 된 자료형이 있다.

np.sort(data['education-num'].unique()) # 아까 자료형을 선형적으로 보여준 것(매칭이 되는지만 확인해도된다.)

data[data['education-num'] == 1]['education'].unique()# 둘 다 같은 형인지 확인한다

for i in np.sort(data['education-num'].unique()): # 1대 1 매칭되는지 확인하는 절차

  print(i, data[data['education-num'] == i]['education'].unique())

data.drop('education', axis=1, inplace = True) # 필요없는 값 삭제

data['occupation'].value_counts() # 직업에 서열도 귀천도 없으므로 숫자형으로 변형하기는 어렵다. 더미 변수 14개 정도면 할만하다는 판단으로 사용한다.

data['native-country'].value_counts() # 국가는 굉장히 다양하다. 미국이 대부분을 차지한다. -> 미국이냐 아니냐로 판단 가능(연산에는 좋으나 세세한 정보 안쓰는 것), 대륙별로 묶기도 가능

data.groupby('native-country').mean().sort_values('class')# 유사성 확인하기 위해 그룹 별로 묶고 평균내고, 클래스를 낮은 순서대로 보여준다. 지역별로 묶기도 애매하다. > 그대로 사용할 것을 고려, 기준에 대해 분류하기 때문에 범주형 변수를 숫자로 바꿔도 크게 상관이 없다고 알려짐 

country_group = data.groupby('native-country').mean().sort_values('class')

country_group = country_group.reset_index() # 국가를 인덱스로 표현하는 것이 아닌 숫자로 표현해줌

data = data.merge(country_group, on = 'native-country', how='left') #어떠한 기준으로 머지 할지, 어떠한 방식으로

data.drop('native-country', axis=1, inplace = True)#국가가 CLASS_Y로 표현 되었기 때문에 국가 지우기

data = data.rename(columns = {'class_x': 'class', 'class_y': 'native-country'}) #이름 바뀐 것 다시 바꿔주기

더미 변수 변환, 결과 해석

data.isna().mean()# 결측이 있으면 0이아님

data.drop(['age_y', 'education-num_y', 'capital-gain_y', 'capital-loss_y', 'hours-per-week_y'], axis=1, inplace=True) # 지워버릴 데이터, 축

data = data.rename(columns = {'age_x': 'age', 'education-num_x': 'education-num', 'capital-gain_x': 'capital-gain', 'capital-loss_x': 'capital-loss', 'hours-per-week_x': 'hours-per-week'}) # X가 없는 형태로 다시 바꾸기

data['native-country'] = data['native-country'].fillna(-99) #결측치를 채우는데 관계없는 숫자로 넣어서 결측치라고 약속하기

data['workclass'].value_counts()#범주형 변수이기 때문에 숫자를 넣을 수가 없다. 행 자체를 지우는 방법도 있다. 일단 확인

data['workclass'] = data['workclass'].fillna('Private') # 최빈값의 비중이 크므로 최빈값으로 채우기

data['occupation'].value_counts()# 어느 특정 값이 많다고 할 수 없다.

data['occupation'] = data['occupation'].fillna('Unknown')# 언노운이라는 새로운 값으로 결측치 채우기

data = pd.get_dummies(data, drop_first=True)#더미 변수만들기

from sklearn.model_selection import train_test_split # 훈련셋 분리

X_train, X_test, y_train, y_test = train_test_split(data.drop('class', axis=1), data['class'], test_size=0.4, random_state=100)# 훈련할 샘플이 많으므로 테스트 사이즈 늘리기

from sklearn.tree import DecisionTreeClassifier #리그레쉬 : 값을 예측 , 클레스파이어: 분류 

model = DecisionTreeClassifier() # 모델 형성

model.fit(X_train, y_train) # 훈련하기

pred = model.predict(X_test) # 예측하기

from sklearn.metrics import accuracy_score # 예측 점수 

accuracy_score(y_test, pred)

하이퍼 파라미터 튜닝을 통해 점수 높이기

조건을 세부적으로 나눌수록 점수가 높아진다. 오버 피팅도 발생할 수 있다. 기본값은 최대한 세부적으로 나눈다. 즉 파라미터 설정을 안하면 훈련셋 점수는 높고 예측 점수는 낮다. (오버피팅)

model = DecisionTreeClassifier(max_depth=5) # 매개변수 지정 (하이퍼 파라미터) 트리의 깊이이다.

model.fit(X_train, y_train)

train_pred = model.predict(X_train)

test_pred = model.predict(X_test)

print('Train score:', accuracy_score(y_train, train_pred))

print('Test score:', accuracy_score(y_test, test_pred)) # 테스트 점수가 증가했다.

Max_depth의 값은 경험과 테스트를 통한 값으로 나온다.

설명력이 좋은 결정 트리 그래프 보기

from sklearn.tree import plot_tree

plt.figure(figsize=(30, 15))

plot_tree(model)

plt.show()

plt.figure(figsize=(30, 15))

plot_tree(model, max_depth=3, fontsize=15, feature_names=X_train.columns)# 각각의 질문에 대해 어떠한 형태로 답변했는지 보여준다. 이름도 붙여줌

plt.show()

결과에 설명이 가능한 기법이다!

11주차 랜덤 포레스트 결정 트리의 단점인 오버 피팅 문제를 완화시켜주는 발전된 형태의 트리모델

무수히 많은 트리로 예측을 하는 것이 랜덤 포레스트이다.

앙상블-여러 모델을 활용하여 하나의 모델을 이루는 기법

장점 아웃라이어의 영향을 받지 않고, 선형 비선형 데이터 상관없이 잘 작동함(가정 없이 작동)

단점 학습 속도가 상대적으로 느리고, 수많은 트리를 동원하기 때문에 모델에 대한 해석이 어렵다

실습 단계 1. 문제 정의 2. 라이브러리 및 데이터 불러오기, 데이터 확인하기

전처리 3. 텍스트 데이터 4. 결측치 처리와 더미 변수 변환 5. 모델링 예측하기

이해하기 6. K겹 교차검증 7. 랜덤 포레스트 8. 하이퍼파라미터 튜닝

from google.colab import drive

drive.mount('/content/drive')

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

import seaborn as sns

 

data = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/car.csv')

data.info() # 결측치 확인, 빼도 되는 단위 확인(cc, bp 등)

round(data.describe(), 2) # 아웃 라이어 존재 확인 가능 (선형 회귀에서는 영향을 많이 받는다. 트리 모델은 영향이 없기 때문에 따로 처리해주지 않는다.)

data[['engine', 'engine_unit']] =data['engine'].str.split(expand=True)# 단위 일치 시키기 위해 분리해준다 숫자와 문자 구분

data['engine'].head() # 숫자지만 데이터 타입은 오브젝트이므로 주의

data['engine'] = data['engine'].astype('float32') #데이터 타입 바꾸는 법

data[['max_power', 'max_power_unit']] = data['max_power'].str.split(expand=True) # 위와 같음

data[data['max_power'] == 'bhp'] # 스플릿이 안된 경우 이 것 때문에 오류가 난다. 샘플이 하나 이므로 지울 수 있다.

def isFloat(value): # 에러 처리 함수

  try: # 에러의 종류에 따라 여러가지 처리 가능하다

    num = float(value)

    return num

  except ValueError:  # 예외일 경우

    return np.NaN

data['max_power'] = data['max_power'].apply(isFloat) # 함수 적용해서 시리즈 전체에 적용

data.drop('max_power_unit', axis=1, inplace=True) # 필요 없는 데이터 지우기

data[['mileage', 'mileage_unit']] = data['mileage'].str.split(expand=True) # 이전에 해왔던 방식이랑 같다

data['mileage'] = data['mileage'].astype('float32') # 데이터 변환

data['mileage_unit'].unique() # 단위가 다양해서 숫자 그대로 보기 어렵다

data['fuel'].unique() # 연료 종류 확인

def mile(x): # 연료 가격이 다르므로 단위 환산

  if x['fuel'] == 'Petrol':

    return x['mileage'] / 80.43

  elif x['fuel'] == 'Diesel':

    return x['mileage'] / 73.56

  elif x['fuel'] == 'LPG':

    return x['mileage'] / 40.85

  else:

    return x['mileage'] / 44.23

data['mileage'] = data.apply(mile, axis=1)  # 단위 환산 하기

data.drop('mileage_unit', axis=1, inplace=True) # 유닛 필요 없으니 지우기

여러 트리를 이용하기 때문에 다양한 트리의 의견(각각의 중요도를 다르게 생각)을 반영하여 오버 피팅의 위험을 낮출 수 있다.

랜덤 포레스트가 여러 개의 트리를 만들 때는 데이터 전체를 사용하지 않고, 매번 다른 일부의 데이터를 사용하여 다른 트리를 만들어 낸다. (복원, 비복원)

각 트리에서 주어진 모든 독립변수를 사용하지 않고, 일부 변수들만을 매번 다르게 추출 후 사용

대표적으로 오버 피팅의 위험을 낮추면서 많은 트리의 내용을 사용하므로 예측력도 높다.

But 결과 해석 어렵고, 느리다. 결과를 다수결로 사용하면 분류문제, 평균으로 하면 회귀문제

data['torque'] = data['torque'].str.upper() # 너무 다양해서 일단 전부 대문자로 바꾼다

def torque_unit(x):

  if 'NM' in str(x):

    return 'Nm'

  elif 'KGM' in str(x):

    return 'kgm'

data['torque_unit'] = data['torque'].apply(torque_unit) # 변환하여 새로운 곳에 저장한다.

data['torque_unit'].unique() # 데이터 확인하기

data[data['torque_unit'].isna()]# 빈값 확인하기

data['torque_unit'].fillna('Nm', inplace=True) # 다들 수가 크므로 Nm인 것 같아서 Nm으로 채워버리기

def split_num(x):

  x = str(x) # 데이터 타입 확실하게 지정해주기

  for i, j in enumerate(x): # 숫자가 아닌 곳을 찾기 위한 반복분

    if j not in '0123456789.': # 숫자가 아닌곳을 찾으면 자르기

      cut = i

      break

  return x[:cut] # 자른 곳 직전까지 반환

data['torque'] = data['torque'].apply(split_num) # 함수 적용해서 바꿔버리기

data['torque'] = data['torque'].replace('', np.NaN) # 빈칸을 np.NaN으로 바꿔주기

data['torque'] = data['torque'].astype('float64') # 숫자로 바꿔주기

def torque_trans(x): # 단위 변환 함수

  if x['torque_unit'] == 'kgm':

    return x['torque'] * 9.8066

  else:

    return x['torque']

data['torque'] = data.apply(torque_trans, axis=1) # 전체 데이터에 대해 적용

data.drop('torque_unit', axis=1, inplace=True) # 이제 단위 필요 없으니 삭제하기

data['name'] = data['name'].str.split(expand=True)[0]#이름에서 브랜드만 따로 뽑기

# Land Rover

data['name'] = data['name'].replace('Land', 'Land Rover')# 이름 띄어쓰기로 인해 삭제된 것 복사해주기

data.isna().mean()# 결측치 찾기

data.dropna(inplace=True)# 결측치가 있는 행 삭제해버리기

data = pd.get_dummies(data, columns = ['name', 'fuel', 'seller_type', 'transmission', 'owner'], drop_first=True) # 더미로 바꾸기

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(data.drop('selling_price', axis=1), data['selling_price'], test_size=0.2, random_state=100) # 셋 나누기

from sklearn.ensemble import RandomForestRegressor # 회귀이기 때문이다 앙상블 안에 있다

model = RandomForestRegressor(random_state = 100)# 같은 결과를 나타내기 위해

model.fit(X_train, y_train)# 훈련 시키기  시간 좀 걸릴 수 있다.

train_pred = model.predict(X_train)

test_pred = model.predict(X_test)

from sklearn.metrics import mean_squared_error #RMSE다

print("train_rmse:", mean_squared_error(y_train, train_pred) ** 0.5)

print("test_rmse:", mean_squared_error(y_test, test_pred) ** 0.5)# 테스트가 오차가 훨씬 더 많다

from sklearn.model_selection import KFold

data.reset_index(drop=True, inplace=True)# 제거한 값 때문에 인덱스가 엉망이므로 인덱스 다시 넣기

kf = KFold(n_splits=5) # 하이퍼 파라미터 데이터 몇개로 분할할지

X = data.drop('selling_price', axis=1) #독립

y = data['selling_price']# 종속

for train_index, test_index in kf.split(X): # KF를 5개로 분할한다고 했기 때문에 분할해준다.

  X_train, X_test = X.loc[train_index], X.loc[test_index] # 이걸 각각 따로 저장한다

  y_train, y_test = y[train_index], y[test_index]

train_rmse_total = []

test_rmse_total = []

for train_index, test_index in kf.split(X):

  X_train, X_test = X.loc[train_index], X.loc[test_index]

  y_train, y_test = y[train_index], y[test_index]

 

  model = RandomForestRegressor(random_state = 100) # 똑같이 한다

  model.fit(X_train, y_train) # 훈련

  train_pred = model.predict(X_train)

  test_pred = model.predict(X_test)

 

  train_rmse = mean_squared_error(y_train, train_pred) ** 0.5

  test_rmse = mean_squared_error(y_test, test_pred) ** 0.5

 

  train_rmse_total.append(train_rmse) # 결과 추가

  test_rmse_total.append(test_rmse) # 야도

 

 

랜덤 포레스트 해석: K-폴드 교차 검증 (목적)- 교차 타당성

모델의 예측력을 더 안정적으로 평가하기 위함

새로운 데이터를 얼마나 잘 예측하는지 확인하고자 시험셋을 나누어 평가함

시험셋과 훈련셋으로 데이터 분할을 랜덤하게 했으므로 어느정도 안정적인 성능을 보장받는다.

데이터를 특정 개수(K)로 쪼개어 그 중 하나씩을 선택하여 시험셋으로 사용하되, 이 과정을 K번만큼 반복함 (다 다르다)

하이퍼 파라미터 튜닝

N_estimators:랜덤 포레스트를 구성하는 결정 트리의 개수, 기본값은 100, 적정 수준 값 필요

Max_depth: 결정 트리와 동일하게, 각 트리의 최대 깊이를 제한, 숫자가 작으면 오버피팅을 피할 수 있으나 언더피팅의 위험도 올라간다. 수를 늘리면 오버 피팅 가능

Min_samples_split: 해당 노드를 나눌 것인지 말 것인지를 노드 데이터 수를 기준으로 판단한다. 이 매개변수에 지정된 숫자보다 적은 수의 데이터가 노드에 있으면 더는 분류하지 않는다. 숫자가 높을수록 분리되는 노드가 적어지므로, 오버 피팅을 피할 수 있으나 언더피팅의 위험도 있다. 기본 값은 2.

Min_samples_leaf: 분리된 노드의 데이터에 최소 몇 개의 데이터가 있어야 할지를 결정하는 매개변수이다. 여기에 지정된 숫자보다 적은 수의 데이터가 분류된다면, 해당 분리는 이루어지지 않는다. 마찬가지로 숫자가 클수록 오버피팅을 피할 수 있고, 언더피팅의 위험도가 높아진다. 기본값은 1이다.

N_jobs: 병렬처리에 사용되는 CPU코어 수이다. 많은 코어를 사용할수록 속도가 빨라지며, -1을 입력하면 지원하는 모든 코어를 사용한다. 기본값은 None으로, 실제는 1개 코어를 사용한다. 랜덤 포레스트의 속도가 다소 느린만큼 충분한 코어를 사용하는게 좋다.

12주차 부스팅- 순차적으로 트리를 만들어 이전 트리로부터 더 나은 트리를 만들어내는 알고리즘

트리모델을 기반으로 한 최신 알고리즘으로 빠른 속도와 높은 예측력을 보여준다. 실제 산업 현장에선 굉장히 중요한 가치이다.

대표적인 알고리즘으론 XG부스트, 라이트GBM, 캣부스트가 있다.

XG부스트는 가장 먼저 개발되어 널리 활용되고 있고, 손실함수뿐만 아니라 모형 복잡도까지 고려한다. 이전 트리의 결과를 다음 트리에 반영해 연속성 있는 트리를 만들어 분류하는 알고리즘이다. 예측 속도가 빠르고 좋으며, 변수종류가 많고 데이터가 클수록 상대적으로 뛰어난 성능을 보여준다. 단점으론 복잡한 모델인만큼, 해석에 어려움이 있고, 하이퍼파라미터 튜닝이 까다롭다.

1.다양한 데이터 모두 사용가능하여 종속변수가 연속형 데이터, 범주형 데이터인 경우 모두 사용 가능하다.

2.거의 모든 상황에 활용가능하여 이미지나 자연어가 아닌 표로 정리된 정형데이터의 경우, 거의 모든 상황에 활용될 수 있다. TXT, EXEL 등등

XG부스트는 부스팅 기법의 하나로, 각 트리가 독립적인 랜덤 포레스트와 달리 이전 트리를 기반으로 새로운 트리를 생성하며, 2차 도함수 활용과 정규화 하이퍼파라미터 지원이라는 특징을 지닌다.

1문제정의 2라이브러리 및 데이터 불러오기

전처리 3데이터 클리닝 4피처 엔지니어링

5모델링 및 예측하기 6이해하기: 경사하강법 7하이퍼파라미터 튜닝: 그리드서치 8중요변수 확인

from google.colab import drive

drive.mount('/content/drive')

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

import seaborn as sns

data = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/dating.csv')

data.head() # 기본으로는 열은 20개만 보여준다 일단 확인하기위해 HEAD를 봤는데 뒤에가 안보여서 전략을 짤 수 없다,

pd.options.display.max_columns = 40 # 열을 끝까지 다 보여주게 만들어준다. 전략을 짤 수 있게 해준다.

round(data.describe(), 2) # 소수점 반올림 데이터의 값 확인하며 어떤 내용인지 확인

data.isna().mean()# 결측치 확인하기 트리기반은 결측치 확인하기가 쉽다. 결측치를 -99로 일정하게 해두면 알아서 묶어준다.

data = data.dropna(subset=['pref_o_attractive', 'pref_o_sincere', 'pref_o_intelligence', 'pref_o_funny', 'pref_o_ambitious', 'pref_o_shared_interests', 'attractive_important', 'sincere_important', 'intellicence_important', 'funny_important', 'ambtition_important', 'shared_interests_important']) # 결측치 해결하기  중요도와 관련된 것은 지우기

data = data.fillna(-99) # -99로 채우기

트리 모델 진화 과정

1.     결정트리 가장 기본적인 트리 모델

2.     배킹 부트스트랩(데이터의 일부분을 무작위로 반복 추출하는 방법, 추출한 데이터의 여러 부분집합을 사용해 여러 트리를 만들어 오버 피팅을 방지한다.) 훈련셋을 사용하는 트리 모델

3.     랜덤 포레스트 데이터와 변수의 일부를 사용하여 여러 트리를 만드는 모델

4.     부스팅 이전 트리의 학습 내용을 다음 트리에 반영하여 여러 트리를 만드는 방법

5.     경사 부스팅 부스팅에 경사 하강법을 적용한 모델(XGBoost, LightGBM, Catboost)

6.     XG포레스트 경사 부스팅에서 계산 속도와 알고리즘 효율을 개선한 모델

에이다부스트(Adaptive Boosting)- 단계적으로 트리를 만들 때 이전 단계에서의 분류 결과에 따라 각 데이터에 가중치를 부여/수정한다. (ex-이전 트리에서 가중치가 덜 부여되고 잘못 분류된 데이터들에 더 높은 가중치를 부여한다. 후속 트리에서는 가중치가 높은 데이터를 분류하는 데 우선순위를 둔다. 부트스트랩 즉 복원추출 허용

부스팅 랜덤포레스트에서 그 다음 세대로 진화하게 되는 중요한 개념, 랜덤 포레스트에서는 각각의 트리를 독립적으로, 즉 서로 관련없이 만듦

부스팅 알고리즘 트리를 순차적으로 만들면서 이전 트리에서 학습한 내용이 다음 트리를 만들 때 반영된다.

def age_gap(x):

  if x['age'] == -99: # 결측치

    return -99

  elif x['age_o'] == -99:

    return -99

  elif x['gender'] == 'femail': // 남자가 연상이면 양수 연하면 음수

    return x['age_o'] - x['age']

  else:

    return x['age'] - x['age_o']

data['age_gap'] = data.apply(age_gap, axis=1)

data['age_gap_abs'] = abs(data['age_gap'])

def same_race(x):# 인종

  if x['race'] == -99: # 결측치처리

    return -99

  elif x['race_o'] == -99:

    return -99

  elif x['race'] == x['race_o']: # 같으면

    return 1

  else:# 다르면

    return -1

data['same_race'] = data.apply(same_race, axis=1) # 새로운 변수에 집어넣기

def same_race_point(x): # 동일 인종 중요 여부

  if x['same_race'] == -99:

    return -99

  else:

    return x['same_race'] * x['importance_same_race'] # 동일 인종시 중요도가 높으면 큰 양수 인종 다르고 중요도 높다면 매우 작은 음수

data['same_race_point'] = data.apply(same_race_point, axis=1) # 이것도 집어 넣기

def rating(data, importance, score):

  if data[importance] == -99:

    return -99

  elif data[score] == -99:

    return -99

  else:

    return data[importance] * data[score]

partner_imp = data.columns[8:14]# 변수의 이름 설정해주기

partner_rate_me = data.columns[14:20]

my_imp = data.columns[20:26]

my_rate_partner = data.columns[26:32]

new_label_partner = ['attractive_p', 'sincere_partner_p', 'intelligence_p', 'funny_p', 'ambition_p', 'shared_interests_p'] # 새로운 변수 창출 파트너 관련

new_label_me = ['attractive_m', 'sincerer_partner_m', 'intelligence_m', 'funny_m', 'ambition_m', 'shared_interests_m'] # 본인 관련

for i, j, k in zip(new_label_partner, partner_imp, partner_rate_me): # 집함수 사용

  print(i, ' & ', j, ' & ', k) # 각 리스트 별로 한개씩 추출

for i, j, k in zip(new_label_partner, partner_imp, partner_rate_me):

  data[i] = data.apply(lambda x: rating(x, j, k), axis=1)# 집함수 사용해서 중요도 까지 곱해주기

data = pd.get_dummies(data, columns=['gender', 'race', 'race_o'], drop_first=True)# 숫자 형태가 되도록 더미변수 사용

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(data.drop('match', axis=1), data['match'], test_size = 0.2, random_state = 100) # 훈련셋 나누기

import xgboost as xgb

model = xgb.XGBClassifier(n_estimators = 500, max_depth = 5, random_state = 100) #모델 만들기

model.fit(X_train, y_train)#훈련시키기

pred = model.predict(X_test) # 예측하기

from sklearn.metrics import accuracy_score, confusion_matrix, classification_report

accuracy_score(y_test, pred) # 이건 점수보기

print(confusion_matrix(y_test, pred)) # 잘 예측한것, 잘예측하지 못한것 행렬 형태로 보여줌

print(classification_report(y_test, pred))# 점수 확인

from sklearn.model_selection import GridSearchCV # 하이퍼 파라미터 튜닝하기 위해 가장 중요한 것은 그리드 서치(일정 간격을 두고 찾는 것)이다.

parameters = {

    'learning_rate': [0.01, 0.1, 0.3], # 학습률

    'max_depth': [5, 7, 10],

    'subsample': [0.5, 0.7, 1],

    'n_estimators': [300, 500, 1000]

}

model = xgb.XGBClassifier()

gs_model = GridSearchCV(model, parameters, n_jobs=-1, scoring='f1', cv = 5) # 위에서 파라미터 설정한 것 집어넣기

gs_model.fit(X_train, y_train) # 훈련 시키기

gs_model.best_params_ # 최고 성능 파라미터

pred = gs_model.predict(X_test) # 예측

accuracy_score(y_test, pred) # 점수보기

model = xgb.XGBClassifier(learning_rate = 0.3, max_depth = 5, n_estimators = 1000, subsample = 0.5, random_state=100) #변수의 영향력 확인 하기 위해 모델 만들기

model.fit(X_train, y_train) # 훈련

model.feature_importances_ # 중요도 보여준다

feature_imp = pd.DataFrame({'features': X_train.columns, 'values': model.feature_importances_}) # 중요한 걸 찾아보고 싶기 때문에 위의 것 밸류에 넣어주기

plt.figure(figsize=(20, 10)) # 크기설정

sns.barplot(x='values', y='features', data=feature_imp.sort_values(by='values', ascending=False).head(10)) # 해석에 유의해야된다.

이 해석이 크게 우수한 성능이라고 볼 수 없다 (매칭된 비율이 적기 때문이다) 혼동 행렬을 통해 확인해보기

정밀도 = 1로 예측한 경우 얼마만큼이 실제로 1인지를 나타냄(TP(TP+FP) =양성을 양성으로 판단 / ( 양성을 양성으로 판단 + 1종오류) = 양성을 양성으로 판단한 수/ 양성으로 판단한 수 ) FP가 커질수록 분모가 커지므로, 정밀도는 낮아진다. 1종오류와 관련되어 있다.

재현율 = 실제로 1중에, 얼마만큼을 1로 예측했는가(TP/(TP+FN) = 양성을 양성으로 판단/ 양성을 양성으로 판단 + 2종오류) = 양성을 양성으로 판단 / 실제로 양성인 수)FN이 커질수록 recall값이 작아진다. 2종 오류와 관련되었다.

F1-점수(F1-score) : 정밀도와 재현율의 조화평균 : 2*정밀도*재현율/(정밀도+재현율) :정밀도와 재현율이 높을 때 함계 높아지며, 둘의 값이 비슷할수록 더 높은 값을 보인다. 1종오류가 중요하다면 정밀도에, 2종 오류가 중여하다면 재현율에 더욱 신경써야 한다. 특별히 더 중요한 오류 유형이 없다면 F1-점수를 검토하는 것이 무난하다.

13주차 – LIGHTGBM

장점 - XGBoost보다도 빠르고 높은 정확도를 부여주는 경우가 많다. 예측을 영향을 미친 변수의 중요도를 확인할 수 있다. 변수 종류가 많고 데이터가 클수록 상대적으로 뛰어난 성능을 보여준다.

딘점 복잡한 모델인만큼, 해석에 어려움이 있다. 더 나은 성능을 위한 하이퍼파라미터 튜닝이 까다롭다.

유용한곳 정형 데이터에서 catBoost, LightGBM, XGBoost 중에서 가장 좋은 성능을 보여준다.

트리기반의 최신 알고리즘이다. XGBoost와의 비교 시 장점- 빠른 학습 및 예측, 더 적은 메모리 사용, 데이터셋 자동 변환 및 최적 분할

균형 분할 방식(XGBoost): 좌우 노드 수가 균등하다 >분류가 필요없어도 나뉜다.

리프 중심 트리 분할 방식(LightGBM): 좌우 노드 수가 균등하지 않고, 깊게 펼쳐진다.

1문제정의 2 라이브러리 및 데이터 불러오기

전처리 3데이터 클리닝 4피처 엔지니어링 5모델링 및 평가하기

from google.colab import drive

drive.mount('/content/drive')

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

import seaborn as sns

data = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/fraud.csv')

data.info() # 데이터 많으면 낫널 카운트도 보여주지 않는다.

data.info(show_counts=True) # 결측치확인하기

round(data.describe(), 2)# 데이터 형태 확인하며 의미 없는 값 보기

data.drop(['first', 'last', 'street', 'city', 'state', 'zip', 'trans_num', 'unix_time', 'job', 'merchant'], axis=1, inplace=True) # 필요 없는 변수 지우기

data['trans_date_trans_time'] = pd.to_datetime(data['trans_date_trans_time']) # 변수 데이터 타입 변환하기

Z점수 = (특정값-평균)/표준편차

amt_info = data.groupby('cc_num').agg(['mean','std'])['amt'].reset_index() #z점수를 통한 정규화

data = data.merge(amt_info, on='cc_num', how='left') # 카드 번호를 기준으로 뒤에 붙이기

data['amt_z_score'] = (data['amt'] - data['mean']) / data['std'] # amt의 z점수 구해서 뒤에 붙이기

data[['amt', 'mean', 'std', 'amt_z_score']].head() # Z점수가 크면 평소의 표준편차 범위를 넘어 선 값이다> 특이한 값이다.

data.drop(['mean', 'std'], axis=1, inplace=True) # 다 쓴 값이니 버리기

category_info = data.groupby(['cc_num', 'category']).agg(['mean', 'std'])['amt'].reset_index() # 많이 쓰는 영역이 따로 있으므로 점수 따로 만들어 보기. 카드넘버와 카테고리를 기준으로

data = data.merge(category_info, on=['cc_num', 'category'], how='left') # 만든 점수 붙여주기

data['cat_z_score'] = (data['amt'] - data['mean']) / data['std'] # 이걸로 카테고리 점수 만들기

data.drop(['mean', 'std'], axis=1, inplace=True) # 다 썼으니 버리기

import geopy.distance # 거리계산. 두 지점에 대한 위도와 경도를 받으면 거리를 계산해준다.

data['merch_coord'] = pd.Series(zip(data['merch_lat'], data['merch_long'])) # 위도와 경도가 나뉘어져 있으므로 집으로 하나에 묶어준다.

data['cust_coord'] = pd.Series(zip(data['lat'], data['long']))

data['distance'] = data.apply(lambda x: geopy.distance.distance(x['merch_coord'], x['cust_coord']).km, axis=1) # 각 행마다 계산을 해야되기 때문에 apply를 붙인다.

distance_info = data.groupby('cc_num').agg(['mean', 'std'])['distance'].reset_index() # 거리에 따른 Z를 또 구한다.

data = data.merge(distance_info, on='cc_num', how='left')

data['distance_z_score'] = (data['distance'] - data['mean']) / data['std']# Z구하기!

data.drop(['mean', 'std'], axis=1, inplace=True) # 이것도 필요없으니까 삭제

data['age'] = 2021 - pd.to_datetime(data['dob']).dt.year # 나이 계산하기 2021년이라고 생각하고

data.drop(['cc_num', 'lat', 'long', 'merch_lat', 'merch_long', 'dob', 'merch_coord', 'cust_coord'], axis=1, inplace=True) # 필요없는 정보 다 삭제

data = pd.get_dummies(data, columns=['category', 'gender'], drop_first=True) # 문자열 더미 변수로 바꾸기

data.set_index('trans_date_trans_time', inplace=True) # 인덱스를 거래 시간으로 바꾸기

train = data[data.index < '2020-07-01'] # 랜덤적으로 훈련셋을 가지고 가면 안되기 때문에 시간으로 나눈다.

test = data[data.index >= '2020-07-01']

len(test)/len(data) # 비율 확인

X_train = train.drop('is_fraud', axis=1) # 값 빼줄꺼 빼주기

X_test = test.drop('is_fraud', axis=1)

y_train = train['is_fraud']

y_test = test['is_fraud']

import lightgbm as lgb#모델 불러오기

model_1 = lgb.LGBMClassifier(random_state = 100) # 모델 생성

model_1.fit(X_train, y_train) # 모델 훈련

pred_1 = model_1.predict(X_test) # 모델 예측

from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, roc_auc_score #여러가지의 점수를 보기 위해 많이 불러온다.

print(confusion_matrix(y_test, pred_1))# 혼동행렬 보여주기

print(classification_report(y_test, pred_1)) # 초점은 재현율이 중요하다.

proba_1 = model_1.predict_proba(X_test) # 어떻게 예측했는지 보여준다. 참과 거짓을 기준으로

proba_1 = proba_1[:,1] # 뒤의 열만 가지고 온다.

proba_int1 = (proba_1 > 0.2).astype('int') # 기준 변경해서 0.2보다 크면 1

proba_int2 = (proba_1 > 0.8).astype('int') # 0.8보다 크면 1

print(confusion_matrix(y_test, proba_int1))

print(classification_report(y_test, proba_int1))

print(confusion_matrix(y_test, proba_int2))

print(classification_report(y_test, proba_int2))

roc_auc_score(y_test, proba_1)# 0.8이상이면 높다.

L1,L2정규화 : 둘 다 매개변수에 패널티를 가해서 그 영향력을 감소시키는 방법으로, 오버피팅을 방지하는 목적으로 쓰인다.  L1정규화는 일부 매개변수가 0이 되도록 패널티를 가할 수 있기 때문에 피처 설렉션 효과도 있다

ROC곡선과 AUC: 이진분류 모델을 평가하는 방법으로, 기준점에 영향을 받지 않기 때문에 여러 모델을 비교할 때 요긴하게 사용된다. AUCROC곡선 아래의 면적을 의미하고, 0.5 ~ 1사이의 값을 지니며 높을수록 좋은 모델이다.

ROC곡선 : 민감도와 특이도의 개념을 통해 만들어진다.

14주차 – k평균 군집화

비지도 학습의 대표적인 알고리즘으로 목표 변수가 없는 상태(정답이 없는)에서 데이터를 비슷한 유형끼리 묶어내는 머신러닝 기법이다.

k-최근접 이웃 알고리즘과 비슷하게 거리기반으로 작동하며 적절한 k값을 사용자가 지정해야 한다. 거리기반으로 작동하기 때문에 데이터 위치가 가까운 데이터끼리 한 그룹으로 묶는다. 이때 전체 그룹의 수는 사용자가 지정한 k(하이퍼 파라미터)개이다.

순서: k평균 군집화는 중심점 k개를 임의로 설정합니다 > 각 중심점을 기준으로 가까이에 있는 데이터들을 해당 클러스터로 할당합니다. > 더 이상 클러스터에 변동이 없을 때까지 이 과정을 계속하여 반복합니다.

장점 구현이 비교적 간단하고, 클러스터링 결과를 쉽게 해석할 수 있다.

단점 최적의 k값을 자동으로 찾지 못하고, 사용자가 직접 선택해야 한다. 거리기반 알고리즘으로 변수의 스케일에 따라 다른 결과를 나타낼 수 있다.

예측하려는 종속변수가 존재하지 않을 때 사용하는 대표적인 비지도적 알고리즘이다.

from google.colab import drive

drive.mount('/content/drive')

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

import seaborn as sns

data = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/example_cluster.csv')

data#변수(열)가 2개이기 때문에 모니터에서 볼 수 있다.

sns.scatterplot(x='var_1', y='var_2', data=data) # 산점도로 확인. 이미 그룹화가 되어 있다.

from sklearn.cluster import KMeans

kmeans_model = KMeans(n_clusters=3, random_state=100)# 3개로 데이터를 나눈 것이다.

kmeans_model.fit(data)# 학습시키기

kmeans_model.predict(data) # 군집 위치 보여준다

data['label']=kmeans_model.predict(data)

sns.scatterplot(x='var_1', y='var_2', data=data, hue='label', palette='rainbow')# 경계가 뚜렸하게 보인다.

kmeans_model_new = KMeans(n_clusters=4, random_state=100)#하이퍼 파라미터 4

kmeans_model_new.fit(data)#훈련 시키기

data_new = data #훈련시킨거 저장하기 위해

data_new['new_label'] = kmeans_model_new.predict(data)# 여기에 저장

sns.scatterplot(x='var_1', y='var_2', data=data, hue='new_label', palette='rainbow')# 가시화

이너셔(inertia): 각 샘플과 가장 가까운 군집 중심 사이의 평균 제곱 거리를 측정한 수치

이너셔가 작다: 거리가 좁다: 오밀조밀하다. (군집이 많을 수 있다.)

kmeans_model.inertia_ #크다 작다는 말하기 애매하다.

temp_model = KMeans(n_clusters=500, random_state=100)#500개로 나누었다.

temp_model.fit(data)# 이 군집분류는 1000개를 500개로 나눈 것으로 과하게 나누었다.의미가 없다.

temp_model.inertia_# 낮으면 낮을 수록 좋은 군집 분류이다. 그러나 이건 과하다.

distance = []

for k in range(2, 10):

  k_model = KMeans(n_clusters=k)

  k_model.fit(data)

  distance.append(k_model.inertia_) # 계속 추가한다.

sns.lineplot(x=range(2, 10), y=distance)# 군집의 갯수가 늘어날 수록 이너샤가 줄어든다. 또한 이너샤가 급격하게 줄어드는 구간이 존재한다. 3개가 가장 적절하다. 이너샤가 의미있게 줄어드는 곳 즉 변곡점을 찾아되는데 3이 제일 적절하다.

customer = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/customer.csv')# 새로운 클러스터 실습

customer['cc_num'].nunique()# 카드 갯수

customer['category'].nunique() #사용처 갯수

customer_dummy = pd.get_dummies(customer, columns=['category']) # 사용처 더미로 변환

cat_list = customer_dummy.columns[2:] # 카테고리 리스트 별로 정리한다.

for i in cat_list:

  customer_dummy[i] = customer_dummy[i] * customer_dummy['amt']# 사용처와 금액 곱해서 보여주기

customer_agg = customer_dummy.groupby('cc_num').sum()#총금액으로 보여주기

from sklearn.preprocessing import StandardScaler # 스케일링이 필수다!

scaler = StandardScaler()

scaled_df = pd.DataFrame(scaler.fit_transform(customer_agg), columns=customer_agg.columns, index=customer_agg.index)

scaled_df.head() # 평균이 0이고 표준편차가 1인 것으로 변경되었다.

distance = [] # 이너셔 확인 단계
for k in range(2, 10):
  k_model = KMeans(n_clusters=k)
  k_model.fit(scaled_df)
  labels = k_model.predict(scaled_df)
  distance.append(k_model.inertia_)

sns.lineplot(x=range(2, 10), y=distance)
from sklearn.metrics import silhouette_score # 시루엣 스코어 계산
silhouette = []
for k in range(2, 10):
  k_model = KMeans(n_clusters=k)
  k_model.fit(scaled_df)
  labels = k_model.predict(scaled_df) # 군집 안거리,밖의 거리도 계산하기 때문에 오래걸린다.
  silhouette.append(silhouette_score(scaled_df, labels))# 데이터와 라벨 둘다가 필요하다.
sns.lineplot(x=range(2, 10), y=silhouette) # 높을수록 좋은 군집 분류이다.
k_model = KMeans(n_clusters=4)# 4일때가 가장 좋으므루
k_model.fit(scaled_df)
labels = k_model.predict(scaled_df)
scaled_df['label'] = labels# 추가해서 저장해놓기
scaled_df_mean = scaled_df.groupby('label').mean()
scaled_df_count = scaled_df.groupby('label').count()['category_travel']# 한 변수만 불러와보기
scaled_df_count = scaled_df_count.rename('count')
scaled_df_all = scaled_df_mean.join(scaled_df_count)#데이터 합치기

15주차 -PCA 주성분 분석

비지도 학습, 종속변수 없음

Pca의 목적 - 데이터의 차원(변수의 개수)을 축소한다. = 정보가 줄어든다. 가능한 그 특성을 최대한 보존하는 방법. 기존의 변수들의 정보를 모두 반영하는 새로운 변수를 주로 만들었다. > 새로운 변수를 만들어서 차원을 축소하는 방법이다.

장점: 다차원을 2차원에 적합하도록 차원을 축소하여 시각화에 유용하고, 변수 간의 높은 상관관계 문제를 해결해준다.

단점: 기존 변수가 아닌 새로운 변수를 사용하여 해석하는 데 어려움이 있다. 차원이 축소됨에 따라 정보 손실이 불가피하다.

유용한 곳: 다차원 변수들을 2차원 그래프로 표현할 경우, 변수가 너무 많아 모델 학습 시간에 시간이 너무 오래걸릴 경우( 차원 축소를 진행하면 연산의 시간을 줄일 수 있다.) 오버피팅을 방지하는 용도

주성분 분석의 이해: 선형대수 eigen value, eigen vector, 역행렬 계산, 주성분 계산

차원 축소에는 변수 선택(특정 변수만을 선택함으로써 데이터의 차원을 줄이는 것)과 변수 추출(기존의 변수들을 이용하여 새로운 변수를 생성)이 있다. PCA는 변수 추출이다.

from google.colab import drive

drive.mount('/content/drive')

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

import seaborn as sns

customer = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/customer_pca.csv')

customer_X = customer.drop('label', axis=1)#라벨 분리

customer_y = customer['label']

from sklearn.decomposition import PCA # 분리하는 것 불러오기

pca = PCA(n_components=2) #주성분을 그래프에 그릴 수 있도록 2개만 추출

pca.fit(customer_X)#학습하기

customer_pca = pca.transform(customer_X)

customer_pca = pd.DataFrame(customer_pca, columns = ['PC1', 'PC2'])# 데이터 프레임 형태로 변화

customer_pca = customer_pca.join(customer_y)# 라벨값 뒤에 붙이기

sns.scatterplot(x='PC1', y='PC2', data = customer_pca, hue = 'label', palette = 'rainbow') # 그래프(산점도) 형식으로 보여주기

pca.components_# 어떻게 변수를 만들었나

df_comp = pd.DataFrame(pca.components_, columns = customer_X.columns)# 데이터 프레임 형태로 확인

sns.heatmap(df_comp, cmap='coolwarm')#그래프로 확인

다음 PCA실습

anonymous = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/anonymous.csv')

anonymous['class'].mean()

anonymous.isna().sum().sum() # 데이터 전체 결측치 확인

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(anonymous.drop('class', axis=1), anonymous['class'], test_size=0.2, random_state=100)

from sklearn.preprocessing import StandardScaler # 모델간 차이 없애주

 

scaler = StandardScaler()# 스케일러 선언

scaler.fit(X_train)# 정규화 시키기

X_train_scaled = scaler.transform(X_train)# 스케일시키기

X_test_scaled = scaler.transform(X_test)# 훈련데이터로 스케일 되는 거다.

from sklearn.ensemble import RandomForestClassifier

model_1 = RandomForestClassifier(random_state = 100)

model_1.fit(X_train_scaled, y_train)#훈련시키기

from sklearn.metrics import accuracy_score, roc_auc_score

pred_1 = model_1.predict(X_test_scaled)

accuracy_score(y_test, pred_1)# 점수 확인

proba_1 = model_1.predict_proba(X_test_scaled)

roc_auc_score(y_test, proba_1[:, 1])# 모든 데이터 셋을 활용하였으므로 좋은 점수가 나왔다.

pca = PCA(n_components=2)

pca.fit(X_train_scaled)

pca.explained_variance_ratio_#기존 변수의 분산(변동)을 어떻게 설명하는가

for i in range(100, 550, 50):

  pca = PCA(n_components=i)

  pca.fit_transform(X_train_scaled)

  ratio = pca.explained_variance_ratio_.sum()

  var_ratio.append(ratio)

sns.lineplot(x=range(100, 550, 50), y=var_ratio) # 경향 보기

pca = PCA(n_components = 400, random_state = 100) # 80퍼에 맞춰서 주성분 분석

pca.fit(X_train_scaled)

X_train_scaled_pca = pca.transform(X_train_scaled)

X_test_scaled_pca = pca.transform(X_test_scaled)

model_2 = RandomForestClassifier(random_state = 100) # 이것으로 랜덤 포레스트

model_2.fit(X_train_scaled_pca, y_train)

pred_2 = model_2.predict(X_test_scaled_pca)# 점수 확인

accuracy_score(y_test, pred_2)

proba_2 = model_2.predict_proba(X_test_scaled_pca)

roc_auc_score(y_test, proba_2[:, 1])#점수 높은걸 봐서 변수를 10퍼센트로 줄여서 전체와 같은 효과를 내었다,

 

 

          

728x90