Bootcamp/KT aivle school

4.3 kt 에이블 스쿨 7일차 - 머신러닝, 코딩테스트 풀이

Nyamggoon 2025. 4. 3. 16:54

이제 데이터 불러오기, 탐색적 데이터 분석, 전처리, 시각화 및 분석을 끝마치고 머신러닝을 배웠습니다.

사실 이거 하루만에 배우기에는 힘든 내용이라 주요 모델에는 어떤게 있나 정도만 살펴보고, 상세 파라미터나 모델 개선 등등은 직접 알아가면서 해봐야 할 것 같습니다. 이전에 들었던 내용들이었기에 망정이지, 아니었으면 따라가기 좀 벅찰 것 같네요 ㅋㅋㅋ

 

필수 라이브러리 모음

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import sklearn

 

데이터 분석

df.head() 
df.tail()
df.info()
df.describe() # 기술통계
df.corr(numeric_only=True) # 상관계수

 

데이터 준비

df.isnull().sum() # 결측값 확인

# 시계열 데이터에서 주로 쓰는 결측값 채우기
df.ffill(inplace=True) # 바로 이전 값들로 결측값 채우기
df.bfill(inplace=True) # 바로 이후 값들로 결측값 채우기

# 변수 제거 : 의미없다고 생각되는 변수들 제거
drop_cols = ['col1', 'col2' ...]
df.drop(columns=drop_cols, inplace=True)

# x, y 데이터 분리
target = 'col'

x = df.drop(target, axis=1) # axis=1 을 해줘야 열을 삭제함
y = df.loc[: , target]

# train, test 데이터셋 분리
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=1)

모델링

Regression model : 종속변수가 수치형 일 때 + 오차를 줄이는 것이 목표

-종류 : LinearRegression, KNeighborsRegressor, DecisionTreeRegressor, RandomForestRegressor, XGBRegressor

-평가지표 : SSE, MSE, RMSE, MAE, MAPE, R^2(결정계수), Adjusted R^2 (조정된 결정계수)

제곱하고 루트를 씌우는 RMSE, 절댓값으로 계산해주는 MAE

 

R^2 = 1 - SSE(Sum Squared Error) / SST(Sum Squared Total) = SSR(sum of squares regression) / SST

전체 오차 중에서 회귀식이 개선한 비율

그림보고 참고하세요 근데 내가 정리하려고 만든거임 못그려도 이해바랍니다

+조정된 결정계수는 독립변수의 수를 고려하여 결정계수를 조정해줌. 독립변수의 수가 많으면 당연하게도 오차 정도는 줄어들 것이고, 결정계수는 좋게 나올 확률이 올라가기에. 그래서, 의미있는 독립변수가 추가될 때 조정된 결정계수는 높게 나타남.

 

Classifier model : 종속변수가 범주형 일 때 + 정확도를 높이는 것이 목표

-종류 : DecisionTreeClassifier, KNeighborsClassifier, LogisticRegression, RandomForestClassifier, XGBClassifier

-평가지표 : Accuracy, Precision, Recall, F1-Score // Precision과 Recall 은 trade-off 관계

# LinearRegression

from sklearn.linear_model import LinearRegression

from sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_squared_error
from sklearn.metrics import root_mean_squared_error
from sklearn.metrics import mean_absolute_percentage_error
from sklearn.metrics import r2_score

# 선언!
model = LinearRegression()

# 학습!
model.fit(x_train, y_train)

# 예측!
y_pred = model.predict(x_test)

# 평가!
mean_absolute_error(y_test, y_pred)
mean_squared_error(y_test, y_pred)
root_mean_squared_error(y_test, y_pred)
mean_absolute_percentage_error(y_test, y_pred)
r2_score(y_test, y_pred)
# Classification
from sklearn.tree import DecisionTreeClassifier

from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
from sklearn.metrics import classification_report

model = DecisionTreeClassifier(random_state=n) # random_state로 결과를 항상 일정하게!
model.fit(x_train, y_train)
y_pred = model.predict(x_test)



# 성능 평가
confusion_matrix(y_test, y_pred) # 혼동 행렬
sns.heatmap(confusion_matrix(y_test, y_pred)) # annot, cmap, cbar 파라미터 조정 가능)
accuracy_score(y_test, y_pred) # Accuracy
precision_score(y_test, y_pred, average=None) # Precision, 0과 1꺼 둘다 나옴 average=None 하면
recall_score(y_test, y_pred, average=None)
f1_score(y_test, y_pred, average=None)

print(classification_report(y_test, y_pred)) # classification_report로 한 번에 다 출력! 굳

 

성능 개선 등등..

# MinMax 정규화 : KNN을 위해 필요한 전처리
from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
scaler.fit(x_train)
x_train = scaler.transform(x_train)
x_test = scaler.transform(x_test)

#GridSearchCV, RandomSearchCV로 최적의 파라미터값 찾아서 학습시키기

param = {'parameter': range(2, 11)}

# param에 넣을 값들은 보통
# knn에서는 n_neighbors
# DecisionTree, RandomForest에서는 max_depth



model = GridSearchCV(model,
                     param,
                     cv=5)


model_knn.fit(x_train_s, y_train)


model.best_params_
model.best_score_

model.feature_importances_ # 변수 중요도 볼 수 있대..

 

하루만에 다 나가서 어떤 파라미터가 있는지 그런 것들 좀 더 살펴보고 싶은데, 이건 주말에 해야겠다..

생각보다 내용이 방대해서 정리할 시간이 잘 없다. 코딩테스트, AICE Asso, COS Pro 1급, 정보처리기사까지 다 준비하려고 하니까 머리가 터질 것 같다. 거기다 공모전에 미니프로젝트, 빅프로젝트까지? 와우 6개월 헬파티 시작 파이팅

 


코딩테스트 입문

1. 최소공배수 구해서 기약분수 덧셈 출력하기

class Solution {
    public int[] solution(int numer1, int denom1, int numer2, int denom2) {
            for (int a=2; a <= Math.min(denom1, denom2); a++) {
                for( int b=2; b <= Math.min(denom1, denom2); b++) {
                    if ( (denom1 * a) == (denom2 * b) ) {
                        numer1 = numer1 * a;
                        denom1 = denom1 * a;
                        numer2 = numer2 * b;
                        denom2 = denom2 * b;
                } else {}
            }
        }           
          int numer3 = numer1 + numer2;
          int denom3 = denom1 + denom2;
          int answer[] = {numer3, denom3};
          return answer;

    }
}

왜 인지 if 문을 도는데 연산이 하나도 처리가 안됐다.. 구조적으로 문제가 참 많다고 한다..ㅜ

a랑 b가 1일 때도 통과하니까 2로 바꿔줬는데 그것도 안되는 것 같고, denom1 = 2, denom2 = 4 일 때는 같아야 하니까 등호도 넣어줬는데 뭔가 문제가 많은 것 같다. gpt 한테 물어보고 검색해보니 유클리드 호제법이라는 게 있는데 for문을 그대로 활용하고 싶어서..

class Solution {
    public int[] solution(int numer1, int denom1, int numer2, int denom2) {

        boolean converted = false;
        for (int a = 1; a <= 1000 && !converted; a++) {
            for (int b = 1; b <= 1000; b++) {
                if (denom1 * a == denom2 * b) {
                    numer1 *= a;
                    denom1 *= a;
                    numer2 *= b;
                    denom2 *= b;
                    converted = true;
                    break;
                }
            }
        }


        int numer3 = numer1 + numer2;
        int denom3 = denom1; 

        int gcd = gcd(numer3, denom3);
        numer3 /= gcd;
        denom3 /= gcd;

        int[] answer = {numer3, denom3};
        return answer;
    }

    private int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }
}

이렇게 했다. 결국 gcd() 를 쓰는거여서 다른 풀이를 찾아봤다.

class Solution {
    public int[] solution(int numer1, int denom1, int numer2, int denom2) {
        int[] answer = new int[2];

        int denom3 = denom1 * denom2;

        int numer3 = numer1 * denom2 + numer2 * denom1;

        int max = 1;
        for (int i = 1; i <= numer3 && i <= denom3; i++) {
            if (numer3 % i == 0 && denom3 % i == 0) {
                max = i;
            }
        }

        answer[0] = numer3 / max;
        answer[1] = denom3 / max;

        return answer;
    }
}

냅다 다 곱하고 더해서, 이후 기약분수를 찾기위해 공통 값으로 나눠주는 것. 이게 유클리드 호제법이라고 한다.

 

유클리드 호제법

유클리드 호제법(-互除法, Euclidean algorithm) 또는 유클리드 알고리즘은 2개의 자연수 또는 정식(整式)의 최대공약수를 구하는 알고리즘의 하나이다. 호제법이란 말은 두 수가 서로(互) 상대방 수를 나누어(除)서 결국 원하는 수를 얻는 알고리즘을 나타낸다. - 위키백과

두 수가 서로 상대방 수를 나누어 원하는 수를 얻는 알고리즘을 호제법이라고 한대요.

식으로 살펴 보자면 a = 56, b = 21 일 때, (56, 21) = (21, 14) = (14, 7) = (7, 0) => 56과 21의 최대공약수는 7

 

유클리드 호제법 이해 후, GPT 한테 출력해달라고 한 코드. 호제법을 공부하니까 해당 코드가 이해가 되네요 굳

# 유클리드 호제법

# 방법1 재귀방식
private int gcd(int a, int b) {
	return b == 0 ? a : gcd(b, a % b);
    }
    

# 방법2 반복문 방식
int gcd(int a, int b) {
    while (b != 0) {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}

# 전체코드
class Solution {
    public int[] solution(int numer1, int denom1, int numer2, int denom2) {
        int[] answer = new int[2];

        // 1. 통분
        int commonDenom = denom1 * denom2;
        int commonNumer = numer1 * denom2 + numer2 * denom1;

        // 2. 최대공약수 구하기
        int gcd = gcd(commonNumer, commonDenom);

        // 3. 약분
        answer[0] = commonNumer / gcd;
        answer[1] = commonDenom / gcd;

        return answer;
    }

    // 유클리드 호제법 사용
    private int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }
}

 

2. 정수 배열 numbers가 매개변수로 주어집니다. numbers의 각 원소에 두배한 원소를 가진 배열을 return하도록 solution 함수를 완성해주세요.

class Solution {
    public int[] solution(int[] numbers) {
        int[] answer = new int[numbers.length];
        for (int i=0; i < numbers.length; i++) {
            answer[i] = numbers[i] * 2;
        }
        return answer;
    }
}

혼자 힘으로 거의다 해결 했는데, java에서는 array 를 선언할 때 크기를 정해야 한다는 걸 까먹고 있었다.

gpt의 도움 덕분에 new int[numbers.length] 힌트를 얻어서 해결! 배열 선언할 때는 길이를 지정해주기

 

이제 막히는 문제 있으면 20분? 30분 정도 고민해보다가 안되면 넘어가거나 힌트 받아야지 시간이 없다

하루에 10문제 풀려고 했는데 오늘은 두문제가 땡이다. 사실 코딩마스터스 한 문제 풀었으니까 사실상 세문제.

그냥 if 문 활용한 간단한 문제였다. 근데, 실행 방식이 프로그래머스랑 달라서 그거 때문에 애를 먹었다.

내일도 파이팅!