반응형

데이터를 자동으로 분류할 수 있는 클러스터링 알고리즘 중 가장 널리 사용되는 K-means Clustering!
이번 포스트에서는 이론적인 배경부터, 저사양 CPU에서도 무리 없이 돌릴 수 있는 실습 코드까지 깔끔하게 정리해볼게요.

목차

  1. K-means Clustering이란?
  2. 작동 원리 (알고리즘 흐름)
  3. 수학적 개념 정리
  4. 장점과 단점
  5. 실행 가능한 예제 코드 (CPU 저사양 OK!)
  6. 마무리 요약

1.  K-means Clustering 이란?

K-means는 데이터를 **K개의 클러스터(군집)**로 나누는 대표적인 비지도 학습(Unsupervised Learning) 알고리즘입니다.
각 클러스터는 중심점(centroid)을 가지며, 데이터는 가장 가까운 중심점에 소속됩니다.

📌 예를 들어, 고객을 3개의 소비 성향 그룹으로 나누고 싶을 때 사용할 수 있어요.


2.  작동 원리

K-means는 아래 4단계를 반복하며 군집을 형성합니다.

  1. 초기 중심점 설정 (보통 랜덤 또는 K-means++ 방식)
  2. 데이터 포인트를 가장 가까운 중심점에 할당
  3. 각 클러스터의 평균으로 중심점 업데이트
  4. 중심점 변화가 없으면 종료 (또는 max 반복 횟수까지)

3.  수학적으로 살펴보기

 유클리드 거리

데이터 간의 거리는 보통 **유클리드 거리(Euclidean Distance)**로 계산합니다:

 최적화 목표 (Objective)

K-means는 Within-Cluster Sum of Squares (WCSS) 를 최소화하는 것이 목표입니다:

J = i=1k x  Ci x  μi2J = \sum_{i=1}^{k} \sum_{x \in C_i} \|x - \mu_i\|^2

  • CiC_i: i번째 클러스터
  • μi\mu_i: 클러스터 중심점

4.  장점과 단점

장점

  • 구현이 매우 간단하고 빠름
  • 대용량 데이터에서도 확장 가능
  • 널리 사용됨

단점

  • K를 미리 알아야 함
  • 이상치(outlier)에 민감
  • 구형(원형)이 아닌 클러스터에 부적합

5.  실습 코드: 저사양 CPU에서도 OK!

아래 코드는 scikit-learn을 이용한 간단한 2D 데이터 클러스터링 예제입니다.
저사양 환경(CPU 1코어, 1GB RAM 정도)에서도 무리 없이 실행됩니다.

필요한 라이브러리 설치

pip install numpy matplotlib scikit-learn

 

전체 코드

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans

# 1. 2D 클러스터 데이터 생성
X, y_true = make_blobs(n_samples=300, centers=3, cluster_std=0.60, random_state=0)

# 2. K-means 모델 학습
kmeans = KMeans(n_clusters=3, random_state=0, n_init='auto')
kmeans.fit(X)

# 3. 클러스터 예측 결과
y_kmeans = kmeans.predict(X)

# 4. 시각화
plt.scatter(X[:, 0], X[:, 1], c=y_kmeans, s=40, cmap='viridis')

# 중심점 시각화
centers = kmeans.cluster_centers_
plt.scatter(centers[:, 0], centers[:, 1], c='red', s=200, alpha=0.5, marker='X')
plt.title("K-means Clustering 결과")
plt.xlabel("X1")
plt.ylabel("X2")
plt.show()

결과

  • 3개의 색깔로 나뉜 점들이 각각 클러스터
  • 빨간 X는 각 클러스터의 중심점

마무리 요약

항목설명
알고리즘 종류 비지도 학습 (Unsupervised)
사용 목적 자동으로 데이터 분류
주요 개념 중심점, 유클리드 거리, WCSS 최소화
실습 환경 저사양 CPU에서도 실행 가능

🔗 참고 자료

 

https://matplotlib.org/stable/tutorials/introductory/pyplot.html

 

matplotlib.org

 

 

make_blobs

Gallery examples: Release Highlights for scikit-learn 1.1 Release Highlights for scikit-learn 0.23 Probability Calibration for 3-class classification Probability calibration of classifiers Normal, ...

scikit-learn.org

 

 

KMeans

Gallery examples: Release Highlights for scikit-learn 1.1 Release Highlights for scikit-learn 0.23 A demo of K-Means clustering on the handwritten digits data Bisecting K-Means and Regular K-Means ...

scikit-learn.org

 

728x90
반응형
반응형

TensorFlow/Keras에서 Sequential 모델을 정의할 때 발생할 수 있는 경고 메시지와 이를 해결하는 방법에 대해 알아볼게요. 특히, keras.Input()을 사용한 올바른 모델 정의 방식과 왜 이를 권장하는지 설명하겠습니다.


1️⃣ 경고 메시지의 원인

아래와 같은 코드를 실행할 때, 경고 메시지가 출력될 수 있습니다:

from tensorflow import keras

# 모델 정의
model = keras.Sequential()
model.add(keras.layers.Conv2D(32, kernel_size=3, activation='relu', padding='same', input_shape=(28, 28, 1)))​

출력되는 경고 메시지

/usr/local/lib/python3.10/dist-packages/keras/src/layers/convolutional/base_conv.py:107: 
UserWarning: Do not pass an input_shape/input_dim argument to a layer. 
When using Sequential models, prefer using an Input(shape) object as the first layer in the model instead.​

이 메시지는 Keras의 최신 버전에서 권장하는 모델 정의 방식과 관련이 있어요.

경고 발생 이유

  1. Sequential 모델에서 첫 번째 레이어에 **input_shape**을 전달하는 방식은 여전히 작동하지만, 이제는 **keras.Input()**을 사용하는 것이 권장됩니다.
  2. 최신 Keras에서는 입력 크기를 명시적으로 정의할 수 있는 Input() 객체를 사용하는 것이 더 명확하고 유지보수에 유리하다고 보고 있어요.

2️⃣ 해결 방법: keras.Input() 사용

경고를 제거하고, Keras에서 권장하는 방식을 따르려면 keras.Input() 객체를 사용하여 입력 크기를 명확히 정의하세요.
수정된 코드는 아래와 같아요:

수정된 코드

from tensorflow import keras

# 모델 정의
model = keras.Sequential([
    keras.Input(shape=(28, 28, 1)),  # 입력 크기 명시
    keras.layers.Conv2D(32, kernel_size=3, activation='relu', padding='same')
])​

수정 코드의 특징

  1. keras.Input(shape=(28, 28, 1)):
    • 모델의 입력 크기를 명시적으로 정의합니다.
    • 이후 레이어는 입력 크기를 자동으로 상속받으므로 첫 번째 레이어에 input_shape를 전달할 필요가 없어요.
  2. 코드가 더 간결해지고 유지보수가 쉬워집니다.

3️⃣ 기존 방식과의 비교

기존 방식

model = keras.Sequential()
model.add(keras.layers.Conv2D(32, kernel_size=3, activation='relu', padding='same', input_shape=(28, 28, 1)))​
  • 여전히 작동하지만 경고 메시지가 출력됩니다.
  • 입력 크기를 레이어에 전달하는 방식으로, 입력 정의가 덜 명확합니다.

수정된 방식

model = keras.Sequential([
    keras.Input(shape=(28, 28, 1)),  # 명시적 입력 정의
    keras.layers.Conv2D(32, kernel_size=3, activation='relu', padding='same')
])​
  • 경고 메시지가 제거됩니다.
  • 입력 크기가 명확히 드러나며, 모델 구조의 가독성이 개선됩니다.

4️⃣ 왜 keras.Input()이 권장될까?

1. 코드의 명확성

  • 입력 크기를 레이어 속성이 아닌 별도의 Input() 객체로 정의하므로,
    모델 구조에서 입력 크기를 명확히 볼 수 있어요.

2. 유지보수성 향상

  • 입력 크기를 모델 정의와 분리해 관리할 수 있으므로,
    입력 크기를 변경하거나 다양한 입력 구조를 사용할 때 유리합니다.

3. 확장성

  • keras.Input()은 다중 입력이나 복잡한 네트워크 구조에서도 유연하게 사용할 수 있어요.
    Sequential 모델뿐만 아니라 Functional API나 Subclassing API에서도 활용됩니다.

5️⃣ 전체 코드 예시

아래는 수정된 방식으로 Sequential 모델을 정의한 전체 코드입니다:

from tensorflow import keras

# 모델 정의
model = keras.Sequential([
    keras.Input(shape=(28, 28, 1)),  # 입력 크기 명시
    keras.layers.Conv2D(32, kernel_size=3, activation='relu', padding='same'),
    keras.layers.MaxPooling2D(pool_size=2),
    keras.layers.Flatten(),
    keras.layers.Dense(10, activation='softmax')
])

# 모델 요약
model.summary()​

model.add()로 은닉층과, 출력층을 추가해도 됩니다.


6️⃣ 경고를 무시하고 기존 방식 사용하기

만약 기존 방식으로 작성하고 경고를 무시하고 싶다면, 아래 코드처럼 작성해도 정상적으로 작동합니다.

코드

model = keras.Sequential()
model.add(keras.layers.Conv2D(32, kernel_size=3, activation='relu', padding='same', input_shape=(28, 28, 1)))​

⚠️ 하지만 이는 경고 메시지가 출력되며, 장기적으로는 권장되지 않는 방식입니다.


결론

  • Keras의 최신 방식에서는 Sequential 모델을 정의할 때 keras.Input()을 사용하는 것이 권장됩니다.
  • 이를 통해 경고 메시지를 제거할 뿐만 아니라, 코드의 가독성과 유지보수성을 높일 수 있어요.
  • 특히 복잡한 모델을 다룰 때 유용하며, 모델 정의의 확장성도 개선됩니다.

해시태그
#Keras #딥러닝 #TensorFlow #Sequential모델 #Input #모델정의 #코딩팁 #머신러닝

728x90
반응형
반응형

모델 학습시 출력되는 로그의 각 요소에 대해 알아보겠습니다

Epoch 1/20
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 72s 46ms/step - accuracy: 0.7422 - loss: 0.7300 - val_accuracy: 0.8734 - val_loss: 0.3386

출력 설명

  1. Epoch 1/20:
    • 학습의 첫 번째 에포크(Epoch 1)를 진행 중이며, 전체 학습 과정은 총 20개의 에포크(1/20)로 설정되어 있습니다.
  2. 1500/1500:
    • 학습 데이터가 1500개의 배치(batch)로 나뉘어 있으며, 현재 에포크에서 모든 배치의 처리가 완료되었습니다.
    • 이 숫자는 전체 배치(1500/1500)를 의미하며, 한 에포크 동안 모델이 모든 데이터를 학습한 상태를 나타냅니다.
  3. 72s:
    • 한 에포크를 처리하는 데 걸린 시간(초)입니다. 여기서는 72초가 소요되었습니다.
  4. 46ms/step:
    • 한 스텝(즉, 하나의 배치 처리)에 걸린 평균 시간입니다. 여기서는 약 46밀리초(ms)입니다.
  5. accuracy: 0.7422:
    • 훈련 데이터의 정확도를 나타냅니다. 이 에포크에서 모델이 훈련 데이터에 대해 74.22%의 정확도를 달성했습니다.
  6. loss: 0.7300:
    • 훈련 데이터의 손실 값을 나타냅니다. 손실 값이 작을수록 모델이 훈련 데이터에 대해 더 나은 예측을 하고 있음을 의미합니다. 여기서는 손실 값이 0.7300입니다.
  7. val_accuracy: 0.8734:
    • 검증 데이터의 정확도를 나타냅니다. 이 에포크에서 모델이 검증 데이터에 대해 87.34%의 정확도를 달성했습니다.
  8. val_loss: 0.3386:
    • 검증 데이터의 손실 값을 나타냅니다. 이 값은 모델이 검증 데이터에 대해 얼마나 잘 예측하고 있는지를 평가하는 지표입니다. 여기서는 손실 값이 0.3386입니다.

핵심 포인트

  • 훈련 성능(accuracy, loss): 모델이 훈련 데이터에 대해 얼마나 잘 학습했는지를 나타냅니다.
  • 검증 성능(val_accuracy, val_loss): 모델이 보지 않은 검증 데이터에 대해 얼마나 일반화되었는지를 평가합니다.
  • 시간(72s, 46ms/step): 한 에포크와 각 배치를 처리하는 데 걸린 시간으로, 모델의 효율성을 확인할 수 있습니다.

추가적으로 확인해야 할 점

  1. 과적합 여부:
    • 훈련 정확도(accuracy와 loss)와 검증 정확도(val_accuracy와 val_loss)의 차이가 지나치게 클 경우 과적합(overfitting)의 신호일 수 있습니다.
  2. 학습 속도:
    • 훈련 시간이 길다면, 배치 크기를 줄이거나, 데이터셋 크기를 최적화하거나, 하드웨어(GPU/TPU)를 활용해 학습 속도를 높일 수 있습니다.
  3. 손실 감소와 정확도 증가:
    • 에포크가 진행되면서 손실(loss)은 감소하고, 정확도(accuracy 및 val_accuracy)는 증가하는지 확인합니다. 손실이 일정 수준 이하로 줄어들지 않으면 학습률을 조정하거나 모델 구조를 개선해야 합니다.
728x90
반응형
반응형

오류 메시지에서 나타난 **sklearn.utils._param_validation.InvalidParameterError**는 SGDClassifier의 loss 매개변수에 잘못된 값을 전달했기 때문에 발생합니다.

 

  1. 원인:
    • SGDClassifier에서 loss 매개변수에 "log"를 사용했지만, 이는 허용되지 않는 값입니다.
    • SGDClassifier는 "log_loss"를 사용해야 합니다.
  2. log vs log_loss:
    • 이전 버전의 Scikit-learn에서는 loss='log'를 사용하여 로지스틱 회귀를 수행했지만, 최신 버전에서는 log가 log_loss로 변경되었습니다.
    • 따라서 최신 Scikit-learn에서 "log"를 사용하면 오류가 발생합니다.

해결 방법

1. loss='log_loss'로 수정

SGDClassifier의 loss 매개변수를 "log_loss"로 변경해야 합니다.

from sklearn.linear_model import SGDClassifier

# SGDClassifier 생성 시 'log_loss' 사용
sgd = SGDClassifier(loss='log_loss', random_state=42)

추가 설명

loss 매개변수란?

loss는 SGDClassifier가 사용하는 손실 함수의 종류를 정의합니다. 다음은 주요 loss 옵션의 설명입니다:

  • log_loss: 로지스틱 회귀를 수행하는 손실 함수. 분류 작업에 적합합니다.
  • hinge: SVM의 서포트 벡터 머신 손실 함수. 선형 SVM에 사용됩니다.
  • squared_hinge: SVM 손실 함수의 제곱 버전.
  • perceptron: 퍼셉트론 학습을 위한 손실 함수.
  • huber: 회귀 작업에 사용되는 Huber 손실 함수.
  • squared_error: MSE(Mean Squared Error). 회귀 문제에 사용됩니다.

Scikit-learn 버전과의 관계

Scikit-learn의 최신 버전에서는 loss 매개변수 값에 대해 엄격한 검증을 수행합니다. 예전에는 허용되던 "log"와 같은 값이 더 이상 허용되지 않으며, 최신 이름(예: "log_loss")으로 대체되었습니다.

Scikit-learn 버전 확인

현재 사용하는 Scikit-learn 버전을 확인하려면 다음 명령을 실행합니다:

import sklearn
print(sklearn.__version__)

 

최신 버전을 설치하려면 다음을 실행하세요:

pip install --upgrade scikit-learn

 

요약

  • 오류 원인: SGDClassifier에서 loss='log'를 사용했기 때문에 발생.
  • 해결 방법: loss='log_loss'로 변경.
  • 최신 Scikit-learn에서는 loss 매개변수 값에 대해 최신 옵션을 확인하고 사용해야 합니다.
728x90
반응형

+ Recent posts