본문 바로가기
IT & 데이터 사이언스/Python

[Python Data Analytics] Python을 활용한 Machine Learning

by 바른 호랑이 2023. 6. 23.
728x90
반응형

안녕하세요. 바른 호랑이입니다.

이번 게시글에서는 실제 데이터들과 Python을 활용하여 다양한 Machine Learning 실습을 진행해볼 예정입니다.

결국 데이터를 잘 가공하고 전처리하는 과정을 통해 얻어내고자 하는 것은 그 데이터 속의 패턴을 분석하여 결과를 예측함으로써 보다 더 나은 판단을 하기 위함입니다. 이와 같은 예측을 보다 편리하게 할 수 있게 Python은 여러가지 ML(Machine Learning)패키지들을 제공하고 있으며, 이를 활용하여 보다 편리하게 패턴을 파악하고 결과를 예측할 수 있습니다.

ML에는 크게 지도학습, 비지도학습으로 분류할 수 있으며, 이번에는 이와 같은 학술적이고 이론적인 부분들을 다루기 보다는 실제로 그와 같은 모델들을 어떤 식으로 사용하고 코딩해야하는지에 대한 실습 위주로 알아볼 예정이며, 실제 업무를 진행할 때는 원천 소스로부터 가져온 로우 데이터들을 처리하고 정형화하는 과정을 거쳐야하지만 그와 같은 데이터를 처리하는 부분은 생략하고 이미 잘 정리되어 있는 학습 데이터들을 사용할 예정입니다. 실습 환경은 Colab을 활용하여 진행하였으며, 보다 상세한 코드 구성이 궁금하신 분들은 아래의 실습파일을 참고해주시면 되겠습니다.

※ 실습파일

Python_DataAnalysis_08(Data Analysis_ML).ipynb
1.13MB

'''
* 머신러닝의 개념
- 기계(machine) 스스로 데이터를 학습하여 서로 다른 변수 간의 관계를 찾아 나가는 과정이라 할 수 있으며,
예측(prediction), 분류(classification), 군집(clustering) 알고리즘 등으로 분류됨.
- 정답 데이터를 가지고 학습에 활용하면 지도학습(supervised learning), 정답 데이터 없이 컴퓨터 알고리즘
스스로 데이터로부터 숨은 패턴을 찾아내면 비지도학습(unsupervised learning)이라고 함.
- 머신러닝 프로세스
1. 데이터 정리
2. 데이터 분리(훈련/검증)
3. 알고리즘 준비
4. 모형학습(훈련데이터)
5. 예측(검증데이터)
6. 모형평가(confusion matrix+α)
7. 모형활용
'''
# 필요 패키지 설치
!pip install numpy
!pip install pandas
!pip install scikit-learn
!pip install scipy

# 경고메세지 제거
import warnings
warnings.filterwarnings(action='ignore')

# 단순회귀분석(Simple Linear Regression) : 2개의 변수 사이의 확률적, 통계적 상관성을 찾는 알고리즘
# 필요 패키지 불러오기
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import sklearn

# 필요 데이터셋 불러오기
df = sns.load_dataset('mpg')
df.info()

# 데이터 기초통계정보 확인
df.describe()

# 누락데이터 수 체크
print(df.isnull().sum(), len(df), sep='\n')

# 누락데이터 삭제 후 재확인
df.dropna(subset=['horsepower'], inplace=True)
print(df.isnull().sum(), len(df), sep='\n')

# 두 매개 변수에 대한 산점도 그리기 - Pandas
df.plot(kind='scatter', x='weight', y='mpg', c='coral', s=10, figsize=(10, 5))

# 두 매개변수에 대한 산점도 그리기 - seaborn
sns.regplot(x='weight', y='mpg', data=df) # 회귀선 미표시

sns.jointplot(x='weight', y='mpg', data=df, kind='reg') # 회귀선 표시

# 모든 변수들에 대한 산점도 그리기
sns.pairplot(df, height=2.5, aspect=1)

# 독립/종속 변수 선택
X = df[['weight']]
y = df['mpg']

# 훈련/종속 데이터 분할
X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(X, y, test_size=0.3, random_state=10)
print(len(X_train), len(X_test), sep=' / ')

# sklearn에서 선형회귀분석 모듈 가져오기
lr = sklearn.linear_model.LinearRegression()

# 모델 학습 시키기
lr.fit(X_train, y_train)

# 학습시킨 모델의 결정계수 계산
r_square = lr.score(X_test, y_test)
print(r_square)

# 회귀식의 내용 확인
print(f'기울기 : {lr.coef_}\ny절편 : {lr.intercept_}')

# 실제 값과 예측값의 차이 확인
y_hat = lr.predict(X)

plt.figure(figsize=(10, 5))
ax1 = sns.kdeplot(y, label='y')
ax2 = sns.kdeplot(y_hat, label='y_pred')
plt.legend()
plt.show()

# 다항 회귀분석(Ploynomial Regression) : 2차 함수 이상의 다항 함수를 이용하여 두 변수간의 선형관계를 설명하는 알고리즘
# 데이터 확인
df.info()

# train, test data 분리
X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(df[['weight']], df['mpg'], test_size=0.3, random_state=10)

print(f'훈련 데이터 : {X_train.shape}\n검증 데이터 : {X_test.shape}')

# 데이터 변형을 위한 함수 로드
poly = sklearn.preprocessing.PolynomialFeatures(degree=2) # 2차항 적용
X_train_poly = poly.fit_transform(X_train) # X_train data를 2차항으로 적용

print(f'원 데이터 : {X_train.shape}\n2차항 변환 데이터 : {X_train_poly.shape}')

# 모델로드 후 학습
pr = sklearn.linear_model.LinearRegression()
pr.fit(X_train_poly, y_train)

# 테스트 데이터로 결정계수 계산
X_test_poly = poly.fit_transform(X_test)
r_square = pr.score(X_test_poly, y_test)
print(r_square)

# 분석 결과 시각화
X_poly = poly.fit_transform(X)
y_hat = pr.predict(X_poly)

plt.figure(figsize=(10, 5))
ax1 = sns.kdeplot(y, label='y')
ax2 = sns.kdeplot(y_hat, label='y_hat, ax=ax1')
plt.legend()
plt.show()

# 다중회귀분석(Multivariate Regression) : 2개 이상의 독립변수들이 종속변수에 미치는 영향을 확인하기 위해 사용하는 알고리즘
# 훈련, 검증 데이터 분할
X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(df[['cylinders', 'horsepower', 'weight']], df['mpg'], test_size=0.3, random_state=10)

print(f'훈련 데이터 : {X_train.shape}\n검증 데이터 : {X_test.shape}')

# 모델 로드 후 학습
lr = sklearn.linear_model.LinearRegression()
lr.fit(X_train, y_train)

# 결과 확인
r_square = lr.score(X_test, y_test)
print(f'결정계수 : {r_square}\n\nX변수의 계수 : {lr.coef_}\n\n상수항 : {lr.intercept_}')

# 결과 시각화
y_hat = lr.predict(X_test)

plt.figure(figsize=(10, 5))
ax1 = sns.kdeplot(y_test, label='y_test')
ax2 = sns.kdeplot(y_hat, label='y_hat', ax=ax1)
plt.legend()
plt.show()

# 분류 모델
# KNN(K-Nearest-Neigbors) : k개의 가장 가까운 이웃으로 집단을 구성하는 알고리즘으로 k값에 따라 정확도가 상이함.
df_titanic = sns.load_dataset('titanic')

# 데이터 살펴보기
df_titanic.info()

df_titanic.describe()

# 불필요 컬럼 삭제
rdf = df_titanic.drop(['deck', 'embark_town'],  axis=1)

# 나이데이터가 NaN인 모든 행 삭제
rdf = rdf.dropna(subset=['age'], how='any', axis=0)
print(f'{rdf.isnull().sum()}\n\n행의 길이 : {len(rdf)}')

# embarked NaN값 처리
most_freq = rdf['embarked'].value_counts(dropna=True).idxmax()

rdf['embarked'].fillna(most_freq, inplace=True)
print(f'{rdf.isnull().sum()}\n\n행의 길이 : {len(rdf)} / embarked 컬럼의 최대값 : {most_freq}')

# 분석에 사용할 열 분리
ndf = rdf[['survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'embarked']]

# embarked, sex열 원핫인코딩
onehot_sex = pd.get_dummies(ndf['sex'])
onehot_embarked = pd.get_dummies(ndf['embarked'], prefix='town')

ndf = pd.concat([ndf, onehot_sex], axis=1)
ndf = pd.concat([ndf, onehot_embarked], axis=1)

ndf.drop(['sex', 'embarked'], axis=1, inplace=True)
print(ndf.head())

# X, y변수 분할
X = ndf[['pclass', 'age', 'sibsp', 'parch', 'female', 'male', 'town_C', 'town_Q', 'town_S']]
y = ndf['survived']

# 설명변수 데이터 정규화
X = sklearn.preprocessing.StandardScaler().fit(X).transform(X)

# 훈련, 검증 데이터 분할
X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(X, y, test_size=0.3, random_state=10)

print(f'훈련 데이터 : {X_train.shape}\n검증 데이터 : {y_train.shape}')

# 모델 로드 후 학습
knn = sklearn.neighbors.KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)

y_hat = knn.predict(X_test)

print(f'{y_hat[0:10]}\n{y_test.values[0:10]}')

# 모형 성능 평가
knn_matrix = sklearn.metrics.confusion_matrix(y_test, y_hat)
knn_matrix

# 결과 확인 : classification_report는 precision[TP/(TP+FP)], recall[TP/(TP+FN)], f1_score[2*((precision*recall)/(precision+recall))]를 출력해줌.
knn_report = sklearn.metrics.classification_report(y_test, y_hat)
print(knn_report)

# SVM(Support Vector Machine) : 데이터셋의 여러 속성들을 열 벡터 형태로 변환하여 벡터공간을 구현하고 그 위에 좌표로 각 데이터를 분류하여 집단을 나누는 방법
# 데이터 탐색 / 전처리
# NaN값이 많은 deck 열 삭제, embarked와 의미가 겹치는 embark_town 열 삭제
rdf_2 = df_titanic.drop(['deck', 'embark_town'], axis=1)

# age열에 나이 데이터가 없는 행 삭제
rdf_2 = rdf_2.dropna(subset=['age'], how='any', axis=0)

# embarked 열의 NaN 값을 최대 빈도 수 값으로 치환
most_freq_2 = rdf_2['embarked'].value_counts(dropna=True).idxmax()
rdf['embarked'].fillna(most_freq, inplace=True)

# 분석에 활용할 열 선택
ndf_2 = rdf_2[['survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'embarked']]

# 원핫인코딩 진행
onehot_sex_2 = pd.get_dummies(ndf_2['sex'])
onehot_embarked_2 = pd.get_dummies(ndf_2['embarked'], prefix='town')

ndf_2 = pd.concat([ndf_2, onehot_sex_2, onehot_embarked_2], axis=1)

ndf_2.drop(['sex', 'embarked'], axis=1, inplace=True)

# 데이터셋 구분
X = ndf_2[['pclass', 'age', 'sibsp', 'parch', 'female', 'male', 'town_C', 'town_Q', 'town_S']] # 독립변수
y = ndf_2['survived'] # 종속변수

# 설명 변수 정규화
X = sklearn.preprocessing.StandardScaler().fit(X).transform(X)

# 훈련, 검증 데이터 분할
X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(X, y, test_size=0.3, random_state=10)

print(f'훈련 데이터 : {X_train.shape} / 검증 데이터 : {X_test.shape}')

# 모델 로드 후 학습
svm = sklearn.svm.SVC(kernel='rbf')
svm.fit(X_train, y_train)

# 학습시킨 모델로 예측값 계산
y_hat = svm.predict(X_test)

print(f'{y_hat[:10]}\n\n{y_test.values[:10]}')

# 모형 성능 평가
svm_matrix = sklearn.metrics.confusion_matrix(y_test, y_hat)
svm_report = sklearn.metrics.classification_report(y_test, y_hat)

print(f'{svm_matrix}\n\n{svm_report}')

# 의사결정 나무(Decision Tree) : 트리 구조를 사용하여 각 분기점에서 분석 대상의 속성을 위치시켜 각 분기점마다 목표값을 가장 잘 분류할 수 있는 속성을 찾아 배치하고 가지를 만들어 분류하는 방법
# 데이터 셋 로드
uci_path = 'https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data'
df_cancer = pd.read_csv(uci_path, header=None)
# 열 이름 지정
df_cancer.columns = ['id', 'clump', 'cell_size', 'cell_shape', 'adhesion', 'epithlial', 'bare_nuclei', 'chromatin', 'normal_nucleoli', 'mitoses', 'class']

# data 구조 확인
df_cancer.info()

df_cancer.describe()

# NaN 데이터 변경
df_cancer['bare_nuclei'].replace('?', np.nan, inplace=True)
df_cancer.dropna(subset=['bare_nuclei'], axis=0, inplace=True)
df_cancer['bare_nuclei'] = df_cancer['bare_nuclei'].astype('int')

df_cancer.info()

df_cancer.describe()

# 훈련, 검증 데이터 분할
X = df_cancer[['clump', 'cell_size', 'cell_shape', 'adhesion', 'epithlial', 'bare_nuclei', 'chromatin', 'normal_nucleoli', 'mitoses']]
y = df_cancer['class']

# 설명변수 정규화
X = sklearn.preprocessing.StandardScaler().fit(X).transform(X)

X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(X, y, test_size=0.3, random_state=10)

print(f'훈련 데이터 : {X_train.shape} / 검증 데이터 : {X_test.shape}')

# 모델 로드 후 학습
tree = sklearn.tree.DecisionTreeClassifier(criterion='entropy', max_depth=5)
tree.fit(X_train, y_train)

# 학습모델로 예측
y_hat = tree.predict(X_test)

print(f'{y_hat[:10]}\n\n{y_test.values[:10]}')

# 모형 성능 평가
tree_matrix = sklearn.metrics.confusion_matrix(y_test, y_hat)
tree_report = sklearn.metrics.classification_report(y_test, y_hat)

print(f'{tree_matrix}\n\n{tree_report}')

# 군집분석
# K-Means : 각 클러스터의 중심까지의 거리를 이용하여 데이터 간의 유사성을 측정하여 군집을 분류하는 알고리즘
# 데이터 셋 로드
uci_path = 'https://archive.ics.uci.edu/ml/machine-learning-databases/00292/Wholesale%20customers%20data.csv'
df_ws = pd.read_csv(uci_path, header=0)

# 데이터 살펴보기
df_ws.info()

df_ws.describe()

# 데이터 정규화
X = sklearn.preprocessing.StandardScaler().fit(df_ws).transform(df_ws)
print(X[:5])

# 모델 생성 후 학습
kmeans = sklearn.cluster.KMeans(init='k-means++', n_clusters=5, n_init=10)
kmeans.fit(X)

# 예측 후 결과를 데이터프레임에 저장
cluster_label = kmeans.labels_
print(cluster_label)

df_ws['Cluster'] = cluster_label
df_ws.head()

# 결과 시각화
df_ws.plot(kind='scatter', x='Grocery', y='Frozen', c='Cluster', cmap='Set1', colorbar=False, figsize=[10, 10])

P.S 더 나은 개발자가 되기위해 공부중입니다. 잘못된 부분을 댓글로 남겨주시면 학습하는데 큰 도움이 될 거 같습니다

728x90
반응형

댓글