Linear algebra is the branch of mathematics that deals with vector spaces.
๐ Vectors
์ถ์์ ์ผ๋ก, vector๋ ์๋ก ๋ํ๊ณ , scalar๋ฅผ ๊ณฑํ๊ณ , ์๋ก์ด ๋ฒกํฐ๋ฅผ ์์ฑํ ์ ์๋ ๊ฐ์ฒด์ด๋ค.
๊ตฌ์ฒด์ ์ผ๋ก๋, vector๋ ์ด๋ค ์ ํํ ์ฐจ์์ ๊ณต๊ฐ์์์ ์ ์ด๋ค. ์ง๊ธ๊น์ง ๋ณด์๋ data๋ฅผ vector๋ผ๊ณ ์๊ฐํ์ง ์๊ฒ ์ง๋ง, ๊ทธ data๋ค์ numeric data๋ฅผ ๋ํํ ์ ์๋ ์ข์ ์๊ฐ ๋๋ค.
์๋ฅผ ๋ค์ด, ๋ง์ ์ฌ๋๋ค์ ํค, ๋ชธ๋ฌด๊ฒ, ๋์ด ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์์ ๋, ๊ทธ ๋ฐ์ดํฐ๋ 3์ฐจ์์ vector๋ก ๋ค๋ฃฐ ์ ์๋ค. ํน์ ํ์๋ค์ ์ํ ์ฑ์ ๋ฐ์ดํฐ๋ฅผ 4์ฐจ์์ vector(exam1, exam2, exam3, exam4
)๋ก ๋ค๋ฃฐ ์ ์์ ๊ฒ์ด๋ค.
vector๋ฅผ ํํํ ์ ์๋ ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ์ซ์๋ค์ list๋ก ํํํ๋ ๊ฒ์ด๋ค. 3๊ฐ์ ์ซ์๋ก ๊ตฌ์ฑ๋์ด ์๋ list์ 3์ฐจ์์ ๋ฒกํฐ๋ ์๋ก ๋์๋ ์ ์์ ๊ฒ์ด๋ค.
Abstractly, vectors are objects that can be added together(to form new vectors) and that can be multiplied by scalars, also to form new vectors.
Concretely (for us), vectors are points in some finite-dimensional space. Although you might not think of your data as vectors, they are a good way to represent numeric data.
For example, if you have the heights, weights, and ages of a large number of peaple, you can treat your data as three-dimensional vectors(`height, weight, age`). If you're teaching a class with four exams, you can treat student grades as four-dimensional vectors(`exam1, exam2, exam3, exam4`)
The simplest from-scratch approach is to represent vectors as list of numbers. A list of three numbers corresponds to a vector in three-dimensional space, and vice versa:
height_weight_age = [70, 170, 40] # height(inches), weight(pounds), age(years)
grades = [95, 80, 75, 62] # exam1, exam2, exam3, exam4
ํ์ง๋ง ์ด๋ฐ ๋ฐฉ์์ผ๋ก ์ ๊ทผํ์ ๋์ ๋ฌธ์ ์ ์ ํ์ด์ฌ์์ list๋ vector๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ๋ vector์ ๋ํ ์ํ์ ์ธ ๋๊ตฌ๋ค์ ์ฐ๋ฆฌ ์ค์ค๋ก ๋ง๋ค์ด ์ฌ์ฉํด์ผ ํ๋ค.
์๋ฅผ ๋ค๋ฉด, ๋ ๊ฐ์ ๋ฒกํฐ๋ฅผ ๋ํ๋ ๊ฒ์ ์๊ฐํด๋ณด์.
Vectors add componentwise : ๋ ๊ฐ์ ๋ฒกํฐ์ ๊ธธ์ด๊ฐ ๊ฐ๋ค๋ฉด, ๋ ๋ฒกํฐ์ ํฉ์ ์๋ก ๊ฐ์ ์์น์ ์ธ๋ฑ์ค์ ์๋ ๊ฐ๋ค๋ผ๋ฆฌ ๋ํ list์ด๋ค. (If they're not the same length, then we're not allowed to add them.)
ex) [1, 2] + [2, 1]
result in [1+2, 2+1
] or [3, 3]
def vector_add(v, w):
"""adds corresponding elements"""
return [v_i + w_i
for v_i, w_i in zip(v, w)]
def vector_subtract(v, w):
"""subtracts corresponding elemnts"""
return [v_i - w_i
for v_i, w_i in zip(v, w)]
We'll also sometimes want to componentwise sum a list of vectors. That is, create a new vector whose first element is the sum of all the first elemnts, whose second element is the sum of all of second elemnts, and so on. The easiest way to do this is by adding one vector at a time:
def vector_sum(vectors):
"""sums all corresponding elements"""
result = vectors[0] # start with first vector
for vector in vectors[1:]: # then loop over the others
result = vector_add(result, vector) # and add them to the result
return result
we can rewrite this more briefly
from functools import partial, reduce
def vector_sum(vectors):
return reduce(vector_add, vectors)
vector_sum = partial(reduce, vector_add) # this one is more clever and helpful
vector_sum([[1, 2, 3], [1, 2, 3], [1, 2, 3]])
[3, 6, 9]
def scalar_multiply(c, v):
"""c is a number(scalar), v is a vector"""
return [c * v_i for v_i in v]
def vector_mean(vectors):
"""compute the vector whose ith element is the mean of the
ith elements of the input vectors"""
n = len(vectors)
return scalar_multiply(1/n, vector_sum(vectors))
The dot product of two vectors is the sum of their componentwise products:
def dot(v, w):
"""v_i * w_i + ... + v_n * w_n"""
return sum(v_i * w_i
for v_i, w_i in zip(v, w))
dot([1, 2], [1, 2])
5
dot product๋ v
๋ฒกํฐ๊ฐ w
์ ๋ฐฉํฅ์ผ๋ก ์ผ๋ง๋ ํ์ฅ๋ ์ ์๋์ง๋ฅผ ์ธก์ ํ๋ค. ์๋ฅผ๋ค์ด, w = [1, 0]
์ด๋ฉด dot(v, w)
๋ v
๋ฒกํฐ์ ๊ฐ๋ค.
์ด๊ฒ์ v
๋ฅผ w
์ _project_ํ์ ๋ ๊ทธ ๋ฒกํฐ์ ๊ธธ์ด์ ๊ฐ๋ค.
The dot product measures how far the vector v extends in the w direction. For example, if w=[1, 0]
then dot(v, w)
is just the first component of v. Another way of saying this is that it's the length of the vector you'd get if you projucted v
onto w
์ด๋ฅผ ์ด์ฉํด์ vector์ ์ ๊ณฑํฉ_sum of square_๋ฅผ ์ฝ๊ฒ ๊ตฌํ ์ ์๋ค.
def sum_of_squares(v):
"""v_1 * v_1 + v_2 * v_2 + ... + v_n * v_n"""
return dot(v, v)
sum_of_squares([3, 4])
25
import math
def magnitude(v): #magnitude of vector means length of vector
return math.sqrt(sum_of_squares(v)) #math.sqrt is square root function
magnitude([3, 4])
5.0
let's get a distance of two vectors!
def squared_distance(v, w):
"""(v_1 - w_1) ** 2 + ... (v_n - w_n) ** 2"""
return sum_of_squared(vector_subtract(v, w))
def distance(v, w):
return math.sqrt(sqquared_disatnce(v, w))
def distance(v, w):
return magnigude(vector_subtract(v, w))
๐ Matrix
matrix๋ 2์ฐจ์์ผ๋ก ๊ตฌ์ฑ๋ ์ซ์๋ค์ ๋ชจ์์ด๋ค. ํ์ด์ฌ์๋ ๋งคํธ๋ฆญ์ค๋ฅผ ์ค์ฒฉ๋ listํํ๋ก ๋ํ๋ธ๋ค. ์๋ฅผ ๋ค์ด A๊ฐ ํ๋ ฌ์ด๋ผ๋ฉด, A[i][j]
๋ i๋ฒ์งธ row์ j๋ฒ์งธ column์ ๊ฐ์ ๋งํ๋ค. (๋ณดํต, ํ๋ ฌ์ ์ด๋ฆ์ ๋๋ฌธ์๋ฅผ ์ฌ์ฉํ๋ค.)
A = [[1, 2, 3],
[4, 5, 6]] # A has 2 rows and 3 columns
B = [[1, 2],
[3, 4],
[5, 6]] # B has 3 rows and 2 columns
def shape(M):
num_rows = len(M)
num_cols = len(M[0]) if M else 0 # number of elements in first row
return num_rows, num_cols
shape(A)
(2, 3)
matrix๊ฐ n๊ฐ์ row์ k๊ฐ์ column์ ๊ฐ์ง๊ณ ์๋ค๋ฉด, ์ด ํ๋ ฌ์ nโk
matrix๋ผ๊ณ ๋ถ๋ฅธ๋ค.
์ฌ๊ธฐ์ nโk
matrix์ ๊ฐ๊ฐ์ row๋ค์ ๊ธธ์ด๊ฐ k
์ธ ๊ฐ๊ฐ์ ๋ฒกํฐ๋ค์ด๊ณ / ๊ฐ๊ฐ์ column๋ค์ ๊ธธ์ด๊ฐ n์ธ ๊ฐ๊ฐ์ ๋ฒกํฐ๋ค๋ก ์๊ฐํ ์ ์๋ค.
def get_row(M, i):
return M[i]
def get_column(M, j):
return [M_i[j]
for M_i in M]
get_row(A, 0)
[1, 2, 3]
get_column(A, 1)
[2, 5]
def make_matrix(num_rows, num_cols, entry_fn):
"""returns a num rows x num cols matrix
whose (i,j)th entry is entry_fn(i, j)"""
return [[entry_fn(i, j) # given i, create a list
for j in range(num_cols)] # [entry_fn(i, 0), ...]
for i in range(num_rows)] # create one list for each i
def is_diagonal(i, j):
"""1's on the 'diagonal', 0's everywhere else"""
return 1 if i == j else 0
identity_matrix = make_matrix(5, 5, is_diagonal)
identity_matrix
[[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 0, 1]]
matrix๊ฐ ์ฐ๋ฆฌ์๊ฒ ์ค์ํ ์ด์ !
- matrix๋ฅผ ํ๋์ row๋ก์ ์ทจ๊ธ๋๋ ๊ฐ๊ฐ์ ๋ฒกํฐ๋ค๋ก ์ด๋ฃจ์ด์ง ๋ฐ์ดํฐ์ ์ ํํํ ๋ ์ฌ์ฉํ ์ ์๋ค.
nโk
matrix๋ฅผ k์ฐจ์ ๋ฒกํฐ์ n์ฐจ์ ๋ฒกํฐ๋ฅผ ๋งคํํ๋ ์ ํ ํจ์๋ฅผ ํํํ๋๋ฐ์ ์ฌ์ฉํ ์ ์๋ค.- matrix๋ค์ binary relationships๋ฅผ ํํํ๋๋ฐ์ ์ฌ์ฉํ ์ ์๋ค.
์๋ฅผ ๋ค์ด, ์๋์์ ์๋์๋ friendships๋ฅผ(i, j)
์๋ค๋ก binary ๊ด๊ณ๋ฅผ ํํํ๋ค๋ฉด, ํ๋ ฌ์ ํตํด์๋ ๊ด๊ณ๊ฐ ์์ ๋ 1, ์์ ๋ 0์ ๊ฐ์ ํ์ํจ์ผ๋ก์จ user ํ ๋ช ๋น ํ๋์ vector๋ฅผ ๋์์ํฌ ์ ์๋ค.
friendships = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3), (3, 4), (4, 5), (5, 6), (5, 7), (6, 8), (7, 8), (8, 9)] # user0 1 2 3 4 5 6 7 8 9 friendships = [[0, 1, 1, 0, 0, 0, 0, 0, 0, 0], # user 0 [1, 0, 1, 1, 0, 0, 0, 0, 0, 0], # user 1 [1, 1, 0, 1, 0, 0, 0, 0, 0, 0], # user 2 [0, 1, 1, 0, 1, 0, 0, 0, 0, 0], # user 3 [0, 0, 0, 1, 0, 1, 0, 0, 0, 0], # user 4 [0, 0, 0, 0, 1, 0, 1, 1, 0, 0], # user 5 [0, 0, 0, 0, 0, 1, 0, 0, 1, 0], # user 6 [0, 0, 0, 0, 0, 1, 0, 0, 1, 0], # user 7 [0, 0, 0, 0, 0, 0, 1, 1, 0, 1], # user 8 [0, 0, 0, 0, 0, 0, 0, 0, 1, 0]] # user 9
์ฐ๊ฒฐ๋ ๊ด๊ณ๊ฐ ์ ๋ค๋ฉด, tuple๋ก ์ ์ฅํ frinedships
๋ณด๋ค 0์ ๋ ๋ง์ด ์ ์ฅํด์ผํ๋ฏ๋ก ๋นํจ์จ์ ์ธ friendships
๊ฐ ๋ ์ ์๊ฒ ์ง๋ง, ํ๋ ฌ ํํ์ ๋ ๊ฐ์ node๊ฐ ์ฐ๊ฒฐ๋์๋์ง ํ์ธํ๋๋ฐ์ ์์ด์ ํจ์ฌ ๋น ๋ฅด๋ค. (๋ชจ๋ edge๋ฅผ ํ์ํ์ง ์๊ณ ํ๋์ matrix๋ง ๋ณด๋ฉด ๋๊ธฐ ๋๋ฌธ์ด๋ค.)
print(friendships[0][2] == 1) # True, user0 and user2 are friends.
print(friendships[0][8] == 1) # False, user0 and user8 are not friends.
True
False
์ ์ฌํ๊ฒ, ํ๋์ ๋ ธ๋๊ฐ ๊ฐ์ง๊ณ ์๋ connection์ ์ฐพ์ ๋๋ ํ๋์ column(๋๋ row)๋ง ํ์ธํ๋ฉด ๋๋ค.
friends_of_user5 = [i
for i, is_friend in enumerate(friendships[5])
if is_friend]
friends_of_user5
[4, 6, 7]
๋๊ธ