Scaling , Z-score
저번 게시글에서는 왜 도미 데이터를 넣고 빙어 데이터로 인식 했는지에 대해 분석해보려고 했습니다.
직관적으로 확인했을 때 가장 가까운 점은 어떤 점이라고 생각하시나요? 직관적으로만 봤을 때 빨간 점 즉 도미데이터에 KNN이 적용될 것이라고 생각합니다. 이를 정확하게 분석해보기 위해서 다른 함수를 소개하겠습니다.
distances, indexes = kn.kneighbors([[25,150]])
kn.kneighbors()는 K-최근접 이웃(KNN, k-nearest neighbors) 알고리즘에서 특정 데이터의 가장 가까운 k개의 이웃을 찾는 역할을 합니다. 이를 활용하게 되면 indexes 에서는 최근접으로 선정된 인덱스가 나오게 됩니다.
plt.scatter(train_input[:,0], train_input[:,1])
plt.scatter(25,150,marker='^')
plt.scatter(train_input[indexes,0], train_input[indexes,1],marker='D')
plt.show()
보기에는 멀리에 있는 점들이 최근접 이웃으로 선정 된 것을 확인할 수 있다면
파란색점이 가까워 보여도 실제 거리에서는 더욱 멉니다. 이유는 현재 x축과 y축의 scaling이 일치하지 않기 때문입니다.
그렇다면 y를 언더샘플 하듯이 맞춘다면 정보의 손실이 있으니 x의 축을 늘려야 할 까요?
X축을 늘린다면 X의 영향은 아예 없어 보이고 오직 1차원에서만 움직이는 거와 같습니다. 그렇다고 차원 축소를 해도 되는 것은 아닙니다. 이 방식이 애초에 틀린 방식입니다. X를 Y에 맞춰 lim 을 늘리는 것이 아닌 scaling을 해줘야 합니다.
여기서 대표적으로 사용되는게 z스코어 입니다.
Z-Score(표준화 점수)는 데이터 값이 평균(μ)에서 얼마나 떨어져 있는지를 표준편차(σ) 단위로 측정한 값입니다.
X=데이터
u=평균
a=표준편차
Z-Score 활용
- 데이터 표준화 (Standardization)
- 서로 다른 단위를 가진 데이터를 비교할 때 사용
- 평균이 0, 표준편차가 1이 되도록 변환
- 머신러닝 모델 (특히 KNN, SVM, PCA 등)에서 필수적으로 사용됨
- 이상치 탐지 (Outlier Detection)
- 일반적으로 ∣Z∣>2|Z| > 2 또는 ∣Z∣>3|Z| > 3이면 이상치로 간주
이를 이용하여 x를 scaling 해보겠습니다.
여기서 엄청나게 중요한 내용이 추가 됩니다. 바로 Z-score를 구하고 표준화 할 때에는 Train 데이터의 평균과 분산을 사용해야 한다는 점 입니다. 당연히 Train 데이터에서는 Train의 평균과 표준편차를 사용하는거 아닌가라고 생각하실 수 있습니다. 이 말은 틀리지 않았습니다. 하지만 Test 데이터에서도 Train의 평균과 표준편차를 사용하여 표준화 해야 합니다. 왜냐하면 학습 할 때의 정보가 애초에 z-score로 학습이 되었던 것입니다. 따라서 Train 데이터의 평균과 분산으로 Test데이터에서도 마찬가지로 적용해야 올바른 학습 및 평가 방법입니다. 이를 실습해보겠습니다.
먼저 np.mean() np.std()로 평균과 표준편차를 구하고 Z-score를 구하겠습니다.
mean = np.mean(train_input , axis =0)
std = np.std(train_input, axis=0)
train_scaled = (train_input - mean) / std
브로드캐스팅이 적용되고 ndarray객체 이기 때문에 연산이 가능합니다 따라서 train_scaled는 Z-score가 적용된 수치입니다.
이제 이 train_scaled를 적용한 데이터에서 도미를 예측해보겠습니다. 하지만 여기서 도미 데이터는 예측이 불허한 데이터입니다. 왜냐하면 트레인 데이터는 Z-score가 적용되지 않았기 때문입니다.
예시를 시각화해보겠습니다.
plt.scatter(train_scaled[:,0],train_scaled[:,1])
plt.scatter(25,150,marker='^') #스케일이 아직 되지않음
plt.xlabel('length')
plt.ylabel('weight')
이는 의미있는 정보가 아니라고 생각합니다. 예측 데이터를 Z-score로 나타내지 않았기 때문에 혼자 동 떨어져있는 것을 알 수 있습니다. 이를 KNN 에 적용하면 가장 끝단에 있는 데이터만 예측을 하게 되므로 Z-Score가 오히려 더 안좋은 결과를 초래하는 상황이 됩니다. 따라서 현재 들어가는 데이터 즉 예측 데이터 또한 Z-score로 스케일 해보겠습니다.
zscore_ = (np.array([25,150]) - mean) / std
plt.scatter(train_scaled[:,0],train_scaled[:,1])
plt.scatter(zscore_[0], zscore_[1],marker='^') #스케일이 아직 되지않음
plt.xlabel('length')
plt.ylabel('weight')
#원래는 axis에 단위를 표시해야 함
#같은 그림이여도 분산은 변하지 않기 때문이다.
이제 익숙한 산점도가 나왔습니다. 이 산점도는 이전에 저희가 스케일 하기전 산점도와 매우 일치합니다.
산점도가 일치하는 이유는 분산은 변하지 않기 때문입니다. 하지만 달라진 점은 X축과 Y축의 범위가 -1.5~ 1.5사이로 바뀌었다는 점입니다. 이제 훈련 데이터의 두 특성이 비슷한 범위를 차지 하고 있습니다. 이를 통해서 다시 학습을 하면 됩니다.
예측을 잘 했다는 것을 알 수 있습니다. 이번에는 이 산점도에 KNN이 근접한 점을 선택한 것을 시각화해보겠습니다.
distances , indexes = kn.kneighbors([zscore_])
plt.scatter(train_scaled[:,0],train_scaled[:,1])
plt.scatter(zscore_[0],zscore_[1],marker='^')
plt.scatter(train_scaled[indexes,0],train_scaled[indexes,1],marker='D',color='g')
plt.show()
정확히 고른 것을 확인할 수 있었습니다.
이전에 스케일링 하기전과 후의 산점도입니다. 하지만 별 차이가 없는 이유는 분산은 변하지 않기 때문입니다.
하지만 최근점 이웃을 정할 때 데이터 값을 z-score로 표준화 해준다면 근점접이 달라집니다.
'Machine-Learning' 카테고리의 다른 글
Linear Regression _ 선형 회귀 (1) | 2025.03.26 |
---|---|
K-NN Regression _ K-최근접 이웃 회귀 (0) | 2025.03.26 |
데이터 전처리, 데이터셋 나누기 (0) | 2025.03.19 |
K-Nearest Neighbors, KNN (0) | 2025.03.13 |