# 훈련 데이터와 테스트 데이터 분리
from sklearn.model_selection import train_test_split
# 입력 변수(X)와 타겟 변수(y) 분리
X = df_no_outliers.drop(columns=['MEDV']) # 'target'은 목표 변수(예: CRIM과 무관한 타겟 변수)
y = df_no_outliers['MEDV'] # 타겟 변수 이름을 지정
# 훈련 데이터와 테스트 데이터로 분리 (80% 훈련, 20% 테스트)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 결과 확인
print("훈련 데이터 크기:", X_train.shape)
print("테스트 데이터 크기:", X_test.shape)
4.2. 모델 학습
4.2.1. 선형 회귀형 모델
# 선형 회귀형 모델 생성, 학습
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
# 선형 회귀 모델 생성 및 학습
model = LinearRegression()
model.fit(X_train, y_train)
# 예측
y_pred = model.predict(X_test)
4.2.2. 의사결정나무
# 의사결정나무 회귀 모델 생성 및 학습
from sklearn.tree import DecisionTreeRegressor
# 의사결정 회귀 나무 모델 생성 및 학습
tree_model = DecisionTreeRegressor()
tree_model.fit(X_train, y_train)
# 예측
y_pred = tree_model.predict(X_test)
# DecisionTreeRegressor의 하이퍼 파라미터
tree_model = DecisionTreeRegressor(
max_depth=5, # 개별 트리의 최대 길이를 5로 설정
min_samples_split=10) # 노드를 분할 시 필요한 최소 샘플 개수 10으로 지정
4.2.3. 랜덤 포레스트
# 랜덤 포레스트 모델 생성 및 학습
from sklearn.ensemble import RandomForestRegressor
# 랜덤 포레스트 회귀 모델 생성 및 학습
forest_model = RandomForestRegressor(
n_estimators=100, random_state=42
)
forest_model.fit(X_train, y_train)
# 예측
y_pred = forest_model.predict(X_test)
# RandomForestRegressor의 하이퍼 파라미터
forest_model = RandomForestRegressor(
n_estimators=200, # 생성할 나무 개수를 200으로 설정
max_depth=10, # 개별 트리의 최대 길이를 10으로 설정
min_samples_split=5, # 노드를 분할하기 위한 최소 샘플 수를 5개로 설정
random_state=42 # 모델의 결과를 재현 가능하도록 랜덤 시드를 설정함(생략 가능)
)
## n_estimators : 랜덤 포레스트에서 생성할 나무의 개수 지정 (기본값 == 100)
## max_depth: 개별 트리의 최대 깊이.
## min_samples_split: 노드를 분할하기 위한 최소 샘플 수.
## random_state : 모델의 결과를 재현 가능하게 하기 위해 랜덤 시드를 설정함 (필요 시, 생략 가능)
5. 모델 성능 평가
선형 회귀형 모델 평가
📚 선형 회귀형 모델 평가 결과 분석
오차의 평균(높을수록 오차가 많이 일어난다는 것을 의미)
Mean Squared Error: 56.675544148847685
Mean Squared Error는 제곱근의 평균이에요 대충 56에 루트를 씌운 만큼의 차이가 발생한다는 거예요
숫자가 적을수록 오차가 적다는 것을 의미해요
R^2 Score: 0.006371530245328549
R^2는 변동성을 뜻해요
범위가 0~1 사이에 있는 값이에요
1에 가까울수록 예측을 잘한다는 뜻이고, 0에 가까울수록 예측을 못한다는 뜻이에요 :)
의사결정나무 회귀 모델 평가
# 의사결정나무 회귀 모델 평가
## 선형 회귀형과 비교하였을 때 mse가 더 높은 것을 보아 선형 회귀형 모델의 성능이 좋아보임
from sklearn.metrics import mean_squared_error, r2_score
# 성능 평가
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"Mean Squared Error: {mse}")
print(f"R2 Score: {r2}")
📚 의사결정나무 회귀 모델 평가 결과 분석
Mean Squared Error: 68.93506172839507
MSE가 선형 회귀형 보다 높게 나왔기 때문에 선형 회귀형 보단 성능이 낮아 보인다고 판단함
R2 Score: -0.20856078095584807
1과 가까울수록 예측을 잘한다는 것을 의미하지만, 음수값이 도출됨
랜덤 포레스트 모델 평가
# 랜덤 포레스트 모델 평가
## 다른 모델들과 비교했을 시, mse 지수가 가장 낮게 나옴
## 따라서, 가장 성능이 좋은 모델은 랜덤 포레스트라고 판단함
from sklearn.metrics import mean_squared_error, r2_score
# 성능 평가
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"Mean Squared Error: {mse}")
print(f"R2 Score: {r2}")
📚 의사결정나무 회귀 모델 평가 결과 분석
Mean Squared Error: 44.79970725925926
MSE가 앞선 2개의 모델 중 가장 낮게 나옴
R2 Score: 0.2145772001312125
R^2 Score도 마찬가지로 가장 높게 나옴
요약
결측치가 포함된 행을 삭제하면 데이터 양이 줄어들어 이상치를 찾기 어렵다.
CRIM, NOX, AGE의 적은 데이터 양만으로는 MEDV(주택 가격 예측)를 알기 힘듦
모델을 학습 시킬 때 데이터 양이 많을수록 R^2 Score은 1에 가까워지고, MAE, MSE들의 값은 작아질 것으로 추정됨
# 결측값이 포함된 행 제거
df_dropped_rows = df.dropna()
# 결측값이 포함된 열 제거
df_dropped_cols = df.dropna(axis=1)
행 제거
= df.dropna()
열 제거
= df.dropna(axis=1)
1.1.2. 대체
정의 : 결측값을 특정 값으로 대체
1.1.2.1. 결측값을 0으로 대체
# 결측값을 0으로 대체
df_filled = df.fillna(0)
0으로 대체
= df.fillna(0)
1.1.2.2. 결측값을 각 열의 평균값으로 대체
# 결측값을 각 열의 평균값으로 대체
df_filled_mean = df.fillna(df.mean())
평균값
= df.fillna(df.mean())
1.1.2.3. 결측값을 각 열의 중간값으로 대체
# 결측값을 각 열의 중간값으로 대체
df_filled_median = df.fillna(df.median())
중간값
= df.fillna(df.median())
1.1.2.4. 결측값을 각 열의 최빈값으로 대체
# 결측값을 각 열의 최빈값으로 대체
df_filled_mode = df.fillna(df.mode().iloc[0])
최빈값
= df.fillna(df.mode().iloc[0])
1.1.3. 예측
정의 : 머신러닝 모델을 사용하여 결측값을 예측
from sklearn.linear_model import LinearRegression
# 결측값이 있는 열과 없는 열 분리
df_with_na = df[df['column_with_na'].isnull()]
df_without_na = df[df['column_with_na'].notnull()]
# 회귀 모델 학습
model = LinearRegression()
model.fit(df_without_na[['feature1', 'feature2']], df_without_na['column_with_na'])
# 결측값 예측
predicted_values = model.predict(df_with_na[['feature1', 'feature2']])
# 예측된 값으로 결측값 대체
df.loc[df['column_with_na'].isnull(), 'column_with_na'] = predicted_values
# 이상치를 평균값으로 대체
mean_value = df['column_name'].mean()
df['column_name'] = df['column_name'].apply(
lambda x: mean_value if x < lower_bound or x > upper_bound else x)
from sklearn.feature_selection import SelectKBest, f_classif
# 특징 선택 (상위 5개의 특징 선택)
selector = SelectKBest(score_func=f_classif, k=5)
X_new = selector.fit_transform(X, y)
# 선택된 특징의 인덱스
selected_features = selector.get_support(indices=True)
print(selected_features)
Pandas와 Scikit-learn을 사용하여 특징 선택을 수행
7.3. 특징 추출 방법
# 두 열의 곱을 새로운 특징으로 추가
df['new_feature'] = df['feature1'] * df['feature2']
# 두 열의 합을 새로운 특징으로 추가
df['new_feature_sum'] = df['feature1'] + df['feature2']