AI/머신러닝

수업[2.3](데이터프레임, 데이터분포, 하이퍼파라미터, 교차검증, 군집화)

edcrfv458 2025. 2. 3. 18:10

베이직

 

datetime 변환

  • datetime 객체는 기본적으로 YYYY-MM-DD HH:MM:SS(연-월-일 시:분:초) 형태

datetime 형태로 변환

import pandas as pd

pd.to_datetime(df, format='mixed', errors='coerce')
#errors='coerce': 변환 불가능한 값은 NaT 처리

 

날짜 형식 지정

  • 날짜 및 시간 형식 변환
    • strftime: 날짜 객체를 문자열로 변환
    • strptime: 문자열을 날짜 객체로 변환
  • 주요 포맷 코드
    • %Y: 4자리 연도(2025)
    • %y: 2자리 연도(25)
    • %m: 월
    • %B: 월의 전체 이름(January)
    • %d: 일
    • %H:%M:%S: 시, 분, 초
from datetime import datetime

now = datetime.now()
formatted_date = now.strftime("%Y-%m-%d %H:%M:%S")
print(formatted_date, type(formatted_date))  # 2025-02-03 08:48:39 <class 'str'>

date_str = "2025-02-01"
date_obj = datetime.strptime(date_str, "%Y-%m-%d")
print(date_obj, type(date_obj))  # 2025-02-01 00:00:00 <class 'datetime.datetime'>

 

날짜 속성 추출(dt.month, dt.year, dt.day 등)

df = pd.DataFrame({"date": ["2025-02-01", "2025-03-15", "2025-06-20"]})
df["date"] = pd.to_datetime(df["date"])
df["year"] = df["date"].dt.year
df["month"] = df["date"].dt.month
df["day"] = df["date"].dt.day

 

sort

  • sort_values(): 특정 열을 기준으로 데이터 정렬
    • ascending=True: (default) 오름차순
    • ascending=False: 내림차순
df = pd.DataFrame({
    "이름": ["철수", "영희", "민수", "수진"],
    "국어": [85, 90, 75, 95],
    "영어": [80, 70, 95, 85]
})

# 국어 점수 기준 오름차순 정렬
df_sorted = df.sort_values(by="국어")
print(df_sorted)

# 국어 점수 기준 내림차순 정렬
df_sorted_desc = df.sort_values(by="국어", ascending=False)
print(df_sorted_desc)

 

  • sort_index(): 인덱스를 기준으로 정렬
    • ascending=True: (default) 오름차순
    • ascending=False: 내림차순
# 인덱스를 변경한 후 정렬
df = df.set_index("이름")

# 인덱스(이름) 기준 오름차순 정렬
df_sorted = df.sort_index()
print(df_sorted)

# 인덱스(이름) 기준 내림차순 정렬
df_sorted_desc = df.sort_index(ascending=False)
print(df_sorted_desc)

 

groupby

  • 데이터 프레임을 특정 기준으로 그룹화하여 집계 및 변환
    • aggregation: 그룹별 연산
      • 집계함수 종류: mean, median, sum, count, min, max

groupby([컬럼1,컬럼2])["값"].(집계함수) 

# groupby([컬럼1,컬럼2])["값"].(집계함수) 

df = pd.DataFrame({
    "부서": ["HR", "HR", "IT", "IT", "Finance", "Finance"],
    "성별": ["여", "남", "여", "남", "여", "남"],
    "연봉": [5000, 5500, 6000, 7000, 6500, 7500],
    "근속년수": [5, 7, 3, 8, 6, 10]
})

# 부서별 연봉 평균
df.groupby("부서")["연봉"].mean() # median, sum, min 

# 성별 부서별 평균 연봉 
df.groupby(["성별","부서"])["연봉"].mean() # median, sum, min

 

df.groupby("컬럼")["값"].agg([집계함수1, 집계함수2]) : 복수의 집계함수 연산도 가능

df.groupby(["성별","부서"])["연봉"].agg(["mean", "sum", "max"])

 

transform

  • 그룹 내 개별 값 반환

개별 데이터별 변환을 수행하여 원본 데이터의 개수 유지

df["부서_평균연봉"] = df.groupby("부서")["연봉"].transform("mean")
df

 

데이터프레임 결합(concat / merge / join)

  • concat: 축(Axis) 기준으로 단순히 붙임(행 또는 열)
    • axis=0: (default) 아래로 이어 붙임
    • axis=1: 옆으로 이어 붙임
df1 = pd.DataFrame({"A": ["A0", "A1"], "B": ["B0", "B1"]})
df2 = pd.DataFrame({"A": ["A2", "A3"], "B": ["B2", "B3"]})

# 행 기준 연결 (axis=0, 기본값)
df_concat0 = pd.concat([df1, df2], ignore_index=True) # ignore_index=True 기존 인덱스 무시 
print(df_concat0)

print('-------')
# 열 기준 연결 (axis=1)
df_concat1 = pd.concat([df1, df2], axis=1)
print(df_concat1)

 

  • merge: 공통 키를 기준으로 두 테이블 병합(join과 유사)
    • left, inner, right, ...
df_employees = pd.DataFrame({
    "직원ID": ["E001", "E002", "E003", "E004"],
    "이름": ["김철수", "이영희", "박지성", "손흥민"],
    "직급": ["사원", "대리", "과장", "부장"]
})
# 부서 데이터
df_departments = pd.DataFrame({
    "직원ID": ["E001", "E002", "E004", "E005"],
    "부서": ["영업팀", "마케팅팀", "개발팀", "재무팀"]
})

# ✅ Inner Join (공통 직원ID 기준)
df_inner = pd.merge(df_employees, df_departments, on="직원ID", how="inner")
df_inner

 

  • join: 인덱스 기준으로 병합(기본적으로 left join)
df_employees = pd.DataFrame({
    "직원ID": ["E001", "E002", "E003", "E004"],
    "이름": ["김철수", "이영희", "박지성", "손흥민"],
    "직급": ["사원", "대리", "과장", "부장"]
})
# 부서 데이터
df_departments = pd.DataFrame({
    "직원ID": ["E001", "E002", "E004", "E005"],
    "부서": ["영업팀", "마케팅팀", "개발팀", "재무팀"]
})

# ✅ Left Join (모든 직원 포함)
df_left = pd.merge(df_employees, df_departments, on="직원ID", how="left")
df_left

 

비교

메서드 사용 목적 기준 SQL 개념 결과 크기
concat() 여러 개의 테이블 연결 행 또는 열 UNION ALL 연결한 만큼
merge() 공통 키 기준 병합 지정된 on 키 JOIN (inner, left, right, outer) 키에 따라 달라짐
join() 인덱스 기준 병합 행의 인덱스 LEFT JOIN left 기준

챌린지

 

  • Boxplot: 중앙 값, IQR, 이상치를 확인 가능
    • 간단한 분포 비교, 이상치 확인

 

  • Vilolin Plot: Boxplot + KDE(분포 밀도)
    • 데이터의 밀도 분포를 더 명확하게 시각화 가능
    • 단점이 있다면 이상치 확인이 불가능
    • 데이터가 많을 수록 뚱뚱해짐

 

  • KDE Plot: 데이터의 분포를 부드럽게 추정한 확률 밀도 함수(PDF)를 시각화
    • 히스토그램보다 부드럽고 직관적
    • 두 개 이상의 분포 비교할 때 효과적
    • 밀도 차이 분석
    • 겹치는 부분의 색이 진해져 분포의 유사성을 직관적으로 파악 가능
    • fill=True 파라미터로 면적을 채워 가독성 향상

 

  • ECDF Plot(잘 사용하지는 않음): 누적 분포를 시각화
    • 분산 및 중앙값 차이 확인
    • 데이터가 특정 값 이하일 확률을 누적해서 표시
    • 분포의 차이를 누적 확률 관점에서 비교 가능

머신러닝

 

하이퍼파라미터 튜닝

  • 모델이 학습하는 과정에서 스스로 학습할 수 없는, 사람이 직접 설정해야 하는 값
  • 여러 개가 서로 상호작용하므로 독립적으로 생각하면 모델의 성능이 떨어질 수 있음
  • 각 모델마다 하이퍼파라미터가 다름
    • GridSearch: 하이퍼파라미터 조합을 격자 형태로 만들어 탐색
    • RandomSearch: 하이퍼파라미터 공간에서 무작위로 값을 추출하여 탐색

 

교차 검증

  • 모델의 일반화 성능을 정확하게 평가하기 위한 방법
    • 특정 테스트 데이터에서는 우연히 좋은 성능을 보일 수 있지만
    • 이것이 모델의 실제 성능을 대표한다고 보기는 어렵습니다.
    • 이러한 문제를 해결하기 위해 교차 검증이 필요
  • K-fold Cross Validation: 전체 데이터를 K개의 비슷한 크기의 그룹(fold)으로 나누어 평가
  • Stratified K-fold Cross Validation: 각 fold에서 클래스의 비율을 원본 데이터와 동일하게 유지
    • K-fold CV를 개선한 버전으로, 특히 분류 문제에서 중요
    • 각 fold가 전체 데이터의 분포를 대표
    • 편향된 평가를 방지
    • 분류 문제에서 더 안정적인 성능 평가가 가능
    • 데이터가 불균형할때 유용
  • LOOCV: K를 데이터의 개수(총 샘플 수)와 같게 설정한 경우
    • K-fold CV의 극단적인 형태
    • 마치 각 학생을 한 명씩 테스트하는 것
    • 장점
      • 거의 모든 데이터를 학습에 사용
      • 편향이 적은 평가가 가능
    • 단점
      • 계산 비용이 매우 높음
      • 데이터가 많을 경우 현실적으로 사용이 어려움
  • GridSearch ‘CV’& RandomSearch ‘CV’
    • 기존 grid search처럼 하이퍼파라미터 조합을 격자 형태로 만들어 탐색하되 각 하이퍼파라미터 조합마다 CV를 수행
    • random search처럼 하이퍼파라미터 공간에서 무작위로 값을 추출하여 탐색하되 각 무작위 하이퍼파라미터 조합마다 CV를 수행

 

군집화

  • 비슷한 애들을 묶음
  • 핵심
    • 같은 그룹 내의 데이터들은 최대한 비슷하게
    • 서로 다른 그룹 간의 데이터들은 최대한 다르게
  • K-means
    • 구현이 간단
    • 하지만 초기 중심점 위치에 따라 결과가 달라
    • 팀의 개수(K)를 미리 정해야 한다는 제한
    • k를 조절하기 위해 엘보우(elbow) 방법 ➡️ 꺾이는 지점이 최적의 군집 수
  • 계층적 군집화(Hierarchical Clustering)
    • 상향식: 작은 팀에서 시작해 점점 큰 조직 만들어가는 방식
    • 하향식: 큰 조직에서 시작해 점점 작은 단위로 나누는 방식
  • 실루엣 계수
    • 군집화가 얼마나 잘 되었는지 평가하는 방법
    • -1에서 1사이의 값으로, 1일 수록 잘된것
  • 엘보우 방법
    • k를 조절하기 위한 방법
    • 꺾이는 지점이 최적의 군집 수