[ML/Python] 산점도 그래프 및 회귀 분석 (pandas, matplotlib, seaborn, numpy, sklearn)

2026. 5. 8. 16:16·AI

기존 가지고 있던 boston.csv 엑셀 파일로 산점도 그래프 및 회귀 분석 실습을 진행해 보았다.

skill: pandas, matplotlib, seaborn, numpy, sklearn

## 회귀 분석
- 특정한 값을 찾아내는 과정 ( 기기가 스스로 데이터간의 규칙을 찾아내는 과정 )

- 평가 지표
    - MAE
        - 실젯값과 예측값의 차이에 절대값으로 평균을 구한 값
    - MSE
        - 실젯값과 예측값의 차이를 제곱한 뒤 평균을 구한 값
    - RMSE
        - MSE에 루트를 씌운 값
    - MSLE
        - MSE 값에 로그를 적용한 값
    - MAPE
        - MAE를 퍼센트로 표시
    - R2 Score
        - 가장 대중적으로 사용하는 성능 평가 지표
        - 1 - (예측에 대한 오차의 제곱) / (평균값의 오차의 제곱)

- 회귀 분석의 순서
    1. 모델을 선택
    2. 모델 객체(class)를 생성
    3. 모델에 학습 (독립변수+종속변수)
    4. test 독립변수를 이용하여 예측
    5. 성능 평가 지표를 이용하여 모델의 성능을 확인

 

- 라이브러리 import

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
# model load
from sklearn.linear_model import LinearRegression
# 평가지표
from sklearn.metrics import mean_absolute_error, mean_squared_error, mean_squared_log_error, root_mean_squared_error, mean_absolute_percentage_error, r2_score

 

- boston 파일을 로드한 후 head 확인

# pandas를 이용하여 데이터(boston) 로드
boston = pd.read_csv("../csv/boston.csv")
boston.head()

 

해당 csv파일은 가격을 예측하기 위해 만들어진 sample인것을 확인할 수 있다.

- boston data column 설명 : 해당 csv파일은 가격을 예측하기 위해 만들어진 sample이다.
    - CRIM : 범죄율 ( 해당 지역 1인당 범죄 발생 수 )
    - ZN : 25000 평방피트 이상 주거지역 비율
    - INDUS : 비상업 영역(상업지구 아닌 지역) 토지 비율
    - CHAS : 찰스강 경계 여부 (1: 경계, 0: 비경계)
    - NOX : 일산화탄소 농도 ( 10ppm 단위 )
    - RM : 주택 1가구당 평균 방의 개수
    - AGE : 1940년 이전의 지어진 주택 비율 ( 건물이 30년 이상의 주택 비율 )
    - DIS : 작업 중심지 ( 보스턴에는 5개의 중심지가 있다. ) 까지의 가중 거리
    - RAD : 방사형 고속도로 접근성 지수
    - TAX : $10000 당 제산세율
    - PTRATIO : 지역별 학생-교사의 비율
    - B : 인종 지수 ( 흑인 거주 비율 )
    - LSTAT : 저소득층 비율 (%)
    - Price : 주택의 가격의 중앙값

 

각 컬럼의 관계 분석

: ZN과 INDUS는 서로 연관성이 있을수 있다. (ZN가 높다면, INDUS도 높을수도 있다. = 상관계수가 높다는 의미)

: 연관성이 있는 필드가 있다면 두개의 영향력이 다른부분에 비해 클 가능성이 있다. (종속변수에 큰 영향을 줄수 있다.)

: 만약, RM에 "면적"이라는 부분이 같이 있었다면 "면적"의 부분과 "방의개수"라는 부분이 연관성이 있었을것이다. (그렇다면, Price에 큰 영향을 미칠수도 있다.)

=> 연관성이 높은 것들을 잘 선별하여 몇가지는 제외하고 학습하는것이 좋을것이다. (다중공선성)

=> 데이터 간 상관관계를 유심히 봐야함.

 

상관관계 함수는 corr() -> Heatmap으로 보기편하게 확인

 

- boston의 info 확인

 

정보를 확인해보니 Dtype은 float64로 수식이다. 계산이 가능할것이다.

결측치는 따로 보이지 않는다.

 

- 독립 변수 따로 저장 (CHAS, Price 제외)

연관성 : Price

CHAS : 범주형데이터

 

! 위와 같은 또 다른 방법 (difference 이용) : 컬럼의 목록에서 특정 원소들을 제외시킨다.

drop으로 삭제해도 되지만 또 다른 삭제방법으로는 columns를 직접 확인한 후 difference를 이용하는 방법도 있다.

 

- Price와 독립변수들의 연관성을 그래프로 표시 (산점도 그래프, 회귀선을 표시)

# 12개 컬럼을 하나의 캔버스에 그린다.
fig, axes = plt.subplots(3, 4, figsize=(19,10))

# cols을 기준으로 그래프 생성
for i in range(len(cols)):
    # i -> index
    # seaborn에 산점도, 회귀선 그려주는 그래프 : regplot, ax는 위치 (캔버스의 flat i)
    sns.regplot( data = boston, x = cols[i], y = 'Price', ax = axes.flat[i] )

plt.show()

 

그래프 분석

- B라고 되어있는 부분 (흑인) 데이터가 400+에 몰려있는데, 실제로는 흑인의 비율이 높은 지역의 집값이 분포되어 있다. (이 회귀선 만으로는 정확한 집계가 어렵다.)

- CRIM : 한쪽에 너무 몰려있다. (좋은 부분은 아님)

- DIS : 중심지와의 거리가 짧을수록 데이터들이 많을줄 알았는데, 멀수록 가격대가 올라간다고 표현되어 있음.

- NDUS : 기울기가 -로 내려가있음. (비상업지역 높을수록 해당하는 부분은 떨어진다.)

- LSTAT : 저소득층의 비율이 높으면 집값이 내려간다

- NOX : 농도가 낮은게 좋음 (-의 형태)

- PTRATIO : 학생과 선생님들의 비율. ( - )

- RAD : 고속도로 접근성, 방사선으로 방사형태의 값을 의미하는 부분이기 때문에 일렬로 나열됨. 데이터가 얼마 없음. 해당하는 부분도 기울기가 낮게 설정이 되어있다.

- RM : 방의 개수

- TAX : 높으면 집값이 떨어질것

- ZN : 주거지역의 비율

 

12개의 그래프 중 0에 가깝거나 불필요한 데이터set : B, CRIM(한쪽에 몰려있다.), RAD (설명이 부족할수도 있을것 같다.)

 

해당 데이터들은 sklearn 작업이 필요한가? 

- 각 컬럼 간의 데이터의 범위가 큰 차이가 나는가? : 최대범위 700, 최소 범위 1

- Min Max 확인 : describe()

=> 최대값은 차이가 나는편이다. 해당 근거로 Sklearn 작업이 필요하다.

 

- train, test 셋으로 분할 (8:2)

from sklearn.model_selection import train_test_split
# train, test 셋으로 분할 (8:2)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

 

# 계층화 분할 필요할까? : CARS(범위데이터)가 있었다면 필요했겠지만 지우고 사용하기 때문에 필요하지 않다.
# Price는 가격인데, 가격으로 계층화를 하기에는 조금 이상하다.
# 셔플을 안해야하는 이유? : 시계열데이터가 없다. 시간에 따라 집값의 변화량을 봤다면 확인했을것.

 

- 종속 변수들의 평균 값 확인

큰 차이가 나지 않아 이대로 진행해도 될것 같다.

 

- 객체 생성

lr = LinearRegression()

 

- 모델에 학습을 시킨다. (각 컬럼당 가격에 대한 규칙을 찾는 과정)

- 예측 ( 문제 풀이 )

 

행렬로 나타남

 

- 실제 정답과 예측값을 비교

 

실제 차이를 계산해보자. (actual price - price_df)

 

평가지표에서는 제곱해서 평균을 내거나, 절댓값으로 평균내거나, 제곱한 값에 루트 또는 로그를 씌우거나, 평균의 실제 데이터의 차이 값이랑 나눠주고 1에서 빼주는 등의 방식이 있다.

 

- 실제 값과 예측값을 이용하여 평가 지표 생성

 

mae = mean_absolute_error(y_test, pred) #실제 정보, 예측 정보
mse = mean_squared_error(y_test, pred)
rmse = root_mean_squared_error(y_test, pred)
# msle = mean_squared_log_error(y_test, pred)
mape = mean_absolute_percentage_error(y_test, pred)
rmse2 = np.sqrt(mse) # rmse가 종종 안먹히는 이슈가 있음
r2 = r2_score(y_test, pred)

 

rmse가 종종 안먹히는 이슈가 있었어서 기존방식인 np.sqrt을 사용하여 rmse2와 같이 계산해도 결과값은 같다.

$$R^2 = 1 - \frac{\sum(y - \hat{y}_i)^2}{\sum(y - \bar{y}_i)^2}$$

 

상관관계를 통해 낮은 값들을 구해볼 수 있을것 같다.

 

- 상관계수 출력

 

상관을 판단할 때에는 상관계수의 부호보다는 abs로 제외할지 판단을 진행한다.

 

만약 0.8이라면 강한 상관이므로 유지한다.

만약 0.1이라면 약한 상관이므로 제외를 고려하는게 일반적이다.

 

target(집값)을 예측하려고 할 때에는, 

방 개수 → 집값과 관련 높음 → 유지
강까지 거리 → 집값과 관련 낮음 → 제외 고려
학교까지 거리 → 집값과 관련 없음 → 제외

 

만약 0.1, 0.05와 같이 의미가 없는 값들이 변하더라도 집값은 변하지 않을것이다.

해당 컬럼을 가지고 간다면 노이즈가 발생할 수 있기 때문에 오히려 제거를 하는게 좋을수도 있다.

 

위 내용은 단일 target이 해당 모델에 필요한지 알아보는 과정이었고,

지금 우리가 알아보고자 하는것은 다중공선성이다. 

독립변수끼리 상관관계가 높으면 모델이 혼란스러워해서 정확한 집계가 어렵기 때문에, 이러한 경우는 절댓값이 높은것을 제외한다. (만약 제하지 않는다면 계수가 외곡되고 모델의 신뢰도가 하락한다.)

 

- 예시. CHAS, DIS, B 3개의 컬럼을 제외하고 선형 회귀 모델을 구동하여 평가 지표를 확인

X = boston.drop( ['CHAS', 'DIS', 'B', 'Price'], axis=1 )
y = boston['Price']

# train, test 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 모델 생성
lr = LinearRegression()

lr.fit(X_train, y_train)

# 모델에 테스트 데이터 넣어준다.
pred = lr.predict(X_test)

mae = mean_absolute_error(y_test, pred)
mse = mean_squared_error(y_test, pred)
rmse = root_mean_squared_error(y_test, pred)
mape = mean_absolute_percentage_error(y_test, pred)
r2 = r2_score(y_test, pred)

print(f"MAE : {round(mae, 2)}")
print(f"MSE : {round(mse, 2)}")
print(f"RMSE : {round(rmse, 2)}")
print(f"RMSE2 : {round(rmse2, 2)}")
print(f"MAPE : {round(mape, 2) * 100}%")
print(f"R2 Score : {round(r2, 2)}")

 

 

모든 컬럼을 다 쓰면 약 0.74정도 나오는데, 산점도를 확인해보면

 

0,1 로 나누어져 있다. 위와 같은 데이터가 오히려 영향력이 더 클수도 있다.

 

컬럼 추가하거나, 제거하거나 하면 성능이 높아지거나 줄어들 수 있다.

 

 

저작자표시 (새창열림)
'AI' 카테고리의 다른 글
  • [ML/Python] 분류 분석 (DecisionTreeClassifier) (matplotlib, sklearn, pandas)
  • 머신 러닝 기초 이론 정리
Beaver
Beaver
Automation · Data · AI | Contact : hykim.develop@gmail.com
  • Beaver
    다람디비버
    Beaver
  • 전체
    오늘
    어제
    • ALL
      • portfolio.
      • Data Analysis & Scientist
        • Python
        • Database
      • AI
      • Data Engineer
      • Automation
      • IT
        • C
        • C++
        • Github
      • 자격증
        • 자격증 준비
        • 합격후기
      • 잡지식
      • hobby :)
        • game
        • travel
  • 블로그 메뉴

    • 홈
    • 태그
    • 미디어로그
    • 위치로그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    멀티캠퍼스 부트캠프
    정보처리기사
    데이터 분석가 부트캠프
    멀티캠퍼스부트캠프
    부트캠프
    자격증
    AIPOT
    KPC
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
Beaver
[ML/Python] 산점도 그래프 및 회귀 분석 (pandas, matplotlib, seaborn, numpy, sklearn)
상단으로

티스토리툴바