SKN/Remind

sk네트웍스 family AI 캠프 11기 4주차 회고록

claovy☘️ 2025. 2. 28. 22:52

4차 회고기간 : 2025.02.24월~2025.02.28금

이번주는 3일 간의 프로젝트, 2일 간의 데이터분석(numpy 이론) 수업이 진행되었다

우당탕탕 지나가버린 일주일을 정리해보겠습니닷

02.24월 ~ 02.26수
 

sk네트웍스 family AI 캠프 1차 프로젝트 회고

🖥️ 1. 프로젝트 소개"연령별 신차 구매 트렌드 분석 및 FAQ 플랫폼"인터넷 각 사이트에서는 신차 등록 데이터를 개별적으로 제공하고 있지만, 연령 별 구매 패턴을 한눈에 파악할 수 있는 시각

dscience26.tistory.com

 

 

GitHub - SKNETWORKS-FAMILY-AICAMP/SKN011-1st-5Team

Contribute to SKNETWORKS-FAMILY-AICAMP/SKN011-1st-5Team development by creating an account on GitHub.

github.com

 


📖 Review

1. 데이터분석 Overview

1. 데이터 분석

01. 데이터란?

💡1. 이론을 세우는 데 기초가 되는 사실 또는 자료
     2. [컴퓨터] 프로그램을 운용할 수 있는 형태로 기호화 또는 숫자화한 자료
(출처 : Oxford Languages)
  • 정형 데이터
    • 고정된 구조를 가진 데이터로, 일반적으로 행과 열로 구성된 표 형태로 저장된다.
    • 예시 : 관계형 데이터베이스, 스프레드시트 파일(Excel, CSV 등)
  • 비정형 데이터
    • 고정된 구조가 없는 데이터로, 다양한 형태와 형식을 가진다.
    • 예시 : 텍스트, 멀티미디어(이미지, 동영상, 오디오 등)

 

02. 데이터 분석이란?

💡 데이터 분석은 원시 데이터를 실행 가능한 인사이트로 변환한다. 여기에는 데이터를 사용해 추세를 찾아서 문제를 해결하는 데 사용되는 도구, 기술, 프로세스가 포함된다.
데이터 분석을 통해 비즈니스 프로세스를 구성하고, 의사 결정을 개선하며, 비즈니스 성장을 증진할 수 있다.
(출처 : AWS)

 

03. 데이터 분석 프로세스

[CRISP-DM]

 💡CRISP-DM은 Cross Industry Standard Process for Data Mining의 약자이다. 데이터 분석과 데이터 마이닝 프로젝트를 체계적으로 수행하기 위해 널리 사용되는 표준 프로세스이다. CRISP-DM은 6단계로 구성되어 있으며, 각 단계는 순차적이면서도 반복적인 특성을 가진다.

또한 CRISP-DM은 어떤 산업이나 문제 유형에도 적용 가능한 유연성을 가지며 명확한 가이드를 제공하므로 협업에 유리하다.

 

1. 비즈니스 이해 : 프로젝트의 목표와 요구사항을 명확히 정의한다

 

2. 데이터 이해 : 프로젝트에서 사용할 데이터를 이해한다

3. 데이터 준비 : 분석에 적합한 형태로 데이터를 가공한다

 

4. 모델링 : 데이터에 적합한 모델을 선택하고 학습시킨다

 

5. 평가 : 모델의 성능과 비즈니스 목표 적합성을 평가한다

6. 배포 : 분석 결과를 비즈니스 환경에 적용한다.

 

2. 데이터 분석 도구

파이썬 자료형 복습하기

머신러닝에서는 데이터 구조(리스트 등)의 기본 개념을 이해하는 것이 필수적이다.
따라서 데이터 접근과 조작을 할 수 있는 인덱싱, 슬라이싱을 잘 사용할 수 있어야 한다.

* 파이썬 카테고리에 정리되어있으니 참고하도록 하자

2025.02.18 - [SKN/01. python] - 01. 변수와 자료형

 

01. 변수와 자료형

01. 변수1. 변수프로그램에서 다루는 어떤 자료를 담는 공간(변수명) (대입연산자) (자료)2. 변수 생성변수 생성은 대입 연산자 = 을 기준으로 좌항에는 변수의 이름, 우항에는 변수에 담을 자료를

dscience26.tistory.com

 


2. Numpy Overview

1. numpy 개요

01. numpy란?

💡Numpy란 Numerical Python의 줄임말로, 대규모 다차원 배열과 행렬 연산을 지원하는 파이썬 라이브러리이다. NumPy는 수학적 연산을 빠르고 효율적으로 수행할 수 있도록 설계되어 있어, 데이터 분석, 머신러닝, 인공지능, 이미지 처리, 신호 처리, 통계 분석 등 여러 분야에서 활용된다.

 

02. numpy의 주요 특징

  • NumPy의 핵심 자료 구조인 ndarray는 다차원 배열을 효율적으로 관리할 수 있다.
  • 벡터화 연산(Vectorized Operations)을 통해 for문을 사용하지 않고 배열 간 연산을 빠르게 수행할 수 있다.
  • 선형대수, 통계, 푸리에 변환 등 다양한 수학적 연산을 함수로 지원한다.
  • 파이썬 리스트에 비해 적은 메모리를 사용하며, 대규모 데이터를 효과적으로 처리할 수 있다.

03. ndarray 구조

  • shape : 배열의 모양
  • ndim : 차원
  • size : 요소의 개수를 반환 
  • dtype : 요소의 데이터 타입

04. ndarray 생성

n으로 채운 배열
# 0으로 채운 배열 생성
arr = np.zeros((2, 3))  # 2x3 배열
print(arr)

# 1로 채운 배열 생성
arr = np.ones((3, 2))  # 3x2 배열
print(arr)
수열을 가진 배열
# 등간격으로 배열 생성
arr = np.linspace(0, 1, 5)  # 0에서 1까지 5개의 등간격 값
print(arr)

# 지수 | 로그로 배열 생성
arr = np.logspace(1, 3, 4) # a의 1제곱이 10, a의 3제곱이 1000이므로, base를 주지 않으면 default 값이 10 이라는 것을 알 수 있다.(기본적인 상용로그값)
print(arr)
형변환
# 형변환
arr = np.array([1.234, 5.678, 9, 10]) # 묵시적 형 변환
arr = np.array([1.234, 5.678, 9, 10], dtype = float) # 명시적 형 변환
arr = np.array([1.234, 5.678, 9, 10], dtype = int) # float -> int 형 변환은 소숫점은 그대로 버림 
arr, arr.dtype

 

05. fancy indexing

1차원 배열 fanct indexing
arr = np.arange(5,31,5)
print(arr)
print(arr[[1, 3, 5]])

indices = [1, 3, 5]
print(arr[indices])

[출력]
[ 5 10 15 20 25 30]
[10 20 30]
[10 20 30]
2차원 배열 fancy indexing
arr = np.array([
    [5, 10, 15, 20],
    [25, 30, 35, 40],
    [45, 50, 55, 60]
])

# 찾고 싶은 인덱스 = [10 35]
indices1 = [0,1]
indices2 = [1,2]

print(arr[indices1,indices2])
print(arr[[0,1],[1,2]])

[출력]
[10 35]
[10 35]

 

06. 조건반환

 

np.all() : ndarray의 모든 요소가 조건을 만족할 때 True 반환
arr = np.array([10, 20, 30, 40, -50])

is_all_positive = np.all(arr>0)

if is_all_positive:
    print('모든 수는 양수입니다')
else:
    print('모든 수가 양수는 아닙니다.')
    
[출력]
모든 수가 양수는 아닙니다
np.any() : ndarray의 요소가 조건을 하나라도 만족할 때 True 반환
arr = np.array([10, 20, 30, 40, -50])

has_positive = np.any(arr>0)

if has_positive:
    print('양수가 포함되어 있습니다다')
else:
    print('모든 수가 양수입니다.')
    
[출력]
양수가 포함되어 있습니다

3. Numpy 연산 

01. Dot Product 연산

💡점곱연산 (Dot Product / 내적)   
- 두 행렬 A, B의 곱셈은 첫 번째 행렬 A의 행과 두 번째 행렬 B열 간의 곱셈을 수행한다.    
- 첫 번째 행렬 A의 열의 수와 두 번째 행렬 B의 행의 수가 같아야 한다.   
- 연산 결과의 shape은 (첫 번째 행렬 A의 행수, 두 번째 행렬 B의 열수) 이다.
arr3 = np.array([[1, 2, 3],[4, 5, 6]]) #(2,3)
arr4 = np.array([[7, 8],[9, 10],[11, 12]]) #(3,2)
arr3.shape, arr4.shape # arr3과 arr4가 내적되었을 떄 shape을 상상해보자. arr3의 행, arr4의 열이 나올 것이다

print(np.dot(arr3,arr4).shape)
print(np.dot(arr4,arr3).shape) 

[출력]
(2, 2)
(3, 3)
[[ 7  8]
 [ 9 10]
 [11 12]]
[[1 2 3]
 [4 5 6]]

 

02. broadcasting 연산

arr_a = np.arange(1,10).reshape(3,3)

result_arr = arr_a * np.array([[5, 5, 5],[5, 5, 5],[5, 5, 5]]) # (3, 3)
result_arr = arr_a * np.array([5, 5, 5]) # (3, )
result_arr = arr_a * np.array([5]) # (1, )
result_arr = arr_a * 5 # 스칼라값 
result_arr

[출력]
array([[ 5, 10, 15],
       [20, 25, 30],
       [35, 40, 45]])

3,3 배열인 arr_a과 같은 요소값을 가진 여러 배열들을 곱한 결과 모두 같은 값이 출력된다.

이는 numpy의 broadcating 연산 때문이다.

⭐ 2차원과 1차원의 연산을 고려해보자
- 두 배열이 shape이 다르면 broadcating 연산을 수행한다
- shape이 작은 쪽에서 큰 쪽에 맞춰 확장한다
- 두 배열의 행 또는 열이 일치해야 확장 가능하다
- 크기가 1인 경우 무조건 확장 가능하다
- shape이 다른 경우 마지막 축부터 차원이 동일한지 비교한다
- 1차원이 자신보다 큰 차원을 만나면 요소의 개수를 맞춰주기 위해 확장된다!!!! (작은쪽에서 큰 쪽으로 확장)

4. Numpy 통계

1. 통계 기초

01. 모집단과 표본

  • 모집단(Population): 연구 대상 전체를 의미하며, 모든 데이터를 포함한다.
    • ex) 특정 나라의 모든 사람의 키 데이터
  • 표본(Sample): 모집단의 일부를 추출한 데이터를 의미하며, 모집단의 특성을 추정하는 데 사용된다.

02. 중심 경향 측도

🤔 우리반의 평균 키와 최빈값을 구해보자!

height = np.array([160, 170, 180, 150, 150, 155, 165, 175, 185, 180, 175, 170, 173, 164, 189, 175])

# 평균값
print(np.mean(height))

# 정렬
print(np.sort(height))

# 중앙값
print(np.median(height))

# 최빈값 --> 중복값을 제외하고 고유한 값 / 그 갯수 
values, count = np.unique(height, return_counts = True)
print(values,count)

# 최빈값 
most = np.max(count)
print(most == count) # boolean으로 해당값의 True, False 여부를 확인해줌 
print(values[count == most])

[출력]
169.75
[150 150 155 160 164 165 170 170 173 175 175 175 180 180 185 189]
171.5
[150 155 160 164 165 170 173 175 180 185 189] [2 1 1 1 1 2 1 3 2 1 1]
[False False False False False False False  True False False False]
[175]

 

03. 정규분포와 균등분포

  • 정규분포
    • 평균을 중심으로 데이터가 대칭적으로 분포하며, 종 모양의 분포를 나타낸다.
    • 정규분포에서는 평균 근처의 값이 자주 나타나고, 양 끝으로 갈수록 빈도가 감소한다.
arr = np.random.randn(1000)  # 평균 0, 표준편차 1인 정규분포 난수 1000개
print(np.mean(arr), np.std(arr))
  • 균등분포
    • 모든 값이 동일한 확률로 발생하는 분포를 의미한다.
    • 0.0 이상 ~ 1.0 미만 수에서 균등하게 난수 추출 
    • np.random.randint(start, end, size) => start 이상 end 미만의 난수를 size 만큼 추출
arr = np.random.uniform(0, 1, 1000)  # 0과 1 사이의 균등분포 난수 1000개
print(np.mean(arr), np.std(arr))

5. Numpy 정렬

01. 기본 배열 정렬

arr = np.random.randint(1, 11, 10)

print(np.sort(arr)) # 오름차순(기본) 정렬
print(np.sort(arr)[::-1]) # 내림차순 정렬
print(arr)

=> 인덱스를 사용하여 내림차순 정렬이 가능하다

[출력]
[2 2 3 3 4 6 8 9 9 9]
[9 9 9 8 6 4 3 3 2 2]
[4 3 9 9 2 6 8 2 3 9]

 

02. 특정 축을 기준으로 정렬

print(np.sort(arr, axis=0)) # 행 방향 정렬 (같은 열 안에서 정렬)
print(np.sort(arr, axis=1)) # 열 방향 정렬 (같은 행 안에서 정렬) ⭐기본값 
print(np.sort(arr, axis=None).shape) # axis = None 축 무시 (행/열 구분없이 모든 값 정렬)
[출력]
[[1 5 2 7]
 [8 6 4 8]
 [8 9 7 9]]
[[1 5 7 9]
 [2 8 8 9]
 [4 6 7 8]]
(12,)
(12,)

 

03. 인덱스를 반환하는 정렬

💡np.argsort
- 배열의 값을 정렬했을 때, 각 값의 원래 인덱스를 반환
- 정렬할 때 어떤 순서로 값을 배치해야 하는지 알려주는 인덱스를 반환
- 배열의 값을 정렬한 후, 정렬된 순서에 해당하는 인덱스를 반환

 

(1) 1차원 배열에서 argsort 사용

names = np.array(['리사','로제','제니','지수'])
album_sales = np.array([900, 870, 1000, 670])

result = np.argsort(album_sales)
print(names[result][::-1])

[출력]
['제니' '리사' '로제' '지수']

 

(2) 2차원 배열에서 argsort 사용

# 2차원 배열에서 argsort
arr = np.array([[2025, 2, 28],[17, 18, 30]])
print(arr)
print(np.argsort(arr))
print(np.argsort(arr, axis=1)) # 열 방향 정렬의 순서 (같은 행 안에서 정렬)
print(np.argsort(arr, axis=0)) # 행 방향 정렬의 순서 (같은 열 안에서 정렬)

[출력]
[[2025    2   28]
 [  17   18   30]]
[[1 2 0]
 [0 1 2]]
[[1 2 0]
 [0 1 2]]
[[1 0 0]
 [0 1 1]]

6. Numpy 병합

01. ndarray 요소 추가

ndarray는 고정 길이 배열이므로 크기 변경이 불가하다 (즉, 요소를 추가할 수 없다)

np.insert(     ,     ,      ,     )

np.insert (원본배열, 삽입할 위치 인덱스, 삽입할 요소, axis (행기준)
1차원 배열에서의 insert
#np.insert() : 요소의 추가한 새로운 배열을 반환

arr1 = np.append(arr, 40) # NO!!!
arr2 = np.insert(arr, 1, 15) # 원본배열, 삽입할 위치 인덱스, 삽입할 요소 

print(arr2 is arr, arr2)
[출력]
[10 20 30]
False [10 15 20 30]
[10 15 20 30]

append() 함수는 새로운 배열을 반환하는 함수이므로 원본배열 arr에 영향을 주지 않는다.

 

2차원 배열에서의 insert
# 2차원 배열에서의 insert
arr = np.arange(1, 13).reshape(3, 4)
print(arr)

# arr2 = np.insert(arr, 1, 100) 
arr2 = np.insert(arr, 1, [100, 200, 300, 400], axis=0)  # 1번 인덱스에 해당하는 위치에 배열을 추가 
print(arr2)
[출력]
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]

[[  1   2   3   4]
 [100 200 300 400]
 [  5   6   7   8]
 [  9  10  11  12]]

 


💡 Keep

1. 저녁은 건강한 음식으로 챙겨먹기2. 미루지 않고 블로그 정리 꾸준히 하기

 

⚠️ Problem

감기약 때문에 졸린데 잠을 깨야 할 필요가 ..... 

 

🔥 Try

집에 가면 쳐지는 것 때문에 그냥 저녁 도시락을 싸다니면서 공부를 할까 한다

SKN 시작하고 하던 운동도 멈춰있는 상태인데, 어느정도 적응한 것 같으니 다시 노력하쟈