[한컴AI 아카데미 | 2026.06.15 | Day 77] 데이터 분석 ① - Numpy

2026. 6. 16. 08:20·부트캠프

📘 NumPy 내용 정리

1. NumPy 기본 개념 및 배열 정보 확인

NumPy는 다차원 배열 ndarray를 사용하여 Python 기본 리스트보다 훨씬 빠른 속도로 대량의 수치 계산을 처리하는 라이브러리이다.

하나의 배열에는 단 하나의 데이터 타입(dtype)만 저장할 수 있으며, 서로 다른 타입이 섞이면 더 넓은 범위의 타입으로 자동 변환되는 업캐스팅(Upcasting)이 발생한다.

import numpy as np

# 배열 생성 및 타입 확인
arr = np.array([[1, 2, 3], [4, 5, 6.5]])  # 실수형이 섞여 Upcasting 발생

print("배열 출력:\n", arr)
print("shape (형태):", arr.shape)     # (행, 열)
print("ndim (차원 수):", arr.ndim)    # 2차원
print("size (원소 개수):", arr.size)   # 6개
print("dtype (자료형):", arr.dtype)   # float64

2. 벡터화 연산과 차원의 이해

NumPy는 루프(Loop) 문 없이 배열 단위로 곧바로 연산하는 벡터화 연산을 지원한다.

차원은 데이터의 구조에 따라 스칼라, 벡터, 행렬, 텐서로 구분된다.

  • 0차원 (Scalar): 하나의 값 (ndim: 0)
  • 1차원 (Vector): 숫자의 나열 (ndim: 1)
  • 2차원 (Matrix): 행(Row)과 열(Column)로 구성 (ndim: 2)
  • 3차원 이상 (Tensor): 깊이, 행, 열의 구조 (ndim: 3)
# 벡터화 연산 예시 (원소별 연산)
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print("원소별 곱셈:", a * b)  # [4, 10, 18]

# 배열 구조 변경 (reshape / flatten)
arr_1d = np.arange(1, 13)  # 1부터 12까지 생성
matrix = arr_1d.reshape(3, 4)  # 3행 4열 행렬로 변환 (전체 원소 개수가 같아야 함)
flat = matrix.flatten()  # 다시 1차원 배열로 평평하게 펼침

3. 인덱싱, 슬라이싱 및 통계 (axis의 이해)

NumPy 배열은 arr[행, 열] 형태로 접근하며, 특정 행이나 열 전체를 선택할 수 있다.

통계 함수를 사용할 때 axis 설정이 매우 중요하다.

  • axis=0: 행 방향(↓)으로 계산 👉 열별 결과 도출
  • axis=1: 열 방향(→)으로 계산 👉 행별 결과 도출
# 3개 매장(행), 4개 제품(열)의 재고 데이터
stocks = np.array([
    [10, 30, 45, 15],  # 매장 1
    [20, 15, 25, 35],  # 매장 2
    [40, 10, 20, 30]   # 매장 3
])

print("첫 번째 매장의 전체 제품 재고:", stocks[0])      # 행 인덱싱
print("모든 매장의 첫 번째 제품 재고:", stocks[:, 0])   # 열 인덱싱

print("매장별 총 재고 (행별 합계):", stocks.sum(axis=1))
print("제품별 총 재고 (열별 합계):", stocks.sum(axis=0))

4. 조건 필터링 (Boolean Masking & np.where)

조건식을 배열에 적용하면 True / False로 구성된 마스크가 생성되며, 이를 통해 조건에 맞는 데이터만 추출하거나 특정 값으로 치환할 수 있다.

# Boolean Masking: 30 이하인 재고 데이터만 추출
print(stocks[stocks <= 30])

# np.where(조건) : 조건을 만족하는 (행 인덱스 배열, 열 인덱스 배열) 위치 반환
rows, cols = np.where(stocks <= 30)

# np.where(조건, 참일 때 값, 거짓일 때 값) : 조건 치환
status = np.where(stocks >= 30, '충분', '부족')
print(status)

5. 데이터 정제 (결측치 및 이상치 처리)

데이터에 포함된 누락값(NaN)이나 비정상적인 이상치를 다룬다.

# 결측치(NaN) 처리: NaN을 제외한 평균값으로 결측치 채우기
temps = np.array([23.1, np.nan, 24.5, 22.8, np.nan, 25.0])
mean_temp = np.nanmean(temps)  # NaN을 제외하고 평균 계산
temps[np.isnan(temps)] = mean_temp
print("결측치 정제 후:", np.round(temps, 1))

# 이상치 대체: 0 이하의 비정상 지출 데이터를 정상 데이터의 평균값으로 대체
expenses = np.array([55, 62, -10, 58, 0, 67, 70, 59])
normal_mean = np.mean(expenses[expenses > 0])  # 정상 데이터 평균
new_expenses = np.where(expenses <= 0, normal_mean, expenses)
print("이상치 정제 후:", np.round(new_expenses, 2))

6. 다차원 응용 (이미지 RGB → Gray Scale)

컬러 이미지는 (높이, 너비, 채널) 구조의 3차원 텐서이다.

RGB 채널을 나타내는 마지막 축(axis=2)의 평균을 구하면 흑백 이미지로 변환할 수 있다.

# 3x3 크기의 가상 가상 컬러 이미지 (마지막 축 axis=2가 R, G, B 채널)
color_image = np.array([
    [[255, 0, 0], [0, 255, 0], [0, 0, 255]],
    [[255, 255, 0], [255, 0, 255], [0, 255, 255]],
    [[255, 255, 255], [128, 128, 128], [0, 0, 0]]
], dtype=np.uint8)

# R, G, B 채널 축(axis=2)을 기준으로 평균값 계산
gray_image = np.mean(color_image, axis=2)
print("흑백 이미지 배열:\n", gray_image)

🚀 코사인 유사도를 이용한 도서 추천 시스템

앞서 배운 배열 연산, 통계(내적 및 Norm), Boolean Masking, 인덱싱 기술을 총동원하여 실제 추천 시스템의 핵심 알고리즘을 구현해 보려고 한다.


1. 코사인 유사도(Cosine Similarity)의 원리

추천 시스템에서는 사용자 간 취향이 얼마나 비슷한지 판단하는 것이 중요하다.

코사인 유사도는 두 벡터 사이의 각도(Angle)를 이용해 유사성을 측정한다.

  • 방향이 완전히 동일할 때 (1): 취향이 완벽히 일치
  • 서로 직교할 때 (0): 취향이 전혀 관련 없음
  • 정반대 방향일 때 (-1): 취향이 정반대

수학적 공식은 두 벡터의 내적을 각각의 크기(Norm)로 나누어 구한다.


2. 추천 시스템 전체 구현 코드

4명 사용자의 6개 도서 평점 데이터를 바탕으로, 타깃 사용자 A에게 취향이 가장 유사한 사용자가 높게 평가한 책을 추천하는 파이프라인이다.

import numpy as np

# 1. 데이터 정의 (행: 사용자 A~D / 열: 도서 6권)
# 평점 0점은 아직 읽지 않은 도서(결측치)를 의미함
ratings = np.array([
    [5, 4, 5, 1, 4, 0],  # 사용자 A (Target)
    [5, 5, 4, 1, 5, 5],  # 사용자 B
    [1, 1, 2, 5, 1, 4],  # 사용자 C
    [0, 4, 5, 1, 4, 5],  # 사용자 D
])

books = np.array([
    "Python 입문", "NumPy 기초", "FastAPI 실전", 
    "Docker 배포", "데이터 분석", "웹 크롤링"
])

# 2. 코사인 유사도 함수 정의
def cosine_similarity(a, b):
    # 분자: np.dot (내적) / 분모: np.linalg.norm (벡터 크기)의 곱
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))


# --- Step 1: 타깃 사용자(A)와 다른 사용자들 간의 유사도 계산 ---
target_user = ratings[0]
similarities = []

print("=== 사용자별 유사도 측정 ===")
for i in range(1, len(ratings)):
    sim = cosine_similarity(target_user, ratings[i])
    similarities.append(sim)
    print(f"사용자 A ↔ 사용자 {i}: {sim:.3f}")


# --- Step 2: 가장 유사한 성향의 유저(이웃) 탐색 ---
# np.argmax()는 배열 내 최댓값의 인덱스를 반환하므로 유저 번호 매칭을 위해 +1 처리
most_similar_user_idx = np.argmax(similarities) + 1
print(f"\n★ 가장 유사한 취향을 가진 이웃: 사용자 {most_similar_user_idx}")


# --- Step 3: Boolean Masking을 활용한 맞춤 도서 필터링 및 추천 ---
similar_user_ratings = ratings[most_similar_user_idx]

# 조건 1: 타깃 사용자 A는 아직 안 읽었어야 함 (0점)
# 조건 2: 취향이 비슷한 이웃은 좋게 평가했어야 함 (4점 이상)
condition = (target_user == 0) & (similar_user_ratings >= 4)
recommended_books = books[condition]

print(f"★ [사용자 A님을 위한 추천 도서]: {recommended_books}")
=== 사용자별 유사도 측정 ===
사용자 A ↔ 사용자 1: 0.981
사용자 A ↔ 사용자 2: 0.474
사용자 A ↔ 사용자 3: 0.885

★ 가장 유사한 취향을 가진 이웃: 사용자 1
★ [사용자 A님을 위한 추천 도서]: ['웹 크롤링']

💡 최종 정리

주요 학습 키워드 핵심 메커니즘 및 매칭 함수
차원 및 형태 확인 shape, ndim, size, dtype 속성으로 데이터 구조 파악
축(axis) 연산 axis=0은 열 방향 계산(열별 결과), axis=1은 행 방향 계산(행별 결과)
데이터 정제 np.isnan(), np.nanmean()으로 결측치 제어 및 np.where()로 이상치 치환
유사도 계산 (분자) np.dot(A, b) 두 벡터의 상호 취향 패턴의 가중치 합산(내적) 계산
유사도 계산 (분모) np.linalg.norm(A) 데이터의 절대적인 스케일/크기(L2 Norm) 계산
최적 이웃 매칭 np.argmax()를 통해 유사도 수치가 가장 높은 대상의 위치 인덱스 확보
최종 콘텐츠 필터링 & 연산자와 조건절을 묶어 타깃 데이터를 선별하는 Boolean Masking 적용

💭 메무아

이번 실습에서는 NumPy의 기본적인 배열 생성, 인덱싱, 슬라이싱, 조건 인덱싱, axis, reshape 등의 기능을 학습했다. 문법 자체는 비교적 직관적이어서 이해하는 데 큰 어려움은 없었지만, 단순히 기능을 익히는 것에서 끝나지 않고 실제로 어떻게 활용되는지 확인해보고 싶었다.

그래서 학습한 내용을 바탕으로 추천 시스템의 핵심 원리 중 하나인 코사인 유사도(Cosine Similarity)를 직접 구현해보았다. 사용자의 평점 데이터를 벡터로 표현하고, 벡터 간의 유사도를 계산하여 추천 대상을 선정하는 과정을 통해 NumPy가 단순한 수치 계산 라이브러리가 아니라 다양한 데이터 분석과 머신러닝의 기초가 된다는 점을 느낄 수 있었다.

다만 코사인 유사도 공식에 사용되는 내적(Dot Product)과 벡터의 크기(Norm) 계산 과정은 아직 완전히 익숙하지 않아 수식을 해석하는 데 어려움이 있었다. 앞으로는 단순히 코드를 따라 작성하는 것을 넘어 각 수식이 어떤 의미를 가지는지 이해하고, 이를 다른 알고리즘에도 적용할 수 있도록 추가적으로 공부해볼 계획이다.

이번 실습을 통해 NumPy의 기본 문법을 정리할 수 있었고, 동시에 실제 알고리즘 구현까지 경험해보며 데이터 처리와 추천 시스템의 기초 원리를 이해할 수 있는 의미 있는 시간이었다.

 

 

 

 

더보기

[참고]

 

Mastering Cosine Metrics: A Data Scientist’s Essential Toolkit

Table of Contents

python.plainenglish.io

————————————————————————————————————————————————————— 

 

본 후기는 [한글과컴퓨터x한국생산성본부x스나이퍼팩토리]

한컴 AI 아카데미 (B-log) 리뷰로 작성 되었습니다.

'부트캠프' 카테고리의 다른 글

[한컴AI 아카데미 | 2026.06.17 | Day 79] 데이터 분석 ③ - Pandas로 포켓몬 데이터 분석하기  (0) 2026.06.17
[한컴AI 아카데미 | 2026.06.16 | Day 78] 데이터 분석 ② - Matplotlib로 포켓몬 데이터 시각화해보기  (0) 2026.06.17
[한컴AI 아카데미 | 2026.06.11 | Day 73] FastAPI ② - Cookie, Session, JWT 인증 구현 및 비교  (0) 2026.06.11
[한컴AI 아카데미 | 2026.06.09 | Day 71] 크롤링 ③ - BeautifulSoup으로 안 되던 데이터, Selenium 없이 수집할 수 있었던 이유  (0) 2026.06.09
[한컴AI 아카데미 | 2026.06.08 | Day 70] 크롤링 ② - BeautifulSoup과 Selenium  (0) 2026.06.09
'부트캠프' 카테고리의 다른 글
  • [한컴AI 아카데미 | 2026.06.17 | Day 79] 데이터 분석 ③ - Pandas로 포켓몬 데이터 분석하기
  • [한컴AI 아카데미 | 2026.06.16 | Day 78] 데이터 분석 ② - Matplotlib로 포켓몬 데이터 시각화해보기
  • [한컴AI 아카데미 | 2026.06.11 | Day 73] FastAPI ② - Cookie, Session, JWT 인증 구현 및 비교
  • [한컴AI 아카데미 | 2026.06.09 | Day 71] 크롤링 ③ - BeautifulSoup으로 안 되던 데이터, Selenium 없이 수집할 수 있었던 이유
NGC463l
NGC463l
무한한 우주에서 헤엄치는 고래 한 마리
  • NGC463l
    고래별
    NGC463l
  • 전체
    오늘
    어제
    • 🚀 (66) N
      • 부트캠프 (56) N
      • CS (3)
      • 코딩 테스트 (2)
        • 백준 (1)
      • 프로젝트 (4)
        • 크보패스 (4)
      • 일상 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    개발자취업
    AI개발자
    코딩테스트
    데이터전처리
    위치기반서비스
    한글과컴퓨터
    스나이퍼팩토리
    알고리즘
    한컴ai아카데미
    PYTHON
    AI아카데미
    API연동
    이것이코딩테스트다
    크롤링
    kakaoapi
    ai개발자교육
    한국생산성본부
    selenium
    ai전문가양성
    BFS
    TCP
    fastapi
    부트캠프
    LLM
    프로젝트
    UDP
    백엔드
    이코테
    컴퓨터네트워크
    개발자교육
  • hELLO· Designed By정상우.v4.10.6
NGC463l
[한컴AI 아카데미 | 2026.06.15 | Day 77] 데이터 분석 ① - Numpy
상단으로

티스토리툴바