본문 바로가기
Python (Linux)

11. Python - 데이터 탐색과 시각화

by #Glacier 2018. 11. 23.
반응형

저번에 테스트 셋과 훈련셋으로 나누었습니다. 

이제 테스트 셋 확인 후 훈련 세트에 대해서만 탐색을 합니다.


이 그림은 캘리포니아 지역을 잘 나타내지만, 어떤 특별한 패턴을 찾기는 힘듭니다.

alpha 옵션을 0.1로 주면 데이터 포인트가 밀집된 영역을 잘 보여줍니다.


housing.plot(kind="scatter", x="longitude", y="latitude", alpha=0.1)

 


이렇게 보면, Bay Area와 Los Angeles 근처, San Diego 같이 밀집된 지역이 눈에 잘 띄고, 

Central Valley 특히 Sacramento와 Fresno 근처를 따라 밀집된 지역이 긴 띠를 이루고 있다고 하네요. (미국 지리는 잘..ㅠ)


이제 이 그림에다가, 주택 가격을 나타내봅니다. 

원의 반지름은 구역의 인구를 나타내고(매개변수 s), 색깔은 가격을 나타냅니다.(매개변수 c)

여기서는 미리 정의된 컬러 맵 중 파란색(낮은 가격) - 빨간색(높은 가격)까지 범위를 가지는 jet를 사용합니다. 

 (매개변수 cmap)


housing.plot(kind="scatter", x="longitude" , y="latitude", alpha=0.4, s=housing["population"]/100, label="population", figsize=(10,7), c="median_house_value", cmap=plt.get_cmap("jet"), colorbar=True, sharex=False)


plt.legend()


이 그림에서 주택 가격은 지역(ex. 바다 근처)과 인구 밀도에 관련이 매우 크다는 것을 알 수 있습니다.

바다 주변을 보면 주택 중간 가격이 노랗고 뻘게지기 시작하고, 인구 분포의 원도 상대적으로 크다는 것을 알 수 있죠.

이런 내용은 군집 알고리즘(clustering algorithm)을 사용하여 주요 군집을 찾고, 군집의 중심까지의 거리를 재는 특성을 추가할 때 도움이 됩니다. 해안 근접성 특성이 유용할 수도 있지만, 북부 캘리포니아 지역의 해안가는 주택 가격이 그리 높지 않아 간단한 규칙이 적용되기 어렵습니다.


상관관계 조사를 해보면, 데이터 셋이 너무 크지 않으므로 모든 특성 간의 표준 상관계수(Standard correlation coefficient, 피어슨의 r)를 corr 메서드를 사용하여 쉽게 계산할 수 있습니다.




이렇게 보면, 중간 주택 가격에 대해 중간소득이 큰 상관관계를 보이네요. 

위도와, 방 개수도 약한 상관관계가 있음을 알 수 있습니다. 

즉, 위도가 북쪽으로 갈 수록 점점 중간 주택가격이 낮아지겠죠.


다른 방법으로 특성 사이의 관계를 측정하는 방법은 산점도를 이용한 scatter_matrix를 이용하는 방법입니다.

특성이 11개 이므로 모두 다 표현하면 121개나 되므로 몇 가지의 특성을 주로 살펴보는 것이 좋습니다. 


 


대각선 방향은 자기 자신과의 상관관계이므로 유용하지 않습니다.

그래서 판다스는 이곳의 특성을 scatter plot이 아닌 histogram으로 나타냅니다.( 다른 옵션은 판다스를 참고.)

중간 주택 가격을 예측하는 데 가장 유용할 것 같은 데이터는 중간 소득이므로 상관관계 산점도를 확대합니다.


housing.plot(kind="Scatter", x="median_income", y="median_house_value", alpha=0.1)

 

매우 큰 상관관계를 보여주네요.

$280,000, $350,000, $470,000, $500,000 근처에서는 직선적 형태가 보이기 때문에, 

알고리즘이 이러한 데이터를 학습하지 않도록 해당 구역을 제거하는 것이 좋습니다.

앞서서 데이터에 대한 탐색을 했습니다. 이후에 데이터를 삭제해야 하는 부분도 있고, 

꼬리가 두꺼운 데이터들은 예를 들면 로그 스케일로 변형해야 합니다.


이렇게 하기 위해서 여러 특성의 조합을 보아야 합니다. 


 

가구 당 총 방의 개수, 방 개수 당 총 침실 수, 가구 당 인구 수와 같은 특성을 만듭니다.


 


이렇게 본 결과, 중간주택가격이 중간소득 이외에도

rooms_per_household, total_rooms, bedrooms_per_room, latitude 변수와 상관관계가 보입니다.

확실히 bedrooms_per_room을 보면 방 개수 당 침실의 개수가 낮은 집이 더 비싼 경향이 있습니다. 

이제 이러한 결과를 프로토타입을 만들고 실행한 후, 다시 이 단계로 돌아오게 됩니다.

이제 머신러닝 알고리즘을 위해 데이터를 준비합니다.

이 작업을 수동화하지 않고 함수를 만들어 자동화하는 이유는 다음과 같습니다.


1. 어떤 데이터셋에 대해서도 데이터 변환을 손쉽게 반복할 수 있다.

2. 향후 프로젝트에 사용할 수 있는 변환 라이브러리를 점진적으로 구축하게된다.

3. 실제 시스템에서 알고리즘에 새 데이터를 주입하기 전에 변환시키는 데 이 함수를 사용할 수 있다.

4. 여러 가지 데이터 변환을 쉽게 시도해볼 수 있고 어떤 조합이 가장 좋은지 확인하는 데 편리하다.


먼저, 원래 훈련 세트로 복원하고, 예측 변수와 타깃 값에 같은 변형을 적용하지 않기 위해 예측 변수와 레이블을 분리합니다. 

(drop()은 데이터 복사본을 만들며 strat_train_set에는 영향을 주지 않습니다.)


housing = strat_train_set.drop("median_house_value", axis=1)

housing_labels =strat_train_set["median_house_value"].copy()


이제, 데이터 정제를 하는데, total_bedroom 변수에 없는 값이 있다는 사실을 알고 있기 때문에 이를 고쳐야 합니다.

방법은 3가지입니다.

1. 해당 구역을 제거합니다.

2. 전체 특성을 삭제합니다.

3. 어떤 값으로 채웁니다. 


이러한 방법은 데이터 프레임의 dropna(), drop(), fillna() 메서드를 이용해 간단히 처리할 수 있습니다.

housing.dropna(subset=["total_bedrooms"])

housing.drop("total_bedrooms", axis=1)

median = housing["total_bedrooms"].median()

housing["total_bedrooms"].fillna(median, inplace=True)


가장 좋은 방법으로 알려진 결측치를 추정하는 방법도 있는데 (데이터 손실을 막음) 이는 차후에 해보도록 할게요.


위의 방법은 사이킷런의 Imputer를 통해 손쉽게 다룰 수 있습니다.

먼저, 누락된 값을 중간값으로 대체한다고 지정하여 Imputer의 객체를 생성합니다.

중간값은 수치형 자료에서만 계산될 수 있기 때문에, 텍스트 특성인 ocean_proximity를 제외한 데이터 복사본을 생성합니다.


 


imputer 객체의 fit()메서드를 이용해 훈련 데이터에 적용할 수 있습니다.

imputer는 각 특성의 중간값을 계산해서 그 결과를 객체의 statistics_속성에 저장합니다.

total_bedrooms 특성에만 누락된 값이 있지만 나중에 시스템이 서비스 될 때 어떤 값이 누락될 지 확신할 수 없으므로, 

모든 수치형 특성에 imputer를 적용하는 것이 바람직합니다. 



이제 학습된 imputer객체를 이용해 훈련 세트에서 누락된 값을 학습한 중앙값으로 바꿀 수 있습니다.

잠시 사이킷런의 설계 철학을 보겠습니다.


 


 【 사이킷런의 설계 철학】


사이킷런 API 특징


1) 일관성 : 모든 객체가 일관되고 단순한 인터페이스 제공


 - 추정기 (estimator) : 데이터셋을 기반으로 일련의 모델 파라미터를 추정하는 객체를 추정기라고 합니다.

 - 추정 자체는 fit() 메서드에 의해 수행되고 하나의 매개변수로 하나의 데이터 셋을 전달합니다. 

    (지도 학습 알고리즈메서는 매개변수가 2개로, 2번째 데이터셋은 레이블)

 - 추정 과정에서 필요한 모든 다른 매개변수는 하이퍼파라미터로 간주되고,

   (imputer 객체의 strategy 매개변수) 인스턴스 변수로 저장됩니다. (생성자의 매개변수로 전달)


 - 변환기 (transformer) : 데이터셋을 변환하는 추정기를 변환기라고 합니다.

                            변환은 데이터셋을 매개변수로 전달받은 transform() 메서드가 수행합니다.


 - 모든 변환기는 fit()과 transform()을 연달아 호출하는 것과 동일한 fit_transform() 메서드도 가지고 있습니다.

   (더 빠른 경우도 있음) 


 - 예측기 (predictor) : 일부 추정기는 주어진 데이터셋에 대해 예측을 만들 수 있습니다. 

                          예를 들어 LinearRegression 모델이 예측기입니다.


 - 또한 테스트 세트(지도 학습 알고리즘이라면 레이블도 함께)를 사용해 예측의 품질을 측정하는

   score() 메서드를 가집니다.

 

2) 검사 가능 : 모든 추정기의 하이퍼파라미터는 공개(public) 인스턴스 변수로 직접 접근이 가능하고, 

                (예를 들면 imputer.strategy) 

   모든 추정기는 접미사로 밑줄을 붙여서 공개 인스턴스 변수로 제공됩니다. (ex. imputer.statistics_)


3) 클래스 남용 방지 : 데이터셋을 별도의 클래스가 아니라 넘파이 배열이나 사이파이 희소(sparse) 행렬로 표현합니다. 

     하이퍼파라미터는 보통 파이썬 문자열이나 숫자입니다.


4) 조합성 : 기존의 구성요소를 최대한 활용합니다. 

       앞으로 보겠지만 여러 변환기를 연결한 다음 마지막에 추정기 하나를 배치한 pipeline 추정기를 쉽게 만듭니다.


5) 합리적인 기본값 : 사이킷런은 일단 돌아가는 기본 시스템을 빠르게 만들 수 있도록 

                        대부분의 매개변수에 합리적인 기본값을 지정해두었습니다.



앞서 범주형 특성 ocean_proximity가 텍스트 형식으로 되어 있어 중간값을 계산할 수 없었죠.

대부분의 머신러닝 알고리즘은 숫자형을 다루므로 이 카테고리를 텍스트에서 숫자로 바꿔보도록 하겠습니다.



판다스의 .factorize()메서드는 카테고리 리스트도 반환해줍니다. 


<1H OCEAN은 0으로 매핑되고, 

NEAR OCEAN은 1, 

INLAND는 2, 

NEAR BAY는 3,

 ISLAND는 4 처럼 숫자로 변환되었습니다.




하지만 이 표현의 문제는 머신러닝 알고리즘이 가까이 있는 두 값이 떨어져 있는 두 값보다 더 비슷하다고 생각한다는 점입니다. 실제로는 카테고리 0과 1보다 카테고리 0과 4가 더 비슷합니다. 이 문제는 일반적으로 카테고리별 이진 특성을 만들어 해결합니다.


즉 NEAR OCEAN이 1인경우 나머지는 0 처럼 한 특성만 1이고(핫), 나머지는 0 이므로,

이를 원-핫 인코딩(one-hot encoding)이라고 부릅니다.


사이킷런은 숫자로 된 범주형 값을 원-핫 벡터로 바꿔주는 OneHotEncoder를 제공합니다. 

카테고리들을 원-핫 벡터로 인코딩해보면



fit_transform()메서드는 2차원 배열을 넣어주어야 하는데, housing_cat_encoded는 1차원 배열이므로, 구조를 바꿔야 합니다. 또한 출력을 보면 Numpy 배열이 아니고 SciPy 희소 행렬(sparse matrix)입니다. 


​이는 수천 개의 카테고리가 있는 범주형 특성일 경우 매우 효율적입니다. 

이런 특성을 원-핫 인코딩하면 열이 수천 개인 행렬로 변하고

각 행은 1이 하나이며 그 외에는 0으로 채워져 있을 것입니다.

0을 모두 메모리에 저장하는 것은 비효율적이므로 희소 행렬은 0이 아닌 원소의 위치만 저장합니다. 

이 행렬을 거의 일반적인 2차원 배열처럼 사용할 수 있지만 넘파이 배열로 바꾸려면 toarray()메서드를 호출하면 됩니다.


#넘파이의 reshape()함수에서 -1은 차원을 지정하지 않는다는 뜻입니다. 

 해당 차원의 크기는 전체 배열에서 다른 차원이 정해지고 남은 크기가 됩니다.


텍스트 카테고리를 숫자 카테고리로, 숫자 카테고리를 원-핫 벡터로 바꿔주는 두가지 변환을 CategoricalEncoder를 사용하여 한 번에 처리할 수 있습니다. 이 파이썬 클래스는 사이킷런 0.19.0 이하에는 포함되어 있지 않습니다. 라고 해서 해봤더니



 


Runtime Error : 가 뜨면서 0.20dev에 잠시 존재했으며, 

현재는 OneHotEncoder 및 OrderalEncoder에 적용되어있다고 하네요.

(sparse matrix와 dense matrix 모두)


다음 장에서는 특성 스케일링에 대해 알아보겠습니다.


 블로그 

출처


이 글의 상당 부분은  [핸즈온 머신러닝, 한빛미디어/오렐리앙 제롱/박해선] 서적을 참고하였습니다.


나머지는 부수적인 함수나 메서드에 대해 부족한 설명을 적어두었습니다.

학습용으로 포스팅 하는 것이기 때문에 복제보다는 머신러닝에 관심이 있다면 구매해보시길 추천합니다.


도움이 되셨다면 로그인 없이 가능한

아래 하트♥공감 버튼을 꾹 눌러주세요! 



반응형