[개발자를 위한 실전 선형대수학] Chapter 1 연습문제

[chapter 1] 벡터, 파트1 : 벡터와 벡터의 기본 연산 

 

1-1

그림 1-2를 만드는 코드 작성하기

그림 1-2

그림 1-2를 파이썬으로 그린 그림

내 코드

v = np.array([1,2])
w = np.array([4,-6])
vPlusW = v+w

1-2

식 1-7을 코드로 변환해서 벡터 노름을 계산하는 알고리즘 작성하기

차원과 방향이 다른 난수 벡터를 사용해서 np.linalg.norm()과 동일한 결과를 얻는지 확인

식 1-7

$$ \left\| v\right\| = \sqrt{\sum_{i=1}^{n}v_{i}^{2}} $$

내 코드

# 벡터
v = np.array([1,2,3,4])

norm1 = np.sqrt(np.sum(v**2))
norm2 = np.linalg.norm(v)
print(norm1, norm2) # 5.477225575051661 5.477225575051661

 

1-3

벡터를 입력으로 받아 동일한 방향의 단위벡터를 출력하는 파이썬 함수 구현

내 코드

# 벡터
v = np.array([1,2,3,4])
w = np.array([0,1,0])
zeroV = np.array([0,0,0,0])

def createUnitVector(v):
  norm = np.linalg.norm(v)
  return v / norm

print(createUnitVector(v)) # [0.18257419 0.36514837 0.54772256 0.73029674]
print( createUnitVector(w) ) # [0. 1. 0.]
createUnitVector( np.zeros((4,1)) ) #  RuntimeWarning: invalid value encountered in divide

1-4

벡터와 원하는 크기를 입력 받고 벡터와 동일한 방향이지만 두 번째 입력에 해당하는 크기를 가진 벡터를 반환하는 파이썬 함수\

내 코드

v = np.array([1,0,0]) # 벡터
vNorm = np.linalg.norm(v) # 벡터 크기
v2 = v / vNorm # 단위 벡터
size = 4 # 크기

print(v2) # 단위 벡터 [1. 0. 0.]
print(v2 * size) # [4. 0. 0.]

단위벡터를 구한 뒤 크기를 곱함(스칼라-벡터 곱셈)

1-5

np.transpose(v) 또는 v.T와 같은 내장 함수 또는 메서드를 사용하지 않고 행벡터를 열벡터로 전치하는  for 루프 작성

정답 코드

v = np.array([[1,2,3]]) # 행벡터
vt = np.zeros((3,1), dtype=np.int) # 열벡터. 데이터 타입을 맞춰줌

for i in range(v.shape[1]):
  vt[i,0] = v[0,i]

print(v), print(' ') # [[1 2 3]]
print(vt)
# [[1.]
#  [2.]
#  [3.]]

1-6

벡터의 제곱 노름을 그 벡터 자체의 내적으로 계산할 수 있다.(식 1-7 참고) 파이썬으로 확인하기.

식 1-7

$$ \left\| v\right\| = \sqrt{\sum_{i=1}^{n}v_{i}^{2}} $$

내 코드

v = np.array([1,2,3]) # 벡터
w = np.array([1,2,3]) # 같은 벡터를 선언함

norm = np.linalg.norm(v) # 노름
dot = np.dot(v,w) # 같은 두 벡터의 내적

print(norm * norm) # 14.0
print(dot) # 14

정답 코드

def normOfVect(v):
  return np.sqrt(np.sum(v**2))

# some vector
c = np.random.randn(5)

# squared norm as dot product with itself
sqrNrm1 = np.dot(c,c)

# squared norm via our function from exercise 1
sqrNrm2 = normOfVect(c)**2

# print both to confirm they're the same
print( sqrNrm1 )
print( sqrNrm2 )

1-7

내적의 교환법칙을 입증하는 코드 작성. 코드를 통해 구현한 다음 식 1-9를 사용해 내적이 교환 가능한 이유 이해하기

내적의 교환 법칙

$$  a^{T}b = b^{T}a $$

식 1-9

$$\partial = \sum_{i=1}^{n}a_{i}b_{i} $$

정답 코드

n = 11 # 차원

a = np.random.randn(n,1) # 랜덤한 두 개의 열벡터를 만듦
b = np.random.randn(n,1)

atb = np.sum(a*b) # 내적
bta = np.sum(b*a) # 내적(반대로)

atb - bta # 두 개가 같으면 0이 나와야 함

🤔궁금했던 점 with ChatGPT

위 코드에서 np.sum(a*b)는 가능한데, np.dot(a,b)를 하면 에러가 났다. 

np.dot(a, b)는 행렬 곱셈을 수행하는 함수이기 때문에, 두 벡터가 앞 행렬의 열 수 = 뒤 행렬의 행 수 형태여야 한다.

즉, 두 벡터 shape의 조건이

atb = np.dot(a.T, b)   # (1, n) · (n, 1)  -> (1,1)
bta = np.dot(b.T, a)   # (1, n) · (n, 1)  -> (1,1)

 

위는 행렬 곱이었고, 파이썬에서 a*b로 구현한 곱은 아다마르곱이다.

아다마르곱의 경우 두 벡터의 모양이 완전히 같아야 성립한다.

즉, 열벡터끼리 내적을 구할때는 하나를 전치해서 행벡터로 만들거나, 아다마르곱을 사용해야 한다.

(크기가 다르면 선형대수 관점에서 차원이 다르기 때문에 내적을 구할 수 없다)

1-8

코드로 그림 1-6을 만들기

내 코드

a = np.array([1,2])
b = np.array([1.5,.5])

beta = np.dot(a,b) / np.dot(a,a)
projection = b - beta*a
print(projection)

1-9

직교벡터 분해 구현하기.

두 난수 벡터 t와 r로 시작해서 그림 1-8 재현하고, 두 성분의 합이 t이고  $t\perp_{r}$과 $t\parallel_{r}$이 직교하는지 확인

정답 코드

# 난수 벡터
t = np.random.randn(2) 
r = np.random.randn(2) 

t_para = r * (np.dot(t,r) / np.dot(r,r))
t_perp = t - t_para

print(t)
print( t_para+t_perp ) # 두 성분의 합이 벡터와 같다

print( np.dot(t_para,t_perp) ) # 두 성분은 직교한다

1-10은 생략