Day1
import pandas as pd
df = pd.DataFrame(dt.feature_importances_).T
df.columns=dt.feature_names_in_
df.T.sort_values(by=[0],ascending=False)
| 0 | |
|---|---|
| concave_points1 | 0.691420 |
| concave_points3 | 0.065651 |
| texture1 | 0.058478 |
| radius3 | 0.052299 |
| perimeter3 | 0.051494 |
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt
plt.figure(figsize=(15,15))
plot_tree(dt)
plt.show()

from sklearn.model_selection import GridSearchCV
params = {'max_depth' : [3, 4, 5, 6], 'min_samples_split' : [2,3,4,5,6]}
gs = GridSearchCV(DecisionTreeClassifier(random_state=42), params, n_jobs=-1)
gs.fit(X_train,y_train)
원하는 파라미터 종류 작성하면 코드가 알아서 조합을 짜서 확인함
한 번에 n개의 작업을 돌릴 수 있는 것 - threads
threads - dead lock
파이썬은 GIL 걸려있는 상황
그리드서치에서 n_jobs 파라미터가 여기서 병렬처리를 몇 개 거는지 결정

gs.best_estimator_

gs.best_params_
{'max_depth': 3, 'min_samples_split': 2}
gs.cv_results_['mean_test_score']
array([0.92967033, 0.92967033, 0.92967033, 0.92967033, 0.92967033,
0.92307692, 0.92307692, 0.92087912, 0.92087912, 0.92307692,
0.92527473, 0.92527473, 0.92747253, 0.92307692, 0.92527473,
0.91648352, 0.91648352, 0.91868132, 0.91868132, 0.91648352])
import numpy as np
from sklearn.model_selection import GridSearchCV
params = {'min_impurity_decrease': np.arange(0.0001,0.001,0.0001),
'max_depth':range(3,20,1),
'min_samples_split':range(2,100,10)
}
gs = GridSearchCV(DecisionTreeClassifier(random_state=42), params, n_jobs=-1)
gs.fit(X_train,y_train)

gs.cv_results_['mean_test_score'].__len__()
1530
gs.best_params_
{'max_depth': 4,
'min_impurity_decrease': np.float64(0.0001),
'min_samples_split': 12}
np.max(gs.cv_results_['mean_test_score'])
from sklearn.metrics import accuracy_score
dt = DecisionTreeClassifier(max_depth=4,
min_impurity_decrease= np.float64(0.0001),
min_samples_split= 12)
dt.fit(X_train,y_train)
accuracy_score(y_test, dt.predict(X_test))
0.9473684210526315
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import uniform, randint
params = {
'min_impurity_decrease' : uniform(0.0001, 0.001),
'max_depth' : randint(3,100),
'min_samples_split' : randint(2,30),
'min_samples_leaf' : randint(1,30)
}
rs = RandomizedSearchCV(DecisionTreeClassifier(random_state=42),
params, n_iter=100, n_jobs=-1, random_state=42)
rs.fit(X_train,y_train)
rs.best_params_
{'max_depth': 54,
'min_impurity_decrease': np.float64(0.0006632755719763837),
'min_samples_leaf': 4,
'min_samples_split': 6}
rs.best_estimator_

https://pypi.org/project/mlflow/



rosie@ming9:~/encore$ history |grep build
208 docker build -t sk25:0.1 .
237 history |grep build
rosie@ming9:~/encore$
rosie@ming9:~/encore$ docker build -t sk25:0.2 .

환경 구축 자동화 - 젠킨스. 못생김.
현재 docker images 저장 목록들
docker images
docker stop sk25
docker run -itd --name sk25_mlflow -p 9000:8888 -p 5000:5000 -v ~/mydata:/home/ict/work sk25:0.2


멀쩡히 연결됨을 확인
주피터 서버 연결되어있는 곳에서 서버 열기
# bash
root@a5ba42c017e5:/home/ict/work/wk6# mlflow server --port 5000 --host 0.0.0.0
Backend store URI not provided. Using sqlite:///mlflow.db


rosie@ming9:~/encore$ docker exec -it sk25_mlflow /bin/bash
mlflow server --port 5000 --host 0.0.0.0
import mlflow
mlflow.set_tracking_uri("http://localhost:5000")
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import pandas as pd
mlflow.set_experiment('sk25_first')

from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.model_selection import train_test_split
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target
# 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
from sklearn.metrics import accuracy_score, classification_report
with mlflow.start_run(run_name = 'baseline'):
params = {
'max_depth' : 3,
'random_state' : 42
}
mlflow.log_params(params)
dt = DecisionTreeClassifier(**params)
dt.fit(X_train, y_train)
y_pred = dt.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
mlflow.log_metric('accuracy', accuracy)
mlflow.sklearn.log_model(dt, 'decision_model')
report = classification_report(y_test, y_pred)
mlflow.log_dict(report, 'classification_report.json')
print(mlflow.active_run().info.run_id)


mlflow.set_experiment('sk25_second')
mlflow.sklearn.autolog()
with mlflow.start_run(run_name = 'haha'):
model = DecisionTreeClassifier(**params)
model.fit(X_train, y_train)
y_pred = dt.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)

import mlflow
mlflow.set_tracking_uri("http://localhost:5000")
model = mlflow.sklearn.load_model("models:/sk25/1")

import numpy as np
model.predict(np.array([5.1,3.5,1.4,0.2]).reshape(-1,4))
rosie@ming9:~$ docker exec -it sk25_mlflow /bin/bash
root@a5ba42c017e5:/home/ict/work# export MLFLOW_TRACKING_URI=http://localhost:5000
root@a5ba42c017e5:/home/ict/work#
root@a5ba42c017e5:/home/ict/work# mlflow models serve -m "models:/sk25/1" -p 123 --env-manager=local

import requests
url='http://127.0.0.1:123/invocations'
import pandas as pd
df = pd.DataFrame(
[[5.1, 3.5, 1.4, 0.2]],
columns=["sepal length (cm)", "sepal width (cm)", "petal length (cm)", "petal width (cm)"]
)
{'dataframe_split': df.to_dict(orient='split')}
<output>
{'index': [0],
'columns': ['sepal length (cm)',
'sepal width (cm)',
'petal length (cm)',
'petal width (cm)'],
'data': [[5.1, 3.5, 1.4, 0.2]]}
서버가 받는 데이텨 형태로 변형
requests.post(url,json={'dataframe_split': df.to_dict(orient='split')}).text
'{"predictions": [0]}'
| 🔵bagging | 🔵voting | 🔵boosting |
|---|---|---|
| 다수의 decision tree | soft | |
| • 레이블 값을 결정하는 확률값을 모두 더해서 사용 | xgboost, lightgbm | |
| 다수 dt가 각자의 데이터를 독립적으로 사용(샘플링) | hard |
• 사람이 하는 투표와 동일
• 다른 종류의 알고리즘 혼합 가능 | |
| ex) random forest | soft가 hard voting보다 성능이 앞선다고 알려짐 | |
클래스가 불균형할 때 사용 → smote
Day2
from sklearn.metrics import classification_report
y_true = [0,0,0,0,0,1,1,1,2,2]
y_pred = [0,0,0,0,1,0,1,2,1,2]
print(classification_report(y_true, y_pred))
precision recall f1-score support
0 0.80 0.80 0.80 5
1 0.33 0.33 0.33 3
2 0.50 0.50 0.50 2
accuracy 0.60 10
macro avg 0.54 0.54 0.54 10
weighted avg 0.60 0.60 0.60 10

from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
knn = KNeighborsClassifier()
knn.fit(load_iris().data, load_iris().target)
import pandas as pd
df= pd.read_csv("./data/credit_card_default.csv")
df.shape
y= df.pop('default_payment_next_month')
X= df.copy()
import numpy as np
np.unique(y,return_counts=True)
`(array([0, 1]), array([23364, 6636]))`
히스토그램 - 남녀별 나이 분포
import matplotlib.pyplot as plt
import seaborn as sns
fig, ax = plt.subplots()
sns.histplot(df.loc[df.sex == 'Male', 'age'])
# sns.kdeplot(df.loc[df.sex == 'Male', 'age'], ax=ax)
plt.show()

커널밀도추정

남녀 동시에 커널밀도값 보기

범주형, 양적 데이터 상관없이 상관관계 한 번에 보기
pair_plot = sns.pairplot(df[['age', 'limit_bal', 'previous_payment_sep']])
plt.show()

상관관계 표시
df.select_dtypes(include='number').corr()
삼각행렬 활용해서 삼각형 절반만 출력하기
# 상관계수 히트맵 그리기
import numpy as np
mask = np.zeros_like(df.select_dtypes(include='number').corr(), dtype=bool)
mask[np.triu_indices_from(mask)] = True
#df.select_dtypes(include='number').corr()
fig, ax = plt.subplots()
cmap = sns.diverging_palette(240, 10, n=9, as_cmap=True)
sns.heatmap(df.select_dtypes(include='number').corr(), mask=mask, vmax=3, cmap=cmap,
center=0, square=0, linewidths=0.5, ax = ax)
ax.set_title("correlation Matrix", fontsize=20)
plt.show()

# 상관계수 히트맵 그리기
import numpy as np
matrix_corr = pd.concat([df, y], axis=1).select_dtypes(include='number').corr()
mask = np.zeros_like( matrix_corr , dtype=bool)
mask[np.triu_indices_from(mask)] = True
#df.select_dtypes(include='number').corr()
fig, ax = plt.subplots()
cmap = sns.diverging_palette(240, 10, n=9, as_cmap=True)
sns.heatmap(matrix_corr, mask=mask, vmax=0.3, cmap=cmap,
center=0, square=0, linewidths=0.5, ax = ax)
ax.set_title("correlation Matrix", fontsize=20)
plt.show()

vis_df=pd.concat([df['education'] , y],axis=1)
data=vis_df.groupby('education')['default_payment_next_month'].value_counts(normalize=True).plot(kind='barh')

vis_df=pd.concat([df['education'] , y],axis=1)
data=vis_df.groupby('education')['default_payment_next_month'].value_counts(normalize=True).unstack().plot(kind='barh',stacked=True)

#pip install missingno
import missingno
missingno.matrix(X)
plt.show()

missingno.bar(X)

타겟 인코더
!pip install category-encoders==2.6.3
import category_encoders
import category_encoders
target_en = category_encoders.TargetEncoder(smoothing=0)
target_en.fit(X.sex,y)
pd.concat([X.sex, target_en.transform(X.sex)] ,axis=1).iloc[:, 1].value_counts()
sex
0.207578 18027
0.241648 11823
0.246667 150
Name: count, dtype: int64
num_feautures=['age']
cat_features=['sex','education','marriage']
from sklearn.impute import SimpleImputer
num_imputer = SimpleImputer(strategy='median')
num_imputer.fit(X[['age']])
no_missing_values = num_imputer.transform(X[['age']])
X.loc[:, 'age_nomv' ] = no_missing_values
오토인코더
명령어 모드에서 대문자 G → 맨 아래로 이동
소문자 g 2번 → 맨 위로 이동
:set nu → vim에 숫자번호 추가
/xgboost → / 키워드는 검색
dd → 라인 제거
u → 원상복구
[숫자]dd → 숫자에서 삭제
vim /etc/vim/vimrc → 환경파일
빈 줄에 set nu 입력 시 vim에 기본적으로 번호 설정
1 FROM python:3.10.8-slim-bullseye
2
3
4 # 작업 디렉토리 설정
5 WORKDIR /home/ict/work
6
7 ENV MLFLOW_TRACKING_URI = http://localhost:5000
8
9
10 COPY . /home/ict/work
11
12 RUN apt-get update && apt-get install -y \
13 python3-dev default-libmysqlclient-dev build-essential pkg-config graphviz
14
15
16 RUN pip install --upgrade pip
17 RUN pip install -r requirements.txt
18
19 RUN jupyter notebook --generate-config
20 COPY jupyter_notebook_config.py /root/.jupyter/
21
22
23 EXPOSE 9000
24
25
26 CMD ["jupyter", "lab", "--ip=0.0.0.0", "--allow-root"]
~
~
~
rosie@ming9:~/encore$ docker rmi sk25:0.1
docker build -t sk25:0.3 .
docker run -itd --name sk25_mlflow -p 9000:8888 -p 5000:5000 -v ~/mydata:/home/ict/work sk25:0.3

# eXtreme Gradient Boosting
import xgboost as xgb
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report
import pandas as pd
df=pd.DataFrame(load_breast_cancer()['data'],columns=load_breast_cancer().feature_names)
from ydata_profiling import ProfileReport
profile = ProfileReport(df, title = 'eda')
profile.to_file('./report.html')
data = load_breast_cancer()
X = pd.DataFrame(data.data, columns=data.feature_names)
y = data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
model = xgb.XGBClassifier(
n_estimators=100, # 트리의 개수
max_depth=4, # 깊이 제한
learning_rate=0.1,
random_state=42,
objective='binary:logistic',
use_label_encoder=False,
eval_metric='logloss' # 회귀 : rmse , mae # 분류 : logloss, auc
)
model.fit(X_train, y_train)
print(classification_report(y_test, model.predict(X_test)))
import matplotlib.pyplot as plt
from xgboost import plot_importance
plt.figure(figsize=(10,8))
plot_importance(model, max_num_features=10)
plt.show()

pip install shap --upgrade
#설명 가능한 인공지능(xai)
import shap
# 협력적 게임 이론에서 나오는 이론적 개념을 바탕으로 머신러닝 모델 해석에 적용한 방법론
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test)
shap.summary_plot(shap_values, X_test, feature_names=data.feature_names)

import optuna
def objective(trial):
param = {
'n_estimators': trial.suggest_int('n_estimators', 100, 1000),
'learning_rate': trial.suggest_float('learning_rate', 0.01, 0.3, log=True),
'max_depth': trial.suggest_int('max_depth', 3, 10),
'subsample': trial.suggest_float('subsample', 0.5, 1.0),
'colsample_bytree': trial.suggest_float('colsample_bytree', 0.5, 1.0),
'reg_alpha': trial.suggest_float('reg_alpha', 1e-8, 1.0, log=True), # L1
'reg_lambda': trial.suggest_float('reg_lambda', 1e-8, 1.0, log=True), # l2
'n_jobs': -1,
'random_state': 42,}
model=xgb.XGBClassifier(**param)
pruning_callback=optuna.integration.XGBoostPruningCallback(trial, 'validation_0-logloss')
study = optuna.create_study(direction='maximize')
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=50)
# 콜백 정의
pruning_callback = optuna.integration.XGBoostPruningCallback(trial, "validation_0-logloss")
#하이퍼파라미터 설정
param = {
'n_estimators': trial.suggest_int('n_estimators', 100, 1000),
'learning_rate': trial.suggest_float('learning_rate', 0.01, 0.3, log=True),
'max_depth': trial.suggest_int('max_depth', 3, 10),
'subsample': trial.suggest_float('subsample', 0.5, 1.0),
'colsample_bytree': trial.suggest_float('colsample_bytree', 0.5, 1.0),
'reg_alpha': trial.suggest_float('reg_alpha', 1e-8, 1.0, log=True),
'reg_lambda': trial.suggest_float('reg_lambda', 1e-8, 1.0, log=True),
'n_jobs': -1,
'random_state': 42,
'eval_metric': 'logloss',
'callbacks': [pruning_callback]
}
# 모델 정의
model = xgb.XGBClassifier(**param)
# 모델 학습
model.fit(
X_train,
y_train,
eval_set=[(X_test, y_test)],
verbose=False
)
preds = model.predict(X_test)
accuracy = accuracy_score(y_test, preds)
return accuracy
def objective(trial):
data = load_breast_cancer()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
import optuna
import xgboost as xgb
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import mlflow
import mlflow.xgboost
mlflow.set_tracking_uri("http://localhost:5000")
mlflow.set_experiment("XGBoost_SHAP_Analysis")
data = load_breast_cancer()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
def objective(trial):
with mlflow.start_run(run_name=f"trial_{trial.number}", nested=True):
# callback 함수
pruning_callback = optuna.integration.XGBoostPruningCallback(trial, "validation_0-logloss")
# 하이퍼파라미터 설정
param = {
'n_estimators': trial.suggest_int('n_estimators', 100, 1000),
'learning_rate': trial.suggest_float('learning_rate', 0.01, 0.3, log=True),
'max_depth': trial.suggest_int('max_depth', 3, 10),
'subsample': trial.suggest_float('subsample', 0.5, 1.0),
'colsample_bytree': trial.suggest_float('colsample_bytree', 0.5, 1.0),
'reg_alpha': trial.suggest_float('reg_alpha', 1e-8, 1.0, log=True),
'reg_lambda': trial.suggest_float('reg_lambda', 1e-8, 1.0, log=True),
'n_jobs': -1,
'random_state': 42,
'eval_metric': 'logloss',
'callbacks': [pruning_callback]
}
mlflow.xgboost.autolog(log_input_examples=True, log_model_signatures=True, silent=True)
model = xgb.XGBClassifier(**param)
# 모델 학습
model.fit(
X_train,
y_train,
eval_set=[(X_test, y_test)],
verbose=False
)
preds = model.predict(X_test)
accuracy = accuracy_score(y_test, preds)
mlflow.log_metric("val_accuracy", accuracy)
return accuracy
with mlflow.start_run(run_name="HPO_Session_Main") as parent_run:
print(f"Parent Run ID: {parent_run.info.run_id}")
study = optuna.create_study(direction='maximize')
print("XGBoost 최적화 시작...")
study.optimize(objective, n_trials=50)
print("\n================ 결과 ================")
print(f"Best Trial Score: {study.best_value:.4f}")



Day3
import pandas as pd
df= pd.read_csv("./creditcard.csv")
df['Class'].value_counts(normalize=True)
Class
0 0.998273
1 0.001727
Name: proportion, dtype: float64
from sklearn.model_selection import train_test_split
y = df.pop('Class')
X_train, X_test, y_train,y_test= train_test_split(df,y,random_state=42,stratify=y)
print(y_train.value_counts(normalize=True))
print(y_test.value_counts(normalize=True))
Class
0 0.998273
1 0.001727
Name: proportion, dtype: float64
Class
0 0.998273
1 0.001727
Name: proportion, dtype: float64
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(10,6))
df.boxplot()
plt.show()

import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(10,6))
df[['Amount']].boxplot()
plt.show()

X_train.drop(columns='Time',inplace=True)
X_test.drop(columns='Time',inplace=True)
X_train.Amount.describe()
count 213605.000000
mean 88.216558
std 250.522258
min 0.000000
25% 5.640000
50% 22.000000
75% 77.500000
max 25691.160000
Name: Amount, dtype: float64
from sklearn.preprocessing import StandardScaler
ss=StandardScaler()
amount_ss=ss.fit_transform(X_train[['Amount']])
amount_ss=pd.DataFrame(amount_ss)
from sklearn.preprocessing import MinMaxScaler
mm=MinMaxScaler()
amount_mm=mm.fit_transform(X_train[['Amount']])
amount_mm=pd.DataFrame(amount_mm)
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(10,6))
amount_ss.boxplot()
plt.show()

import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(10,6))
amount_mm.boxplot()
plt.show()

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
log_df=pd.DataFrame(np.log1p(X_train[['Amount']]))
plt.figure(figsize=(10,6))
log_df.boxplot()
plt.show()

https://brilliant.org/wiki/truth-tables/
https://brilliant.org/wiki/logic-gates/

모든 파라미터를 편미분을 활용하여 값을 조절함
미분의 연쇄법칙 활용하여 품, 오차역전파
순방향, 역방향에 따른 계산법 상이
https://compmath.korea.ac.kr/deeplearning/BackPropagation.html
DNN은 유명한 완전연결층임
각 동그라미를 node, neural이라고 부른다.
역전파
lose function과 cost function을 줄이는 방향
왼쪽에서 오른쪽으로 간다 → 순전파




q1 = np.percentile(X_train.Amount, 25)
q3 = np.percentile(X_train.Amount, 75)
iqr = q3 - q1
lowest = q1 - (iqr * 1.5)
highest = q3 + (iqr * 1.5)
X_train[(X_train.Amount < lowest) | (X_train.Amount > highest)].index
remove_index = X_train[(X_train.Amount < lowest) | (X_train.Amount > highest)].index
X_train_remove = X_train[~X_train.index.isin(remove_index)].copy()
y_train_remove = y_train[~y_train.index.isin(remove_index)].copy()
smote = SMOTE(random_state=42)
X_train_sm, y_train_sm = smote.fit_resample(X_train, y_train)
y_train_sm.value_counts()
Class
0 213236
1 213236
Name: count, dtype: int64
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from sklearn.metrics import precision_recall_curve
%matplotlib inline
def precision_recall_curve_plot(y_test , pred_proba_c1):
# threshold ndarray와 이 threshold에 따른 정밀도, 재현율 ndarray 추출.
precisions, recalls, thresholds = precision_recall_curve( y_test, pred_proba_c1)
# X축을 threshold값으로, Y축은 정밀도, 재현율 값으로 각각 Plot 수행. 정밀도는 점선으로 표시
plt.figure(figsize=(8,6))
threshold_boundary = thresholds.shape[0]
plt.plot(thresholds, precisions[0:threshold_boundary], linestyle='--', label='precision')
plt.plot(thresholds, recalls[0:threshold_boundary],label='recall')
# threshold 값 X 축의 Scale을 0.1 단위로 변경
start, end = plt.xlim()
plt.xticks(np.round(np.arange(start, end, 0.1),2))
# x축, y축 label과 legend, 그리고 grid 설정
plt.xlabel('Threshold value'); plt.ylabel('Precision and Recall value')
plt.legend(); plt.grid()
plt.show()
precision_recall_curve_plot( y_test, lr.predict_proba(X_test)[:, 1] )


jax → 최적화를 위한 라이브러리.
linux arm 체제 존재. 휴대폰 안에 들어있음
Day4

import torch
torch.cuda.is_available()
`True`



데이터 생성
import torch.nn as nn
import torch.optim as optim
torch.manual_seed(42)
data= torch.randn(100,1)*10
시각화
import matplotlib.pyplot as plt
x = data
y = 2 * data + 1 + torch.randn(100, 1) * 2
plt.scatter(x, y)
plt.show()
모델을 선언해본다
class LRModel(nn.Module):
def __init__(self):
pass
def forword(self,y):
pass
초기함수에 사용 원하는 함수 설정 가능
def __init__(self):
super(LRModel, self).__init__()
self.linear = nn.Linear(1,1)
class LRModel(nn.Module):
def __init__(self):
super(LRModel, self).__init__()
self.linear = nn.Linear(1,1)
def forword(self,x):
return self.linear(x)
model=LRModel()
model.state_dict().items()
odict_items([('linear.weight', tensor([[-0.0098]])), ('linear.bias', tensor([-0.7605]))])
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr = 0.001)
epochs = 100
for epoch in range(epochs):
pred_y = model(x)
loss = criterion(pred_y, y)
# print(optimizer.state_dict())
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (epoch + 1) % 10 == 0:
print(model.state_dict().items())
print(f"{epoch+1} Loss: {loss.item():.3f}")
odict_items([('linear.weight', tensor([[1.8260]])), ('linear.bias', tensor([0.8543]))])
10 Loss: 7.860
odict_items([('linear.weight', tensor([[1.9830]])), ('linear.bias', tensor([0.8595]))])
20 Loss: 3.230
odict_items([('linear.weight', tensor([[2.0012]])), ('linear.bias', tensor([0.8638]))])
30 Loss: 3.165
odict_items([('linear.weight', tensor([[2.0034]])), ('linear.bias', tensor([0.8679]))])
40 Loss: 3.163
odict_items([('linear.weight', tensor([[2.0036]])), ('linear.bias', tensor([0.8719]))])
50 Loss: 3.161
odict_items([('linear.weight', tensor([[2.0036]])), ('linear.bias', tensor([0.8759]))])
60 Loss: 3.160
odict_items([('linear.weight', tensor([[2.0036]])), ('linear.bias', tensor([0.8797]))])
70 Loss: 3.158
odict_items([('linear.weight', tensor([[2.0035]])), ('linear.bias', tensor([0.8835]))])
80 Loss: 3.157
odict_items([('linear.weight', tensor([[2.0035]])), ('linear.bias', tensor([0.8872]))])
90 Loss: 3.155
odict_items([('linear.weight', tensor([[2.0035]])), ('linear.bias', tensor([0.8909]))])
100 Loss: 3.154
model.to(’cuda’) ⇒ vram에 파라미터 올리기. 속도가 개선될 수 있음
predicted=model(x).detach().numpy()
명령어 설명
x (입력)
↓
model(x) → 모델이 계산한 예측값 (Tensor)
↓
.detach() → 학습 그래프에서 분리
↓
.numpy() → NumPy 배열로 변환
↓
predicted → "예측값"이 담김
predicted=model(x).detach().numpy()
plt.scatter(x.numpy(),y.numpy())
plt.scatter(x.numpy(),predicted, color='red')

if torch.cuda.is_available():
DEVICE = torch.device('cuda')
else:
DEVICE = torch.device('cpu')
print('Using PyTorch version:', torch.__version__, ' Device:', DEVICE)
DNN 기반 모델링을 시작한다………………
from torchvision import transforms, datasets
BATCH_SIZE = 32
EPOCHS = 10
train_dataset = datasets.MNIST(root = "../data/MNIST",
train = True,
download = True,
transform = transforms.ToTensor())
test_dataset = datasets.MNIST(root = "../data/MNIST",
train = False,
transform = transforms.ToTensor())
train_loader = torch.utils.data.DataLoader(dataset = train_dataset,
batch_size = BATCH_SIZE,
shuffle = True)
test_loader = torch.utils.data.DataLoader(dataset = test_dataset,
batch_size = BATCH_SIZE,
shuffle = False)
유명한 앤드류 응.


import gzip
import numpy as np
import torch
from torch.utils.data import Dataset, DataLoader
def load_ubyte_images(filepath):
with gzip.open(filepath, 'rb') as f:
# 헤더 읽기 (Magic number, Number of images, Rows, Cols)
magic, num, rows, cols = np.frombuffer(f.read(16), dtype=np.uint32, count=4).byteswap()
# 데이터 읽기 및 정규화 (0~255 -> 0~1)
data = np.frombuffer(f.read(), dtype=np.uint8).reshape(num, 1, rows, cols)
result = data.astype(np.float32)
return result
def load_ubyte_labels(filepath):
with gzip.open(filepath, 'rb') as f:
# 헤더 읽기 (Magic number, Number of items)
magic, num = np.frombuffer(f.read(8), dtype=np.uint32, count=2).byteswap()
# 데이터 읽기
return np.frombuffer(f.read(), dtype=np.uint8).astype(np.int64)
class MNISTManualDataset(Dataset):
def __init__(self, image_path, label_path, transform=None):
self.images = torch.from_numpy(load_ubyte_images(image_path))
self.labels = torch.from_numpy(load_ubyte_labels(label_path))
self.transform = transform
def __len__(self):
return len(self.images)
def __getitem__(self, idx):
image = self.images[idx]
label = self.labels[idx]
if self.transform:
image = self.transform(image)
return image, label
img_path = './data/MNIST/MNIST/raw/t10k-images-idx3-ubyte.gz'
lbl_path = './data/MNIST/MNIST/raw/t10k-labels-idx1-ubyte.gz'
# 데이터셋 인스턴스 생성
manual_dataset = MNISTManualDataset(img_path, lbl_path)
# 데이터로더 생성
manual_loader = DataLoader(
manual_dataset,
batch_size=64,
shuffle=True
)
⇒ 데이터셋과 로더는 세트이다.
# 데이터 확인
images, labels = next(iter(manual_loader))
print(f"Batch Image Shape: {images.shape}") # [64, 1, 28, 28]
print(f"Batch Label Shape: {labels.shape}") # [64]
for (X_train, y_train) in train_loader:
print('X_train:', X_train.size(), 'type:', X_train.type())
print('y_train:', y_train.size(), 'type:', y_train.type())
break
import matplotlib.pyplot as plt
pltsize = 1
plt.figure(figsize=(10 * pltsize, pltsize))
for i in range(10):
plt.subplot(1, 10, i + 1)
plt.axis('off')
plt.imshow(X_train[i, :, :, :].numpy().reshape(28, 28), cmap = "gray_r")
plt.title('Class: ' + str(y_train[i].item()))

초기함수
DNN 구조에서 노드 개수로 생각
forward 함수
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(28 * 28, 512)
self.fc2 = nn.Linear(512, 256)
self.fc3 = nn.Linear(256, 10)
def forward(self, x):
x = x.view(-1, 28 * 28)
x = self.fc1(x)
x = F.sigmoid(x)
x = self.fc2(x)
x = F.sigmoid(x)
x = self.fc3(x)
x = F.log_softmax(x, dim = 1)
return x
model = Net().to(DEVICE)
optimizer = torch.optim.SGD(model.parameters(), lr = 0.01, momentum = 0.5)
criterion = nn.CrossEntropyLoss()
print(model)
Net(
(fc1): Linear(in_features=784, out_features=512, bias=True)
(fc2): Linear(in_features=512, out_features=256, bias=True)
(fc3): Linear(in_features=256, out_features=10, bias=True)
)
from torchinfo import summary
summary(model, input_size=(32,784))
==========================================================================================
Layer (type:depth-idx) Output Shape Param #
==========================================================================================
Net [32, 10] --
├─Linear: 1-1 [32, 512] 401,920
├─Linear: 1-2 [32, 256] 131,328
├─Linear: 1-3 [32, 10] 2,570
==========================================================================================
Total params: 535,818
Trainable params: 535,818
각 간선은 wx+b 로 구성되어있으므로 양쪽 노드의 곱과 바이어스 개수의 합으로 파라미터의 수를 산출해낼 수 있다.
훈련 함수 정의
def train(model, train_loader, optimizer, log_interval):
model.train()
for batch_idx, (image, label) in enumerate(train_loader):
image = image.to(DEVICE)
label = label.to(DEVICE)
optimizer.zero_grad()
output = model(image)
loss = criterion(output, label)
loss.backward()
optimizer.step()
if batch_idx % log_interval == 0:
print("Train Epoch: {} [{}/{} ({:.0f}%)]\tTrain Loss: {:.6f}".format(
epoch, batch_idx * len(image),
len(train_loader.dataset), 100. * batch_idx / len(train_loader),
loss.item()))
평가 함수 정의
def evaluate(model, test_loader):
model.eval()
test_loss = 0
correct = 0
with torch.no_grad():
for image, label in test_loader:
image = image.to(DEVICE)
label = label.to(DEVICE)
output = model(image)
test_loss += criterion(output, label).item()
prediction = output.max(1, keepdim = True)[1]
correct += prediction.eq(label.view_as(prediction)).sum().item()
test_loss /= (len(test_loader.dataset) / BATCH_SIZE)
test_accuracy = 100. * correct / len(test_loader.dataset)
return test_loss, test_accuracy
진짜 훈련시켜보기
for epoch in range(1, EPOCHS + 1):
train(model, train_loader, optimizer, log_interval = 200)
test_loss, test_accuracy = evaluate(model, test_loader)
print("\n[EPOCH: {}], \tTest Loss: {:.4f}, \tTest Accuracy: {:.2f} % \n".format(
epoch, test_loss, test_accuracy))
농땡이 치는 간선 처리, 과적합 방지
def train(model, train_loader, optimizer, criterion, device, epoch, log_interval, batch_size):
global loss, label
model.train()
correct = 0
train_loss = 0
total_samples = 0
for batch_idx, (image, label) in enumerate(train_loader):
image = image.to(device)
label = label.to(device)
optimizer.zero_grad()
output = model(image)
loss = criterion(output, label)
train_loss += loss.item() * label.size(0)
loss.backward()
optimizer.step()
preds = output.argmax(dim=1)
correct += (preds == label).sum().item()
total_samples += label.size(0)
if batch_idx % log_interval == 0:
print("Train Epoch: {} [{}/{} ({:.0f}%)]\tTrain Loss: {:.6f}".format(
epoch, total_samples,
len(train_loader.dataset), 100. * batch_idx / len(train_loader),
loss.item()))
train_loss /= total_samples
train_accuracy = 100. * correct / total_samples
return train_loss, train_accuracy
def evaluate(model, test_loader):
model.eval() # 평가 모드 전환 (드롭아웃, 배치 정규화 등 비활성화)
test_loss = 0
correct = 0
with torch.no_grad(): # 기울기 계산 비활성화 (메모리 절약 및 속도 향상)
for images, labels in test_loader: # 복수형(images, labels)으로 통일 권장
# 1. 데이터를 동일한 장치(GPU/CPU)로 이동
images = images.to(DEVICE)
labels = labels.to(DEVICE)
# 2. 모델 예측
outputs = model(images)
# 3. 손실 계산 및 누적
# criterion의 결과는 보통 배치당 평균이므로, 전체 평균을 구하기 위해 배치 크기를 곱해줍니다.
loss = criterion(outputs, labels)
test_loss += loss.item() * images.size(0)
# 4. 정확도 계산
predictions = outputs.argmax(dim=1) # 가장 높은 확률을 가진 인덱스 추출
correct += (predictions == labels).sum().item() # 현재 배치의 정답 수 누적
# 전체 데이터셋에 대한 평균 손실과 정확도 계산
test_loss /= len(test_loader.dataset)
test_accuracy = 100. * correct / len(test_loader.dataset)
return test_loss, test_accuracy
class early_stopping:
def __init__(self, patience, verbose, delta, path='checkpoint.pt'):
self.patience = patience
self.verbose = verbose
self.delta = delta
self.count = 0
self.best_score = None
self.early_stop = False
self.val_loss_min = np.inf
self.path = path
def __call__(self, val_loss, model):
score = -val_loss
if self.best_score is None:
self.best_score = score
self.save_checkpoint(val_loss, model)
elif score < self.best_score + self.delta:
self.count += 1
if self.verbose:
print(f"Early Stopping counter: {self.count} out of {self.patience}")
if self.count >= self.patience:
self.early_stop = True
else:
self.best_score = score
self.save_checkpoint(val_loss, model)
self.count =0
def save_checkpoint(self, val_loss, model):
if self.verbose:
print(f"Validation loss decreased ({self.val_loss_min:.6f}) --> {val_loss:.6f}. saving model..")
torch.save(model.state_dict(), self.path)
self.val_loss_min = val_loss
patience = 2
EPOCHS = 50
import numpy as np
early_stopping = early_stopping(patience=2, verbose=True, path='best_model.pt', delta=0)
loss_hist_train = [0] * EPOCHS
accuracy_hist_train = [0] * EPOCHS
loss_hist_valid = [0] * EPOCHS
accuracy_hist_valid = [0] * EPOCHS
for epoch in range(1, EPOCHS + 1):
loss_, acc_ = train(model, train_loader, optimizer, criterion, DEVICE, epoch, log_interval = 200, batch_size=BATCH_SIZE)
loss_hist_train[epoch-1] = loss_
accuracy_hist_train[epoch-1] = acc_
test_loss, test_accuracy = evaluate(model, test_loader)
loss_hist_valid[epoch-1] = test_loss
accuracy_hist_valid[epoch-1] = test_accuracy
print("\n[EPOCH: {}], \tTest Loss: {:.4f}, \tTest Accuracy: {:.2f} % \n".format(
epoch, test_loss, test_accuracy))
early_stopping(test_loss, model)
if early_stopping.early_stop:
print("Early stopping")
break
import matplotlib.pyplot as plt
epochs_range = np.arange(1,50)
epochs_range = np.arange(0, len(loss_hist_train))
plt.figure(figsize=(12, 5)) # 전체 그래프 크기 설정
# --- 첫 번째 그래프: Loss (손실) ---
plt.subplot(1, 2, 1) # 1행 2열 중 첫 번째
plt.plot(epochs_range, loss_hist_train, label='Train Loss', color='blue', marker='o')
plt.plot(epochs_range, loss_hist_valid, label='Valid Loss', color='red', marker='s')
plt.title('Training and Validation Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.grid(True)
plt.legend()
# --- 두 번째 그래프: Accuracy (정확도) ---
plt.subplot(1, 2, 2) # 1행 2열 중 두 번째
plt.plot(epochs_range, accuracy_hist_train, label='Train Accuracy', color='blue', marker='o')
plt.plot(epochs_range, accuracy_hist_valid, label='Valid Accuracy', color='red', marker='s')
plt.title('Training and Validation Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy (%)')
plt.grid(True)
plt.legend()
plt.tight_layout() # 그래프 간 간격 자동 조절
plt.show()

train_dataset = datasets.CIFAR10(root = "./data/CIFAR_10",
train = True,
download = True,
transform = transforms.ToTensor())
test_dataset = datasets.CIFAR10(root = "./data/CIFAR_10",
train = False,
transform = transforms.ToTensor())
train_loader = torch.utils.data.DataLoader(dataset = train_dataset,
batch_size = BATCH_SIZE,
shuffle = True)
test_loader = torch.utils.data.DataLoader(dataset = test_dataset,
batch_size = BATCH_SIZE,
shuffle = False)
for (X_train, y_train) in train_loader:
print('X_train:', X_train.size(), 'type:', X_train.type())
print('y_train:', y_train.size(), 'type:', y_train.type())
break
X_train.shape
pltsize = 1
plt.figure(figsize=(10 * pltsize, pltsize))
for i in range(10):
plt.subplot(1, 10, i + 1)
plt.axis('off')
plt.imshow(np.transpose(X_train[i], (1, 2, 0)))
plt.title('Class: ' + str(y_train[i].item()))

import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(32 * 32 * 3, 512)
self.fc2 = nn.Linear(512, 256)
self.fc3 = nn.Linear(256, 10)
def forward(self, x):
x = x.view(-1, 32 * 32 *3)
x = self.fc1(x)
x = F.sigmoid(x)
x = self.fc2(x)
x = F.sigmoid(x)
x = self.fc3(x)
x = F.log_softmax(x, dim = 1)
return x
model = Net().to(DEVICE)
optimizer = torch.optim.SGD(model.parameters(), lr = 0.01, momentum = 0.5)
criterion = nn.CrossEntropyLoss()
from torchinfo import summary
summary(model, input_size=(64, 32*32*3))
Layer (type:depth-idx) Output Shape Param #
==========================================================================================
Net [64, 10] --
├─Linear: 1-1 [64, 512] 1,573,376
├─Linear: 1-2 [64, 256] 131,328
├─Linear: 1-3 [64, 10] 2,570
==========================================================================================
Total params: 1,707,274
Trainable params: 1,707,274
Non-trainable params: 0
Total mult-adds (Units.MEGABYTES): 109.27
import numpy as np
class early_stopping:
def __init__(self, patience, verbose, delta, path='checkpoint.pt'):
self.patience = patience
self.verbose = verbose
self.delta = delta
self.count = 0
self.best_score = None
self.early_stop = False
self.val_loss_min = np.inf
self.path = path
def __call__(self, val_loss, model):
score = -val_loss
if self.best_score is None:
self.best_score = score
self.save_checkpoint(val_loss, model)
elif score < self.best_score + self.delta:
self.count += 1
if self.verbose:
print(f"Early Stopping counter: {self.count} out of {self.patience}")
if self.count >= self.patience:
self.early_stop = True
else:
self.best_score = score
self.save_checkpoint(val_loss, model)
self.count =0
def save_checkpoint(self, val_loss, model):
if self.verbose:
print(f"Validation loss decreased ({self.val_loss_min:.6f}) --> {val_loss:.6f}. saving model..")
torch.save(model.state_dict(), self.path)
self.val_loss_min = val_loss
patience = 2
EPOCHS = 50
early_stopping = early_stopping(patience=2, verbose=True, path='best_model.pt', delta=0)
loss_hist_train = [0] * EPOCHS
accuracy_hist_train = [0] * EPOCHS
loss_hist_valid = [0] * EPOCHS
accuracy_hist_valid = [0] * EPOCHS
for epoch in range(1, EPOCHS + 1):
loss_, acc_ = train(model, train_loader, optimizer, criterion, DEVICE, epoch, log_interval = 200, batch_size=BATCH_SIZE)
loss_hist_train[epoch-1] = loss_
accuracy_hist_train[epoch-1] = acc_
test_loss, test_accuracy = evaluate(model, test_loader)
loss_hist_valid[epoch-1] = test_loss
accuracy_hist_valid[epoch-1] = test_accuracy
print("\n[EPOCH: {}], \tTest Loss: {:.4f}, \tTest Accuracy: {:.2f} % \n".format(
epoch, test_loss, test_accuracy))
early_stopping(test_loss, model)
if early_stopping.early_stop:
print("Early stopping")
break

import torch.nn.functional as F
from torchinfo import summary
import torch.nn as nn
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(32 * 32 * 3, 512)
self.fc2 = nn.Linear(512, 256)
self.fc3 = nn.Linear(256, 10)
self.dropout_prob = 0.5
def forward(self, x):
x = x.view(-1, 32 * 32 * 3)
x = self.fc1(x)
x = F.relu(x)
x = F.dropout(x, training = self.training, p = self.dropout_prob)
x = self.fc2(x)
x = F.relu(x)
x = F.dropout(x, training = self.training, p = self.dropout_prob)
x = self.fc3(x)
x = F.log_softmax(x, dim = 1)
return x

import numpy as np
A = np.array([[4, 2],
[1, 3]])
np.linalg.eig(A)
EigResult(eigenvalues=array([5., 2.]), eigenvectors=array([[ 0.89442719, -0.70710678], [ 0.4472136 , 0.70710678]]))
eigenvalues, eigenvectors = np.linalg.eig(A)
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
iris = load_iris()
X = iris.data
y = iris.target
feature_names = iris.feature_names
X_means = X-np.mean(X,axis=0)
np.cov(X_means, rowvar=False)
eigenvalues, eigenvectors = np.linalg.eig(cov_mat)
sorted_idex = np.argsort(eigenvalues)[::-1]
sorted_eigenvectors = eigenvectors[:, sorted_idex]
eigenvector_subset = sorted_eigenvectors[:, :2]
X_reduced = np.dot(X_means,eigenvector_subset)
array([[-2.68412563, -0.31939725],
[-2.71414169, 0.17700123],
[-2.88899057, 0.14494943],
[-2.74534286, 0.31829898],
pca = PCA(n_components=2)
X_pca=pca.fit_transform(X)
X_pca
array([[-2.68412563, 0.31939725],
[-2.71414169, -0.17700123],
[-2.88899057, -0.14494943],
[-2.74534286, -0.31829898],
eigenvalues/eigenvalues.sum()
`array([0.92461872, 0.05306648, 0.01710261, 0.00521218])`
iris = load_iris()
X = iris.data
y = iris.target
# 2. 데이터 전처리: 표준화 (Standardization)
# PCA 수행 전 반드시 거쳐야 하는 과정입니다.
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 3. Scikit-learn을 이용한 PCA 수행
# 4차원의 데이터를 시각화가 가능한 2차원으로 축소합니다.
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
# 4. 고유값(Explained Variance) 확인
# 각 주성분이 원본 데이터의 전체 분산 중 얼마만큼을 설명하는지 나타냅니다.
print("각 주성분의 분산 비율:", pca.explained_variance_ratio_)
print("총 보존된 정보량:", np.sum(pca.explained_variance_ratio_))
# 5. 시각화 결과 분석
plt.figure(figsize=(10, 7))
colors = ['navy', 'turquoise', 'darkorange']
for i, color, target_name in zip([0, 1, 2], colors, iris.target_names):
plt.scatter(X_pca[y == i, 0], X_pca[y == i, 1], color=color, alpha=.8, lw=2,
label=target_name)
plt.legend(loc='best', shadow=False, scatterpoints=1)
plt.title('PCA of IRIS dataset')
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.grid(True)
plt.show()

각 주성분의 분산 비율: [0.72962445 0.22850762] 총 보존된 정보량: 0.9581320720000166
Day5

CNN → DNN



⇒ padding 적용하여 각 칸이 동일 연산 횟수를 가질 수 있게 함
맥스 풀링



import torch
from torchvision import transforms, datasets
BATCH_SIZE = 64
train_dataset = datasets.CIFAR10(root = "./data/CIFAR_10",
train = True,
download = True,
transform = transforms.ToTensor())
test_dataset = datasets.CIFAR10(root = "./data/CIFAR_10",
train = False,
transform = transforms.ToTensor())
train_loader = torch.utils.data.DataLoader(dataset = train_dataset,
batch_size = BATCH_SIZE,
shuffle = True)
test_loader = torch.utils.data.DataLoader(dataset = test_dataset,
batch_size = BATCH_SIZE,
shuffle = False)
sample = iter(train_loader)
sample_data = next(sample)
sample_data[0].shape
torch.Size([64, 3, 32, 32])
from PIL import Image
import numpy as np
import pickle
with open("./data/CIFAR_10/cifar-10-batches-py/data_batch_1", 'rb') as f:
dict_data = pickle.load(f, encoding='bytes')
dict_data[b'data'].shape
sample1 = dict_data[b'data'][0]
import matplotlib.pyplot as plt
sample1 = sample1.reshape( 3, 32, 32 )
#torch, numpy와 matplotlib 축이 다르므로 전환시켜줌.
plt.imshow(sample1.transpose(1,2, 0))
plt.show()
torch와 matplotlib 축 순서 다름 유의
dict_data[b'data']→ shape: (10000, 3072)→ (3072, ) = 3 × 32 × 32 👉 이건 채널 우선(Channel First) 구조
sample1.shape == (3, 32, 32)
PyTorch / NumPy에서 자주 쓰는 이미지 축 - (C, H, W)
matplotlib imshow()가 기대하는 축
(32, 32, 3)
transpose(1, 2, 0) 의미
sample1.transpose(1, 2, 0) => (H, W, C)
1 → Height2 → Width0 → Channel결과
(C, H, W)(H, W, C)
import torch
import torch.nn as nn
import torch.nn.functional as F
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Conv2d(in_channels = 3, out_channels = 8, kernel_size = 3, padding = 1)
self.conv2 = nn.Conv2d(in_channels = 8, out_channels = 16, kernel_size = 3, padding = 1)
self.pool = nn.MaxPool2d(kernel_size = 2, stride = 2)
self.fc1 = nn.Linear(8 * 8 * 16, 64)
self.fc2 = nn.Linear(64, 32)
self.fc3 = nn.Linear(32, 10)
def forward(self, x):
x = self.conv1(x)
x = F.relu(x)
x = self.pool(x)
x = self.conv2(x)
x = F.relu(x)
x = self.pool(x)
x = x.view(-1, 8 * 8 * 16)
x = self.fc1(x)
x = F.relu(x)
x = self.fc2(x)
x = F.relu(x)
x = self.fc3(x)
x = F.log_softmax(x)
return x
if torch.cuda.is_available():
DEVICE = torch.device('cuda')
else:
DEVICE = torch.device('cpu')
print('Using PyTorch version:', torch.__version__, ' Device:', DEVICE)
model = CNN().to(DEVICE)
from torchinfo import summary
summary(model, input_size=(64, 3, 32, 32))
==========================================================================================
Layer (type:depth-idx) Output Shape Param #
==========================================================================================
CNN [64, 10] --
├─Conv2d: 1-1 [64, 8, 32, 32] 224
├─MaxPool2d: 1-2 [64, 8, 16, 16] --
├─Conv2d: 1-3 [64, 16, 16, 16] 1,168
├─MaxPool2d: 1-4 [64, 16, 8, 8] --
├─Linear: 1-5 [64, 64] 65,600
├─Linear: 1-6 [64, 32] 2,080
├─Linear: 1-7 [64, 10] 330
기본 개념
Output Shape 규칙
Conv2d 파라미터 계산 공식
+1은 biasLinear 파라미터 계산 공식
+1은 biasConv1 파라미터 계산
Conv2 파라미터 계산
Pooling & Activation
Feature Map 크기 변화
Flatten
FC1 파라미터 계산
FC2 파라미터 계산
FC3 파라미터 계산
중요한 포인트
Padding & Stride
옵티마이저와 비용 함수 선언
optimizer = torch.optim.Adam(model.parameters(), lr = 0.001)
criterion = nn.CrossEntropyLoss()
훈련 함수 정의
def train(model, train_loader, optimizer, log_interval):
model.train()
for batch_idx, (image, label) in enumerate(train_loader):
image = image.to(DEVICE)
label = label.to(DEVICE)
optimizer.zero_grad()
output = model(image)
loss = criterion(output, label)
loss.backward()
optimizer.step()
if batch_idx % log_interval == 0:
print("Train Epoch: {} [{}/{} ({:.0f}%)]\tTrain Loss: {:.6f}".format(
epoch, batch_idx * len(image),
len(train_loader.dataset), 100. * batch_idx / len(train_loader),
loss.item()))
평가 함수 정의
def evaluate(model, test_loader):
model.eval()
test_loss = 0
correct = 0
with torch.no_grad():
for image, label in test_loader:
image = image.to(DEVICE)
label = label.to(DEVICE)
output = model(image)
test_loss += criterion(output, label).item()
prediction = output.max(1, keepdim = True)[1]
correct += prediction.eq(label.view_as(prediction)).sum().item()
test_loss /= (len(test_loader.dataset) / BATCH_SIZE)
test_accuracy = 100. * correct / len(test_loader.dataset)
return test_loss, test_accuracy
훈련 실행
EPOCHS = 30
optimizer = torch.optim.Adam(model.parameters(), lr = 0.001)
criterion = nn.CrossEntropyLoss()
for epoch in range(1, EPOCHS + 1):
train(model, train_loader, optimizer, log_interval = 200)
test_loss, test_accuracy = evaluate(model, test_loader)
print("\n[EPOCH: {}], \tTest Loss: {:.4f}, \tTest Accuracy: {:.2f} % \n".format(
epoch, test_loss, test_accuracy))
Train Epoch: 1 [0/50000 (0%)] Train Loss: 2.328551
Train Epoch: 1 [12800/50000 (26%)] Train Loss: 1.878364
Train Epoch: 1 [25600/50000 (51%)] Train Loss: 1.585775
Train Epoch: 1 [38400/50000 (77%)] Train Loss: 1.598529
[EPOCH: 1], Test Loss: 1.5576, Test Accuracy: 42.83 %
Train Epoch: 2 [0/50000 (0%)] Train Loss: 1.432566
Train Epoch: 2 [12800/50000 (26%)] Train Loss: 1.685357
Train Epoch: 2 [25600/50000 (51%)] Train Loss: 1.448450
Train Epoch: 2 [38400/50000 (77%)] Train Loss: 1.545207
img = next(iter(train_loader))
target_img = img[0][0]
target_tensor = target_img.unsqueeze(0)
with torch.no_grad():
feature_map = model.conv1(target_img.to(DEVICE))
feature_map = feature_map.to('cpu')
img_numpy = target_img.permute(1, 2,0).numpy()
plt.imshow(img_numpy)
plt.show()
fig, axes = plt.subplots(2, 4, figsize=(12, 6))
for i in range(8):
ax = axes[i // 4, i % 4]
f_map = feature_map[i].numpy()
ax.imshow(f_map, cmap='gray') # 특성 맵은 보통 그레이스케일로 봅니다
ax.set_title(f"Filter {i+1}")
ax.axis('off')
plt.tight_layout()
plt.show()


pip install opencv-python
import cv2
capture = cv2.VideoCapture(0)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
position = (30,50)
font = cv2.FONT_HERSHEY_SIMPLEX
scale = 1
color = (255,255,255)
thickness = 2
while True:
ret, frame = capture.read()
cv2.putText(frame, "Haha", position, font, scale, color, thickness)
if not ret:
print("카메라 오류")
break
print(type(frame))
cv2.imshow("VideoFrame", frame)
if cv2.waitKey(10) & 0xFF == ord('q'):
capture.release()
cv2.destroyAllWindows()
break
!pip3 install torch torchvision
serving.py
import os
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
os.environ["OMP_NUM_THREADS"] = "1" # 선택: 충돌/과부하 줄이기
import torch
import torch.nn as nn
import torch.nn.functional as F
import cv2
from torchvision import transforms
trans = transforms.Compose(
[
transforms.Resize((64,64)),
]
)
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Conv2d(in_channels = 3, out_channels = 8, kernel_size = 3, padding = 1)
self.conv2 = nn.Conv2d(in_channels = 8, out_channels = 16, kernel_size = 3, padding = 1)
self.pool = nn.MaxPool2d(kernel_size = 2, stride = 2)
self.fc1 = nn.Linear(16 * 16 * 16, 64)
self.fc2 = nn.Linear(64, 32)
self.fc3 = nn.Linear(32, 1)
def forward(self, x):
x = self.conv1(x)
x = F.relu(x)
x = self.pool(x)
x = self.conv2(x)
x = F.relu(x)
x = self.pool(x)
x = x.view(-1, 16 * 16 * 16)
x = self.fc1(x)
x = F.relu(x)
x = self.fc2(x)
x = F.relu(x)
x = self.fc3(x)
x = torch.sigmoid(x)
return x
smile_model = torch.load("./smile.pt", weights_only=False, map_location=torch.device('cpu') )
capture = cv2.VideoCapture(0)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
position = (30,50)
font = cv2.FONT_HERSHEY_SIMPLEX
scale = 1
color = (255,255,255)
thickness = 2
while True:
ret, frame = capture.read()
target_data = trans(torch.from_numpy(frame.transpose(2, 0,1)))
output =smile_model(target_data.reshape(-1, 3, 64, 64).float()).item()
print(output)
if (output >= 0.5):
text = "Smile!!"
cv2.putText(frame, text, position, font, scale, color, thickness)
else:
text = "Angry!!"
cv2.putText(frame, text, position, font, scale, color, thickness)
if not ret:
print("카메라 오류")
break
print(type(frame))
cv2.imshow("VideoFrame", frame)
if cv2.waitKey(10) & 0xFF == ord('q'):
capture.release()
cv2.destroyAllWindows()
break
import kagglehub
# Download latest version
path = kagglehub.dataset_download("chazzer/smiling-or-not-face-data")
print("Path to dataset files:", path)
import random
import os
random.seed(42)
smile = "/kaggle/input/smiling-or-not-face-data/smile/"
non_smile = "/kaggle/input/smiling-or-not-face-data/non_smile/"
smile_files = os.listdir(smile)
random.shuffle(smile_files)
smile_train = smile_files[:480]
smile_test = smile_files[480:]
non_smile_files = os.listdir(non_smile)
random.shuffle(non_smile_files)
non_smile_train = non_smile_files[:480]
non_smile_test = non_smile_files[480:]
from PIL import Image
from torchvision import transforms
from torch.utils.data import Dataset, DataLoader
class facedata(Dataset):
def __init__(self, smile_folder_path, smile_file_list, non_folder_path, non_file_list):
self.smile_file_list = [os.path.join(smile_folder_path, x) for x in smile_file_list]
self.non_file_list = [os.path.join(non_folder_path, x) for x in non_file_list]
self.total_img = self.smile_file_list + self.non_file_list
random.shuffle(self.total_img)
# 이미지 증강 (image augmentaion)
self.transforms = transforms.Compose([
transforms.ToTensor()
])
def __len__(self):
return len(self.total_img)
def __getitem__(self, idx):
img_name = self.total_img[idx]
image = Image.open(img_name)
img = self.transforms(image)
label = 1 if 'non_smile' in img_name else 0
return img, label
train_dataset = facedata(smile, smile_train, non_smile, non_smile_train )
X, y = next(iter(train_dataset))
X.shape
print(y)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
iter_loader = iter(train_loader)
train_dataset = facedata(smile, smile_train, non_smile, non_smile_train )
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
train_test = facedata(smile, smile_test, non_smile, non_smile_test)
test_loader = DataLoader(train_test, batch_size=32, shuffle=True)
파이썬 문법 중 하나로 ,인지 필요
X, y = next(iter(train_dataset))
import torch
import torch.nn as nn
import torch.nn.functional as F
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Conv2d(in_channels = 3, out_channels = 8, kernel_size = 3, padding = 1)
self.conv2 = nn.Conv2d(in_channels = 8, out_channels = 16, kernel_size = 3, padding = 1)
self.pool = nn.MaxPool2d(kernel_size = 2, stride = 2)
self.fc1 = nn.Linear(16 * 16 * 16, 64)
self.fc2 = nn.Linear(64, 32)
self.fc3 = nn.Linear(32, 1)
def forward(self, x):
x = self.conv1(x)
x = F.relu(x)
x = self.pool(x)
x = self.conv2(x)
x = F.relu(x)
x = self.pool(x)
x = x.view(-1, 16 * 16 * 16)
x = self.fc1(x)
x = F.relu(x)
x = self.fc2(x)
x = F.relu(x)
x = self.fc3(x)
x = torch.sigmoid(x)
return x
model, optimizer, criterion 선언
model = CNN().to('cuda')
optimizer = torch.optim.RMSprop(model.parameters(), lr = 0.001)
criterion = nn.BCELoss()
훈련 함수 선언
def train(model, train_loader, optimizer, log_interval):
global label, image, output
model.train()
for batch_idx, (image, label) in enumerate(train_loader):
image = image.to(DEVICE)
label = label.to(DEVICE)
optimizer.zero_grad()
output = model(image)
loss = criterion(output, label.to(torch.float32).reshape(-1, 1))
loss.backward()
optimizer.step()
if batch_idx % log_interval == 0:
print("Train Epoch: {} [{}/{} ({:.0f}%)]\tTrain Loss: {:.6f}".format(
epoch, batch_idx * len(image),
len(train_loader.dataset), 100. * batch_idx / len(train_loader),
loss.item()))
평가 함수 선언
def evaluate(model, test_loader):
global label, image, output
model.eval()
test_loss = 0
correct = 0
with torch.no_grad():
for image, label in test_loader:
# print(image.shape)
image = image.to(DEVICE)
label = label.to(DEVICE)
output = model(image)
test_loss += criterion(output, label.to(torch.float32).reshape(-1, 1)).item()
# print('-----')
# print(output)
# prediction = output.max(1, keepdim = True)[1]
# print(prediction)
# print("---")
# print(label)
correct += ((output > 0.5).long().reshape(-1) == label).reshape(-1).sum().item()
# correct += prediction.eq(label.view_as(prediction)).sum().item()
test_loss /= (len(test_loader.dataset) / BATCH_SIZE)
test_accuracy = 100. * correct / len(test_loader.dataset)
return test_loss, test_accuracy
훈련 실행
EPOCHS = 30
BATCH_SIZE = 32
for epoch in range(1, EPOCHS + 1):
train(model, train_loader, optimizer, log_interval = 10)
test_loss, test_accuracy = evaluate(model, test_loader)
print("\n[EPOCH: {}], \tTest Loss: {:.4f}, \tTest Accuracy: {:.2f} % \n".format(
epoch, test_loss, test_accuracy))