[DL] 스마트폰 센서 기반 인간 행동 분류 모델 구현 및 성능 평가

2025. 5. 1. 04:06·머신러닝 & 딥러닝 & AI 맛보며 친해지기
반응형

 

 

이번 포스팅에서는 인간 행동 인식(HAR: Human Activity Recognition) 기술 프로젝트를 진행하며 센서 데이터를 활용한 이진 및 다중 분류 모델을 설계하고 학습시키는 과정, 그리고 성능 평가를 진행한다.

그 과정에서 겪었던 시행착오와 인사이트를 공유하고자 한다.


데이터 설명 및 이해

 

활용한 데이터셋은 UCI Machine Learning Repository의 Human Activity Recognition Using Smartphones이다.

 

UCI Machine Learning Repository

This dataset is licensed under a Creative Commons Attribution 4.0 International (CC BY 4.0) license. This allows for the sharing and adaptation of the datasets for any purpose, provided that the appropriate credit is given.

archive.ics.uci.edu

 

 

이 데이터는 스마트폰에 내장된 가속도계와 자이로스코프 등의 센서를 통해 사람의 움직임을 수집한 것으로, 사용자의 다양한 활동(예: 걷기, 앉기, 계단 오르기 등)을 분류하는 데 활용된다.

 

이처럼 인간 행동 인식기술은 다양한 센서를 통해 사용자의 동작 패턴을 분석하고 이를 바탕으로 특정 행동을 예측하는 기술이다.


가장 대표적인 예시로는 애플워치와 같은 웨어러블 디바이스가 착용자의 낙상이나 충격을 감지하여 자동으로 긴급 119로 연락하는 기능을 들 수 있다.


 

데이터 분석

 

'df.head(5)' 를 통해 데이터를 확인하였다.

이미지 첨부를 위해 칼럼 중간에 생략하였다.

 

 

이후 'seaborn'과 'matplotlib'를 활용하여 데이터 분석을 위해 시각화를 진행하였다.

 

각 차트의 의미와 도출해낸 인사이트를 정리해보았다.

 

 

 

1. Bar Chart: 활동별 데이터 분포

  • 각 행동 클래스별 샘플 수를 시각화한 결과, LAYING, STANDING, SITTING, WALKING 등의 활동이 비교적 균형 있게 분포되어 있다.
  • 데이터 불균형 문제가 크지 않아 분류 모델 학습 시 클래스 편향의 위험이 낮을 것이라 판단하였다.

막대 그래프 시각화

 

 

2. Pie Chart: 활동 비율 시각화

  • 전체 데이터 중 각 활동이 차지하는 비율을 원그래프로 나타내었다. (데이터의 전반적인 구성과 클래스별 상대적 중요도를 이해하는 데 유용)
  • LAYING과 STANDING이 전체에서 가장 큰 비중을 차지하며, WALKING_DOWNSTAIRS가 가장 적은 비율을 보인다.

파이차트 시각화

 

3. Heatmap: 활동 간 평균 특성 상관관계

  • 각 활동별 평균 피처값의 상관계수를 계산하여 시각화함.
  • WALKING, WALKING_UPSTAIRS, WALKING_DOWNSTAIRS 간 상관계수가 높아 유사한 패턴을 보임.
  • 반면, LAYING은 다른 활동들과 낮은 상관을 보여 명확히 구분되는 특성을 가진다.
  • 클래스 간 유사도를 파악하여 모델의 혼동 가능성을 예측하는 데 효과적이다.

히트맵 시각화

 

 

4. PCA 시각화: 활동의 저차원 투영

  • 고차원 센서 데이터를 주성분 분석(PCA)을 통해 2차원으로 축소하여 각 활동 클래스의 분포를 시각화하였다.
  • 일부 활동(LAYING, WALKING_DOWNSTAIRS)은 뚜렷한 군집을 형성하여 분리 가능성이 높고, 다른 일부는 경계가 겹치는 경향이 있다.
  • 클래스 간 분포 특성을 파악하여 분류 가능성과 경계의 모호성을 사전에 분석할 수 있다.

 

5. Boxplot: 센서 피처의 활동별 분포 비교

  • 데이터의 대표 센서 피처인 tBodyAcc-mean()-X의 활동별 분포를 시각화함.
  • 활동 간 중앙값과 분산의 차이가 뚜렷하게 나타나며, 이는 피처의 분류 기여도를 해석하는 데 도움이 된다.
  • 이상치 및 활동별 특성 차이를 정량적으로 확인할 수 있어 피처 선택에 활용 가능하다.

 

tBodyAcc-mean()-X 의 boxplot


STANDING과 SITTING은 모두 정적인 상태로, 센서의 움직임이 거의 없어 유사한 패턴을 보인다.

 

두 활동의 차이는 주로 사용자의 자세 변화에 따른 높이 차이에 불과하므로, 분류 모델이 이들을 구분하기 어려울 수 있다.

 

반면, WALKING, WALKING_UPSTAIRS, WALKING_DOWNSTAIRS는 모두 동적인 활동으로, 지면과의 상대적인 높이 변화와 움직임의 방향성이 달라지기 때문에 서로 명확히 비교하기 어려우며, 일부 유사한 패턴으로 인해 모델이 함께 분류하는 경향을 보일 수 있다.

 

Active변수에 따라 데이터 분석을 진행한 결과, 이제 Active변수를 정적행동과 동적행동으로 구분하여 분석을 진행하고자 하였다.

 

데이터 전처리

활동을 정적/동적으로 이진 분류하는 ['is_dynamic'] 을 생성하여 분류 모델 학습에 활용하기 위한 전처리 작업을 진행하였다.

print(data['Activity'].unique())
#출력 ['STANDING' 'LAYING' 'WALKING' 'WALKING_DOWNSTAIRS' 'WALKING_UPSTAIRS''SITTING']
 
#정적인 활동이면 0, 그 외(동적인 활동: WALKING, WALKING_UPSTAIRS, WALKING_DOWNSTAIRS)이면 1 
data['is_dynamic'] = np.where(data['Activity'].isin(['STANDING', 'LAYING','SITTING']), 0, 1)

 

전처리 이후 시각화 진행

정적/동적 전처리 후 시각화

시각화를 통해 전처리가 잘되었음을 확인 할 수 있었다. 이후 학습/검증 데이터에 대해 스케일링을 진행하였다.

 

 

간략하게 스케일링이란?

  • 스케일링은 모든 숫자 데이터를 비슷한 크기(0에서 1 사이)로 바꿔주는 작업이다.
  • 모델이 학습 과정에서 데이터를 더 공평하게 보고, 빠르고 정확하게 학습하게 하기 위해서이다.
scaler = MinMaxScaler()
x_train_scaled = scaler.fit_transform(x_train)
x_val_scaled = scaler.transform(x_val)

1단계 분류 ( 정적/동적 ) 를 위한 모델링

주요 작업으로 정적 행동(Laying, Sitting, Standing)과 동적 행동(동적 : Walking, Walking-Up, Walking-Down)을 구분하는 모델 생성을 설정했다.

 

이후 몇 가지 모델을 만들고 가장 성능이 좋은 모델을 선정하자는 목표를 두었다.

 

 

첫번째 모델 설계

model1_1 = Sequential([Dense(512, input_shape = [n_features, ], activation = 'relu'),
                     Dense(256, activation = 'relu'),
                     Dense(128, activation = 'relu'),
                     Dense(64, activation = 'relu'),
                     Dense(32, activation = 'relu'),
                     Dense(1, activation = 'sigmoid')])

 

model.summary()

 

해당 모델은 완전 연결(Dense) 계층으로 구성된 다층 퍼셉트론 구조이며, 입력층과 출력층을 제외하고 총 5개의 은닉층을 사용하였다.


각 은닉층은 순차적으로 512, 256, 128, 64, 32개의 노드로 구성하였고, 활성화 함수로는 비선형성을 확보하기 위해 ReLU 함수를 적용하였다.

출력층은 이진 분류를 위한 sigmoid 함수를 사용하여 최종 확률 값을 출력하도록 설계하였다.

 

복잡한 모델 구조를 통해 데이터의 고차원적 패턴을 효과적으로 학습할 수 있을 것으로 기대하고 학습을 진행하였다.


결과

 

컴파일은 'Adam , 학습률 : 0.001, loss='binary_crossentropy''로 두었다.

학습은 100 Epoch을 진행하였다.

 

성능 평가

 

도출한 나의 인사이트:

 

이진 분류 문제이기 때문에 높은 정확도가 반드시 모델의 성능을 의미하는 것은 아니다. 정답을 전혀 몰라도 무작위로 예측할 경우 맞출 확률이 50%이기 때문에, 단순 정확도 지표만으로는 모델의 유의미한 예측 능력을 판단하기 어렵다. 따라서 실제 성능 평가를 위해서는 정밀도, 재현율, F1-score 등의 보조 지표를 함께 고려할 필요가 있다고 생각하였다.

 

이후 추가적으로 confusion_matrix와 classification_report를 계산하여 평가를 진행하였다.


두번째 모델 설계

do_rate = 0.2

model1_2 = Sequential([Dense(512, input_shape = [n_features, ], activation = 'relu'),
                     Dropout(do_rate),
                     Dense(256, activation = 'relu'),
                     Dropout(do_rate),
                     Dense(128, activation = 'relu'),
                     Dropout(do_rate),
                     Dense(64, activation = 'relu'),
                     Dropout(do_rate),
                     Dense(32, activation = 'relu'),
                     Dropout(do_rate),
                     Dense(1, activation = 'sigmoid')])

 

해당 모델은 입력층과 출력층을 포함하여 총 6개의 완전 연결(Dense) 계층으로 구성된 다층 퍼셉트론(MLP) 구조로 설계하였다.

 

각 은닉층은 ReLU 활성화 함수를 적용하여 비선형성을 확보하였으며, 출력층은 sigmoid 함수를 사용하여 이진 분류 확률 값을 출력하도록 설계되었다.

 

두번째 모델의 주요 특징은 각 은닉층 뒤에 Dropout(rate=0.2) 정규화 기법을 적용했다는 점이다.

 

Dropout은 학습 시 신경망의 일부 노드를 확률적으로 비활성화시켜, 특정 노드에 대한 과도한 의존을 줄이고 과적합을 방지하는 데 효과적이다. 이러한 구조를 통해 모델은 다양한 센서 피처로부터 활동 패턴을 학습하고, 이진 분류일지라도 학습 데이터에 과도하게 적합되지 않도록 안정적인 학습을 유도하고자 하였다.

 

결과

 

컴파일 및 학습 방법은 첫 번째 모델과 같다. 

 

두번째 모델 성능평가

 

발생한 문제:

학습 곡선에서의 안정성과 일관성을 고려할 때, 불필요한 정규화로 인한 손실 진동이 발생하였다.(그래프가 이쁘지 않다.)

 

도출한 인사이트:

두 모델 모두 분류 성능은 매우 우수하고 실제 예측 정확도에 있어 차이는 거의 없다고 판단하였다.

 

이는 문제 자체가 단순하고 구분 가능성이 높은 이진 분류 구조이기 때문에, 복잡한 정규화 기법이 오히려 학습 효율을 저해할 수 있다고 인사이트를 도출하였다.

 


2단계 (정적/ 동적)의 세부 분류를 위한 모델링

주요 작업:

  • 정적 행동(Laying, Sitting, Standing)만 추출하여 세부 정적 행위를 분류하는 모델 생성
  • 세부 동적 행동(Walking, Walking-Up, Walking-Down)을 구분하는 모델 생성

데이터 전처리

# 동적일때 0, 정적일때 1
x_train_0 = x_train[y1_train == 0]
y2_train_0 = y2_train[y1_train == 0]

x_val_0 = x_val[y1_val == 0]
y2_val_0 = y2_val[y1_val == 0]

y2_train_0 = y2_train_0.map({'LAYING':0, 'STANDING':1, 'SITTING':2})
y2_val_0 = y2_val_0.map({'LAYING':0, 'STANDING':1, 'SITTING':2})

 

이미 첫번째 모델을 통해 동적/정적인지 분류가 되었다. 

 

이제는 데이터 전처리를 위해 전체 이진 분류 모델에서 먼저 동적 활동인지 정적인 활동인지를 구분하고, 그 후 동적 활동으로 분류된 데이터만 따로 모아, 세부적으로 어떤 동적 활동인지 다중 분류를 수행하고자 한다.

 

정적 행위 세부 분류 모델링

# 모델 설계
do_rate = 0.1

model2_1 = Sequential([Dense(512, input_shape = [n_features, ], activation = 'relu'),
                     Dropout(do_rate),
                     Dense(512, activation = 'relu'),
                     Dropout(do_rate),
                     Dense(256, activation = 'relu'),
                     Dropout(do_rate),
                     Dense(256, activation = 'relu'),
                     Dropout(do_rate),
                     Dense(128, activation = 'relu'),
                     Dropout(do_rate),
                     Dense(128, activation = 'relu'),
                     Dropout(do_rate),
                     Dense(64, activation = 'relu'),
                     Dropout(do_rate),
                     Dense(64, activation = 'relu'),
                     Dropout(do_rate),
                     Dense(32, activation = 'relu'),
                     Dropout(do_rate),
                     Dense(32, activation = 'relu'),
                     Dropout(do_rate),
                     Dense(3, activation = 'softmax')])

 

해당 모델은 총 10개의 은닉층으로 구성된 심층 다층 퍼셉트론 구조로 설계하였다.

각 층마다 ReLU함수를 적용하여 비선형성을 구상했다. 출력층은 다중 클래스 분류를 위해 softmax 함수를 사용하며, 이는 WALKING, WALKING_UPSTAIRS, WALKING_DOWNSTAIRS의 세 가지 클래스 중 하나를 확률로 예측하는 구조이다.

 

나는 Dropout(rate=0.1)을 각 은닉층 사이에 적용하여 모델의 복잡도에 비해 과적합이 발생하지 않도록 정규화하였다. 이때 Dropout 비율은 이전 이진 분류보다 낮은 0.1로 설정하여 학습 안정성과 성능 간 균형을 고려하였다.

 

 

결과

 

컴파일은 'Adam , 학습률 : 0.001, loss='sparse_categorical_crossentropy''로 두었다.

학습은 100 Epoch을 진행하였다.

 

정적 모델 성능 평가

 


동적 행위 세부 분류 모델링

동적 행위는 정적과 동일하나 전처리만 바꿔주면 된다. 또한 동일한 모델을 사용하였다.

 

결과

 

컴파일은 'Adam , 학습률 : 0.001, loss='sparse_categorical_crossentropy''로 두었다.

학습은 100 Epoch을 진행하였다.

 

 

도출 인사이트:

정적 분류의 경우, 데이터의 복잡도에 비해 모델이 과도하게 깊어 과적합이 발생하였고, 이에 따라 일반화 성능이 저하되는 양상을 보였다. 반면, 동적 분류는 복잡한 활동 간 패턴을 효과적으로 학습하며 안정적으로 수렴하였고, 일반화 성능 또한 우수하여 실제 적용이 가능하다고 판단된다.

 

따라서 데이터의 특성과 복잡도에 따라 모델 구조의 복잡도를 조절하는 것이 중요하며, 특히 정적 분류 모델은 Early Stopping 적용 또는 Dropout 비율 조정 등을 통해 학습 안정성과 성능을 개선할 필요가 있다.

 

 

분류 모델 파이프라인 구성하기

두 단계 모델을 통합하고, 새로운 데이터(test)에 대해서 최종 예측결과와 성능평가가 나오도록 함수로 만들고자 하였다.

 

 

from sklearn.metrics import accuracy_score, confusion_matrix, classification_report

def model_pipeline(model1, model2_1, model2_2, new_data, scaler):
    # 1. 전처리 -----------------------------------
    features = new_data.columns.drop('Activity')
    X = scaler.transform(new_data[features])
    
    # 단계1 예측 (정적/동적 구분)
    pred1 = (model1.predict(X) > 0.5).astype(int).flatten()
    new_data = new_data.copy()
    new_data['pred1'] = pred1

    # 정적(0), 동적(1) 그룹 분리
    groups = {
        0: {'model': model2_1, 'map': {0: 'LAYING', 1: 'STANDING', 2: 'SITTING'}},
        1: {'model': model2_2, 'map': {0: 'WALKING', 1: 'WALKING_UPSTAIRS', 2: 'WALKING_DOWNSTAIRS'}}
    }

    results = []

    for label, group in groups.items():
        subset = new_data[new_data['pred1'] == label].drop(columns=['pred1'])
        x_input = scaler.transform(subset.drop(columns=['Activity']))
        pred2 = group['model'].predict(x_input).argmax(axis=1)
        subset = subset.copy()
        subset['pred2'] = pd.Series(pred2).map(group['map'])
        results.append(subset)

    # 결과 병합 및 성능 평가
    final_result = pd.concat(results)
    y_true = final_result['Activity']
    y_pred = final_result['pred2']

    print('accuracy:', accuracy_score(y_true, y_pred))
    print('=' * 60)
    print(confusion_matrix(y_true, y_pred))
    print('=' * 60)
    print(classification_report(y_true, y_pred))

    return final_result

 

결과 및 성능 평가

성능평가

 

정확도 98%를 달성하였다.


프로젝트 회고 및 향후 계획

이번 프로젝트를 통해 목표로 설정한 정확도 98% 이상의 모델 구현에 성공하였다. 단일 모델의 구조 설계 조정을 넘어, 이진 분류와 다중 분류 모델을 계층적으로 파이프라인화하는 전략이 모델 성능 개선에 실질적인 효과를 준다는 사실을 확인할 수 있었다.

 

이는 모델의 복잡도나 레이어 수를 단순히 조정하는 방식보다, 문제 구조에 맞춘 모델링 전략이 더 큰 영향력을 가질 수 있음을 깨닫게 되었다.

 

다만, 본 프로젝트는 분류 문제를 기반으로 진행되었으며, 이러한 계층적 모델링 접근이 회귀 문제에도 유사하게 적용될 수 있을지는 향후 탐구가 필요한 과제로 남았다.


 

향후 응용 진행할 주제: 5G 네트워크 최적화 시스템

 

다음 프로젝트에서는 이번에 활용한 센서 데이터를 기반으로 데이터를 추가 가공할 계획이다.

 

이후, 5G 네트워크 품질(QoE) 최적화를 목표로 한 사용자 행동 인식 기반 AI 시스템을 개발한다.

 

해당 프로젝트의 주요 방향은 다음과 같다

  • 스마트폰 센서 데이터를 활용하여 사용자의 실시간 활동 상태 인식
  • 활동 유형에 따른 5G 네트워크 품질(QoE) 요구 수준 예측 (누워있는데 OTT 시청중이면 더 네트워크 자원을 더 할당하자 / 걷는데 음악 및 웹서핑을 한다면 네트워크 자원을 줄이자)
  • 통신사 관점에서 행동 유형별로 네트워크 자원을 동적으로 배분할 수 있는 AI 기반 정책 설계

이를 통해 통신사는 사용자의 맥락에 맞는 QoE 중심의 네트워크 운용 전략을 확보하고, 자원 배분의 효율성과 사용자 만족도를 동시에 향상시킬 수 있을 것으로 기대한다.

 

 

 


프로젝트 요약

💡 프로젝트 개요

  • 목표: 스마트폰 센서 데이터를 활용하여 사용자의 행동(걷기, 앉기 등)을 분류하는 머신러닝 모델을 설계
  • 특징:
    • 2단계 계층 모델링 전략 도입
    • 전체 모델 파이프라인 함수화
    • 정확도(Accuracy) 0.97 이상 목표

⚙️ 모델링 단계 요약

✅ Step 1: 상위 행동 분류 (1단계 모델)

  • 정적(0) vs 동적(1) 행동으로 이진 분류
  • 예: 앉기, 서기, 눕기 → 정적 / 걷기, 오르기, 내리기 → 동적

✅ Step 2: 세부 행동 분류 (2단계 모델)

  • 1단계 결과에 따라 두 가지 모델 구성
    • 정적 예측 → 정적 세부 행동 3종 분류
    • 동적 예측 → 동적 세부 행동 3종 분류

✅ Step 3: 전체 모델 통합

  • 위 모델을 통합하여 하나의 예측 함수로 구성
  • 예측 결과와 성능 평가까지 자동화

  • 진행 환경:
    • 구글 Colab - T4 & ubuntu - gtx 4060
    • 필요 패키지: pandas, sklearn, matplotlib, tensorflow

 

반응형

'머신러닝 & 딥러닝 & AI 맛보며 친해지기' 카테고리의 다른 글

통신 3사 셋톱박스 설명서 기반 RAG 챗봇 구축기  (0) 2025.05.11
LangChain으로 구현한 KT 에이블스쿨 QnA RAG 챗봇 개발기  (1) 2025.05.10
실시간 객체탐지 YOLO란?  (2) 2025.04.24
RAG(Retrieval-Augmented Generation)와 Vector DB 란?  (3) 2025.04.21
[ML] 분류(Classification)와 회귀(Regression)의 차이  (0) 2025.04.18
'머신러닝 & 딥러닝 & AI 맛보며 친해지기' 카테고리의 다른 글
  • 통신 3사 셋톱박스 설명서 기반 RAG 챗봇 구축기
  • LangChain으로 구현한 KT 에이블스쿨 QnA RAG 챗봇 개발기
  • 실시간 객체탐지 YOLO란?
  • RAG(Retrieval-Augmented Generation)와 Vector DB 란?
BoChan
BoChan
    반응형
  • BoChan
    보람찬 코기의 개발자 블로그
    BoChan
  • 전체
    오늘
    어제
    • 분류 전체보기 (61)
      • Kubernetes_쿠버네티스 (8)
      • Docker_도커 (6)
      • Public Cloud (3)
      • 머신러닝 & 딥러닝 & AI 맛보며 친해지기 (10)
      • Develop & Project Review (6)
      • git&github (1)
      • Programming Language (2)
      • Computer Science (CS) (15)
      • 일상&인턴 (10)
      • 논문 리뷰 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • Github
    • Baekjoon Online Judge
  • 공지사항

  • 인기 글

  • 태그

    PyTorch
    k8s
    Rag
    대전
    DB project
    Yolov7
    연구연수생
    k3s
    ORACLEDB
    머신러닝
    DB
    딥러닝
    쿠버네티스
    FastAPI
    s3fs-fuse
    인턴
    ip
    onnx
    jetson
    Database
    한국전자통신연구원
    컴퓨터공학
    인터넷공학
    Docker
    JetsonNano
    ETRI
    AWS
    python
    도커
    TensorRT
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
BoChan
[DL] 스마트폰 센서 기반 인간 행동 분류 모델 구현 및 성능 평가
상단으로

티스토리툴바