- 데이터: http://lib.stat.cmu.edu/datasets/boston
- 데이터에 대한 설명
- CRIM per capita crime rate by town
- ZN proportion of residential land zoned for lots over 25,000 sq.ft.
- INDUS proportion of non-retail business acres per town
- CHAS Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)
- NOX nitric oxides concentration (parts per 10 million)
- RM average number of rooms per dwelling
- AGE proportion of owner-occupied units built prior to 1940
- DIS weighted distances to five Boston employment centres
- RAD index of accessibility to radial highways
- TAX full-value property-tax rate per $10,000
- PTRATIO pupil-teacher ratio by town
- B 1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town
- LSTAT % lower status of the population
- MEDV Median value of owner-occupied homes in $1000's
MEDV 컬럼이 타겟이고 나머지가 피처
1. 데이터 가져오기
data_url = "http://lib.stat.cmu.edu/datasets/boston"
raw_df = pd.read_csv(data_url, sep="\s+", skiprows=22, header=None)
print(raw_df.head())
0 1 2 3 4 5 6 7 8 9 10 0 0.00632 18.00 2.31 0.0 0.538 6.575 65.2 4.0900 1.0 296.0 15.3 1 396.90000 4.98 24.00 NaN NaN NaN NaN NaN NaN NaN NaN 2 0.02731 0.00 7.07 0.0 0.469 6.421 78.9 4.9671 2.0 242.0 17.8 3 396.90000 9.14 21.60 NaN NaN NaN NaN NaN NaN NaN NaN 4 0.02729 0.00 7.07 0.0 0.469 7.185 61.1 4.9671 2.0 242.0 17.8 |
- 공백 문자 단위로 데이터를 분할해서 읽을 공백 문자가 \s 이고
+를 추가한 이유는 맨 앞에 공백이 있으면 제거하기 위해서
뒤의 3개의 데이터도 하나의 행에 포함이 되어야 하는데 뒷줄로 넘어감
# 홀수 행에 짝수 행에서 앞의 2개의 열의 데이터를 붙이고 타겟 만들기
#피처 만들기
data = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
#타겟 만들기
target = raw_df.values[1::2, 2]
... |
2. DataFrame 생성
- 피처의 이름을 출력하거나 데이터를 전처리할 때 피처의 이름을 사용하기 위함
bostonDF = pd.DataFrame(data, columns=["CRIM", "ZN", "INDUS", "CHAS", "NOX",
"RM", "AGE", "DIS", "RAD", "TAX", "PTRATIO",
"B", "LSTAT"])
bostonDF["PRICE"] = target
bostonDF.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 506 entries, 0 to 505 Data columns (total 14 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 CRIM 506 non-null float64 1 ZN 506 non-null float64 2 INDUS 506 non-null float64 3 CHAS 506 non-null float64 4 NOX 506 non-null float64 5 RM 506 non-null float64 6 AGE 506 non-null float64 7 DIS 506 non-null float64 8 RAD 506 non-null float64 9 TAX 506 non-null float64 10 PTRATIO 506 non-null float64 11 B 506 non-null float64 12 LSTAT 506 non-null float64 13 PRICE 506 non-null float64 dtypes: float64(14) memory usage: 55.5 KB |
3. 타겟과 피처 사이의 선형 관계 파악
- 산포도를 이용(여러 개의 컬럼 사이의 산포도를 만들 때는 seaborn 의 pairplot 이나 regplot을 이용)
- 예전에는 숫자가 아닌 컬럼이 있으면 제외하고 출력을 했는데
- 최신 API에서는 숫자 컬럼에 대해서만 동작하기 때문에 숫자가 아닌 컬럼이 있으면 에러
- 피처가 많은 경우 불필요한 산포도가 너무 많이 그려져서 알아보기가 어려움
sns.pairplot(bostonDF, height=2.5)
plt.tight_layout()
plt.show()
#타겟 과의 관계를 파악하고자 하는 feature 리스트를 생성
lm_features = ["RM", "ZN", "INDUS", "NOX", "AGE", "PTRATIO", "LSTAT", "RAD"]
#한 줄에 4개씩 8개의 그래프 영역을 생성
fig, axe = plt.subplots(figsize=(16, 8), ncols=4, nrows=2)
#python에서 list를 순회할 때 인덱스를 같이 사용하는 방법
for i, feature in enumerate(lm_features):
row = int(i / 4)
col = i % 4
sns.regplot(x=feature, y="PRICE", data=bostonDF, ax=axe[row][col])
# 타겟과 피처의 상관 계수 확인
#상관 계수 구하기
cols = lm_features.copy()
cols.append("PRICE")
cm = np.corrcoef(bostonDF[cols].values.T)
print(cm)
[[ 1. 0.31199059 -0.39167585 -0.30218819 -0.24026493 -0.35550149 -0.61380827 -0.20984667 0.69535995] [ 0.31199059 1. -0.53382819 -0.51660371 -0.56953734 -0.39167855 -0.41299457 -0.31194783 0.36044534] [-0.39167585 -0.53382819 1. 0.76365145 0.64477851 0.38324756 0.60379972 0.59512927 -0.48372516] [-0.30218819 -0.51660371 0.76365145 1. 0.7314701 0.18893268 0.59087892 0.61144056 -0.42732077] [-0.24026493 -0.56953734 0.64477851 0.7314701 1. 0.26151501 0.60233853 0.45602245 -0.37695457] [-0.35550149 -0.39167855 0.38324756 0.18893268 0.26151501 1. 0.37404432 0.46474118 -0.50778669] [-0.61380827 -0.41299457 0.60379972 0.59087892 0.60233853 0.37404432 1. 0.48867633 -0.73766273] [-0.20984667 -0.31194783 0.59512927 0.61144056 0.45602245 0.46474118 0.48867633 1. -0.38162623] [ 0.69535995 0.36044534 -0.48372516 -0.42732077 -0.37695457 -0.50778669 -0.73766273 -0.38162623 1. ]] |
plt.figure(figsize=(15, 7))
sns.set(font_scale=1.5) #화면 크기에 따라 변경 - 폰트 크기
hm = sns.heatmap(cm, cbar=True, annot=True, square=True, fmt='.2f',
annot_kws={'size':15}, yticklabels=cols, xticklabels=cols)
plt.show()
- ticklabels는 보여질 문자열
- annot_kws 는 글자 크기
- fmt는 포맷으로 숫자의 표시 형식
- annot는 값 출력 여부
- 데이터 탐색 결과
- RM 과 LSTAT 의 PRICE 영향도가 높음
- RM은 양의 상관 관계를 가지고 LSTAT는 음의 상관 관계를 가짐
- 단변량(피처가 1개) 선형 회귀를 수행한다면 2개의 피처 중 하나를 이용하는 것이 효율적
scipy 를 이용한 RM 과 PRICE에 대한 단변량 선형 회귀
from scipy import stats
result = stats.linregress(bostonDF['RM'], bostonDF['PRICE'])
#하나의 속성 출력
print(result.pvalue)
#예측 - 방이 4개 인 경우
print("방이 4개인 경우:", result.slope * 4 + result.intercept)
2.487228871008377e-74 방이 4개인 경우: 1.7378151482826851 |
- scipy는 머신러닝을 수행하지만 머신러닝만을 위한 패키지는 아님
- 피처를 설정할 때 2차원 배열이 아니어도 됨
- scipy 나 seaborn 의 데이터는 pandas의 자료구조가 가능
sklearn을 이용한 단변량 선형 회귀
from sklearn.linear_model import LinearRegression
#모델 생성 - 행렬 분해를 이용하는 선형 회귀 모델
slr = LinearRegression()
#타겟과 피처 생성
X = bostonDF[['LSTAT']].values #sklearn 에서는 피처가 2차원 배열
y = bostonDF['PRICE'].values #타겟은 일반적으로 1차원 배열
#훈련
slr.fit(X, y)
- 통계 패키지는 훈련의 결과를 리턴
- 머신러닝 패키지는 훈련의 결과를 내부에 저장
- 다음 데이터를 예측할 때 통계 패키지는 수식을 직접 만들어야 함
- 머신러닝 패키지는 수식을 만들지 않고 새로운 데이터만 predict에게 제공
- API를 확인할 때 통계 패키지는 리턴하는 데이터를 확인해야 하고
- 머신러닝 패키지는 모델을 확인해야 함
#기울기 와 절편 출력
print("기울기:", slr.coef_[0])
print("절편:", slr.intercept_)
#예측
print(slr.coef_[0] * 4 + slr.intercept_)
print(slr.predict([[4]]))
기울기: -0.9500493537579905 절편: 34.5538408793831 30.75364346435114 [30.75364346] |
'Python > Python 실전편' 카테고리의 다른 글
[딥러닝] Keras _ 패션 이미지 분류 (0) | 2024.03.20 |
---|---|
[딥러닝] Keras 이항분류 _ 레드와 화이트와인 분류 (0) | 2024.03.20 |
[Python] 연관분석 실습 _ 아이템 기반 추천 시스템 (1) | 2024.03.18 |
[Python] 연관분석 실습 _ 영화 콘텐츠 기반 필터링 추천 시스템 (1) | 2024.03.15 |
[Python] Pandas 실습 _ 카카오 검색 API 데이터 가져오기 (0) | 2024.03.15 |