[업무 지식]/Machine learning
[선형회귀] 회귀분석
에디터 윤슬
2024. 11. 18. 20:42
선형회귀 함수 정의
# 회귀분석 함수
def get_linear_regression(X, y, n_components = 1):
# 훈련 및 테스트 데이터 분리
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from sklearn.decomposition import PCA
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# PCA 적용
pca = PCA(n_components=n_components) # n_components: 축소할 차원 수
X_pca = pca.fit_transform(X_scaled)
X_train, X_test, y_train, y_test = train_test_split(X_pca, y, test_size=0.2, random_state=42)
model_lr = LinearRegression()
model_lr.fit(X_train, y_train)
# 모델 예측
y_pred_lr = model_lr.predict(X_test)
# 정확도 측정
print('train 정확도:', model_lr.score(X_train, y_train))
# 정확도 측정
print('test 정확도:', model_lr.score(X_test, y_test))
# 산점도와 회귀선 그리기
plt.figure(figsize=(10, 6))
sns.regplot(x=X_test, y=y_test, scatter_kws={'alpha':0.6}, line_kws={'color':'red'})
plt.title("Scatter Plot with Regression Line")
plt.xlabel("X (Independent Variable)")
plt.ylabel("y (Dependent Variable)")
plt.show()
# # 모든 변수의 회귀선 그리기
# for i in range(X.shape[1]):
# plt.figure(figsize=(10, 6))
# sns.regplot(x=X_scaled[:, i], y=y, scatter_kws={'alpha': 0.6}, line_kws={'color': 'red'})
# plt.title(f"Scatter Plot with Regression Line (Feature {i+1})")
# plt.xlabel(f"Feature {i+1}")
# plt.ylabel("y (Dependent Variable)")
# plt.show()
# 실제 값 vs 예측 값과 잔차 표시
plt.figure(figsize=(10, 6))
# 산점도: 실제 값 vs 예측 값
sns.scatterplot(x=y_test, y=y_pred_lr, alpha=0.6, label="Predicted vs Actual")
# 잔차를 선으로 연결
for i in range(len(y_test)):
plt.plot([y_test.iloc[i], y_test.iloc[i]], [y_test.iloc[i], y_pred_lr[i]], color='gray', alpha=0.5)
# 대각선(완벽한 예측선)
sns.lineplot(x=[y_test.min(), y_test.max()], y=[y_test.min(), y_test.max()], color='red', linestyle='--', label="Perfect Prediction")
plt.title('Actual vs Predicted Values with Residuals')
plt.xlabel('Actual Values (y_test)')
plt.ylabel('Predicted Values (y_pred)')
plt.legend()
plt.show()
# 평가 지표 계산
mse = mean_squared_error(y_test, y_pred_lr) # 평균 제곱 오차
mae = mean_absolute_error(y_test, y_pred_lr) # 평균 절대 오차
r2 = r2_score(y_test, y_pred_lr) # R^2 점수
# 평가 지표 출력
print(f"Mean Squared Error (MSE): {mse:.2f}")
print(f"Mean Absolute Error (MAE): {mae:.2f}")
print(f"R^2 Score: {r2:.2f}")
residuals = y_test - y_pred_lr
plt.figure(figsize=(10, 6))
sns.histplot(residuals, kde=True, bins=30, color='blue', alpha=0.7)
plt.axvline(x=0, color='red', linestyle='--', label="Zero Residual")
plt.title('Residual Distribution')
plt.xlabel('Residuals')
plt.ylabel('Frequency')
plt.legend()
plt.show()
# Z-score 이상치 제거
def get_outlier_zscore(df):
col = ['amount']
zscore_cnt = {}
from scipy import stats
for column in col:
mean = df[column].mean()
std = df[column].std()
z_scores = (df[column] - mean) / std
abs_z_scores = np.abs(z_scores)
threshold = 3
outlier = abs_z_scores > threshold
inlier = abs_z_scores <= threshold
outlier_cnt = df[outlier].shape[0]
zscore_cnt[column] = outlier_cnt
df = df.loc[inlier]
print('컬럼별 이상치 갯수:', zscore_cnt)
return df
# 독립변수, 종속변수 선언
df = customer_info.copy()
lr_df = get_outlier_zscore(df)
X = lr_df[['CLICK', 'SCROLL', 'SEARCH', 'ADD_TO_CART', 'ADD_PROMO',
'ITEM_DETAIL']]
# X['mean'] = (X.sum(axis=1) / X.columns.nunique()).round(2)
y = lr_df['amount']
# get_linear_regression(X[['mean']], y)
get_linear_regression(X, y)
train 정확도: 0.8189672490949147
test 정확도: 0.8170546090423936
Mean Squared Error (MSE): 7207851011240.83
Mean Absolute Error (MAE): 1576086.65
R^2 Score: 0.82
자주 쓰는 함수
- sklearn.linear_model.LinearRegression: 선형회귀 모델 클래스
- coef_: 회귀 계수
- intercept: 편향(bias)
- fit: 데이터 학습
- predict: 데이터 예측
선형회귀 실습
'tips' 데이터를 가지고 전체 금액(X)를 알면 받을 수 있는 팁(y)에 대한 회귀분석을 진행한다.
- seaborn 시각화 라이브러리 데이터셋 'tips'
tips_df = sns.load_dataset('tips')
tips_df.head(3)
- 전체 금액(total_bill)과 팁(tip)과의 선형성을 산점도로 확인한다
sns.scatterplot(data = tips_df, x = 'total_bill', y = 'tip')
- 종속변수(y), 독립변수(x) 설정
# X: total_bill -- X, 대문자
# y: tip
model_lr = LinearRegression()
X = tips_df[['total_bill']]
y = tips_df[['tip']]
model_lr.fit(X, y)
- 편향(w0), 회귀계수(w1) 설정
# y(tip) = w1 * x(total_bill) + w0
w1_tip = model_lr.coef_[0][0]
w0_tip = model_lr.intercept_[0]
print('y = {}x + {}'.format(w1_tip.round(2), w0_tip.round(2)))
y = 0.11x + 0.92
# 전체 결제금액이 1달러 오를때, 팁은 0.11달러 추가된다.
# 전체 결제금액이 100달러 오를때, 팁은 11달러 추가된다.
- 예측값 생성
y_true_tip = tips_df['tip']
y_pred_tip = model_lr.predict(tips_df[['total_bill']])
y_true_tip[:5]
y_pred_tip[:5]
- MSE, rsquare 설정
mean_squared_error(y_true_tip, y_pred_tip)
1.036019442011377
r2_score(y_true_tip, y_pred_tip)
0.45661658635167657
- 예측값 df에 추가
tips_df['pred'] = y_pred_tip
tips_df.head(3)
- 산점도와 라인플롯 시각화
sns.scatterplot(data = tips_df, x = 'total_bill', y = 'tip')
sns.lineplot(data = tips_df, x = 'total_bill', y = 'pred', color = 'red')
범주형 데이터 선형회귀
- 범주형 데이터 숫자로 인코딩
# female 0 , male 1
def get_sex(x):
if x == 'Female':
return 0
else:
return 1
- apply 함수 적용
tips_df['sex_en'] = tips_df['sex'].apply(get_sex)
tips_df.head(3)
- 모델 설계도 가져오기, 학습, 평가
model_lr2 = LinearRegrssion()
X = tips_df[['total_bill', 'sex_en']]
y = tips_df[['tip']]
model_lr2.fit(X, y)
- 예측
y_pred_tip2 = model_lr2.predict(X)
y_pred_tip2[:5]
- MSE, Rsquare 확인
# 단순선형회귀 mse: X변수가 전체 금액
# 다중선형회귀 mse: X변수가 전체 금액, 성별
print('단순선형회귀', mean_squared_error(y_true_tip, y_pred_tip))
print('다중선형회귀', mean_squared_error(y_true_tip, y_pred_tip2))
단순선형회귀 1.036019442011377
다중선형회귀 1.0358604137213614
print('단순선형회귀', r2_score(y_true_tip, y_pred_tip))
print('다중선형회귀', r2_score(y_true_tip, y_pred_tip2))
단순선형회귀 0.45661658635167657
다중선형회귀 0.45669999534149974