티스토리 뷰

SQL 코드카타

Q165. Population Census

1. 문제 링크: https://www.hackerrank.com/challenges/asian-population/problem

2. 정답 코드:

SELECT SUM(c.Population)
FROM CITY as c
JOIN COUNTRY as co
  ON c.CountryCode = co.Code
WHERE co.Continent = 'Asia'

Python 코드카타 (https://github.com/heeso0908/codekata.git)

Q55. 카드 뭉치

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/159994

2. 정답 코드:

def solution(cards1, cards2, goal):
    idx1 = 0
    idx2 = 0
    
    for word in goal:
        if idx1 < len(cards1) and cards1[idx1] == word:
            idx1 += 1
        elif idx2 < len(cards2) and cards2[idx2] == word:
            idx2 += 1
        else:
            return "No"
    return "Yes"
처음에는 cards1과 cards2의 단어 조합으로 goal과 동일하게 만들 수 있는지를 확인하려고 했는데,
반대로 goal에 있는 단어들을 for 문을 사용해서 분리하고,
각각의 단어들이 cards1, cards2에 앞 순서로 있는지를 보는 코드를 작성해야 한다!

여기서 주의할 점!
1) idx1 <= len(cards1)이 아닌 idx1 < len(cards1) 로 해줘야 함
2) cards1과 cards2에서 각각의 인덱스를 뽑아서 goal에서의 word와 같을 때 +=1
3) if문에서 리스트의 길이를 먼저 체크하여, 인덱스가 범위를 벗어나는 즉시 뒷부분의 비교 연산을 생략함으로써 런타임 에러(Index Error)를 방지

주어진 데이터를 순차적으로 비교하며 목표 값을 검증하는 알고리즘!

이 문제는 리스트의 인덱스 제어논리 연산의 우선순위를 학습하기에 매우 좋은 사례이다~!

 

1. 문제 분석 및 핵심 아이디어

이 문제의 핵심은 "두 개의 소스 리스트(cards1, cards2)에서 순서를 어기지 않고 단어를 하나씩 꺼내어 목표 리스트(goal)를 완성할 수 있는가?"를 판별하는 것!

  • 순차적 접근: 각 카드 뭉치에는 보이지 않는 '포인터(Pointer)'가 있다고 가정한다.
  • 그리디(Greedy) 탐색: goal에 필요한 단어가 나올 때마다, 두 뭉치의 맨 앞을 확인하여 일치하는 쪽의 포인터를 한 칸씩 뒤로 밀어준다.

2. 알고리즘 설계 및 구현

def solution(cards1, cards2, goal):
    # 각 리스트의 현재 위치를 추적할 인덱스 변수 선언
    idx1 = 0
    idx2 = 0
    
    for word in goal:
        # 조건 A: cards1에 남은 카드가 있고, 그 카드가 현재 찾는 단어인 경우
        if idx1 < len(cards1) and cards1[idx1] == word:
            idx1 += 1
            
        # 조건 B: cards2에 남은 카드가 있고, 그 카드가 현재 찾는 단어인 경우
        elif idx2 < len(cards2) and cards2[idx2] == word:
            idx2 += 1
            
        # 조건 C: 어느 쪽에서도 단어를 찾을 수 없는 경우 (순서 불일치)
        else:
            return "No"
            
    # 모든 단어를 순서대로 찾았다면 "Yes" 반환
    return "Yes"

 

 

3. 주요 학습 포인트

✅ 리스트 범위 초과(IndexError) 방지

코드에서 idx1 < len(cards1) 조건을 먼저 검사하는 것이 결정적!

파이썬의 and 연산은 앞의 조건이 거짓이면 뒤의 조건을 확인하지 않는 '단락 평가(Short-circuit evaluation)' 특성을 가집니다. 덕분에 리스트가 비어있을 때 발생할 수 있는 런타임 에러를 우아하게 방지할 수 있다!

 

✅ elif를 사용하는 이유

만약 if를 두 번 사용한다면, 한 단어가 두 카드 뭉치에 동시에 존재할 때 불필요한 중복 검사가 일어날 수 있다.

if-elif-else 구조를 통해 하나의 단어는 하나의 뭉치에서만 처리되도록 논리적 배타성을 확보하는 것이 중요하다!

 

4. 결론 및 정리

이 알고리즘은 전체 데이터를 한 번만 훑는 O(N)의 시간 복잡도를 가진다. 복잡한 자료구조 없이도 인덱스 변수 두 개만으로 효율적인 탐색이 가능하다는 점이 이 풀이의 장점!

실제 알고리즘 문제에서는 리스트의 범위를 체크하는 사소한 습관이 정답 여부를 결정짓는 경우가 많으니, 이번 기회에 확실히 익혀두자!


라이브 세션) 머신러닝 실습 8일차: 군집

1) 군집 평가지표

(1) Inertia(SSE): 가장 간단히 구할 수 있는 지표

각 데이터와 군집 중심 사이 거리의 제곱합 → 낮을수록 좋음

but, k가 커지면 항상 감소(군집이 많아지니까) → Elbow Point로 적정한 k값 선택하여 사용

 

(2) Silhouette Score: 가장 많이 사용

자기 군집 안에서는 얼마나 잘 뭉쳐있고, 다른 군집과는 얼마나 떨어져 있는가?

(범위: -1 ~ 1, 1에 가까울수록 좋음)

 

(3) DBI(Davies-Bouldin Index): 보조 검증

군집 간 거리 대비 군집 내 분산의 비율 → 낮을수록 좋음

군집 간 분리도가 중요할 때 사용

 

(4) CHI(Calinski-Harabasz Index): 통계적 분산 확인

군집 간 분산/군집 내 분산 → 높을수록 좋음

분산 기반 통계적 지표


2) K-Means Clustering ★가장 중요★ - 거리 기반 → 스케일링 필수

정답이 없는 비지도학습이기 때문에 데이터 누수를 덜 걱정해도 괜찮음 → train-test split 사용 X

  • n_clusters(k값) : 가장 중요한 하이퍼파라미터, Elbow/Silhouette/DBI/CH로 선택
  • init: 초기 중심 선택 방식, k-means++(기본값, 거의 항상 사용)
  • n_init: 서로 다른 초기값으로 몇 번 반복할지, 기본적으로 설정 되어 있음(auto)

3) DBSCAN - 밀도 기반 → 하이퍼파라미터 중요!

밀도 기반으로 알아서 k값 찾아주니까 설정할 필요가 없음

-1(노이즈) 나올 수 있음!

스케일링 해줘야 함

 

(1) eps: 이웃으로 인정할 거리 반경

너무 작으면 전부 noise, 너무 크면 하나의 군집

DBSCAN의 성능은 eps에 달려있다!

 

(2) min_samples: core point 기준

작으면 군집 많이 생기고, 크면 보수적으로 군집 생성됨

차원 수(feature 수=컬럼 수) * 2 정도로 시작 → PCA 등장 배경!(차원 수를 줄이면 2D, 3D 등으로 그려서 파악할 수 있으니까)


4) GMM: 타원형+군집이 겹치는 경우, 변수가 독립이 아니라 종속 관계에 있을 때(상관 관계 有)

  • n_components: Gaussian 개수(k값)
  • covariance_type: 기본값 사용하면 된다

5) 계층적 클러스터링(Hierarchical Clustering): 군집 구조를 한번에 본다! - 덴드로그램(Dendrogram)

(1) 덴드로그램

linked = linkage(X_scaled, method='ward') # 보통 ward 사용

 

Distance를 조절해서 원하는 군집 개수로 볼 수 있고,

x축에서 (숫자)는 이미 군집이 완성된거, 그냥 숫자는 아래에 딸려있는 군집이 더 있는거

  • n_clusters, distance_threshold(2개 의미 유사): 군집 개수를 정하지 않고, 거리만으로도 군집을 설정할 수 있음

(2) agglomerative(응집형)

(3) divisive(분할형)


6) PCA: 차원 수 줄이기(컬럼들을 하나로 묶어서)

 

 

이전 모델의 오차를 다음 모델이 보완한다

  • 첫 모델 생성
  • 오차 계산
  • 오차를 예측하는 모델 생성
  • 반복

대표적으로는 XGB, Light GBM, Cat Boost


💡각 앙상블 모델은 어떨 때 사용?

  • Random Forest: 빠르고 간단하고 성능 무난
  • XGB: 최고 성능을 목표로 할 때
  • Light GBM: 대용량 데이터
  • Catboost: 범주형 컬럼이 많을 때 - 가장 최근 모델(NIPS에도 올라옴)

3) 랜덤 포레스트(Random Forest)

  • n_estimators: 트리개수 - 많을수록 안정적(속도↓)
  • max_depth: 트리 최대 깊이 - 깊으면 과적합
  • min_samples_split: 노드 분할 최소 샘플 수 - 크면 보수적 모델 (최소 샘플 수가 크면 노드가 안 갈라진다 → 보수적)
  • min_samples_leaf: 리프 최소 샘플 수 - 크면 부드러운 모델
  • max_features: 분할 시 사용할 feature 수 - 작으면 다양성↑

CASE 1. 과적합을 줄이고 싶다

  • max_depth ↓
  • min_samples_leaf ↑
  • max_features ↓

CASE 2. 성능이 약하다

  • n_estimators ↑
  • max_depth ↑

4) XGB

  • n_estimators : Boosting 횟수 - 많을수록 강해짐
  • learning_rate(eta): 학습률 - 작을수록 안정적
  • max_depth: 트리 최대 깊이 - 깊으면 과적합
  • subsample: row 샘플링 비율 - 과적합 방지
  • colsample_bytree: feature 샘플링 비율 - 다양성↑
  • reg_lambda: L2 규제 - 과적합 방지
  • reg_alpha: L1 규제 - sparse 효과

XGB 하이퍼파라미터 추천 수치(실무에서 개인적으로 추천하는 수준)

  • n_estimators = 500
  • learning_rate = 0.03~0.1
  • max_depth = 4~8
  • subsample = 0.8~0.9
  • colsample_bytree = 0.8~0.9

5) Catboost ★실무 추천★

❗cat_features 지정 (전처리 없이 그대로 사용)

cat_cols = X.select_dtypes(exclude=['number']).columns.tolist()
cat_idx = [X.columns.get_loc(c) for c in cat_cols] # get_loc → 인덱스 뽑아내기
model.fit(
    X_train, y_train,
    cat_features=cat_idx
)
  • iterations : Boosting 횟수 - 많을수록 강해짐
  • learning_rate: 학습률 - 작을수록 안정적
  • depth: 트리 깊이 - 깊으면 과적합
  • l2_leaf_reg: L2 규제 - 과적합 방지
  • bagging_temperature: 랜덤성 조절

Catboost 하이퍼파라미터 추천 수치(실무에서 개인적으로 추천하는 수준)

  • iterations = 1000
  • learning_rate = 0.03~0.1
  • depth = 4~8
  • l2_leaf_reg = 3~10

6) 확률적 경사하강법(Stochastic Gradient Descent, SGD)

똑같은 모델이라도(선형회귀, 로지스틱 회귀)

  • 경사하강법 O → 데이터가 많을 때 더 빠르게 처리 가능해서 경사하강법을 많이 사용!
  • 경사하강법 X(수학적인 방식으로 풀기)

alpha = 람다 = 규제 강도 조절 like 수도꼭지

 

  • eta0: 초기 학습률 - learing_rate = 'constant'일 때 중요
  • max_iter: 최대 반복 횟수 - SGD는 반복 학습이라 매우 중요
  • loss: squared_error(일반적), huber(이상치에 강함)
  • penalty: 규제 방식 - l2(Ridge), l1(Lasso)
  • alpha: 규제 강도
  • learning_rate: 학습률 전략
  • tol: 수렴 조건 - 이 정도면(Loss가 0에 가까워지면) 된 걸로 치자
  • early_stopping: 성능 나빠지면 자동 종료

경사하강법 수식, 출처: https://hyomyo.tistory.com/13

세타에 대해서 오차(J(세타))를 편미분하자

  • 기울기가 양수? → 값이 작아져야함(음수 더해주기)
  • 기울기가 음수? → 값이 커져야함(양수 더해주기)

그래서 -(빼기) 해주는 것!

경사하강법 기울기, 출처: https://pasus.tistory.com/28

알파는 학습률(=미분 강도 조절)

 

+ Local minima 문제

: Global minimum을 알고 싶은데, 머신러닝 시작하는 위치가 랜덤이라서 Local minima에 빠질 수도 있음

→ 학습률을 크게 했다가 점진적으로 작게 해서 Global minimum을 찾을 수 있도록 함!

Local minima 문제, 출처: https://angeloyeo.github.io/2020/08/16/gradient_descent.html


심화 프로젝트) 1일차: 주제 선정 및 GitHub 공동 작업 가상 환경 구축

🚀 Hot-Six 프로젝트 환경 세팅 과정 정리

1️⃣ GitHub 레포지토리 생성

  • GitHub에서 hot-six 레포지토리 생성
  • 로컬에서 클론 후 VS Code로 연결
  • 팀원들을 Collaborators로 초대하여 접근 권한 부여

2️⃣ Python 버전 통일 (3.11.x)

🔥 왜 3.11인가?

  • 라이브러리 호환성 안정적
  • numpy / scikit-learn / statsmodels 등과 충돌 없음
  • 팀 환경 재현성 확보 목적

✔ Python 3.11 설치

설치 확인:

python--version

→ 반드시 3.11.x

 

3️⃣ uv 기반 환경 관리 설정

✔ uv 설치

uv--version

설치 안 되어 있으면 설치 진행

 

4️⃣ uv 프로젝트 초기화

uv init

→ pyproject.toml 생성

 

5️⃣ Python 버전 고정

pyproject.toml에 명시:

requires-python = "==3.11.*"

또한:

uv python pin3.11

→ .python-version 생성

 

6️⃣ 가상환경 생성

uv venv

→ .venv 생성

확인:

python--version

→ 3.11.x

 

7️⃣ 프로젝트 필수 패키지 설치

uv add numpy pandas scipy scikit-learn matplotlib seaborn statsmodels pingouin

→ pyproject.toml 업데이트

→ uv.lock 생성

이 uv.lock이 팀 환경 재현의 핵심 파일

 

8️⃣ .gitignore 설정

다음 항목 추가:

.venv/
__pycache__/
*.pyc
.env
.ipynb_checkpoints/

→ 가상환경이 Git에 올라가지 않도록 설정

 

9️⃣ Git 커밋 및 푸시

git add .
git commit-m"Initial project setup with uv environment"
git push

업로드된 핵심 파일:

  • pyproject.toml
  • uv.lock
  • .python-version
  • .gitignore

👥 팀원들이 해야 할 것

git clone <repo-url>
cd hot-six
uv venv
uv sync

그리고 VS Code에서:

  • .venv 인터프리터 선택

📂 Hot-Six 협업 규칙 정리

1️⃣ 폴더 구조 및 코드 관리 방식

📁 작업 파일 관리 규칙

각자 작업한 코드는 아래 구조로 업로드합니다:

hot-six/
│
├── notebooks/
│   ├── 홍길동/
│   │   └── eda_01.ipynb
│   │
│   ├── 김철수/
│   │   └── model_v1.ipynb
│   │
│   └── ...

🔹 규칙

  • notebooks/개인이름/ 이미 생성되어 있는 개인 폴더에서만 작업
  • 다른 팀원 폴더 수정 금지

2️⃣ 작업 시작 전 필수 단계

작업 시작 전 반드시 최신 상태로 업데이트:

git pull origin main

👉 항상 최신 코드 기준으로 작업

👉 충돌 방지 목적

 

3️⃣ 코드 업로드 방법 (Push 규칙)

🔹 개인 작업만 push

# 반드시 터미널에서 개인 폴더로 경로 지정 후에 수행!
cd notebooks/본인이름

# 업로드 하고자 하는 파일명 지정
git add 파일명.ipynb

# 또는 폴더 전체 추가
git add notebooks/본인이름

git commit-m"Add/update personal notebook"
git push origin main

※ 반드시 자기 이름 폴더만 add

 

4️⃣ main 브랜치 규칙

  • main은 공동 작업 공간
  • 임의로 구조 변경 금지
  • 패키지 추가 시 반드시 팀 공유 후 진행
  • 공통 파일 수정 시 사전 협의 필수

5️⃣ 패키지 추가 규칙 (중요 🔥)

❌ pip install 사용 금지

✅ 반드시 uv add 사용

패키지 추가 시:

uv add 패키지명
git add pyproject.toml uv.lock
git commit-m"Add package"
git push

다른 팀원은:

uv sync

 

 

6️⃣ 협업 기본 흐름 요약

 

작업 시작

git pull origin main

 

작업 후 업로드

git add notebooks/개인이름
git commit-m"작업 내용"
git push origin main
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/05   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함