| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- 상속
- 람다식
- 주피터
- C++
- 포인터
- 다형성
- python
- 인프런
- 연산자오버로딩
- 기본클래스
- OOP
- 데이터사이언스
- 멤버함수로구현
- 점프투파이썬
- 제네릭프로그래밍
- 코드잇
- STL
- 동적바인딩
- 백준
- 깊은복사
- 참조자
- 유도클래스
- list comprehension
- 얕은복사
- 스택
- OpenCV
- 11382번
- 프로그래머스lv2
- 코딩테스트
- c++코딩테스트합격자되기
- Today
- Total
WjExplor Story
데이터 사이언스 Toolkit 본문
코딩 테스트 문제를 풀 때 점수 편차는
실행시간이 작고 메모리 사용이 적은 게 높은 점수를 받는다
더 높은 기준을 갖출 수 있는 코딩테스트에서 배울 수 있다.
Numpy 연산은 똑같은 연산을 해도 빠르다.
이유는
python 언어가 장단점있겠지만 python의 단점은
메모리가 많이 들어서 속도가 느리다.
속도가 느린게 단점이다.
python 개발자는 연산이 많은 것을 하려면 속도가 느려서
코딩은 python 은 하고 실제 동작은 c언어로 한다
c엔진이 있다.
python 코드로 무언갈 짜면은 실제 동작은 c엔진으로 한다.
c언어보다 속도가 많이 느렸던 python 이 그나마 c언어만큼
속도가 따라온다
머신러닝 딥러닝할때 아주 많은 연산이 필요하고
내부적으로는 c언어 엔진으로 동작하기 때문에
속도의 장점을 가지고 올 수 있다.
왜 Numpy 는 고성능 수치 연산인지 알 수 있다.
- Numpy: 파이썬에서 **고성능 수치 연산**을 담당하는 **배열 엔진**. ML/DL의 전처리와 수치 연산의 기반.
- Pandas: **표 형식 데이터프레임**으로 정리·가공·집계에 최적. 실무 데이터 핸들링의 표준.
- Matplotlib: 분석 결과를 **시각화**하여 패턴을 발견하고 의사결정을 돕는다.
### Numpy의 특징
- **빠른 배열 연산**
- 파이썬의 기본 리스트보다 훨씬 빠른 속도로 벡터와 행렬 연산을 수행한다.
- 내부적으로 C 언어로 구현되어 있어 반복문을 직접 작성하지 않아도 된다.
아나콘다는 Numpy 는 자동으로 설치된다.
VS Code 파이썬 설치에서 코드 작성하는 경우에는 numpy 설치해야 한다.
! pip install numpy
로 설치해야 한다.
--
복잡한 수학 함수를 제공한다
행렬을 복잡한 모양이면 더할 수가 없다.
모양이 다른 배열이 있을때 알아서 numpy 가 맞춰서 계산한다
그게 브로드캐스팅(Broadcasting) 이다.
행렬
중요하니 잠시 후 다뤄보자.
- **브로드캐스팅(Broadcasting)**
- 크기가 다른 배열끼리도 규칙에 따라 자동으로 맞춰 연산할 수 있다.
- 예: 행렬 전체에 상수 더하기, 벡터를 행렬 각 행에 더하기.
---
벡터
크기와 방향이 있는 값을 벡터라고 한다.
화살표 또는 좌표처럼 생각할 수 있다.
(2,2) 혹은 그래프로 표현한다
벡터는 여러 숫자를 순서대로 나열한것이다.
물리나 공학은 1차 배열을 벡터라고 배웠으나
여기서는 여러 숫자를 순서대로 나열한 것이다.
1차원 벡터 / 2차원 벡터 / 3차원 벡터
차원으로 나눈다.
(Q. 3차원 벡터를 그려줘)
4차원부터는 직관적으로 이해하기 어렵다.
파이썬으로 머신러닝 빅데이터, 딥러닝은 4차원 벡터 그 이상
고차원 벡터를 사용하게 된다.
우리는 직관적으로 어려우니 벡터의 성질을 이해하고
1,2,3차원 벡터에서 적용되는 벡터의 성질이 고차원 벡터에서 적용될 거라고 생각하고 성질을 대입해서 적용한다.
---
정수 형태는 스칼라라고 한다
벡터에 스칼라를 곱하면 원소에서 스칼라 만큼 배를 취하면 된다.
모양이 같으면 덧셈을 할 수 있고
모양이 다르면 numpy 가 브로드캐스팅 을 통해서
연산을 알아서 수행한다.
---
행렬
숫자를 직사각형 모양으로 배열한 것
엑셀 표 데이터가 행렬데이터이다.
#### 💡 행렬의 의미
- **데이터 표**: 행 = 샘플, 열 = 변수
- **벡터의 집합**: 여러 벡터(2개 이상)의 모음
- **선형 변환**: 벡터를 입력하면, 특정 규칙(행렬 곱)에 따라 새로운 벡터로 바꿔주는 과정
→ 마치 벡터를 "회전, 확대/축소, 반사"시키는 것처럼 생각할 수 있다.
--
(3*5) * (7*8) 은 행렬 곱이 가능한가?
모양이 다른 두 행렬을 곱하게 되면은
A B C D 곱하게 되면 A*D이 나온다.
3. **행렬 곱**
- "앞 행렬의 행 × 뒤 행렬의 열"
- (m×n) × (n×p) = (m×p)
행렬곱은 알아야한다.
딥러닝 모델을 의도에 맞게 수정하려면 행렬 곱을 알아야 한다.
(m×n) × (n×p) = (m×p)
딥러닝 모델이
A(m×n) × B (n×p) 이렇게 생겼고
그 가운데 행렬을 계산할 수 있어야 한다
A 앞 , A와 B의 중간, B의 끝에 적용할 수 있는 모델의 크기를 알아야 한다.
명칭을 알아야한다.
전치행렬 (Transpose) : 행과 열을 뒤바꾼 행렬
(3.5)*(3.5)는 불가능하니
자기 자신으로 계산하려면
(3.5)*(5.3)로 돌려줘야 한다.
그래서 Transpose 전치 행렬로 말한다.
연산을 가능하기 위해서 행과 열을 바꿔주는 과정이 있다.
**단위행렬 (Identity)**: 대각선이 1, 나머지는 0
단위행렬을 곱하면 값이 바뀌어지지 않는다.
**역행렬 (Inverse)**: A와 곱했을 때 단위행렬이 되는 행렬
연립방정식
(이건 좀 확인해야겠다)
--
Numpy 기초
## 1. Numpy 기초
#### 배열이란?
- **배열(array)** 은 같은 종류의 데이터를 일정한 모양(행렬 형태)으로 모아놓은 것
- 파이썬 기본 리스트(list)와 달리, 배열은 **모든 원소가 같은 자료형**을 가지며 **고속 연산**이 가능
- 데이터 과학에서 다루는 데이터(표, 이미지, 시계열)는 대부분 "숫자들의 모음" → 배열로 표현하면 효율적
예시:
- 1차원 배열: `[1, 2, 3, 4]` (벡터)
- 2차원 배열: `[[1, 2], [3, 4]]` (행렬)
- 3차원 배열: 이미지(높이 × 너비 × 색상 채널)
#### 배열 생성 방법
- `np.array(리스트)` : 파이썬 리스트를 배열로 변환
- `np.arange(시작, 끝, 간격)` : 특정 범위의 정수를 순차적으로 생성
- `np.zeros(크기)` : 0으로 채운 배열 생성
- `np.ones(크기)` : 1로 채운 배열 생성
- `np.linspace(시작, 끝, 개수)` : 지정한 구간을 일정 간격으로 나눈 값 생성
---
#### 자료형 (dtype)
- 배열의 모든 원소는 **같은 자료형(dtype)** 을 가짐
- 기본적으로는 입력 데이터에 따라 자동 결정되지만, 직접 지정 가능
- 주요 자료형: int32, float64, bool, str
- `dtype` 로 자료형 지정 및 확인 가능
👉 여기서 `int32`의 **32**는 "32비트 정수"라는 뜻
- **비트(bit)** = 컴퓨터가 정보를 저장하는 최소 단위 (0 또는 1)
- **32비트 정수**는 32개의 0/1로 수를 표현 → 약 ±21억까지 표현 가능
- **64비트 정수**는 더 많은 비트를 쓰기 때문에 훨씬 더 큰 수까지 표현 가능
- 마찬가지로 `float32`, `float64`는 소수점 실수를 32비트 / 64비트로 저장
→ 64비트는 더 정밀한 소수 계산 가능
즉, 숫자가 커지거나 정밀도가 필요할수록 더 많은 비트를 사용하는 자료형을 선택한다.
소수를 저장할때는 얼마나 많이 나와서
손해를 보는건 float64를 쓰면 메모리를 크게 사용하다 보니
한정적인 hdd ram 일 경우에는 메모리를 많이 사용해서 느릴 수 있다.
float32를 사용할 거면 오버플로우가 생길 수 있다.
딥러닝에서도 많이 되는 활용
딥러닝 학습에서 속도가 중요할때는 float32를 사용하고
float64의 정밀성이 중요할 때는 float64를 사용한다.
정화다.
Q. 인덱싱과 슬라이싱이 너무 헷갈린다.
*인덱싱(Indexing)**과 **슬라이싱(Slicing)**은 NumPy 배열뿐만 아니라 파이썬의 리스트나 문자열 등에서 데이터를 다루는 데 있어 핵심적인 개념이지만, 처음에는 헷갈리기 쉽습니다.
핵심은 다음과 같습니다.
- 인덱싱은 배열에서 단 하나의 값을 꺼내는 것.
- 슬라이싱은 배열에서 **값의 묶음 (부분 배열)**을 꺼내는 것.
인덱싱 (Indexing): 하나의 값에 접근
인덱싱은 배열 내에서 특정 위치의 원소 하나에 접근하는 방법입니다.
1. 기본 인덱싱 (양수)
- 시작점: 인덱스는 항상 0부터 시작합니다.
- 사용법: arr [위치]
| 인덱스 | 0 | 1 | 2 | 3 |
| 값 | 'a' | 'b' | 'c' | 'd' |
- arr [0] 'a' (첫 번째 원소)
- arr [2] 'c' (세 번째 원소)
2. 음수 인덱싱
- 시작점: 배열의 맨 끝에서부터 역순으로 셉니다.
- 사용법: arr [-1]은 마지막 원소를 의미합니다.
| 인덱스 | 0 | 1 | 2 | 3 |
| 값 | 'a' | 'b' | 'c' | 'd' |
| 음수 인덱스 | -4 | -3 | -2 | -1 |
슬라이싱 (Slicing): 값의 묶음에 접근
슬라이싱은 배열의 **일부분 (부분 배열)**을 잘라내어 새로운 배열로 반환하는 방법입니다. 콜론 기호를 사용하여 범위를 지정합니다.
1. 기본 슬라이싱 문법
슬라이싱은 세 부분으로 구성되며, 콜론으로 구분합니다.
| 부분 | 설명 | 기본값 |
| start | 시작할 인덱스 (포함) | 0 |
| stop | 끝낼 인덱스 (미포함) | 배열의 끝 |
| step | 건너뛸 간격 | 1 |
2. 가장 중요한 규칙: stop은 포함하지 않는다
start 인덱스부터 시작해서, stop 인덱스 바로 앞까지만 포함합니다.
0123456 값 10203040506070
| 인덱스 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| 값 | 10 | 20 | 30 | 40 | 50 | 60 | 70 |
- arr [2:5]
- 인덱스 2 (값 30)에서 시작하여
- 인덱스 5 직전 (인덱스 4, 값 50)까지 포함
- 결과:
3. 생략을 이용한 슬라이싱
| 슬라이싱 | 의미 |
예시: [10,20,30,40,50]
|
| arr[:stop] | 처음부터 stop-1까지 |
arr[:3] → [10, 20, 30]
|
| arr[start:] | start부터 끝까지 |
arr[3:] → [40, 50]
|
| arr[:] | 전체 배열 |
arr[:] → [10, 20, 30, 40, 50]
|
| arr[::step] | 처음부터 끝까지 step 간격으로 |
arr[::2] → [10, 30, 50]
|
| arr[::-1] | 배열을 역순으로 |
→ [50, 40, 30, 20, 10]
|
요약 비교
| 특징 | 인덱싱 (Indexing) |
슬라이싱 (Slicing)
|
| 목적 | 배열에서 단일 원소 접근 |
배열에서 부분 집합 (배열) 접근
|
| 문법 | arr[위치] |
arr[start:stop:step]
|
| 결과 | 값 하나 (스칼라) |
새로운 배열 (부분 배열)
|
| 예시 | arr[1] → 20 |
arr[1:4] → [20, 30, 40]
|
인덱싱은 주소로 집 하나를 찾는 것이고, 슬라이싱은 도로 구간을 지정해서 여러 집을 묶어 보는 것이라고 생각하시면 이해하기 쉬울 거예요.
문제 1
1부터 10까지의 정수를 원소로 가지는 배열을 만들고,
- 첫 번째 원소
- 마지막 원소
- 인덱스 3~6 구간 (즉, 4번째부터 7번째까지)
import numpy as np
arr = np.arange(1,11)
print(arr[0])
print(arr[-1])
print(arr[3:7])
문제 2
다음 배열이 있을 때
arr = np.array([[10, 20, 30],
[40, 50, 60],
[70, 80, 90]])
- 2행 전체를 출력하세요.
- 1열(세로 방향)을 출력하세요.
- 부분 배열 [[20, 30], [50, 60]] 을 슬라이싱으로 꺼내보세요.
1. 2차원 배열 인덱싱/슬라이싱의 기본
2차원 배열(행렬)에서 인덱싱과 슬라이싱을 할 때는 보통 두 개의 인덱스를 사용하며, 콤마(,)로 구분합니다.
✅ 첫 번째 & 두 번째 출력 (정답)
- 2행 전체 출력:
print(arr[1,:])
# [40 50 60]
-
- 설명: 행 인덱스 (0부터 시작하므로 두 번째 행)을 지정하고, 열 인덱스 자리에 (콜론)을 사용하여 '모든 열'을 선택했습니다.
- 1열 전체 출력:
print(arr[:,1])
# [20 50 80]
-
- 설명: 행 인덱스 자리에 $\mathbf{:}$을 사용하여 '모든 행'을 선택하고, 열 인덱스 (두 번째 열)을 지정했습니다.
2. 세 번째 출력 (오답 및 수정)
❌ 당신의 답의 문제점
당신의 답: print(arr[2:3,:1:3])
- 목표: [[20, 30], [50, 60]] (1행과 2행의 2열과 3열)을 꺼내는 것.
- arr[행 슬라이스, 열 슬라이스]
- 행 슬라이스 2:3: 인덱스 2 (세 번째 행, 값 70, 80, 90)만 포함합니다.
- 열 슬라이스 :1:3: 인덱스 0에서 1까지 3단계 간격으로 (즉, 인덱스 0만 선택됨)
- 결과: 목표와 전혀 다릅니다.
💡 올바른 슬라이싱
원하는 부분 배열 [[20, 30], [50, 60]]을 얻기 위해서는 다음 조건을 만족해야 합니다.
- 행 선택: 1행 (인덱스 0)과 2행 (인덱스 1)을 선택해야 합니다.
- 슬라이스: (0부터 2 직전까지)
- 열 선택: 2열 (인덱스 1)과 3열 (인덱스 2)을 선택해야 합니다.
- 슬라이스: (1부터 3 직전까지)
따라서 올바른 코드는 다음과 같습니다.
arr = np.array([[10, 20, 30],
[40, 50, 60],
[70, 80, 90]])
print(arr[1,:])
print(arr[:,1])
print(arr[0:2, 1:3])
'AI 엔지니어 부트캠프 > 파이썬 데이터 분석 기초와 머신 러닝 기초' 카테고리의 다른 글
| DataFrame 마스터하기 (0) | 2025.10.01 |
|---|---|
| 기초 통계와 데이터 시각화 (2) | 2025.10.01 |
| 문자열 압축 게임 (0) | 2025.09.26 |
| 2025.09.26(화) - 1주 2일차 강의 복습 (3) - 객체와 클래스 (0) | 2025.09.26 |
| 단어장 만들기 (0) | 2025.09.26 |