<안내>
필자도 배우는 입장이라 틀린점, 잘못된 점이 있을 수 있습니다.
그러니 지적, 피드백 환영합니다.
1. Numpy 시작하기¶
numpy모듈 불러오기¶
import numpy as np # 넘파이는 속도가 정말 빠름
왜 numpy를 쓰는 지 ?¶
numpy와 array를 활용하여 비교함
list¶
L = range(1000)
%timeit [i**2 for i in L] # %는 노트북 특수의 매직 키워드(주피터노트북의 특수 함수)
206 µs ± 2.51 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
numpy array
N = np.arange(1000)
%timeit N ** 2 # 넘파이가 진짜 뒤지게 빠름
1.34 µs ± 7.54 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
numpy.array¶
numpy의 Container, array
arr = np.array([1,2,3])
arr
array([1, 2, 3])
arr_2d = np.array([[1,2,3],[4,5,6],[7,8,9]])
arr_2d # 하나씩 띄어서 나옴
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
arr.shape
(3,)
arr_2d.shape # .shape 하면 차원을 알 수 있음
(3, 3)
Numpy로 연산하기¶
Vector와 Scalar 사이의 연산¶
벡터의 각 원소에 대해서 연산을 진행
x = np.array([1,2,3])
c = 5
print("더하기 : {}".format(x + c)) # 벡터의 각 원소에 대해 더하기를 함
print("빼기 : {}".format(x - c)) # 벡터의 각 원소에 대해 빼기를 함
print("곱하기 : {}".format(x * c)) # 벡터의 각 원소에 대해 곱하기를 함
print("나누기 : {}".format(x / c)) # 벡터의 각 원소에 대해 나누기를 함
더하기 : [6 7 8]
빼기 : [-4 -3 -2]
곱하기 : [ 5 10 15]
나누기 : [0.2 0.4 0.6]
Vector 와 Vector 사이의 연산¶
벡터와 같은 인덱스 끼리 연산이 진행!
y = np.array([1,3,5])
z = np.array([2,9,20])
print("더하기 : {}".format(y + z))
print("빼기 : {}".format(y - z))
print("곱하기 : {}".format(y * z))
print("나누기 : {}".format(y / z))
더하기 : [ 3 12 25]
빼기 : [ -1 -6 -15]
곱하기 : [ 2 27 100]
나누기 : [0.5 0.33333333 0.25 ]
array의 인자는 하나임! array(리스트를 넣든,,)¶
Array의 indexing¶
array에서 특정위치 원하는 원소를 가져오고싶다면?
파이썬에서는 <리스트이름>[리스트의 인덱스번호]
넘파이에서는 <어레이이름>[어레이의 인덱스번호]
리스트안에 리스트가 있는 경우에 살짝 다른데,
파이썬 : <리스트이름>[리스트 인덱스번호][리스트인덱스번호]
넘파이 : <리스트이름>[리스트 인덱스번호, 리스트인덱스번호]
Array Indexing¶
python의 리스트와 유사하게 진행
w = np.array([[1,2,3,4], [5,6,7,8],[9,10,11,12]])
w[0,0]
1
w[2, 3]
12
w[1,2]
7
w = np.array([[1,2,3,4], [5,6,7,8],[9,10,11,12]])
# 2,3, -> 행 : 인덱스 0~1 : [0:2]
# 6, 7 -> 열 : 인덱스 1~2 : [1,3]
w[0:2, 1:3]
array([[2, 3],
[6, 7]])
w[:2, 1:3]
w[:2, :]
w[:,2:]
array([[ 3, 4],
[ 7, 8],
[11, 12]])
Array의 Broadcasting¶
numpy가 연산을 진행하는 특수한 방법!
m n , m 1 를 더하고 싶다면?
numpy에서는 두번째 m * 1 을 계속 복사해서 더할 수 있음(차원이 달라도 더할 수 있다 라는 말! ) 곱하기 빼기 경우에도 동일하게 적용되네
m 1 , 1 n : 서로서로 도와서 진행이 됨
m n 으로 복사가되고 , m n 으로 복사가 됨
Array의 Broadcasting (강의버전)¶
기본적으로 같은 타입의 data에 대해서 연산이 적용가능
하지만 피 연산자가 연산가능하도록 변환이 가능하다면 연산이 가능합니다
이를 Broadcasting 이라고 합니다
1. M by N , M by 1¶
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
x= np.array([0,1,0]) # 가로로 0 1 0 인 행렬
x = np.transpose([x])
# x = x[:,None] # x를 전치 해줌 (x,y) -> (y,x)
print(a)
print('')
print(x)
print('')
print (a + x)
[[1 2 3]
[4 5 6]
[7 8 9]]
[[0]
[1]
[0]]
[[1 2 3]
[5 6 7]
[7 8 9]]
공식설명을 보시면 확인하실 수 있습니다~ 1차원 벡터를 사용하면 여전히 벡터이기 때문에 효과가 없다라고 나와있습니다. x[:, None] 과 동일한 결과를 transpose로 만들고싶다면 차원을 하나 더 추가해주셔야 합니다
-> np.transpose([x])
으로 만들어주면 댐
2. M by N, 1 by N¶
y = np.array([0,1,-1])
print(a * y)
[[ 0 2 -3]
[ 0 5 -6]
[ 0 8 -9]]
3. M by 1, 1 by N¶
t = np.array([1,2,3]) # 열벡터로 바꿈!
t = t[:,None]
u = np.array([2,0,-2])
print(t + u)
[[ 3 1 -1]
[ 4 2 0]
[ 5 3 1]]
np.zeros((3,3)) # 컨테이너로 묶어야 함
array([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
np.zeros(3)
array([0., 0., 0.])
np.zeros((3,3,3))
array([[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]])
일행렬(일벡터)¶
- 모든 원소가 1 인 행렬(벡터)
np.ones(dim)
을 통해 생성, dim 은 값, 튜플(, )
np.ones((2))
array([1., 1.])
np.ones((3,3))
array([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
대각행렬(diagonal matrix)¶
- Main Diagonal을 제외한 성분이 0인 행렬
np.diag((main_diagonals))
을 통해 생성할 수 있음
np.diag((2,4))
array([[2, 0],
[0, 4]])
np.diag((1,3,5))
array([[1, 0, 0],
[0, 3, 0],
[0, 0, 5]])
항등행렬¶
- main diagonal == 1인 diagonal matirix(대각행렬)
np.eye(n, (dtype = int, uint, float, complex, ...))
를 사용
np.eye(2)
array([[1., 0.],
[0., 1.]])
np.eye(2,dtype = int)
array([[1, 0],
[0, 1]])
np.eye(3)
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
행렬곱¶
- 행렬간에 정의되는 곱 연산(dot product)
np.dot()
or@
사용
mat_1 = np.array([[1,4],[2,3]])
mat_2 = np.array([[7,9],[0,6]])
print(mat_1.dot(mat_2))
print('')
print(mat_1 @ mat_2)
[[ 7 33]
[14 36]]
[[ 7 33]
[14 36]]
트레이스¶
- Main Diagonal의 합
np.trace()
를 사용
arr = np.array([[1,2,3],[4,5,6],[7,8,9]])
arr
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
arr.trace()
15
np.eye(2, dtype= int).trace() # 항등행렬은 그 차원의 갯수와 trace가 같다
2
행렬식(Determinant)¶
- 행렬을 대표하는 값들 중 하나
- 선형변환 과정에서 Vector 의 Scaling 척도
np.linalg.det()
로 계산- det(a) == 0 이면 singular matrix (특이행렬)
arr_2 = np.array([[2,3],[1,6]])
print(np.linalg.det(arr_2))
9.000000000000002
arr_3 = np.array([[1,4,7],[2,5,8],[3,6,9]])
arr_3
array([[1, 4, 7],
[2, 5, 8],
[3, 6, 9]])
np.linalg.det(arr_3)
0.0
역행렬(Inverse matrix)¶
- 행렬 A에 대해서 AB = BA = 1을 만족하는 행렬 B
np.linalg.inv()
을 사용
mat = np.array([[1,4],[2,3]])
print(mat)
print('')
mat_inv = np.linalg.inv(mat)
print(mat_inv)
[[1 4]
[2 3]]
[[-0.6 0.8]
[ 0.4 -0.2]]
mat @ mat_inv
array([[ 1.00000000e+00, 0.00000000e+00],
[-1.11022302e-16, 1.00000000e+00]])
고유값과 고유벡터 ( eigenvalue and eigenvector)¶
- 정방행렬(nxn) A에 대해 $Ax = \lambda x를 만족하는 \lambda 와 x$를 각각 고유값과 고유벡터라고 한다
np.linalg.eig()
으로 계산
mat = np.array([[2,0,-2],[1,1,-2],[0,0,-1]])
np.linalg.eig(mat)
(array([ 1., 2., -1.]),
array([[0. , 0.70710678, 0.48507125],
[1. , 0.70710678, 0.48507125],
[0. , 0. , 0.72760688]]))
eig_val, eig_vec = np.linalg.eig(mat)
eig_val
array([ 1., 2., -1.])
eig_vec
array([[0. , 0.70710678, 0.48507125],
[1. , 0.70710678, 0.48507125],
[0. , 0. , 0.72760688]])
mat @ eig_vec[:, 0] # Ax 의 결과
array([0., 1., 0.])
eig_val[0] * eig_vec[:,0] # (lambda)x
array([0., 1., 0.])
print(mat @ eig_vec[:, 1])
print(eig_val[1] * eig_vec[:,1])
print(mat @ eig_vec[:, 2])
print(eig_val[2] * eig_vec[:,2])
[1.41421356 1.41421356 0. ]
[1.41421356 1.41421356 0. ]
[-0.48507125 -0.48507125 -0.72760688]
[-0.48507125 -0.48507125 -0.72760688]
정의에 따라, 행렬 @ 고유 백터 와 고유 값 * 고유 백터가 완벽하게 일치하는 것을 확인할 수 있다
1번 풀이¶
# 박치기식 코딩하기
arr_2 = np.array([[-1,2]])
def get_L2_norm(arr):
answer = 0
for x,y in arr:
answer= (x**2+y**2)**(1/2)
return answer
get_L2_norm(arr_2)
2.23606797749979
# math 함수 이용하기 (math.sqrt())
import math
arr_2 = np.array([[-1,2]])
def get_L2_norm(arr):
answer = 0
for x,y in arr:
answer= math.sqrt((x**2+y**2))
return answer
get_L2_norm(arr_2)
2.23606797749979
Norm 값이란?¶
벡터의 길이를 구하는 것이라고 보면 되는데, 종류가
L1 norm, L2 norm, L$\infty$ norm, L0 norm 등이 있다.
- L1 norm
택시타고 가는 거리라고 생각하면 된다.
(0,0)에서 (a,b)까지 L1의 방식으로 갈 때,
(0,0) - (a,0) - (a,b)의 방식으로 수직으로 또각또각 가는 거리가 L1 norm이다
식으로 표현한다면,
$$|a| + |b|$$ 로 표현할 수 있다. - L2 norm
비행기 타고 가는 거리라고 생각하면 된다.
(0,0)에서 (a,b)까지 L2 방식으로 갈 때,
(0,0) - (a,b) 로 곧게 뻗은 직선으로 가는 거리가 L2 norm이다
식으로 표현한다면, $$\sqrt{a^2 + b^2}$$ 로 표현할 수 있다. - L$\infty$ norm
현재 벡터에서 가장 큰 원소의 절댓값이다.
- L0 norm
현재 벡터에서 0이 아닌 원소의 개수이다.
2번 풀이¶
import numpy as np
def is_singular(arr):
if np.linalg.det(arr) == 0:
return True
else:
return False
arr_sing = np.array([[2,1],[4,2]])
arr_nonsing = np.array([[2,1],[3,2]])
print('arr_sing:',is_singular(arr_sing))
print('arr_nonsing:',is_singular(arr_nonsing))
arr_sing: True
arr_nonsing: False
문제 접근 방향:
- singular matrix 가 뭔지 일단 알아야함
- singular matrix 조건을 뭔지 알아야함 (det(a) == 0)
- det(a)를 구하는 방법을 알아야함 ( np.linalg.det(a))
- det(a)를 구했다면 det(a)에 따라 판독하는걸로
'TIL > [겨울방학 부트캠프]TIL' 카테고리의 다른 글
TIL 6일차 (22.01.10) (0) | 2022.01.10 |
---|---|
TIL 5일차 (22.01.07) (0) | 2022.01.07 |
TIL 4일차 (22.01.06) (0) | 2022.01.06 |
TIL 3일차 (22.01.05) (0) | 2022.01.05 |
TIL 1일차(22.01.03) (0) | 2022.01.04 |