본문 바로가기
Programming Language/Python

Sklearn

by hleej 2026. 1. 26.

 Obdisian에 정리한 markdownhtml export한 뒤, Tistory로 옮긴 게시글.

 (Obsidian 형식으로 써진 글이라 LaTex 등 일부 형식이 깨짐)

 last update : 2026-02-26

Sklearn

Scikit Learn
머신러닝(간단한 supervised learning, non-supervised learning 위주.)을 위한 파이썬 라이브러리.
Based on Numpy , Scipy, Matplotlib

# Classifier / Regressor base strcuture
class SupervisedEstimator(...):
    
    def __init__(self, hyperparam_1, ...):
        self.hyperparm_1
        ...
    
    def fit(self, X, y): # Train X, y
        ...
        self.fit_attribute_ # something ends with _
        return self
    
    def predict(self, X): # Test X
        ...
        return y_pred
    
    def score(self, X, y): # Test y
        ...
        return score # Classifier: 0~1, Regressor: -1~1
    
    def _private_method(self):
        ...
    ...

Syntax

[ Pipeline ]

여러 Estimator API를 하나의 Pipeline에 담아 편리하게 사용할 수 있게 해준다.
Estimator API: .fit(X, y) (학습), .predict(X) (예측), .transform(X) (변환, 전처리), .fit_transform(X, y)들을 가진 class

from sklearn.pipeline import make_pipeline

#==== way 1: manually named =======================
pipeline = PipeLine([
	('polynomial_features', polynomial_features),
	('lr', linearRegression)
])
print(pipeline.named_step['lr'].coef_) # 각 객체는 `pipeline.named_step`에 있다.

#==== way 2: automatically named =======================
# 이름이 자동으로 생성된다. 이름은 class명을 소문자로(ex: linearregression) 
pipe = make_pipeline(StandardScaler(),
                     KNeighborsClassifier(n_neighbors=3)) 
## 1 pipeline에는 최대 1 model. 여러 모델을 사용하려면 여러개의 pipeline을 만들어야 함.



pipe.fit(X_train, y_train)
pipe.predict(X_test)

[ Sample Data ]

from sklearn.datasets import load_diabetes

#==== Load Sample Data =======================
# Toy Dataset (zero-centered & normalized)

# [1: Details]
dataset = load_iris(as_frame=True)
# print(dataset.keys()) # kind of Dictionary
#   .data           # X             # <class 'numpy.ndarray'>
#   .target         # y             # <class 'numpy.ndarray'>
#   .feature_names  # names of X    # <class 'list'> 
#   .target_names   # names of y    # <class 'numpy.ndarray'> # only for Classification data
#   .DESCR          # details for dataset # str
#   ...
iris_X, iris_y = dataset.data, dataset.target
print(dataset.data.shape) # (150, 4)
print(dataset.feature_names) # ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
print(dataset.target_names) # ['setosa' 'versicolor' 'virginica']
print(dataset.DESCR) # more information of Dataset.

# [2: Quick]
diabetes_X, diabetes_y =  load_diabetes(return_X_y=True, as_frame=True) # Same as above
## as_frame: return as pandas.DataFrame


# Get Large Dataset from Internet
fetch_...() # fetch계열은 용량이 커서 인터넷으로 `home/scikit_learn_data`에 저장한 뒤 불러옴.


#==== Generate Sample Data =======================
from sklearn.datasets import make_blobs
# Including high correlation, useless attribute
make_classifications() # for Classification
X, y = make_blobs(n_samples=n, n_features=p, centers=k, cluster_std=[0.8, 1, ...], random_state=0) # for Clustering

[ Data PreProcessing ]

X_train을 이용해서 fitting하고, fitting한 결과를 이용하여 transform함.

Handling NaN Data

Pandas에서는 NaN / Null / NaT를 동일하게 취급한다.

df.isnull().sum() ## 행 별로 NaN이 몇 개인가?

## 방법 1: 그냥 지워버림
df.dropna(axis=0) ## NaN이 있는 row(data)를 지움.
df.dropna(axis=1) ## NaN이 있는 column(feature)를 지움.

## 방법 2: 평균값(mean, median, mode)로 채워넣기
temp_mean = df['col1'].mean()
df['col1'].fillna(temp_mean)

## ?
from sklearn.impute import SimpleImputer

imputer = SimpleImputer(missing_values=np.nan, strategy='mean') ## mean 사용
X = df.values ## np array로 변환
X = imputer.fit_transform(df.values)

Categorical Data: Nominal Data

특히 문자열.
Data의 Category 분류: 순서가 없는 data -> 항목별로 새로운 column으로 변환하기
ex) 옷의 색. Color: Blue, Yellow, Red -> Color_Blue: 0 or 1 / Color_Yellow: 0 or 1 / Color_Red 0 or 1
무의미한 Nominal이면 그냥 좀 지워라..

from sklearn.preprocessing import LabelEncoder, OneHotEncoder
col = df['Color'] # ['Red', 'Yellow', 'Red', 'Blue']

#==== Label Encoding =======================
# For Classification / Tree-Regressor
encoder = LabelEncoder()
encoder.fit(col)
# print(encoder.classes_) # ['Blue' 'Red' 'Yellow']
labels = encoder.transform(col)
# print(labels) # Label Encoded data # [1, 2, 1, 0]

#==== One-hot Encoding =======================
# 1. 수동으로
col = col.reshape(-1, 1) # Input must 2d array.
encoder = OneHotEncoder()
encoder.fit(col)
labels = encoder.transform(col) # returns Sparse Matrix
 # (0, 1)	1.0    # 대충 (row, col)에 1.0이라는 내용
 # (1, 2)	1.0
 # (2, 1)	1.0
 # (3, 0)	1.0
labels = labels.toarray() # Sparse → Dense Matrix
# [[0. 1. 0.]
#  [0. 0. 1.]
#  [0. 1. 0.]
#  [1. 0. 0.]]
 
# 2. 자동으로
pd.get_dummies(df[['Color', 'Role']]) # 숫자가 아닌 열이라면 여러 개 넣을 수 있다.

Categorical Data: Ordinal Data

Data의 Category 분류: 순서가 중요한 data -> 숫자로 바꾸기
ex) 옷의 사이즈. M L XXL -> 1 2 5

## 수동으로
mapping_dict = {'M': 1, 'L': 2, 'XXL': 5}
df['size_num'] = df['size'].map(mapping_dict) ## make new column

## 자동으로
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
df['classlabel'] = le.fit_transform(df['classlabel'])

Data Scaling (standard / min_max / log)

data의 범위를 0-1로 바꾸거나, 단위를 표준화(cm-mm)할 때 사용.
※ Train/Validation/Test dataset 각각에 대해서 따로따로 Scaling하면 절대 안됨
standard scaler가 min-max scaler보다 oulier에 robust함.
log scaling은 feature unskew의 기능이 있어, unskew 시 gaussian distribution이 된다면, estimator의 성능 향상을 기대할 수 있다.

from sklearn.preprocessing import StandardScaler, MinMaxScaler

#==== Standard Scaling =======================
scaler = StandardScaler()
scaler.fit(X) # find avg, std
X_scaled = scaler.transform(X) # apply avg, std

#==== Min-max Scaling =======================
scaler = MinMaxScaler()
scaler.fit(X)
X_scaled = scaler.transform(X) # returns <class 'numpy.ndarray'>

#==== Log Scaling =======================
# 변환된 값을 원복할 수 있다. 1을 더하는 이유는 Underfitting을 방지하기 위해서이다.
# 특히 y에 많이 적용한다. 변환 시 더 학습이 잘 되는 gaussian의 형태로 변환된다.
X_scaled = np.log1p(X)
X = np.expm1(X_scaled) # 역변환도 가능하다.

# 한번에
X_scaled = scaler.fit_transform(X)

X_scaled = pd.DataFrame(X_scaled) # 다시 pd.dataframe으로

Binarizer

from sklearn.preprocessing import Binarizer

X = np.range(9).resize(3, 3) # (3x3) Matrix
binar = Binarizer(threshold=5) # for each data, data > threshold: 1, else: 0
X_ = binar.fit_transform(X)

[ Model Selection ]

아래로 갈수록 강화버전.
최종 형태는 GridSearchCV인 듯.

Train/Test Dataset Split

X, y →
Train: For train model
Validation: For hyperparameter tuning
Test: For Evaluate model

from sklearn.model_selection import train_test_split
#==== 2-fold (Train/Test) =======================
# X -> X_temp, X_test
X_train, X_test, y_train, y_test = \
        train_test_split(X, y, test_size=0.2, 
                         shuffle=True, random_state=123, stratify=y)
                         
#==== 3-fold (Train/Validation/Test) =======================
# X -> X_temp, X_test
X_temp, X_test, y_temp, y_test = \
        train_test_split(X, y, test_size=0.2, 
                         shuffle=True, random_state=123, stratify=y)
# X_temp -> X_train, X_valid
X_train, X_valid, y_train, y_valid = \
        train_test_split(X_temp, y_temp, test_size=0.2,
                         shuffle=True, random_state=123, stratify=y_temp)

KFold / StratifiedKFold / cross_val_score / cross_validate

KFold (K=5) → ░: train set / █: test set / iter=5 (for Regression)
1: █░░░░ → model fit, Evaluate
2: ░█░░░ → "
3: ░░█░░
4: ░░░█░
5: ░░░░█
StratifiedKFold: 각 fold가 균일한 class분포를 갖도록 개선한 버전. (for Classification)
cross_val_score: 위의 folding → fit → score을 알아서 한 줄로 해주는 함수.
cross_validate: 위와 같으나, return에 여러 개의 scoring, 실행 시간 등을 같이 반환하는 함수.

from sklearn.model_selection import KFold, StratifiedKFold, cross_val_score, cross_validate

#==== KFold =======================
kfold = KFold(n_splits=5) # K=5
kfold_accuracy = []

for train_idx, test_idx in kfold.split(X): # train_idx: range(0, n), test_idx: range(n+1, 5n)
#==== StratifiedKFold =======================
skfold = StratifiedKFold(n_splits=5) # K=5
kfold_accuracy = []

for train_idx, test_idx in skfold.split(X, y) # requires y for even class distribution


	X_train, X_test = X[train_idx], X[test_idx]
	y_train, y_test = y[train_idx], y[test_idx]
	# model Fit
	estimator.fit(X_train, y_train)
	y_pred = estimator.predict(X_test)
	# model score
	acc = accuracy_score(y_test, y_pred)
	kfold_accuracy.append(acc)
	
print(np.mean(kfold_accuracy))

#==== cross_val_score =======================
scores = cross_val_score(estimator, X, y, scoring='accuracy', cv=5) # K=5 / accuracy_score
scores = cross_val_score(estimator, X, scoring='accuracy', cv=5) # y=None: Regression?

print(np.mean(scores))

#==== cross_validate =======================
cv_results = cross_validate(model, X, y, scoring='accuracy', cv=5, return_estimator=True)
print(scores)

GridSearchCV

[ Model Selection ]과 [ Hyerparameter Tuning ]을 동시에 한다.
시간이 조금 걸릴 수 있다.

from sklearn.model_selection import GridSearchCV

#==== GridSearchCV =======================
# Fit Best Model
# example: fit model 30 times. 3(hyperparam 1) × 2(hyperparam 2) × 5(folds) = 30.
hyperparams = {'max_depth': [1, 2, 3], # hyperparamters of DecisionTreeClassifier.
			   'min_samples_split': [2, 3]} # Dictionary
grid_search = GridSearchCV(estimator, param_grid=hyperparams, scoring='neg_mean_squared_error', cv=5, n_jobs=-1) # K = 5 # refit=True (default): re-fit model with best hyperparamer set. # n_jobs: count of CPU core usage. -1: ALL 
grid_search.fit(X_train, y_train) # internally seperate [train] to [train/validation] folds.

# Get Score
df = pd.DataFrame(grid_search.cv_results_) # Dictionary -> pd.DataFrame for readability
print(df) # pd.DataFrame has 6(2*3) ROWS.
print(df['rank_test_score']) # best(max 'mean_test_score') hyperprameter set.

print(grid_search.best_params_) # {'max_depth': 3, 'min_samples_split": 2}
print(grid_search.best_score_) # 0.974...

# Test Model
estimator = grid_search.best_estimator_
y_pred = estimator.predict(X_test)
print(accuracy_score(y_test, y_pred))

Hyperparameter Tuning (Baysian Optimization)

#==== HyperOpt =======================
from hyperopt import hp


Models

# Train
model = Model(random_state=123)
model.fit(X_train, y_train)
# Test
pred = model.predict(X_test)

# Extract Hyperparameter
print(model.get_params())

[ Supervised Learning]

Estimator: 지도학습의 모든 모델들
.fit(): 학습
.predict(): 추론

Recommended:
Regressor:
Classifier: XGBoost, LightGBM

Regressor

VIsualize Regressor Coefficients
coef = pd.Series(model.coef_, index=X.columns) # get coefficients
coef_sorted = coef.sort_values(ascending=False) # Ordering
sns.barplot(x=coef_sorted.values, y=coef_sorted.index) # draw to barplot
Linear Regression

Multi-Collinearity 문제: Feature 간의 상관관계가 매우 높으면 분산이 커져 오류에 매우 민감해짐 ← 차원 축소 OR 규제 적용

from sklearn.linear_model import LinearRegression
#==== Simple Linear Regression =======================
regr = LinearRegression()
## Train model
regr.fit(X_train, y_train)

## Test model
diabetes_y_pred = regr.predict(diabetes_x_test)

regr.coef_ # returns coefficient(weight) of model. `W` (np.ndarray)
regr.intercept_ ## intercept of model. w_0 (np.float64)

# (Analysis)
# 어떤 feature가 결과에 얼마나 중요한 영향을 미치는 지 알아볼 수 있다.
coefficient = pd.Series(data=regr.coef_, index=X.columns) # feature명에 따른 계수
coefficient.sort_values(ascending=False)  # 중요도 내림차순 정렬
# Feature 2    3.2  # Feature 2가 y에 가장 영향이 크다.
# Feature 1    0.1
# Feature 3    -1.0
Polynomial Regression

Polynomial Regression도 Linear Regression이다.
feature를 단순히 로 전처리함으로써 구현한다.

from sklearn.preprocessing import PolynomialFeatures
#==== Polynomial Regression =======================
# 1. preprocessing
poly = PolynomialFeatures(degree=2) # 2차로 mapping
X_degree_2 = poly.fit_transform(X)

Lasso / Ridge Regression / ElasticNet

Objective() = Loss() + Regression()
Regression()
Lasso :
Ridge :
Elasticnet :

from sklearn.linear_model import Lasso, Rigde, ElasticNet

#==== Lasso Regression =======================
lasso = Lasso(alpha=10)
neg_mse_scores = cross_val_score(lasso, X, y, scoring="neg_mean_scores", cv=5)
rmse_scores = np.sqrt(-1*neg_mse_scores)
avg_rmse = mp.mean(rmse_scores)

#==== Ridge Regression =======================
ridge = Ridge(alpha=10)

#==== ElasticNet =======================
elasticnet = ElasticNet(alpha=10, l1_ratio=0.7) # l1_ratio + l2_ratio = 1

KNN Classifier
from sklearn.neighbors import KNeighborsClassifier
from mlxtend.plotting import plot_decision_regions

knn_model = KNeighborsClassifier(n_neighbors=3) ## number of nearst neighbos: 3
knn_model.fit(X_train[:, 2:], y_train)

plot_decision_regions(X_train[:, 2:], y_train, knn_model)
plt.xlabel('petal length[cm]')
plt.ylabel('petal width[cm]')
plt.show()

Classifier

Logistic Regression

Linear Regression에 sigmoid()를 적용하여 확률적으로 class를 분류하기.
hyperparameter:
penalty='l2': Regularization(Lasso / Ridge).
C: power of Regularization. C↑: overfitting↑, C↓: underfitting↑. ()
solver='lbfgs' : 최적화 함수 이름. 성능은 비슷비슷하다고 함.
max_iter: 수렴할 때까지 반복하는 횟수

from sklearn.linear_model import LogisticRegression

logiRegr = LogisticRegression(C=1e5)
logiRegr.fit(X_train, y_train)
SVC (Support Vector Classifer)
from sklearn import svm

## Model 1
svclf = svm.SVC(kernel="linear", C=1e0) ## Support Vector CLassiFier
## Model 2
svclf = svm.LinearSVC(C=1e0, max_iter=10000) ## much faster than above in linear
svclf.fit(X_train_std, y_train)

y_pred = svclf.predict(X_test_std)

Tree based (Regressor & Classifier)

model.featureimportances

DecisionTreeRegressor / DecisionTreeClassifer

Decision Tree: 가장 기본적인 Tree.
반복적으로 기준(규칙)에 따라, Entrophy가 작아지도록, Feature Space를 분할함.
Feature Scaling이나 Regularizaion 등 전처리가 없어도 Robust하다.
규칙이 많다 → Overfitting의 가능성이 높다 → Ensemble에 유리하다.

hyperparameter=default:
min_samples_split=2: node를 분할하기 위한 최소한의 sample 수
min_samples_leaf: 분할 후에 node에 존재해야 할 최소한의 sample 수
max_features=None: 최적의 분할을 위해 고려할 최대 feature 수.
int로 지정: 대상 feature 수,
float로 지정: 전체 중 대상 feature의 비율
'sqrt' OR 'auto': 전체개수
'log': 전체개수
'None': 전체 개수
max_depth=None: tree의 최대 depth. None은 무제한.
max_leaf_nodes: leaf node의 최대 개수

from sklearn.tree import DecisionTreeRegressor, DecisionTreeClassifier

dt_c = DecisionTreeClassifier(random_state=0, max_depth=4)
dt_c.fit(X_train, y_train)

pred = dt_c.predict(X_test)


print(dt_c.feature_importances_) # 각 feature의 중요도(geni 계수를 얼마나 개선했는지)를 정규화된 값으로 나타냄.
sns.barplot(x=dt_c.feature_importances_, y=df.feature_names) # to graph

Tree Based Ensemble

성능이 좋지만, 오래걸리고, hyperparameter가 많다.

  • Voting: 서로 다른 model을 평균내는 방식
    • Hard Voting: 다수결로 Voting
    • Soft Voting: pred의 확률을 모두 평균내서 Voting (흔히쓰임)
  • Bagging: data sampling을 서로 다르게 하는 방식
  • Boosting: 여러 개의 분류기를 학습하되, 이전 model이 다음 model로 weight를 적용

Voting model

VotingRegerssor / VotingClassifier
from sklearn.ensemble import VotingClassifier

# different models for voting
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
lr_clf = LogisticRegression(solver=liblinear)
knn_clf = KNeighborsClassifier(n_neighbors=8)

#==== Voting Classifier =======================
vot_clf = VotingClassifier(estimators=[('LR', lr_clf), ('KNN', knn_clf)], voting='soft')
vot_clf.fit(X_train, y_train)
pred = vot_clf.predict(X_test)

Bagging models

RandomForestRegressor / RandomForestClassifer (emsemble)

ensemble 모델 중 상대적으로 빠름.

n_estimators=10 ensemble에 쓸 모델 개수
나머지는 Decision Tree의 hyperparameter와 99% 같다.

from sklearn.ensemble import RandomForestRegressor, RandomForestClassifer

rfRegr = RandomForestRegressor(random_state=0, n_estimators=1000)
scores = cross_val_score(rfRegr, X, y, scoring="neg_mean_squared_error", cv=5)

Boosting models

GBM: GradientBoostringRegressor / GradientBoostringClassifier (ensemble)

weak learner들을 순차적으로 학습-예측하면서,
잘못된 data에 weight 부여를 통해 오류를 개선하면서 학습하는 방식.
Gradient Descent로 weight를 업데이트한다.

hyperparameters
loss='deviance': Gradient Descent 시 사용할 Loss Function.
learning_rate=0.1: Gradient Descent 시 사용할 learning rate. 작을수록 성능 증가, 오래걸림
n_estimators=100: weak learner의 개수.
subsample=1: weak learner가 학습에 사용할 data의 sampling rate
나머지는 Decision Tree의 hyperparameter와 같다.

from sklearn.ensemble import GradientBoostingRegressor, GradientBoostringClassifier

gbRegr = GradientBoostingRegressor(random_state=0, n_estimators=500)
gbRegr.fit(X_train, y_train)
pred = gbRegr.predict(X_test)
XGBRegressor / XGBClassifier

GBM에서 속도 개선(병렬 처리), Overfitting Regularization(자체 pruning, cross-evaluation) 기법 추가.
C++로 구현된 sklearn 외부 library지만, sklearn에서 쓸 수 있게 wrapper를 지원한다.

hyperparameters
너무 많아서 생략. 파이썬머신러닝완전가이드 228p(244/722) 참고.

from xgboost import XGBRegressor, XGBClassifier

xgbRegr = XGBRegressor(n_estimators=1000)
LGBMRegressor / LGBMClassifier

XGBoost보다 훨씬 빠르지만, 예측 성능은 비슷하다.
대신 data가 적을 경우 Overfitting의 가능성이 높다.

from lightgbm import LGBMRegressor, LGBMClassifier

lgbmRegr = LGBMRegressor(n_estimators=1000)

Custom Estimator

from sklearn.base import BaseEstimator
class MyClassifier(BaseEstimator):
	def fit(self, X, y=None):
		# Fit here
		
	def predict(self, X):
		pred = np.zeros((X.shape[0], 1))
		# Predict here
		return pred

Stacking

ensemble 기법 중 하나.
여러 모델들의 prediction들을 모아, 이를 새로운 X'로 새로운 모델을 훈련하는 방식.

# Basic Stacking Theory Code

# multiple models here
knn_clf = KNeighborsClassifier(n_neighbors=4)
rf_clf = RandomForestClassifier(n_estimators=100, random_state=0)
ada_clf = AdaBoostClassifier(n_estimators=100)
knn_clf.fit(X_train, y_train)
rf_clf.fit(X_train, y_train)
ada_clf.fit(X_train, y_train)
pred1 = knn_clf.predict(X_test)
pred2 = rf_clf.predict(X_test)
pred3 = ada_clf.predict(X_test)

X_final = np.array([pred1, pred2, pred3]).T # shape(N, 3)

# meta model here
lr_final = LogisticRegression()
pred_final = lr_final.predict(X_final)
#  better Accuracy found

다양한 관점의 모델을 섞음으로써 모델의 전체적인 performace향상을 기대할 수 있다.

from sklearn.linear_model import LinearRegression, RidgeCV
from sklearn.ensemble import StackingRegressor

def stacking(train_x, train_y, test_x, test_y):
	# 1. 기본 모델 정의
    base_models = [
	    # LInear Models
        ('lr', LinearRegression()),
        
        # Tree-based Models
        ('rf', RandomForestRegressor(random_state=42)), 
        ('lgb', LGBMRegressor(random_state=42, verbose=-1)),
        ('gb', GradientBoostingRegressor(random_state=42)),
        ('xgb', XGBRegressor(random_state=42)),
        
        # Other Models
        ('kn', KNeighborsRegressor())]
    
    # 2. 메타 모델 정의 (Final Estimator)
    #meta_model = RidgeCV(cv=5)
    meta_model = LinearRegression()
    
    # 3. 스태킹 앙상블 모델 생성
    stacking_model = StackingRegressor(
        estimators=base_models,
        final_estimator=meta_model,
        cv=5,
        n_jobs=-1,
        verbose=2, # How much talk for debugging
        passthrough=False # 기존 데이터를 메타 모델에 다시 넣지 않고, 개별 모델의 예측값만 사용 (True로 하면 성능이 오를 때도 있음)
    )
    
    # 4. 모델 학습
    print("Stacking 모델 학습 중...")
    stacking_model.fit(train_x, train_y)
    
    # 5. 예측 및 평가
    y_pred = stacking_model.predict(test_x)
    final_r2 = r2_score(test_y, y_pred)
    final_mae = mean_absolute_error(test_y, y_pred)
    final_rmse = np.sqrt(mean_squared_error(test_y, y_pred))
    return final_r2, final_mae, final_rmse

[ Unsupervised Learning ]

estimator?
.fit(): 사전 구조 작업
.transform(): 실제 작업
.fit_transform(): 동시에

Dimentionality Reduction

PCA (Principal Component Analysis)

data의 분산을 최대로 하는, orthogonal한 축(Principle Component)들 찾기:

pd.DataFrame.corr()에서 상관도가 높은 column을 제거하는 기능도 있다.

 

고유벡터 : i번째로 분산을 최대로 하는 새로운 축.
고윳값 : 새로운 축 가 전체 데이터를 얼마나 잘 설명하는지에 대한 수치. 이다.
따라서 data를 설명하는 새로운 축의 벡터 :

X = df.iloc[:, :-1]

#==== Scaling =======================
# PCA 전에, feature의 Unit 차이로 인한 왜곡 방지를 위해 scaling.
from sklearn.preprocessing import StandardScalar
X_scaled = StandardScalar().fit_transform(X) # target을 제외한 모든 값에 대해.

#==== PCA =======================
from sklearn.decomposition import PCA

pca = PCA(n_components=2)
X_ = pca.fit_transform(X)

print(pca.explained_variance_ratio_) # [0.73, 0.21] # 각 축이 데이터를 얼마나 잘 설명하는지.

df_pca = pd.DataFrame(X_, columns=['pca_1', 'pca_2'])
df_pca['y'] = df['y']

#==== SVD =======================
# PCA는 내부적으로 SVD로 구성되어 있다.
# SVD는 PCA와 달리 Sparse Matrix에 대한 변환도 가능하다.
from sklearn.decomposition import TruncatedSVD

tsvd = TruncatedSVD(n_components=2) # truncate 2 Principle Component
tsvd.fit(X)
X = tsvd.transform(X) # 결과는 PCA와 거의 동일하다.
LDA (Linear Discriminant Analysis)

Clustering이지만, 학습에 y label이 필요하므로, 비지도학습이 아닌 지도학습이다.

SVD와 비슷하지만, Classification에서 사용하기 좋다.
class 간 분산()을 최대화하고, class 내부 분산()를 최소화하는 관점이다.

 
생략
#==== Scaling =======================
# LDA 전에, feature의 Unit 차이로 인한 왜곡 방지를 위해 scaling.
from sklearn.preprocessing import StandardScalar
df_scaled = StandardScalar().fit_transform(df)

#==== LDA =======================
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

lda = LinearDiscriminantAnalysis(n_components=2)
lda.fit(df_scaled, df['y']) # y label이 필요하다.
df_lda = lda.trasform(df_scaled)
print(df_lda.shape)
NMF (Non-Negative Matrix Factorization)

NMF도 Low-Rank Approximation의 일종이다.

 

의 행에 대해 잠재요소의 값과 대응되며,
의 열에 대해 잠재 요소가 어떻게 구성되었는지는 나타낸다.

이미지/텍스트 데이터/추천 에서 많이 사용.

#==== NMF =======================
from sklearn.decomposition import NMF

nmf = NMF(n_components=2) # k=2
nmf.fit(X)
X_nmf = nmf.transform(X)

Clustering

Data가 어떻게 흩어져 있는지에 따라 최적의 방법이 다르다.

K-means Clustering (K-means++)
  • 쉽고 간결하다.
  • Feature이 매우 많으면 정확도가 떨어진다.(차원축소필요)
  • 각 Cluster가 원형의 분포를 가질 때 유리하다.

hyperparameter:
n_clusters: cluster k
init=k-means++
max_iter=300: 수렴할 때까지 최대 반복 횟수

#==== K-Means++ =======================
from sklearn.cluster import KMeans

km = KMeans(n_clusters=k, random_state=0) 
## n_init=10 (random restarts with random initializers)
## max_iter=300
km.fit(X)

print(km.cluster_centers_) # np.ndarry # pos of cluster centers.
print(km.labels_) ## np.ndarry # cluster labels of X
print(km.inertia_) ## SSE. 135.92823795402757 (

km.predict(X_new) ## equal to above. but can be applied to new data.
Mean Shift

K-means clustering과 비슷하나, 새로운 군집 중심을 찾을 때
Kernel Density Estimation을 이용한다.
kernel(gaussian)의 bandwidth에 따라 peak의 개수가 바뀌고, 각 peak가 새로운 cluster 중심이 된다.
bandwidth ↓: overfitting 증가, cluster 수 증가
bandwidth ↑: underfitting 증가, cluster 수 감소

#==== Mean Shift =======================
from sklearn.cluster import MeanShift

meanshift = MeanShift(bandwidth=0.8)
cluster_labels = meanshift.fit_predict(X)


#==== Find best bandwidth =======================
from sklearn.cluster import estimate_bandwidth

best_bandwidth = estimate_bandwidth(X)
Gaussian Mixture (GMM)

EM algorithm을 이용해, 2가지 반복적으로 구함으로써, 최적의 cluster에 점점 근사함.

  1. 각 cluster에 해당하는 gaussian의 average와 variance를 구함.
  2. 각 data가 어떤 cluster에 해당하는지 구함.
  • 각 Cluster가 길쭉한 분포를 가질 때 유리.

hyperparameters
n_components: gaussian의 개수(=cluster의 개수)

from sklearn.mixture import GaussianMixture

gm = GaussianMixture(n_components=3, random_state=0)
cluster_labels = gm.fit_transform(X)
Agglomerative Clustering
from sklearn.clustring import AgglomerativeClustering

agg = AgglomerativeClustering(n_clusters=5, linkage='ward')
agg.fit(X)

print(agg.fit_predict(X)) ## fit and predict. np.ndarry of cluster index. shape (n, )

####### Draw Dendrogram

from scipy.cluster.hierarchy import dendrogram, ward
import matplotlib.plot as plt ## ?

## Apply the ward clustering to the data array X
## The SciPy ward function returns an array that specifies the distances
## bridged when performing agglomerative clustering
linkage_array = ward(X)
## Now we plot the dendrogram for the linkage_array containing the distances
## between clusters
dendrogram(linkage_array)
## Mark the cuts in the tree that signify two or three clusters
ax = plt.gca()
DBSCAN

Density Based Spatial Clustering of Application with Noise
밀도 기반 알고리즘.

  • 각 Cluster가 복잡한 구조를 가질 때 유리함. ex) 도넛 안의 도넛 같은 구조

Data를 3가지로 분류한다. Core Point와 Neighbor Point가 Cluster가 되고, Border Point는 Noise로 취급한다.

  • Core Point : 범위 epsilon 안에 min_sample 개 이상의 data와 인접한 point
  • Neighbor Point : Core Point는 아니지만 Core Point와 인접한 point
  • Border Point : 나머지 Outlier

hyperparameter
eps: 각 데이터를 중심으로 epsilon만큼의 거리. 일반적으로 1 이하로 지정.
min_samp: epsilon 범위 안에 몇 개?

from sklearn.cluster import DBSCAN

dbscan = DBSCAN(eps=0.6, min_samples=4)
lables = dbscan.fit_predict(X)
#print(labels.unique()) # [-1, 0, 1, 2] # -1 은 Noise, 나머지는 cluster


Evaluate Clustering & Visualize

Silhouette Score



1: 근처의 군집과 멀리 떨어짐(분리가 잘 된 것)
0: 근처의 군집과 인접합
-1: 근처의 군집과 구분이 불가능함.
그리고 개별 sample의 silhouette score가 전체 silhouette score의 평균에서 멀리 떨어지지 않은 것이 좋은 clustering.

#==== Silhouette Analysis =======================
from sklearn.metrics import silhouette_samples, silhouette_score

X_silhouette_coeff = silhouette_samples(X, labels) # for each data. shape=(n,)
X_silhouette_score = silhouette_score(X, labels) # avg silhouette score

# Get silhouette Coefficient by Cluster
df['cluster'] = labels
df['silhouette coeff'] = X_silhouette_coeff
df.groupby('cluster')['silhouette coeff'].mean()
# cluster
# 0    0.417320
# 1    0.798148
# 2    0.451105

df.groupby('cluster')['silhouette coeff'].value_counts()
# target   gm_cluster  count
# 0        0           50
# 1        2           45
#          1           5
# 2        1           50

[ Performance Measurement (Metrics) ]

For Regressor - Errors

from sklearn.metrics import mean_absolute_error, mean_squared_error, mean_squared_log_error, r2_score
#==== Errors =======================
# MAE
score = mean_absolute_error(y, y_pred) # API
scoring='neg_mean_absolute_error' # scoring option in `cross_val_score` OR `GridSearchCV`
# MSE
mean_squared_error(y, y_pred)
scoring='neg_mean_squared_error' # `neg_` means negative(-1*MSE): scoring=big_value means good.
# RMSE
np.sqrt(mean_sqaured_error(y, y_pred))
scoring='neg_root_mean_squared_error'
# MSLE
mean_squared_log_error(y, y_Pred)
scoring='neg_mean_squared_log_error'
# R^2
r2_score(y, y_pred)
scoring='r2'

#==== Errors (Custom) =======================
# RMSLE
squared_error = (np.log1p(y) - np.log1p(y_pred))**2
score = np.sqrt(np.mean(squared_error))

For Classifier - Confusion Matrix / Classification Report / Metrics...

data = load_breast_cancer()

# Fit & Predict
X_train, X_test, y_train, y_test = train_test_split(
	data.data, data.target, stratify=data.target, random_state=0)
lr = LogisticRegression().fit(X_train, y_train)
y_pred = lr.predict(X_test)



#==== Confusion Matrix =======================
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay

print(confusion_matrix(y_test, y_pred)) ## normalize='true' or 'pred'
#== Example for binary classification ==
##   predicted      Neg, Positive
## actual Negative [TN , FP]
## actual Positive [FN , TP]  ←- dtype=int64
ConfusionMatrixDisplay.from_estimator(lr, X_test, y_test, cmap="gray_r") # Same as above, but draws Heatmap with matrix


#==== Classification Report =======================
from sklearn.metrics import classification_report, precision_score, recall_score, f1_score
print(classification_report(y_test, y_pred)) # 
##                precision  recall  f1-score  support
## class 0         0.90      0.95     0.92       100  
## class 1         0.70      0.50     0.58       20
##
## accuracy                            0.88       120
## macro avg        0.80      0.73     0.75       120
## weighted avg     0.87      0.88     0.87       120


#==== Metrics =======================
# Precision: (TP) / (TP + FP)  # Actual P in P_predicted ratio
precision_score(...)

# Recall(=TPR): (TP) / (TP + FN)  # Actual P in P_actual  
## Important when predict T as F is CRITICAL.
print(recall_score(y_test, y_pred, average="macro")) ## average="weighted"

# Accuracy: (TN + TF) / (total)
## Same as classification_report[f1-score, accuracy]
print(accuracy_score(y_test, y_pred))  # (TP + TN) / (total) # Bad when Unbalanced Classes
## lr.score(X_test, y_test) # Same as accuracy_score(), but model-side method

print(balanced_accuracy_score(y_test, y_pred)) # Similar to (recall, macro avg)

# F1-score:  
print(f1_score(y_test, y_pred, average="weighted"))

조화평균

For Classifier - Prediction Threshold / PR(Precesion-Recall) Curve / ROC curve & AUC score

PR(Precision-Recall) Curve:
Prediction의 Threshold를 바꿈에 따라 Recall(x축)과 Precision(y축)의 그래프
Precision과 Recall은 trade-off 관계에 있다.
그래프의 오른쪽 위의 점일수록 최적의 Threshold
ROC(Reciever Operation Characteristic) Curve:
Prediction의 Threshold를 바꿈에 따라 FPR(x축)과 TPR(Recall)(y축)의 그래프


그래프의 왼쪽 위의 점일수록 최적의 Threshold
AUC(Area Under Curve) Score
ROC Curve 아래의 면적. 1에 가까울수록 좋음.

from sklearn.metrics import precision_recall_curve, plot_precision_recall_curve
							roc_curve, roc_auc_score, plot_roc_curve

#==== Classification Prediction Threshold =======================
# Change Prediction Threshold in Classification. - instead of `y_pred = model.predict(X_test)`
## hyperparameter: threshold.  # Tune with Accuracy/Recall/Precision
y_pred_proba = model.predict_proba(X_test)[:, 1] # 각 data별로 각 class(COL)에 속할 확률을 반환. # second column means Positive class Ratio in Binary Classification.
y_pred = y_pred_proba > 0.3 ## default 0.5 (probability)
# 기준을 0.3으로 낮춤 -> 좀 더 후해짐 -> True로 판정할 확률 증가 -> Recall ↑, Precision ↓


#==== PR curve =======================
# Get Scores
precisions, recalls, thresholds = precision_recall_curve(y_test, model.predict_proba(X_test)[:, 1]) # shape: (nx1)
# Draw Plot
plot_precision_recall_curve(model, X_test, y_test, name="123")


#==== ROC curve & AUC score =======================
# Get Scores
fpr, tpr, thresholds = roc_curve(y_test, model.predict_proba(X_test)[:, 1])
# Get AUC Score
auc_score = roc_auc_score(y_test, y_pred_proba)
# Draw Plot
plot_roc_curve(model, X_test, y_test, name="123")


## Names of other metrices
from sklearn.metrics import SCORES
print("\n".join(sorted(SCORES.keys())))

'Programming Language > Python' 카테고리의 다른 글

Seaborn  (0) 2026.01.20
Matplotlib  (0) 2026.01.20
Pandas  (0) 2026.01.20
Numpy  (0) 2026.01.17