2026/04/28 TUE.
| O | |
| X | |
| O | ● |
| O | |
| ↓ 주간 목표 ↓ | |
● 자격증 공부 |
|
⊙ 아티클 스터디
( https://qc-standard.tistory.com/68 )
⊙ 머신러닝 심화 2강
● 2-1 의사결정나무와 랜덤 포레스트
☑️ 의사결정나무(Decision Tree, DT)
- 나무 구조로 나타내어 전체 자료를 몇 개의 소집단으로 분류하거나 예측을 수행하는 분석 방법

- 명칭
: 루트 노드(Root Node): 의사결정나무의 시작점. 최초의 분할조건
: 리프 노드(Leaf Node): 루트 노드로부터 파생된 중간 혹은 최종 노드
: 분류기준(criteria): sex는 여성인 경우 0, 남성인 경우 1로 인코딩. 여성인 경우 좌측 노드로, 남성인 경우 우측 노드로 분류
: 불순도(impurity) - 불순도 측정 방법 중 하나 인 지니 계수는 0과 1사이 값으로 0이 완벽한 순도(모든 샘플이 하나의 클래스), 1은 완전한 불순도(노드의 샘플의 균등하게 분포) 됨을 나타냄
: 불순도(impurity) - 리프 노드로 갈수록 불순도가 작아지는(한쪽으로 클래스가 분류가 잘되는)방향으로 나무가 자람
: 리프 노드로 갈수록 불순도가 작아지는(한쪽으로 클래스가 분류가 잘되는)방향으로 나무가 자람
: 값(value): Y변수에 대한 배열. 549명이 죽었고(Y = 0), 342명이 살았음(Y = 1)
: 클래스(class) - 가장 많은 샘플을 차지하는 클래스를 표현
: 클래스(class) - 위에서는 주황색(Y = 0 다수), 파란색(Y=1 다수)를 표현
☑️ 의사결정나무 정리
- 장점
: 쉽고 해석하기 용이
: 다중분류와 회귀에 모두 적용이 가능
: 이상치에 견고하며 데이터 스케일링이 불필요(데이터의 상대적인 순서를 고려해서) - 단점
: 나무가 성장을 너무 많이하면 과대 적합의 오류에 빠질 수 있다
: 훈련 데이터에 민감하게 반응하여 작은 변화가 노이즈에도 나무의 구조가 크게 달라짐(불안정성)
|
☑️ 실습
더보기
|
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import LabelEncoder
from sklearn.tree import DecisionTreeClassifier,plot_tree
|
|
|
titanic_df = pd.read_csv('/content/train.csv')
titanic_df.info()
|
![]() |
|
X_features = ['Pclass', 'Sex', 'Age']
# Apply LabelEncoder to 'Sex'
le_sex = LabelEncoder()
titanic_df['Sex'] = le_sex.fit_transform(titanic_df['Sex'])
le_pclass = LabelEncoder()
titanic_df['Pclass'] = le_pclass.fit_transform(titanic_df['Pclass'])
age_mean = titanic_df['Age'].astype(float).mean()
titanic_df['Age'] = titanic_df['Age'].fillna(age_mean)
X = titanic_df[X_features]
y = titanic_df['Survived']
# max_depth를 정하지 않으면 나무가 지니계수-최소화 될 때까지 무제한 성장
model_df = DecisionTreeClassifier(max_depth = 1)
model_df.fit(X,y)
plt.figure(figsize=(10,5))
plot_tree(model_df, feature_names=X_features, class_names=['Not Survived', 'Survived'],filled=True)
plt.show()
|
![]() |
|
X_features = ['Pclass', 'Sex', 'Age']
# Apply LabelEncoder to 'Sex'
le_sex = LabelEncoder()
titanic_df['Sex'] = le_sex.fit_transform(titanic_df['Sex'])
le_pclass = LabelEncoder()
titanic_df['Pclass'] = le_pclass.fit_transform(titanic_df['Pclass'])
age_mean = titanic_df['Age'].astype(float).mean()
titanic_df['Age'] = titanic_df['Age'].fillna(age_mean)
X = titanic_df[X_features]
y = titanic_df['Survived']
# max_depth를 정하지 않으면 나무가 지니계수-최소화 될 때까지 무제한 성장
model_df = DecisionTreeClassifier(max_depth = 10)
model_df.fit(X,y)
plt.figure(figsize=(10,5))
plot_tree(model_df, feature_names=X_features, class_names=['Not Survived', 'Survived'],filled=True)
plt.show()
|
![]() |
● 2-2 랜덤 포레스트
- 의사결정 나무는 과적합과 불안정성 대한 문제가 대두
- 이를 해결하기 위한 아이디어는 바로 나무(tree)를 여러 개 만들어 숲(Forest)를 만드는 것
☑️ 배깅(Bagging)의 원리
- 언제나 머신러닝은 데이터의 부족이 문제 → 해결 하기 위한 Bootstrapping + Aggregating 방법론
- Bootstrapping: 데이터를 복원 추출해서 유사하지만 다른 데이터 집단을 생성하는 것
- Aggregating: 데이터의 예측,분류 결과를 합치는 것
- Ensemble(앙상블): 여러 개의 모델을 만들어 결과를 합치는 것
- ㅇㄴㄶ
- Bootstrap은 “자기 스스로 해낸다”의 뜻의 유래
- (신발 뒤 작은 고리 = bootstrap)
- 데이터를 복원추출한다는 것을 뜻
- 데이터 샘플들은 모집단의 분포를 유사하게 따라가고 있으니 다양성을 보장하면서 데이터의 부족한 이슈를 해결

☑️ Tree를 Forest로 만들기
- 여러 개의 데이터 샘플에서 각자 의사결정트리를 만들어서 다수결 법칙에 따라 결론을 냄

- 숫자라면 평균 등을 이용
- 일반적으로 굉장히 뛰어난 성능
☑️ 랜덤 포레스트 정리
- 장점
: Bagging 과정을 통해 과적합을 피할 수 있다
: 이상치에 견고하며 데이터 스케일링이 불필요
: 변수 중요도를 추출하여 모델 해석에 중요한 특징을 파악 할 수 있다 - 단점
: (데이터를 여러개 생성해서) 컴퓨터 리소스 비용이 크다
: 앙상블 적용으로 해석이 어렵다
|
☑️ 실습
더보기
|
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score,f1_score
|
|
|
model_lor = LogisticRegression()
model_dt = DecisionTreeClassifier(random_state=42)
#모델 실행할 때 마다 바뀌는 걸 방지하기 위해
model_rf = RandomForestClassifier(random_state=42)
model_lor.fit(X,y)
model_dt.fit(X,y)
model_rf.fit(X,y)
y_lor_pred = model_lor.predict(X)
y_dt_pred = model_dt.predict(X)
y_rf_pred = model_rf.predict(X)
#평가지표
def get_score(model_name, y_true, y_pred):
acc = round(accuracy_score(y_true, y_pred), 2)
f1 = round(f1_score(y_true, y_pred), 2)
print(model_name, 'acc 스코어는 : ', acc, 'f1_score는 : ', f1)
get_score('lor',y,y_lor_pred)
get_score('dt',y,y_dt_pred)
get_score('rf',y,y_rf_pred)
|
![]() |
|
X_features
|
|
|
model_rf.feature_importances_
#각 변수의 중요도
|
● 2-3 KNN : K-Nearest Neighbor(KNN) 알고리즘
☑️ 최근접 이웃 알고리즘 수행 방법
- 유유상종
- 비슷한 특징, 데이터를 갖고 있는 것끼리 Y값이 유사하지 않을까?라는 아이디어에서 시작
- K-Nearest Neighbor(KNN, KNN)
- 주변의 데이터를 보고 내가 알고 싶은 데이터를 예측하는 방식

- K=3이라면 별 1개와 세모 2개이므로 ? 는 세모로 예측될 것
- K=7이라면 별 4개와 세모 3개이므로 ?는 별로 예측될 것
☑️ 하이퍼 파라미터의 개념
- 파라미터(Parameter) : 머신러닝 모델이 학습 과정에서 추정하는 내부 변수이며 자동으로 결정 되는 값
Ex) 선형회귀에서 가중치와 편향 - 하이퍼 파라미터(Hyper parameter) : 데이터 과학자가 기계 학습 모델 훈련을 관리하는데 사용하는 외부 구성변수이며 모델 학습과정이나 구조에 영향을 미침
- K를 몇개 쯤 봐야하는지 Data Science 재량
- 좋은 평가 지표가 나올 때까지 실험하고 원리를 밝혀 : Grid Serch
☑️ 거리의 개념
- 두 점의 좌표가 주어지면 피타고라스의 정리로 거리를 구할 수 있음 : 유클리드 거리(Euclidean Distance)
- 맨해튼 거리 : 실제 거리

- X와 Y가 차원이 달라서 그 단위가 다르기 때문에 → 단위를 맞춰주기 위해 → 스케일링&표준화 필수
☑️ KNN 모델 정리
- 장점
: 이해하기 쉽고 직관적
: 모집단의 가정이나 형태를 고려하지 않음
: 회귀, 분류 모두 가능함 - 단점
: 차원 수가 많을 수록 계산량이 많아짐
: 거리 기반의 알고리즘이기 때문에 피처의 표준화가 필요함
|
● 2-4 부스팅
- 여러 개의 약한 학습기(weak learner)를 순차적으로 학습하면서 잘못 예측한 데이터에 가중치를 부여하여 오류를 개선해나가는 학습 방식
- 랜덤포레스트는 하나의 트리가 존재할 때, 다수결로 여러가지를 만들어서 복합적으로 앙상블을 이용
- 부스팅 못난 데이터 분리기를 잘 못하는 걸 채찍질 해서 점점 좋게 합쳐나가는 방법

☑️ 부스팅 알고리즘 종류
| Gradient Boosting Model | XGBoost | LightGBM | |
| 특징 | ○ 가중치 업데이트를 경사하강법 방법을 통해 진행 | ○ 트리기반 앙상블 기법으로, 가장 각광받으며 Kaggle의 상위 알고리즘 ○ 병렬학습이 가능해 속도가 빠름 ○ 오래 걸린다는 단점 |
○ XGBoost와 함께 가장 각광받는 알고리즘 ○ XGBoost보다 학습시간이 짧고 메모리 사용량이 작음 ○ 작은 데이터(10,000건 이하)의 경우 과적합 발생 |
| Python 라이브러리 |
|
|
|
- 조절할 변수도 많고 알아야할 개념도 많음
● 2-5 실습
더보기
|
!pip install xgboost
!pip install lightgbm
|
|
|
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import GradientBoostingClassifier
from xgboost import XGBClassifier
from lightgbm import LGBMClassifier
|
|
|
model_knn = KNeighborsClassifier()
model_gbm = GradientBoostingClassifier(random_state=42)
model_xgb = XGBClassifier(random_state=42)
model_lgb = LGBMClassifier(random_state=42)
model_knn.fit(X,y)
model_gbm.fit(X,y)
model_xgb.fit(X,y)
model_lgb.fit(X,y)
y_knn_pred = model_knn.predict(X)
y_gbm_pred = model_gbm.predict(X)
y_xgb_pred = model_xgb.predict(X)
y_lgb_pred = model_lgb.predict(X)
get_score('lor',y,y_lor_pred)
get_score('dt',y,y_dt_pred)
get_score('rf',y,y_rf_pred)
get_score('knn',y,y_knn_pred)
get_score('gbm',y,y_gbm_pred)
get_score('xgb',y,y_xgb_pred)
get_score('lgb',y,y_lgb_pred)
|
![]() |
⊙ 머신러닝 심화 3강 - 비지도 학습
● 3-1 군집화
- 정답이 없는 데이터를 다루는 비지도 학습에 대해서 군집화 알고리즘
- 회귀와 분류는 대표적인 지도학습 | 지도학습은 문제(X)와 정답(Y)가 주어지고 문제(X)가 주어졌을때 정답(Y)을 맞추는/정답(Y)를 예측하는 학습
- 답(Y)을 알려주지 않고 데이터 간 유사성을 이용해서 답(Y)을 지정하는 방법

- = 레이블링 작업
- 정답이 없는 문제이기 때문에 지도 학습보다 조금 어렵고 주관적인 판단이 개입
☑️ 비지도 학습
| sepal_length : 꽃 받침의 길이 |
sepal_width : 꽃 받침의 너비 |
petal_length : 꽃 잎의 길이 |
petal_width : 꽃 잎의 너비 |
species(Y, 레이블) : 붓꽃 종(setosa, virginica, versicolor) |
꽃에 대한 정보(X)로 종, Species(Y)를 맞추는 문제를 푼다면 지도 학습
반면, Species가 없다면? 정보에 따라서 데이터를 분류해볼 수 있지 않을까요?



☑️ K-Means Clustering 수행 순서

- ▲ K개 군집 수 설정
= 최종적으로 몇 개의 그룹으로 나눌 것인가를 설정 - ▲ 임의의 중심을 선정
- ▲ 해당 중심점과 거리가 가까운 데이터를 그룹화
- ▼ 데이터의 그룹의 무게 중심으로 중심점을 이동
- ▼ 중심점을 이동했기 때문에 다시 거리가 가까운 데이터를 그룹화 (3~5번 반복)

- 장점
: 일반적이고 적용하기 쉬움 - 단점
: 거리 기반(knn과 비슷)으로 가까움을 측정하기 때문에 차원이 많을 수록 정확도가 떨어짐
: 반복 횟수가 많을 수록 시간이 느려짐
: 몇 개의 군집(K)을 선정할지 주관적임
: 평균을 이용하기 때문에(중심점) 이상치에 취약함
|
sklearn.cluster.KMeans
|
|
|
|
☑️ 군집평가 지표 - 실루엣 계수
군집화가 잘되어 있다는 것은 같은 군집끼리는 가까이 || 다른 군집끼리는 멀리


- 좋은 군집화의 조건
: 실루엣 값이 높을수록(1에 가까움)
: 개별 군집의 평균 값의 편차가 크지 않아야 함
|
sklearn.metrics.sihouette_score
: 전제 데이터의 실루엣 계수 평균 값 반환 |
|
☑️ 실습-붓꽃
더보기
|
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
|
|
|
iris_df = sns.load_dataset('iris')
iris_df.head(3)
|
![]() |
|
iris_df.info()
|
![]() |
|
sns.scatterplot(data=iris_df, x='sepal_length', y='sepal_width')
|
![]() |
|
#종별로 보고 싶다
sns.scatterplot(data=iris_df, x='sepal_length', y='sepal_width', hue = 'species')
|
![]() |
▽K-means로 y값을 모른다고 가정하고 군집화▽ |
|
|
iris_df2 = iris_df[['sepal_length','sepal_width','petal_length','petal_width']]
iris_df2.head()
|
![]() |
|
from sklearn.cluster import KMeans
#옵션
#군집화(클러스터) 개수=k값
#init = 'k-means++ : 중심점
# max_iter = 300 : 최대 반복횟수
# random_state=42 : 결과값 고정
kmeans = KMeans(n_clusters=3, init = 'k-means++', max_iter = 300, random_state=42)
kmeans.fit(iris_df2)
|
|
|
kmeans.labels_
# 0,1,2로 그룹화 된 것을 알 수 있음
|
![]() |
|
iris_df2['target'] = iris_df['species']
iris_df2['cluster'] = kmeans.labels_
iris_df2
|
![]() |
|
plt.figure(figsize=(12,6))
plt.subplot(1,2,1)
sns.scatterplot(data = iris_df2, x='sepal_length', y='sepal_width', hue='target')
plt.title('Original')
plt.subplot(1,2,2)
sns.scatterplot(data = iris_df2, x='sepal_length', y='sepal_width', hue='cluster', palette='viridis')
plt.title('Clustering')
|
![]() |
☑️ 실습-RFM
비지도 학습이 가장 많이 사용되는 분야는 고객 관계 관리(Customer Relationship Management, CRM)분야
고객 세그멘테이션(Customer Segmentation)은 다양한 기준으로 고객을 분류하는 기법
= 타겟 마케팅
고객 유형에 따라 분류해 맞춤형 마게팅이나 서비스를 제공하는 것을 목표
- RFM의 개념
: Recency(R) 가장 최근 구입 일에서 오늘까지의 시간
: Frequency(F) 상품 구매 횟수
: Monetary value(M) 총 구매 금액
더보기
|
|
| → EDA → 데이터 전처리(customerID 결측치 삭제 / InvoiceNo, UniPrice, Quantity 데이터확인 및 삭제 / 영국데이터만 취함) → RFM 기반 데이터 가공(날짜 데이터 가공 / 최종목표 / StandardScaler 적용) → 고객 세그멘테이션 → 평가 |
|
|
!pip install openpyxl
|
|
|
retail_df = pd.read_excel('/content/Online Retail.xlsx')
retail_df.head(3)
|
|
|
retail_df.info()
|
![]() |
|
retail_df.isnull().sum()
|
![]() |
|
데이터 EDA 및 전처리
|
|
|
retail_df.describe(include = 'all')
#Quantity & Unitprice에 -값이 있어 제거 예정
|
![]() |
|
cond1 = retail_df['Quantity']<0
retail_df[cond1]
# - 값의 공통점은 InvoiceNO가 C(cancel)임
|
![]() |
|
#데이터 전처리 전략
# 조건 1 : customerID 결측치인것은 삭제
# 조건 2 : Invoice가 C로 시작하거나, Quantity가 음수이거나, unitprice가 음수인것은 모두 삭제
|
|
|
#조건 1
#notnull = null인것은 지우겠다
cond_cust = (retail_df['CustomerID'].notnull())
retail_df[cond_cust].isnull().sum()
|
![]() |
|
# 조건 2 - invoice
cond_invo=(retail_df['InvoiceNo'].astype(str).str[0] != 'C')
retail_df[cond_invo].head(3)
|
|
|
# 조건 2 - 나머지
cond_minus = (retail_df['Quantity']>0) & (retail_df['UnitPrice']>0)
retail_df[cond_minus].head(3)
|
|
|
retail_df_2 = retail_df[cond_cust & cond_invo & cond_minus]
retail_df_2.info()
|
![]() |
|
# 국적
retail_df_2['Country'].value_counts()[:10]
|
![]() |
|
# 국적 UK만
cond_uk = (retail_df_2['Country'] == 'United Kingdom')
retail_df_2 = retail_df_2[cond_uk]
retail_df_2
|
![]() |
|
retail_df_2.describe(include='all')
|
![]() |
|
retail_df_2['Amt'] = retail_df_2['Quantity'] = retail_df_2['UnitPrice']
retail_df_2['Amt'] = retail_df_2['Amt'].astype('int')
|
|
|
retail_df_2[['CustomerID']].drop_duplicates()
|
![]() |
|
retail_df_2.pivot_table(index = 'CustomerID', values = 'Amt', aggfunc='sum').sort_values('Amt', ascending=False)
|
![]() |
|
import datetime as dt
# 2011.12.10일 기준으로 각 날짜를 빼고 +1
# 추후 CustomerID 기준으로 Priod의 최소의 Priod를 구하면 그것이 Recency
# 1번 사람 100일전, 20일전, 5일전
#(dt.datetime(2011,12,10) - retail_df_2['InvoiceDate']).apply(lambda x : x.days+1)
retail_df_2['Period'] = (dt.datetime(2011,12,10) - retail_df_2['InvoiceDate']).apply(lambda x : x.days+1)
retail_df_2.head(3)
|
|
|
rfm_df = retail_df_2.groupby('CustomerID').agg({
'Period' : 'min',
'InvoiceNo' : 'count',
'Amt' : 'sum'
})
rfm_df
|
![]() |
|
rfm_df.columns = ['Recency', 'Frequency', 'Monetary']
|
|
|
sns.histplot(rfm_df['Recency'])
|
![]() |
|
sns.histplot(rfm_df['Frequency'])
|
![]() |
|
sns.histplot(rfm_df['Monetary'])
|
![]() |
|
#데이터 정규화
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_features = sc.fit_transform(rfm_df[['Recency', 'Frequency', 'Monetary']])
|
|
|
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
kmeans = KMeans(n_clusters= 3, random_state = 42)
labels = kmeans.fit_predict(X_features)
rfm_df['label'] = labels
silhouette_score(X_features, labels)
|
|
|
from kmeans_visaul import visualize_silhouette
visualize_silhouette([2,3,4,5,6], X_features)
|
![]() |
|
#log 스케일 통한 추가전처리
import numpy as np
rfm_df['Recency_log'] = np.log1p(rfm_df['Recency'])
rfm_df['Frequency_log'] = np.log1p(rfm_df['Frequency'])
rfm_df['Monetary_log'] = np.log1p(rfm_df['Monetary'])
X_features2 = rfm_df[['Recency_log','Frequency_log','Monetary_log']]
sc2 = StandardScaler()
X_features2_sc = sc2.fit_transform(X_features2)
visualize_silhouette([2,3,4,5,6], X_features2_sc)
|
![]() |
⊙ 머신러닝 심화 4강
● 4-1 딥러닝
딥러닝은 자연어처리와 이미지 처리에 뛰어난 발전
공통점: 데이터로부터 가중치를 학습하여 패턴을 인식하고 결정을 내리는 알고리즘 개발과 관련된 인공지능(AI)의 하위 분야
☑️ 딥러닝 유래
- 인공 신경망(Artificial Neural Networks) : 인간의 신경세포를 모방하여 만든 망(Networks)
- 신경세포: 이전 신경세포로 들어오는 자극을 이후 신경세포로 전기신호로 전달하는 기능을 하는 세포


- 가중치를 구해라 - Gradient Descent :
경사 하강법(Gradient Descent)은 모델의 손실 함수를 최소화하기 위해 모델의 가중치를 반복적으로 조정하는 최적화 알고리즘
☑️ 활성화 함수
:비선형적분류를 만들기 위해 활성화 함수(Acitvation Fucntion)을 사용하게 되었습니다. 로지스틱회귀 때 배웠던 로지스틱 함수 역시 활성화 함수의 한 예
● 4-2 딥러닝 실습
● 4-3 딥러닝 동향
● 4-4 마무리
☑️ 머신러닝 요약
더보기
- 머신러닝의 기초
- 머신러닝의 기본, 개념
- 회귀분석
- 가장 설명을 잘하는 직선을 그리는 법 - 선형회귀
- 실제 값과 예측 값의 오차를 계산하라 - Mean Squared Error
- 분류분석
- 특정 범주에 대한 확률 예측하기 - 로지스틱회귀
- 맞춘 것에 대한 지표: 정확도, f1_score
- 데이터 분석 프로세스
- 데이터 수집 → 전처리 → 모델링 → 평가
- 회귀, 분류 모델링 심화
- 의사결정을 기반으로 한 모델 - 의사결정나무
- 나무를 여러 개 만들어서 다수결 원칙을 사용하자 - 랜덤포레스트
- 유유사종의 원리로 예측하자 - KNN
- 약한 학습기를 여러 개 합치자 - 부스팅 모델
- 비지도학습
- 만약 Y(정답이 없다면) 특성을 이용해 그룹화 하자 - K-means 군집화
- 인공 신경망
- 사람의 신경세포를 모방한 네트워크 - 인공 신경망
☑️ 데이터 직군별 활용 방안
|
|
|
|
⊙ 통계&머신러닝 과제 해설


'내일배움캠프(QC,QA_5기)' 카테고리의 다른 글
| [내일배움캠프_QA/QC 5기] 40일차 _ 팀 프로젝트 Day+3 (0) | 2026.05.01 |
|---|---|
| [내일배움캠프_QA/QC 5기] 39일차 _ 팀 프로젝트 Day+2 (0) | 2026.04.30 |
| [내일배움캠프_QA/QC 5기] 36일차(2) _ 머신러닝 심화 1강 (1) | 2026.04.27 |
| [내일배움캠프_QA/QC 5기] 36일차(1) _ 머신러닝 완강 (0) | 2026.04.27 |
| [내일배움캠프_QA/QC 5기] 35일차 _ 데이터 전처리&시각화 4강 (0) | 2026.04.25 |










































