일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- msaez
- aice associate
- kt 에이블스쿨 8기
- kt에이블스쿨8기
- 마이크로서비스
- KT AIVLE School
- kt 에이블스쿨 7기
- Kafka
- MSA
- kt aivle school 7기
- KT에이블스쿨
- 에이블기자단
- 관세용어
- kt aivleschool 8기
- springboot
- 에이블 기자단
- 데이터분석
- 미니프로젝트
- kt aivleschool 7기
- KT 에이블스쿨
- 7일 전사
- 데이터
- 후기
- AI트랙
- 어답터 민
- 기자단
- 에이블스쿨 7기
- kt에이블스쿨7기
- ktaivleschool
- adsp미어캣
- Today
- Total
Hseong
[KT AIVLE SCHOOL 7기] - 미니 프로젝트 1차 후기 본문
안녕하세요! kt 에이블스쿨에서 자소서 제출과 코테를 보던게 어제 같고, 교육 시작한 지가 엊그제 같은데 벌써 한달이 다되어가고 무려 미프 1차 4일의 기간이 끝나고! 후기를 들고 왔습니다~
이번 미니프로젝트 1차 기간에는 1,2일차에는 ai 모델링 과제가 되었구요, 3,4일차에는 다음주에 있을 AICE ASSOCIATION 시험 대비를 위해 관련 프로젝트를 진행했습니다! KT 에이블 스쿨에서는 AICE 시험을 위해 전액 지원을 해주기 때문에 매우 좋았고, 국가공인자격+다수기업 채용우대 해주기 때문에 스텝업 하기 정말 좋았습니다!!
미니 프로젝트 1,2일
데이터 EDA
kt 에이블스쿨에서 그동안 다뤘던 데이터는 column 즉 feature의 갯수가 그렇게 많지 않았다. 근데 데이터 전처리를 하려고 형태를 보았더니 어라?..
562개요?... 조금 당황스러웠지만 그래도 미프 1차에는 가이드라인이 어느정도 있어서 갈피를 못잡진 않았다...(조금 무섭긴 했음)
# 상위 5개 확인
df_test.head()
# 전체 데이터의 수치형 변수 분포 확인
df_train.describe()
#전체 데이터의 모든 변수 확인
df_train.columns
#(추가) 다양하게 기본 정보들을 확인하세요!
df_train.isnull().sum()
# 데이터 자료형 확인
df_train.dtypes
# 타켓 데이터의 분류 수 확인
df_train['Activity'].unique()
- 처음에는 함수 하나하나가 어떤지..이름은 뭐였지 했었던 시절은 지났다. 이제 자연스럽게 위 절차는 tap 의 유혹을 떨쳐내고도 칠 수 있게 되었다!
- 항상 이런 데이터를 처음 접할 때에는 너무 크게 보려하지말고 단계를 세워서 차분히 하나하나 보면 좋은 것 같다
- 중요하다고 생각하는 건 분포 확인 -> 결측치 -> 데이터 타입 확인 -> 시각화로 조금 분석 ( 가닥 잡기)
sns.countplot(y='Activity', data=df_train, hue='Activity')
plt.yticks(rotation=0) # 필요시 y축 라벨 회전 (보통 0도로 둬도 깔끔해)
plt.show()
그래서 간단하게 Y 즉, target 의 라벨이 몇 개인지 보았고, 샘플의 갯수가 불균형/균형 인지 확인을 해본 결과 골고루 되어있지 않아서 Oversampling 을 하지는 않았다.
데이터 전처리
from sklearn.model_selection import train_test_split
# 데이터 분할을 위한 전처리
x = df_train.drop('Activity',axis=1)
y = df_train['Activity']
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2,random_state=42)
모델링
from sklearn.ensemble import RandomForestClassifier
#생성
model = RandomForestClassifier()
#학습
model.fit(x_train,y_train)
#평가
y_pred = model.predict(x_test)
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# 정확도
acc = accuracy_score(y_test, y_pred)
print(f'Accuracy: {acc:.4f}')
# 분류 리포트
print("\n[Classification Report]")
print(classification_report(y_test, y_pred))
# 혼동행렬 시각화
conf_matrix = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(6,5))
sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues')
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Confusion Matrix')
plt.tight_layout()
plt.show()
- 확실히 raw한 데이터는 아니고 , 어느정도 권위있는 곳의 데이터라 결측치와 여러 요인들을 신경쓰지 않아도 랜덤 포레스트 모델을 통해 좋은 성능이 나왔다.
중요도 기반 feature 분석
- 사실 지금까지는 전체의 feature 를 다 사용해서 이중/다중 분류 문제라던지 회귀모델을 사용해왔다.
- 그렇지만 실무자의 입장이나 변수가 많은 raw 데이터에는 noise 나 컴퓨팅 자원 그리고 인사이트를 뽑기 위해서는 수많은 변수중에 간추리고 간추려서 관점을 뽑는게 중요하다고 생각했다.
- 그래서 상위 20개의 변수를 추출해보았다.
# 중요도 상위 top 20
top_20_feature = plot_feature_importance(model.feature_importances_,x_train.columns).head(5)['feature_name'].tolist()
for feature in bottom_5_feature:
plt.figure(figsize=(8, 4))
sns.kdeplot(data=df_train, x=feature, hue='Activity', fill=True, common_norm=False, alpha=0.5)
plt.title(f'Feature: {feature} - Target KDE Plot')
plt.xlabel(feature)
plt.ylabel('Density')
plt.tight_layout()
plt.show()
그리고 추가적으로 5 개의 상위에 포진된 중요한 변수들만을 kdeplot 을 통해서 target 값에 각 변수들이 어떤 영향을 주는지 확인해보았다.
- 그래서 보면 target에 있어서 각 변수들이 주는 영향도인데 확실하게 두 개만 비교해도, 해당 도메인에 대한 지식이 많으면 좋겠지만 정말 없는 도메인의 프로젝트를 맡았을 때 이러한 차이를 쭉 살펴보고 안보고가 꽤 큰 것 같다는 깨달음을 얻었다
단계별 모델링 - 이진 분류
일단 하이라이트 부분은 이 곳부터 이다! 1,2일 차의 의미있는 목적은 조원들과의 협업 그리고 토론 마지막으로 서로의 관점을 공유하며 인사이트를 뽑아내는 과정이 꽃이였는데 1차 때부터 좋은 조원분들을 만나 얻어가는 것이 많았다
일단 위에서 본 것처럼 Y의 라벨은 총 6개로 동적/정적 행동이 각각 3개씩 되어있고, 지금은 1차 단계에서는 이진 분류 모델 즉, 동적이냐 정적이냐를 판단하는 모델을 설계하려고 한다.
데이터 분리
#Lable 추가(1단계 모델:정적(0), 동적(1) 행동 분류 모델 생성 )
# 정적: STANDING, SITTING, LAYING
# 동적: WALKING, WALKING_UPSTAIRS, WALKING_DOWNSTAIRS
def convert_to_dynamic(activity):
static_actions = ['STANDING', 'SITTING', 'LAYING']
return 0 if activity in static_actions else 1
df_train['is_dynamic'] = df_train['Activity'].apply(convert_to_dynamic)
#x,y 분리하기
X = df_train.drop(['Activity', 'is_dynamic'], axis=1)
y = df_train['is_dynamic']
- 일단 분류 모델에 있어서 y의 데이터 타입이 object기 때문에 1차 단계에서는 동적 행동은 1 , 정적 행동은 0 으로 함수를 선언한 후 0과 1의 값으로 바꿔주었다.
데이터 스케일링 / 분할
#스케일링 방식을 선택해서 스케일링을 진행합니다.
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
#데이터 분할 진행(train:val = 8:2 혹은 7:3 권장)
x_train, x_val, y_train, y_val = train_test_split(
X_scaled, y, test_size=0.2, random_state=42, stratify=y
)
- 그리고 여기서 중요한 것은 StandardScaler 인데 보통 다들 MinMaxScaler 를 사용할텐데 여기서 왜 StandardScaler 를 사용했냐면 해당 데이터는 x,y,z 축의 값으로 음수가 있어서 MinMax를 채택한다면 최소0 ~ 최대 1 이런식으로 스케일링을 하여 방향 값의 특성상 제대로된 y값을 뽑아낼 수 없기 때문에 이 부분에 대하여 조원들과 토의를 하며 하나 알아갔다.
이진 분류 모델 설계 ( 1단계 )
# 모델 설계
model2 = models.Sequential([
layers.Dense(128, activation='relu', input_shape=(X_scaled.shape[1],)),
layers.BatchNormalization(),
layers.Dropout(0.2),
layers.Dense(64, activation='relu'),
layers.Dropout(0.2),
layers.Dense(32, activation='relu'),
layers.Dropout(0.2),
layers.Dense(1, activation='sigmoid') # 이진 분류를 위한 출력층
])
# 컴파일 및 학습
from tensorflow.keras import models, layers, optimizers
model2.compile(optimizer=optimizers.Adam(learning_rate=0.001), loss='binary_crossentropy', metrics=['accuracy'])
history2 = model2.fit(x_train, y_train, epochs=10, batch_size=32, validation_data=(x_val, y_val))
- BatchNoramlization 을 넣는 이유는 이러한 많은 feature들과 여러 layer의 모델의 경우 역전파 과정에서 해당 feature에 대한 가중치가 0 으로 수렴하는 경우 Gradient Vanish과 같은 소실 문제가 발생할 수 있어서 정규화를 지속적으로 시켜주면서 어느정도 분포를 유지한다
- 이진 분류 모델이기 때문에 출력층에는 1개의 노드와 sigmoid 를 사용했는데 사실 이 경우에도 softmax 와 출력층 2개를 이용하면 된다
- 근데 이진 분류의 경우 loss 는 binary_crossentropy 를 이용해야하고, 다중분류에서 softmax 를 사용한다면 categorical crossentropy 를 이용해야 한다.
그 결과 과적합은 발생하지 않고, 적절하게 학습이 진행되었다.
# 혼동 행렬
cm = confusion_matrix(y_val, y_pred_classes)
plt.figure(figsize=(6, 6))
sns.heatmap(cm, annot=True, fmt="d", cmap="Blues", xticklabels=["Class 0", "Class 1"], yticklabels=["Class 0", "Class 1"])
plt.title("Confusion Matrix")
plt.xlabel("Predicted")
plt.ylabel("Actual")
plt.show()
설계한 모델에서 1단계의 모델은 해당 모델로 채택되었고, confusion matrix를 통해 아주 좋은( 어쩌면 과적합?...) 성능을 얻어냈다.
다중 분류 모델 설계 ( 2단계 )
해당 모델에서는 아무래도 object y값의 범주형 데이터를 최종적으로 softmax를 통해 분류하기 위해 어떻게 변환을 할것이냐가 관건이였다.
# X, y 분리
X_static = df_static.drop(['Activity', 'is_dynamic'], axis=1)
y_static = df_static['Activity']
# (tip) 인코딩 진행, map 활용해서 숫자레이블로 매핑핑
le_static = LabelEncoder()
y_static_encoded = le_static.fit_transform(y_static)
# 스케일링
scaler = StandardScaler()
X_static_scaled = scaler.fit_transform(X_static)
# train / val 분할
X_train_s, X_val_s, y_train_s, y_val_s = train_test_split(
X_static_scaled, y_static_encoded, test_size=0.2, random_state=42, stratify=y_static_encoded
)
- 범주형 데이터의 경우 각 라벨을 학습을 위해 0,1,2 이렇게 순서를 먼저 매기는 작업을 하는데 이를 LabelEncoder 라고 한다.
- 그리고 이러한 데이터를 스케일링을 통해 정규화를 시켜서 최종적으로 데이터 전처리를 마무리 한다.
# 모델 설계
static_model = models.Sequential([
layers.Dense(256, activation='relu', input_shape=(X_static_scaled.shape[1],)), # 첫 번째 은닉층
layers.Dropout(0.2), # 드롭아웃 추가 (25%)
layers.Dense(128, activation='relu'), # 두 번째 은닉층
layers.BatchNormalization(), # 배치 정규화 추가
layers.Dropout(0.2), # 드롭아웃 추가 (20%)
layers.Dense(256, activation='relu'), # 세 번째 은닉층
layers.Dropout(0.2), # 드롭아웃 추가 (25%)
layers.Dense(128, activation='relu'), # 네 번째 은닉층
layers.Dense(256, activation='relu'), # 다섯 번째 은닉층
layers.BatchNormalization(), # 배치 정규화 추가
layers.Dense(3, activation='softmax') # 출력층 (정적 동작 세분화 분류)
# 컴파일 및 학습
static_model.compile( optimizer=Adam(learning_rate=0.001), loss='sparse_categorical_crossentropy', metrics=['accuracy'],)
history_s1 = static_model.fit(X_train_s, y_train_s, epochs=10, batch_size=32, validation_data=(X_val_s, y_val_s), verbose=2)
])
최종 인사이트
그래서 6명의 조원들과 토의 시간에 각자의 코드 리뷰를 진행하고 토의하면서 ppt 를 작성했다. 각자의 결과와 모델 설계 부분을 중심으로 토의를 진행했고, 최종적으로는 dropout 과 레이어의 과도한 수가 학습에 대한 영향을 절대적으로 주는 건 아니라고 느껴서, 해당 도메인에 대한 지식이 없었어서 아쉽지만 많은 걸 얻었다.
그래서 후기는??
kt 에이블 스쿨 미프 1차 (1,2일차 )의 경우는 너무 만족스러웠다.
- 초반 가이드 라인 제시 + 입문자를 위한 데이터 세트
- 충분한 토의 시간 + 모델링을 하는데 있어서 여러 강사님의 강의
에이블러님들과 대면을 하지 못했던 건 아쉽지만 , 확실히 비대면이 오디오가 겹치고 조금 더 디테일하게 말을 못했던 것이 서로 아쉬웠었다. 그래도 정말 다양한 관점을 공유하면서 최적화 작업을 하다보니 부족한 부분은 얻어가고, 내가 잘하고 있는 부분도 알 수 있어서 유익한 2일 이였다! 처음에 어려웠던 기본적인 작업들이 지금은 눈 감고( 진짜로?..) 할 수 있을 정도니 향후 지원하실 kt 에이블스쿨 8기 이후 분들은 너무 무서워하지말고 지원해서 많은 것을 얻어가면 좋겠습니다!!
'KT AIVLE SCHOOL 7기' 카테고리의 다른 글
[KT AIVLE SCHOOL 7기] - AICE 후기 (feat. 에이블스쿨의 특강) (1) | 2025.04.28 |
---|---|
[KT AIVLE SCHOOL 7기] - LLM ( 행복했다 api야..) (0) | 2025.04.24 |
[KT AIVLE SCHOOL 7기] - 스터디 후기(정보처리기사 실기) (0) | 2025.04.09 |
[KT AIVLE SCHOOL 7기] - 머신러닝 (5) 인사이트 도출 (0) | 2025.04.08 |
[KT AIVLE SCHOOL 7기] - 머신러닝 (4) 최종실습 (feat. 이제 중간 후기를 곁들인....) (1) | 2025.04.08 |