데이터 분석/ADP 자격증 공부

(파이썬 한권으로 끝내기) 모의고사 제1회 소스코드, 샘플 데이터

나르시스트 2026. 4. 6. 21:25

avocado.csv
1.90MB
student_data.csv
0.01MB

 

<머신러닝>

(1) 시각화 포함 탐색적 자료분석을 시행하시오(EDA)

import pandas as pd
import numpy as np
import scipy.stats as stats

import matplotlib.pyplot as plt
import seaborn as sns

df = pd.read_csv('data/student_data.csv')
print(df)

plt.bar(df['grade'].value_counts().index, df['grade'].value_counts().values)
plt.show()

print(stats.shapiro(df['grade']))

df_cor = df.corr(method='pearson')
sns.heatmap(df_cor, xticklabels=df_cor.columns, yticklabels=df_cor.columns, cmap='RdBu_r', annot=True, linewidth=3)
plt.show()

→ 정규분포 형태로 보이지만,

→ Shapiro 결과는 p-value가 0.05 이하이므로, 정규성을 띄고 있다고 보기 어려움
→ 해당 종속변수 값이 정규성을 띄고 다양한 값이 있으므로, 다중 분류 보다는 회귀분석이 좋을 것으로 판단

  • 결측치 존재 여부 확인 – 결측치가 1% 초과일 때, 결측치 대체 고려
  • 종속변수, 독립변수 데이터 타입 확인
    → object 타입은 0 또는 1, get_dummies로 변환
  • 종속변수, 독립변수 상관관계 설명
    → 종속변수 grade와의 상관계수를 확인해봤을때, 수치형 변수와는 큰 상관성이 없음
  • 독립변수 상관관계 설명
    → 다중공선성을 걱정할 만큼(0.9 이상) 독립변수끼리의 상관성이 큰 변수는 보이지 않음
    → G1, G2 관계는 서로 높으므로 주의할 필요가 있음
  • 기타
    → 독립변수 중 school의 경우 비대칭성이 있으므로 주의해야 함

(2) 결측치를 식별, 예측하는 두 가지 방법을 쓰고, 이를 선택한 이유를 설명하시오.

※ 한 행이 전부 결측치인 경우는 삭제하는 편이 나을지도(?)

  • 단순 대치법: 수치형 변수라면, 각 컬럼의 평균이나 중앙값을, 명목/범주형 변수라면 최빈값
  • KNN을 이용한 결측치 대체 – 수치형 변수만 가능
df.isnull().sum()
df[df.isna().any(axis=1)]

→ famrel, freetime, health 변수에서 결측치 발생

from sklearn.impute import KNNImputer

KNN_data = df.drop(columns=['school', 'sex', 'paid', 'activities'])  # 결측치가 있는 수치형 데이터만 추출

imputer = KNNImputer()
df_filled = imputer.fit_transform(KNN_data)
df_filled = pd.DataFrame(df_filled, columns=KNN_data.columns)
df[KNN_data.columns] = df_filled

df.isna().sum()

(3) 범주형 변수 인코딩이 필요한 경우를 식별하고, 변환을 적용하시오. 이를 선택한 이유를 설명하시오.

→ 이산형 변수(school, sex, paid, activities) boolean 타입으로 변환

df = pd.get_dummies(data=df, columns=['school', 'sex', 'paid', 'activities'], drop_first=True)
df.info()

(4) 데이터 분할 방법을 2가지 쓰고, 적절한 데이터 분할을 적용하시오. 이를 선택한 이유를 설명하시오.

  • 랜덤 분할: 특정 비율로 train, test 데이터 세트로 나누어 무작위로 분할 → 연속형 변수
  • 층화 추출 기법: 종속변수가 범주형 변수인 경우에는 종속변수의 클래스 비율을 기준으로 train, test 데이터를 분할
from sklearn.model_selection import train_test_split

X = df.drop('grade', axis=1)
y = df['grade']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=2022)
print(X_train.shape)
print(X_test.shape)
print(y_train.shape)
print(y_test.shape)

(5) svm, xgboost, randomforest 3개 알고리즘의 공통점을 쓰고, 학생 성적 예측 분석에 적합한 알고리즘인지 설명하시오.

  • 회귀분석, 분류분석 모두 사용 가능
  • 범주형 변수를 독립변수로 사용할 수 없어 변환 필요
  • 과대/과소 적합을 피하기 위해 매개변수 설정 필요
  • 회귀분석에서 다중공선성 문제를 해결할 수 있음

→ 해당 데이터는 종속변수 값이 연속형이므로 회귀분석이 적합함
→ 다중공선성 문제를 해결하는 것이 중요한데, svm-커널트릭, xgboost, randomforest-트리모델을 통해 해결

→ 그러므로, 회귀분석을 지원하는 위 3가지 알고리즘은 연속형 변수를 예측하기에 적합하다

(6) 세 가지 모델 모두 모델링해보고 가장 적합한 알고리즘을 선택하시오. 이를 선택한 이유와 모델의 한계점, 보완 가능한 부분을 설명하고, 현업에서 주의할 점 등에 대해 기술하시오.

from sklearn.svm import SVR
from sklearn.ensemble import RandomForestRegressor
from xgboost import XGBRegressor
from sklearn.metrics import mean_squared_error
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

scaler = StandardScaler()
X_train_scaled = pd.DataFrame(scaler.fit_transform(X_train), columns=X_train.columns)
X_test_scaled = pd.DataFrame(scaler.fit_transform(X_test), columns=X_test.columns)

from sklearn.model_selection import GridSearchCV

### 6.1
param_grid = [{'C': [0.1, 1, 10, 100], 'gamma': [0.001, 0.01, 0.1, 1, 10]}]

grid_svm = GridSearchCV(SVR(), param_grid=param_grid, cv=5)
grid_svm.fit(X_train_scaled, y_train)

result = pd.DataFrame(grid_svm.cv_results_['params'])
result['mean_test_score'] = grid_svm.cv_results_['mean_test_score']
print(result.sort_values(by='mean_test_score', ascending=False))
#grid_svm.best_params_

svr = SVR(C=10, gamma=0.010)
svr.fit(X_train_scaled, y_train)
print('R2: ', svr.score(X_test_scaled, y_test))
print('RMSE: ', np.sqrt(mean_squared_error(y_test, svr.predict(X_test_scaled))))

### 6.2
rf_grid = [{'max_depth': [2,4,6,8,10], 'min_samples_split': [2,4,6,8,10]}]
rf = GridSearchCV(RandomForestRegressor(n_estimators=100), param_grid=rf_grid, cv=5)
rf.fit(X_train, y_train)
#print(rf.best_params_)
print('R2: ', rf.score(X_test, y_test))
print('RMSE: ', np.sqrt(mean_squared_error(y_test, rf.predict(X_test))))

### 6.3
xgb_grid = [{'max_depth': [2,4,6,8,10]}]
xgb = GridSearchCV(XGBRegressor(n_estimators=1000), param_grid=xgb_grid, cv=5)
xgb.fit(X_train, y_train)
print('R2: ', xgb.score(X_test, y_test))
print('RMSE: ', np.sqrt(mean_squared_error(y_test, xgb.predict(X_test))))

→ RandomForest 모델이 가장 정확도가 높고, RMSE 값이 낮으므로 예측 분석력이 가장 좋다고 볼 수 있음

from xgboost import plot_importance

plot_importance(xgb.best_estimator_)
plt.show()

 

→ (임의로 샘플 데이터를 수정해서 그런지 결과가 이상한거 같지만) 위에서부터 최종 성적에 영향을 많이 주는 변수이다
→ G1, G2 변수 또한 성적이기 때문에 최종 성적에 영향을 미치는 변수라고 보기는 어려울 수 있음
→ 만약 학생 성적에 영향을 미치는 변수를 찾고 싶다면, 성적과 관련이 있는 다른 변수를 추가해야 함

<통계분석> – 제21회 기출문제

데이터: 연속형 독립변수 1개, 종속변수 1개로 구성된 보스턴 집값 데이터세트

1. 회귀분석

(1) 데이터를 8:2로 분할하고 선형 회귀를 적용하시오. 결정계수와 rmse를 구하시오.

import pandas as pd
import numpy as np
import mglearn

from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.metrics import mean_squared_error

X, y = mglearn.datasets.load_extended_boston()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

### 1. 선형 회귀
lr = LinearRegression()
lr.fit(X_train, y_train)

print('선형 회귀 결정계수: ', lr.score(X_test, y_test))
print('선형 회귀 RMSE: ', np.sqrt(mean_squared_error(y_test, lr.predict(X_test))))

(2) 데이터를 8:2로 분할하고 릿지 회귀를 적용하시오. alpha 값을 0부터 1까지 0.1 단위로 모두 탐색해서 결정계수가 가장 높을 때의 알파를 찾고, 해당 알파로 다시 모델을 학습해서 결정계수와 rmse를 계산하시오.

### 2. 릿지
alpha = np.arange(0, 1.1, 0.1)

ridge = Ridge()  # normalize=True는 이제 안녕~
ridge_model = GridSearchCV(ridge, {'alpha': alpha})
ridge_model.fit(X_train, y_train)

print(ridge_model.best_params_)
print('선형 회귀 결정계수: ', ridge_model.score(X_test, y_test))
print('선형 회귀 RMSE: ', np.sqrt(mean_squared_error(y_test, ridge_model.predict(X_test))))

(3) 데이터를 8:2로 분할하고 라쏘 회귀를 적용하시오. alpha 값을 0부터 1까지 0.1 단위로 모두 탐색해서 결정계수가 가장 높을 때의 알파를 찾고, 해당 알파로 다시 모델을 학습해서 결정계수와 rmse를 계산하시오.

### 3. 라쏘
lasso = Lasso()
lasso_model = GridSearchCV(lasso, {'alpha': alpha})
lasso_model.fit(X_train, y_train)

print(lasso_model.best_params_)
print('라쏘 회귀 결정계수: ', lasso_model.best_estimator_.score(X_test, y_test))
print('라쏘 회귀 RMSE: ', np.sqrt(mean_squared_error(y_test, lasso_model.best_estimator_.predict(X_test))))

→ alpha가 0.1일 때, Ridge 회귀의 예측력이 좋다는 것을 알 수 있음

2. 다항 회귀분석 시각화

단순 선형 회귀를 다항 회귀로 3차까지 적용시켜 계수를 구하고, 3차항을 적용한 모델의 스캐터 플롯과 기울기 선을 그리시오.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures

m = 100
X = 6 * np.random.rand(m, 1) - 3
y = 3 * X**3 + X**2 + 2*X + 2 + np.random.randn(m, 1)  # 노이즈 포함

line = np.linspace(-3, 3, 100, endpoint=False).reshape(-1, 1)

## x**3 까지 3차항을 적용시켜야 함
poly = PolynomialFeatures(degree=3, include_bias=False)  # 다항식 특성을 생성
poly.fit(X)  # X 데이터에 맞춰 다항식의 특성을 학습

## 학습된 다항식 특성을 사용하여 X를 변환 - 다항식 회귀 모델을 훈련하고, 주어진 데이터에 대한 예측을 수행
X_poly = poly.transform(X)
#line_poly = poly.transform(line)
reg = LinearRegression().fit(X_poly, y)

plt.plot(line, reg.predict(line_poly), color='r', linewidth=3)
plt.plot(X, y, 'o', color='g', alpha=0.5)
plt.show()

3. ANOVA 분석

변수 3개(하나는 연속형 변수 / 나머지 두 개는 범주형 연속변수)의 이원분산분석을 수행하고 통계표를 작성하시오.

  • 귀무가설(H0): region 종류에 따른 AveragePrice 차이는 존재하지 않는다
  • 대립가설(H1): region 종류에 따른 AveragePrice 차이는 존재한다
  • 귀무가설(H0): type 종류에 따른 AveragePrice 차이는 존재하지 않는다
  • 대립가설(H1): type 종류에 따른 AveragePrice 차이는 존재한다
import pandas as pd
import numpy as np

from statsmodels.formula.api import ols
from statsmodels.stats.anova import anova_lm

avocado = pd.read_csv('data/avocado.csv')
avocado = avocado[['AveragePrice', 'type', 'region']]
avocado = avocado[(avocado['region'] == 'Orlando') | (avocado['region'] == 'Boston') | (avocado['region'] == 'Chicago')].reset_index(drop=True)
print(avocado)

AveragePrice = avocado['AveragePrice']
avocado_type = avocado['type']
region = avocado['region']

formula = 'AveragePrice ~C(avocado_type)*C(region)'
model = ols(formula, avocado).fit()
aov_table = anova_lm(model, typ=2)
print(aov_table)

→ 주효과 검정 모두 유의하기 때문에 각 변수의 종류에 따른 AveragePrice의 차이가 있다고 할 수 있음
→ 맨 마지막 행의 p-value 값을 통해 상호작용 효과가 있다고 할 수 있음

from statsmodels.graphics.factorplots import interaction_plot
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(6,6))
fig = interaction_plot(avocado_type, region, AveragePrice, colors=['red', 'blue', 'black'], markers=['D', '^', 'o'], ms=10, ax=ax)
plt.show()

→ 상호작용 효과와 각 변수별 차이가 확실히 나타남을 알 수 있음
→ 특히 orlando에서는 다른 지역보다 conventional 대비 organic의 선호도가 높음을 알 수 있음