Notice
Recent Posts
Recent Comments
Link
«   2025/03   »
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
Tags
more
Archives
Today
Total
관리 메뉴

archive

[교재] 2. 데이터 다루기 본문

ML_AI/24_여름방학 인공지능 스터디

[교재] 2. 데이터 다루기

안정민 2024. 7. 4. 14:20

2-1 훈련 세트와 테스트 세트

1. 샘플링 편향

- 훈련 세트와 테스트 세트에 샘플이 골고루 섞여있지 않으면 샘플링이 한 쪽으로 치우쳐져있다는 의미로 샘플링 편향 (Sampling bias)라고 부른다.

- 특정 종류의 샘플이 과도하게 많은 샘플링 편향을 가지고 있다면 제대로 된 지도 학습 모델을 만들 수 없다.

- 따라서 훈련세트와 테스트 세트를 나누기 전에 데이터를 섞던지 아니면 골고루 샘플을 뽑아서 훈련세트와 테스트 세트를 구성해야 한다.

 

2. 두 번째 머신 러닝 프로그램

- K-최근접 이웃 모델의 fit() 메서드는, 이 메서드를 실행할 때만 KNeighborsClassifier 클래스의 객체는 이전에 학습만 모든 것을 잃어버리고 초기화된다.

-따라서 이전의 모델을 그대로 두고 싶다면 KNeighborsClassifier 클래스 객체를 새로 만들어야 한다.

 

- 사이킷런 모델의 입력과 출력은 모두 넘파이 배열이다

- 넘파이 배열을 출력하면 리스트처럼 한 줄로 길게 출력되는 것이 아니라 행과 열을 맞추어 가지런히 정리된 모습으로 보여주게 된다.

 

** 실습 파일

2_1_훈련세트와_테스트세트.ipynb
0.03MB

 

 

 

2-2 데이터 전처리

1. 넘파이로 데이터 준비하기

- np.column_stack()의 매개변수로 전달된 자료의 자료형은 튜플

-튜플은 리스트와 매우 비슷하다. 리스트처럼 원소에 순서가 있지만 한 번 만들어진 튜플은 수정이 불가능하다

-튜플을 사용하면 함수로 전달한 값이 바뀌지 않는다는 것을 믿을 수 있기 때문에 매개변수 값으로 많이 사용된다.

 

- np.column_stack() 과 np.concatenate() 비교

 

 

2. 사이킷런으로 훈련 세트와 테스트 세트 나누기

- 사이킷런은 머신러닝 모델을 위한 알고리즘 뿐만 아니라 다양한 유틸리티 도구도 제공한다.

-train_test_split() 함수는 전달되는 리스트나 배열을 비율에 맞게 훈련세트와 테스트 세트로 나누어주며, 나누기 전 알아서 shuffling까지 진행한다.

- 이는 사이킷런의 model_selection 모듈 아래에 있으며 다음과 같이 import 할 수 있다.

from sklearn.model_selection import train_test_split

 

 

- 이 함수는 기본적으로 25%를 테스트 세트로 떼어낸다.

 

- 그러나 무작위로 데이터를 나누었을 때 샘플이 골고루 섞이지 않을 수 있다, 특히 일부 클래스의 개수가 적어 비율이 맞지 않을 때 이런 일이 생길 수 있다.

-위의 이미지를 보면, 원본 데이터셋의 두 생선 비율은 2.5:1 이지만, 테스트 세트의 비율은 3.3:1 이다.

-샘플링 편향이 나타남!

-훈련 세트와 테스트 세트에 샘플의 클래스 비율이 일정하지 않다면 모델이 일부 샘플을 올바르게 학습할 수 없을 것이다.

-여기서 train_test_split() 함수의 stratify 매개변수에 타깃 데이터를 전달하면 클래스 비율에 맞게 데이터를 나눈다. 

train_input, test_input, train_target, test_target = train_test_split(fish_data, fish_target, stratify = fish_target, random_state=42)

 

 

- 출력 결과, 빙어가 하나 늘어나 테스트 세트의 비율이 3.3:1 -> 2.25:1 

- 예제 상 데이터가 작아 전체 훈련 데이터의 비율과 동일하게 맞출 수는 없으나 꽤 비슷한 비율까지는 조정 가능

 

 

3. 수상한 도미 한 마리

from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier()
kn.fit(train_input, train_target)
kn.score(test_input, test_target)

print(kn.predict([[25, 150]]))

>> [0.]

 

-1로 예측되어야 하는 데이터가 0으로 예측되어, 데이터 시각화를 통해 해당 데이터를 확인해보고자 함

 

- 이 샘플은 분명 오른쪽 위로 뻗어있는 다른 도미 데이터에 더 가깝다. 그러나 왜 왼쪽 아래에 낮게 깔린 빙어 데이터와 가깝다고 판단한 것일까?

- K-최근접 이웃은 주변의 샘플 중에서 다수인 클래스를 예측으로 사용하기 때문

- KNeighborsClassifier의 kneighbors() 메서드를 활용해 이웃까지의 거리와 이웃 샘플의 인덱스를 반환해 이를 시각화하여 확인해보았다

- 이를 통해 확실히 레이블링이 0으로 된 빙어 데이터에 가까움, 그러나 산점도를 보면 직관적으로 도미와 가깝게 보임

- 이는 x축과 y축의 범위의 영향을 받았음

- x축은 범위가 좁고 (10-40), y축은 범위가 넓음 (0-1000)

- 따라서 x축의 범위를 xlim() 함수를 활용하여 지정해 같은 범위를 나타내도록 데이터를 시각화하면 다음과 같다

-산점도가 거의 일직선으로 나타남, 이러한 데이터라면 x축은 가장 가까운 이웃을 찾는 것에 큰 영향을 미칠 수가 없음

-두 특성의 값이 놓인 범위가 매우 다르다, 이를 두 특성의 스케일(scale) 이 다르다고도 이야기한다.

-특성간 스케일이 다른 일은 매우 흔하나, 데이터를 표현하는 기준이 다르면, 특히 알고리즘이 거리 기반일 땐 특히 알고리즘이 올바른 예측을 하기 어려워진다.

-거리 기반 알고리즘인 K-최근접 이웃 알고리즘은 샘플 간의 거리에 영향을 많이 받으므로 제대로 사용하려면 특성 값을 일정한 기준으로 맞춰주어야 하는데, 이러한 작업을 데이터 전처리 (Data Preprocess) 라고 한다.

 

** 표준 점수 (Standard Score)

-가장 널리 사용되는 전처리 방법 중 하나, z점수라고도 불림

-각 특성값이 평균에서 표준편차의 몇 배만큼 떨어져 있는지를 나타냄

-즉, 표준 점수는 각 데이터가 원점에서 몇 표준편차만큼 떨어져있는지를 나타내는 값이다.

-따라서 계산하는 방법은, 평균을 특성값에서 빼고 표준편차를 나누어 주면 된다.

-이를 통해 실제 특성값의 크기와 상관 없이 동일한 조건으로 비교할 수 있다

-np.mean() 함수np.std() 함수 활용

-np.mean()은 평균을 계산, np.std()는 표준편차를 계산, 그리고 특성마다 값의 스케일이 다르므로 평균과 표준편차는 각 특성별로 계산을 해야하기 때문에 axis 매개변수를 0으로 설정, 이렇게 하면 행을 따라 각 열의 통계값을 계산

mean = np.mean(train_input, axis = 0)
std = np.std(train_input, axis = 0)

train_scaled = (train_input - mean) / std  #브로드캐스팅

 

 

**넘파이의 브로드캐스팅

 

-브로드캐스팅은 크기가 다른 넘파이 배열에서 자동으로 사칙연산을 모든 행이나 열로 확장하여 수행하는 기능이

- train_input의 모든 행에 대해 계산이 적용된다

- 넘파이 배열 사이에서 일어나는 계산이다

 

 

 

4. 전처리 데이터로 모델 훈련하기

- 앞에서 표준 점수로 변환한 train_scaled 데이터를 활용해 다시 산점도를 그리면

- 이러한 이유는, 훈련 세트를 mean으로 빼고 std로 나누어 주었기 때문에 샘플 [25,150]과 값의 범위가 상응하지 않는다

-샘플 [25, 150]도 동일한 비율로 변환하지 않으면 위와 같은 현상 발생

new = ([25,150]-mean)/std
plt.scatter(train_scaled[:, 0], train_scaled[:, 1])
plt.scatter(new[0], new[1], marker='^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

 

-이와 같이 볂환된 데이터셋으로 모델을 다시 훈련해 분류 작업을 해 본다면, 올바르게 도미로 데이터를 분류하게 된다.

 

 

**실습파일

2_2_데이터_전처리.ipynb
0.11MB

 

 

 

 

 


** 핵심 패키지와 함수

패키지 함수 설명
numpy np.array() 파이썬 리스트를 매개변수로 전달하면, 파이썬 리스트를 넘파이 배열로 변환
np.arange() 매개변수로 전달된 수의 양 만큼 0부터 1씩 증가하는 인덱스를 만들어냄
매개변수가 2 개면 시작 숫자와 종료 숫자를 의미
매개변수가 3 개면 마지막 매개변수가 간격 step을 의미한다.
np.random.seed() numpy.random을 엄밀하게 말하면 유사 난수라 부르는데, 이는 난수 생성기의 시드값에 따라 정해진 난수를 알고리즘으로 생성하기 때문이다. 즉, 컴퓨터 프로그램에서 무작위 수를 구할때는 어떠한 특정 시작 숫자를 기준으로 컴퓨터가 정해진 알고리즘에 의해 마치 난수처럼 보이는 수열을 생성한다. 이러한 시작 숫자를 시드(seed)라고 한다. 
즉, 시드값을 고정하면 그 값에 해당하는 수열만이 출력되어 같은 값을 도출해낼 수 있는 것
np.random.shuffle() random 패키지 아래의 이 함수는 주어진 배열을 무작위로 섞는다
다차원 배열일 경우 첫 번째 축 (행)에 대해서만 섰습니다.
np.column_stack() 전달받은 리스트를 일렬로 세운 다음 차례대로 나란히 연결
연결할 리스트는 튜플로 전달
np.concatenate() 전달을 받은 배열을 일렬로 나란히 연결
np.zeros() 각각 원하는 개수를 매개변수로 전달 받아 그 수 만큼 0로 채운 배열을 만든다
np.ones() 각각 원하는 개수를 매개변수로 전달 받아 그 수 만큼 1로 채운 배열을 만든다
np.mean 평균을 계산
np.std() 표준편차를 계산
sklearn.model_selection train_test_split() 전달되는 리스트나 배열을 비율에 맞게 훈련세트와 테스트 세트로 나누어주며, 나누기 전 알아서 shuffling까지 진행한다.

stratify 매개변수에 타깃 데이터를 전달하면 샘플링 편향 없이, 클래스 비율에 맞게 데이터를 나눈다. 
KNeighborsClassifier kneighbors() 매개변수로 주어진 샘플에서 가장 가까운 이웃을 찾아 주는 메서드
이웃까지의 거리와 이웃 샘플의 인덱스를 반환