Python 으로 행렬 만들기

 

Vector & Matrix

 

벡터와 행렬도 숫자처럼 덧셈, 뺄셈, 곱셈 등의 연산을 있다. 벡터와 행렬의 연산을 이용하면 대량의 데이터에 대한 계산을 간단한 수식으로 나타낼 있다. 물론 벡터와 행렬에 대한 연산은 숫자의 사칙 연산과는 가지 다른 점이 있으므로 이러한 차이를 알아야 한다.

절에서는 넘파이를 이용하여 벡터와 행렬의 연산을 실행하는 법도 공부한다. 다음처럼 넘파이와 맷플롯립 패키지가 임포트되어 있어야 한다.

In [1]:

import numpy as np

import matplotlib.pylab as plt

벡터/행렬의 덧셈과 뺄셈

같은 크기를 가진 개의 벡터나 행렬은 덧셈과 뺄셈을 있다. 벡터와 행렬에서 같은 위치에 있는 원소끼리 덧셈과 뺄셈을 하면 된다. 이러한 연산을 요소별(element-wise) 연산이라고 한다.

예를 들어 벡터 𝑥x 𝑦y 다음과 같으면,

𝑥=⎡⎣⎢⎢101112⎤⎦⎥⎥,𝑦=⎡⎣⎢⎢012⎤⎦⎥⎥(2.2.1)(2.2.1)x=[101112],y=[012]

벡터 𝑥x 𝑦y 덧셈 𝑥+𝑦x+y 뺄셈 𝑥−𝑦x−y 다음처럼 계산한다.

𝑥+𝑦=⎡⎣⎢⎢101112⎤⎦⎥⎥+⎡⎣⎢⎢012⎤⎦⎥⎥=⎡⎣⎢⎢10+011+112+2⎤⎦⎥⎥=⎡⎣⎢⎢101214⎤⎦⎥⎥(2.2.2)(2.2.2)x+y=[101112]+[012]=[10+011+112+2]=[101214]

𝑥−𝑦=⎡⎣⎢⎢101112⎤⎦⎥⎥−⎡⎣⎢⎢012⎤⎦⎥⎥=⎡⎣⎢⎢10−011−112−2⎤⎦⎥⎥=⎡⎣⎢⎢101010⎤⎦⎥⎥(2.2.3)(2.2.3)x−y=[101112]−[012]=[10−011−112−2]=[101010]

벡터의 덧셈과 뺄셈을 넘파이로 계산하면 다음과 같다. 여기에서는 편의상 1차원 배열로 벡터를 표시하였다.

In [2]:

x = np.array([10, 11, 12, 13, 14])

y = np.array([0, 1, 2, 3, 4])

In [3]:

x + y

array([10, 12, 14, 16, 18])

In [4]:

x - y

array([10, 10, 10, 10, 10])

행렬도 같은 방법으로 덧셈과 뺄셈을 있다.

[5768]+[10302040]−[1324]=[14342444](2.2.4)(2.2.4)[5678]+[10203040]−[1234]=[14243444]

In [5]:

np.array([[5, 6], [7, 8]]) + np.array([[10, 20], [30, 40]]) - \

np.array([[1, 2], [3, 4]])

array([[14, 24],

    [34, 44]])

스칼라와 벡터/행렬의 곱셈

벡터 𝑥x 또는 행렬 𝐴A 스칼라값 𝑐c 곱하는 것은 벡터 𝑥x 또는 행렬 𝐴A 모든 원소에 스칼라값 𝑐c 곱하는 같다.

𝑐[𝑥1𝑥2]=[𝑐𝑥1𝑐𝑥2](2.2.5)(2.2.5)c[x1x2]=[cx1cx2]

𝑐[𝑎11𝑎21𝑎12𝑎22]=[𝑐𝑎11𝑐𝑎21𝑐𝑎12𝑐𝑎22](2.2.6)(2.2.6)c[a11a12a21a22]=[ca11ca12ca21ca22]

브로드캐스팅

원래 덧셈과 뺄셈은 크기(차원) 같은 벡터에 대해서만 있다. 하지만 벡터와 스칼라의 경우에는 관례적으로 다음처럼 1-벡터를 사용하여 스칼라를 벡터로 변환한 연산을 허용한다. 이를 브로드캐스팅(broadcasting)이라고 한다.

⎡⎣⎢⎢101112⎤⎦⎥⎥−10=⎡⎣⎢⎢101112⎤⎦⎥⎥−10⋅1=⎡⎣⎢⎢101112⎤⎦⎥⎥−⎡⎣⎢⎢101010⎤⎦⎥⎥(2.2.7)(2.2.7)[101112]−10=[101112]−10⋅1=[101112]−[101010]

데이터 분석에서는 원래의 데이터 벡터 𝑥x 아니라 데이터 벡터의 원소의 평균값을 평균제거(mean removed) 벡터 혹은 0-평균(zero-mean) 벡터 사용하는 경우가 많다.

𝑥=⎡⎣⎢⎢⎢⎢𝑥1𝑥2⋮𝑥𝑁⎤⎦⎥⎥⎥⎥→𝑥−𝑚=⎡⎣⎢⎢⎢⎢𝑥1−𝑚𝑥2−𝑚⋮𝑥𝑁−𝑚⎤⎦⎥⎥⎥⎥(2.2.8)(2.2.8)x=[x1x2⋮xN]→x−m=[x1−mx2−m⋮xN−m]

식에서 𝑚m 샘플 평균이다.

𝑚=1𝑁∑𝑖=1𝑁𝑥𝑖(2.2.9)(2.2.9)m=1N∑i=1Nxi

선형조합

벡터/행렬에 다음처럼 스칼라값을 곱한 더하거나 것을 벡터/행렬의 선형조합(linear combination)이라고 한다. 벡터나 행렬을 선형조합해도 크기는 변하지 않는다.

𝑐1𝑥1+𝑐2𝑥2+𝑐3𝑥3+⋯+𝑐𝐿𝑥𝐿=𝑥(2.2.10)(2.2.10)c1x1+c2x2+c3x3+⋯+cLxL=x

𝑐1𝐴1+𝑐2𝐴2+𝑐3𝐴3+⋯+𝑐𝐿𝐴𝐿=𝐴(2.2.11)(2.2.11)c1A1+c2A2+c3A3+⋯+cLAL=A

𝑐1,𝑐2,…,𝑐𝐿𝐑(2.2.12)(2.2.12)c1,c2,…,cL∈R

𝑥1,𝑥2,…,𝑥𝐿,𝑥∈𝐑𝑀(2.2.13)(2.2.13)x1,x2,…,xL,x∈RM

𝐴1,𝐴2,…,𝐴𝐿,𝐴∈𝐑𝑀×𝑁(2.2.14)(2.2.14)A1,A2,…,AL,A∈RM×N

벡터나 행렬의 크기를 직사각형으로 표시하면 다음과 같다.

𝑐1𝑥1+𝑐2𝑥2+⋯+𝑐𝐿𝑥𝐿(2.2.15)(2.2.15)c1(x1(+c2(x2(+⋯+cL(xL(

𝑐1𝐴1+𝑐2𝐴2+⋯+𝑐𝐿𝐴𝐿(2.2.16)(2.2.16)c1A1+c2A2+⋯+cLAL

벡터와 벡터의 곱셈

행렬의 곱셈을 정의하기 전에 우선 벡터의 곱셈을 알아보자. 벡터를 곱셈하는 방법은 여러 가지가 있지만 여기서는 내적(inner product) 대해서만 다룬다. 벡터 𝑥x 벡터 𝑦y 내적은 다음처럼 표기한다.

𝑥𝑇𝑦(2.2.17)(2.2.17)xTy

내적은 다음처럼 (dot)으로 표기하는 경우도 있어서 프로덕트(dot product)라고도 부르고 < 𝑥,𝑦x,y > 기호로 나타낼 수도 있다.

𝑥⋅𝑦=<𝑥,𝑦>=𝑥𝑇𝑦(2.2.18)(2.2.18)x⋅y=<x,y>=xTy

벡터를 내적하려면 다음과 같은 조건이 만족되어야 한다.

1. 우선 벡터의 차원(길이) 같아야 한다.

2. 앞의 벡터가 벡터이고 뒤의 벡터가 벡터여야 한다.

이때 내적의 결과는 스칼라값이 되며 다음처럼 계산한다. 우선 같은 위치에 있는 원소들을 요소별 곱셈처럼 곱한 다음, 값들을 다시 모두 더해서 하나의 스칼라값으로 만든다.

𝑥𝑇𝑦=[𝑥1𝑥2⋯𝑥𝑁]⎡⎣⎢⎢⎢⎢𝑦1𝑦2⋮𝑦𝑁⎤⎦⎥⎥⎥⎥=𝑥1𝑦1+⋯+𝑥𝑁𝑦𝑁=∑𝑖=1𝑁𝑥𝑖𝑦𝑖(2.2.19)(2.2.19)xTy=[x1x2⋯xN][y1y2⋮yN]=x1y1+⋯+xNyN=∑i=1Nxiyi

𝑥∈𝐑𝑁×1(2.2.20)(2.2.20)x∈RN×1

𝑦∈𝐑𝑁×1(2.2.21)(2.2.21)y∈RN×1

𝑥𝑇𝑦∈𝐑(2.2.22)(2.2.22)xTy∈R

다음은 벡터의 내적의 예다.

𝑥=⎡⎣⎢⎢123⎤⎦⎥⎥,𝑦=⎡⎣⎢⎢456⎤⎦⎥⎥(2.2.23)(2.2.23)x=[123],y=[456]

𝑥𝑇𝑦=[123]⎡⎣⎢⎢456⎤⎦⎥⎥=1⋅4+2⋅5+3⋅6=32(2.2.24)(2.2.24)xTy=[123][456]=1⋅4+2⋅5+3⋅6=32

넘파이에서 벡터와 행렬의 내적은 dot()이라는 명령 또는 @(at이라고 읽는다)이라는 연산자로 계산한다. 2차원 배열로 표시한 벡터를 내적했을 때는 결과값이 스칼라가 아닌 2차원 배열이다.

In [6]:

x = np.array([[1], [2], [3]])

y = np.array([[4], [5], [6]])

 

x.T @ y  # 또는 np.dot(x.T, y)

array([[32]])

넘파이에서는 1차원 배열끼리도 내적을 계산한다. 이때는 넘파이가 앞의 벡터는 벡터이고 뒤의 벡터는 벡터라고 가정한다.

In [7]:

x = np.array([1, 2, 3])

y = np.array([4, 5, 6])

 

x @ y  # 또는 np.dot(x, y)

32

벡터의 내적은 덧셈이나 뺄셈과 달리 이렇게 복잡하게 정의된 것일까? 이유는 데이터 분석을 이러한 연산이 필요하기 때문이다. 벡터의 내적을 사용하여 데이터를 분석하는 가지 예를 살펴보자.

가중합

벡터의 내적은 가중합을 계산할 쓰일 있다. 가중합(weighted sum)이란 복수의 데이터를 단순히 합하는 것이 아니라 각각의 수에 어떤 가중치 값을 곱한 곱셈 결과들을 다시 합한 것을 말한다.

만약 데이터 벡터가 𝑥=[𝑥1,⋯,𝑥𝑁]𝑇x=[x1,⋯,xN]T이고 가중치 벡터가 𝑤=[𝑤1,⋯,𝑤𝑁]𝑇w=[w1,⋯,wN]T이면 데이터 벡터의 가중합은 다음과 같다.

𝑤1𝑥1+⋯+𝑤𝑁𝑥𝑁=∑𝑖=1𝑁𝑤𝑖𝑥𝑖(2.2.25)(2.2.25)w1x1+⋯+wNxN=∑i=1Nwixi

값을 벡터 𝑥x 𝑤w 곱으로 나타내면 𝑤𝑇𝑥wTx 또는 𝑥𝑇𝑤xTw 라는 간단한 수식으로 표시할 있다.

𝑖=1𝑁𝑤𝑖𝑥𝑖=[𝑤1𝑤2⋯𝑤𝑁]⎡⎣⎢⎢⎢⎢𝑥1𝑥2⋮𝑥𝑁⎤⎦⎥⎥⎥⎥=[𝑥1𝑥2⋯𝑥𝑁]⎡⎣⎢⎢⎢⎢𝑤1𝑤2⋮𝑤𝑁⎤⎦⎥⎥⎥⎥=𝑤𝑇𝑥=𝑥𝑇𝑤(2.2.26)(2.2.26)∑i=1Nwixi=[w1w2⋯wN][x1x2⋮xN]=wTx=[x1x2⋯xN][w1w2⋮wN]=xTw

예를 들어 쇼핑을 물건의 가격은 데이터 벡터, 물건의 수량은 가중치로 생각하여 내적을 구하면 총금액을 계산할 있다.

만약 가중치가 모두 1이면 일반적인 (sum) 계산한다.

𝑤1=𝑤2=⋯=𝑤𝑁=1(2.2.27)(2.2.27)w1=w2=⋯=wN=1

또는

𝑤=1𝑁(2.2.28)(2.2.28)w=1N

이면

𝑖=1𝑁𝑥𝑖=1𝑇𝑁𝑥(2.2.29)(2.2.29)∑i=1Nxi=1NTx

연습 문제 2.2.1
A, B, C 회사의 주식은 각각 100만원, 80만원, 50만원이다. 주식을 각각 3, 4, 5주를 매수할 필요한 금액을 구하고자 한다.
(1) 주식의 가격과 수량을 각각 𝑝p 벡터, 𝑛n 벡터로 표시하고 넘파이로 코딩한다.
(2) 주식을 매수할 필요한 금액을 곱셈으로 표시하고 넘파이 연산으로 값을 계산한다.

가중평균

가중합의 가중치값을 전체 가중치값의 합으로 나누면 가중평균(weighted average) 된다. 가중평균은 대학교의 평균 성적 계산 등에 사용할 있다.

예를 들어 고등학교에서는 국어, 영어, 과목의 평균 점수를 구할 단순히 과목의 점수(숫자) 더한 2으로 나눈다. 그러나 대학교에서는 중요한 과목과 중요하지 않는 과목을 구분하는 학점(credit)이라는 숫자가 있다. 일주일에 시간만 수업하는 과목은 1학점짜리 과목이고 일주일에 시간씩 수업하는 중요한 과목은 3학점짜리 과목이다. 1학점과 3학점 과목의 점수가 각각 100, 60점이면 학점을 고려한 가중 평균(weighted average) 성적은 다음과 같이 계산한다.

11+3×100+31+3×60=70(2.2.30)(2.2.30)11+3×100+31+3×60=70

벡터로 표현된 𝑁N개의 데이터의 단순 평균은 다음처럼 생각할 있다.

𝑥¯=1𝑁∑𝑖=1𝑁𝑥𝑖=1𝑁1𝑇𝑁𝑥(2.2.31)(2.2.31)x¯=1N∑i=1Nxi=1N1NTx

수식에서 보인 것처럼 𝑥x 데이터의 평균은 보통 𝑥¯라는 기호로 표기하고 "엑스 (x bar)" 라고 읽는다.

다음은 넘파이로 평균을 계산하는 방법이다.

In [8]:

x = np.arange(10)

N = len(x)

 

np.ones(N) @ x / N

4.5

현실적으로는 mean()이라는 메서드를 사용하는 것이 편하다.

In [9]:

x.mean()

4.5

연습 문제 2.2.2
벡터 𝑥x 평균 제거 벡터는 다음과 같이 계산함을 증명하라.
𝑥−1𝑁1𝑇𝑁𝑥1𝑁(2.2.32)(2.2.32)x−1N1NTx1N

유사도

벡터의 곱셈(내적) 벡터 간의 유사도를 계산하는 데도 이용할 있다. 유사도(similarity) 벡터가 닮은 정도를 정량적으로 나타낸 으로 벡터가 비슷한 경우에는 유사도가 커지고 비슷하지 앟은 경우에는 유사도가 작아진다. 내적을 이용하면 코사인 유사도(cosine similarity)라는 유사도를 계산할 있다. 추후 선형대수의 기하학적 의미를 공부할 코사인 유사도에 대해 살펴볼 것이다.

예를 들어 0 1 나타내는 MNIST 이미지에 대해 내적을 계산해보자.

In [10]:

from sklearn.datasets import load_digits

import matplotlib.gridspec as gridspec

 

digits = load_digits()

d1 = digits.images[0]

d2 = digits.images[10]

d3 = digits.images[1]

d4 = digits.images[11]

v1 = d1.reshape(64, 1)

v2 = d2.reshape(64, 1)

v3 = d3.reshape(64, 1)

v4 = d4.reshape(64, 1)

 

plt.figure(figsize=(9, 9))

gs = gridspec.GridSpec(1, 8, height_ratios=[1],

                    width_ratios=[9, 1, 9, 1, 9, 1, 9, 1])

for i in range(4):

plt.subplot(gs[2 * i])

plt.imshow(eval("d" + str(i + 1)), aspect=1,

            interpolation='nearest', cmap=plt.cm.bone_r)

plt.grid(False)

plt.xticks([])

plt.yticks([])

plt.title("image {}".format(i + 1))

plt.subplot(gs[2 * i + 1])

plt.imshow(eval("v" + str(i + 1)), aspect=0.25,

            interpolation='nearest', cmap=plt.cm.bone_r)

plt.grid(False)

plt.xticks([])

plt.yticks([])

plt.title("vector {}".format(i + 1))

plt.tight_layout()

plt.show()

"0" 이미지와 "0" 이미지, 또는 "1" 이미지와 "1" 이미지의 내적값은 다음과 같다.

In [11]:

(v1.T @ v2)[0][0], (v3.T @ v4)[0][0]

(3064.0, 3661.0)

상대적으로 "0" 이미지와 "1" 이미지, 또는 "1" 이미지와 "0" 이미지의 내적값은 작다.

In [12]:

(v1.T @ v3)[0][0], (v1.T @ v4)[0][0], (v2.T @ v3)[0][0], (v2.T @ v4)[0][0]

(1866.0, 1883.0, 2421.0, 2479.0)

연습 문제 2.2.3
다음 코드를 실행하면 MNIST 숫자 이미지 전체 데이터를 모두 벡터로 변환하여 하나의 넘파이 행렬 X 만든다. 행렬을 이용하여 다음 문제를 풀어라.
from sklearn.datasets import load_digits
X = load_digits().data
(1) 내적을 이용하여 번째 이미지와 10번째 이미지의 유사도를 구하라.
(2) 내적을 이용하여 모든 이미지의 조합에 대해 유사도를 구하라. 어떻게 구현하는 것이 효율적일까? (힌트 : 문제는 뒤에서 배울 행렬과 행렬의 곱셈을 이용한다.)

선형회귀 모형

선형회귀 모형(linear regression model)이란 독립변수 𝑥x에서 종속변수 𝑦y 예측하는 방법의 하나로 독립변수 벡터 𝑥x 가중치 벡터 𝑤w와의 가중합으로 𝑦y 대한 예측값 𝑦̂ y^ 계산하는 수식을 말한다.

𝑦̂ =𝑤1𝑥1+⋯+𝑤𝑁𝑥𝑁(2.2.33)(2.2.33)y^=w1x1+⋯+wNxN

수식에서 기호 ^ "캐럿(caret)"이라는 기호이다. 𝑦̂ y^ "와이 (y hat)"이라고 읽는다.

수식은 다음처럼 벡터의 내적으로 나타낼 있다.

𝑦̂ =𝑤𝑇𝑥(2.2.34)(2.2.34)y^=wTx

선형회귀 모형은 가장 단순하면서도 가장 널리 쓰이는 예측 모형이다.

예를 들어 어떤 아파트 단지의 아파트 가격을 조사하였더니 아파트 가격은 (1)면적, (2)층수, (3)한강이 보이는지의 여부, 가지 특징에 의해 달라진다는 사실을 알게 되었다. 이때 단지 내의 아파트 가격을 예측하는 예측 모형을 다음과 같이 만들 있다.

·   면적(𝑚2m2) 입력 데이터 𝑥1x1라고 한다.

·   층수를 입력 데이터 𝑥2x2라고 한다

·   한강이 보이는지의 여부를 입력 데이터 𝑥3x3라고 하며 한강이 보이면 𝑥3=1x3=1, 보이지 않으면 𝑥3=0x3=0이라고 한다.

·   출력 데이터 𝑦̂ y^ 해당 아파트의 예측 가격이다.

위와 같이 입력 데이터와 출력 데이터를 정의하고 회귀분석을 결과, 아파트값이 다음과 같은 선형회귀 모형으로 나타난다고 가정하자. 이러한 모형을 실제로 찾는 방법은 나중에 회귀분석 파트에서 공부하게 된다.

𝑦̂ =500𝑥1+200𝑥2+1000𝑥3(2.2.35)(2.2.35)y^=500x1+200x2+1000x3

모형은 다음과 같이 해석할 있다.

·   면적이 1𝑚2m2 증가할수록 가격은 500 원이 증가한다.

·   층수가 1 높아질수록 가격은 200 원이 증가한다.

·   한강이 보이는 집은 1,000 원의 웃돈(프리미엄) 존재한다.

식은 다음과 같이 벡터의 내적으로 고쳐 있다.

𝑦̂ =[5002001000]⎡⎣⎢⎢𝑥1𝑥2𝑥3⎤⎦⎥⎥=𝑤𝑇𝑥(2.2.36)(2.2.36)y^=[5002001000][x1x2x3]=wTx

, 선형회귀 모형은 다음 가중치 벡터로 대표된다.

𝑤𝑇=[5002001000](2.2.37)(2.2.37)wT=[5002001000]

인공신경망(artificial neural network)에서는 선형회귀 모형을 다음과 같은 그림으로 표현한다. 데이터는 노드(node) 혹은 뉴런(neuron)이라는 동그라미로 표시하고 곱셈은 선분(line)위에 곱할 숫자를 써서 나타낸다. 덧셈은 여러 개의 선분이 만나는 것으로 표시한다.

그림 2.2.1 인공신경망으로 표현한 선형회귀 모형

선형회귀 모형의 단점

선형회귀 모형은 비선형적인 현실 세계의 데이터를 예측하지 못할 있다는 단점이 있다. 예를 들어 집값은 면적에 단순 비례하지 않는다. 소형 면적의 집과 대형 면적의 집은 단위 면적당 집값의 증가율이 다를 있다. 또한 저층이 보통 고층보다 집값이 싸지만 층수가 올라갈수록 정확히 층수에 비례하여 가격이 증가하지도 않는다.

이러한 현실 세계의 데이터와 선형회귀 모형의 괴리를 줄이기 위해 선형회귀 모형이 아닌 완전히 다른 모형을 쓰기보다는 선형회귀 모형을 기반으로 여러 기법을 사용해 수정한 모형을 사용하는 것이 일반적이다. 이러한 수정 선형회귀 모형에 대해서는 나중에 공부하게 된다.

제곱합

데이터의 분산(variance)이나 표준 편차(standard deviation) 등을 구하는 경우에는 각각의 데이터를 제곱한 값을 모두 더한 제곱합(sum of squares) 계산해야 한다. 경우에도 벡터의 내적을 사용하여 𝑥𝑇𝑥xTx 있다.

𝑥𝑇𝑥=[𝑥1𝑥2⋯𝑥𝑁]⎡⎣⎢⎢⎢⎢𝑥1𝑥2⋮𝑥𝑁⎤⎦⎥⎥⎥⎥=∑𝑖=1𝑁𝑥2𝑖(2.2.38)(2.2.38)xTx=[x1x2⋯xN][x1x2⋮xN]=∑i=1Nxi2

행렬과 행렬의 곱셈

벡터의 곱셈을 정의한 후에는 이를 이용하여 행렬의 곱셈을 정의할 있다. 행렬과 행렬을 곱하면 행렬이 된다. 방법은 다음과 같다.

𝐴A 행렬과 𝐵B 행렬을 곱한 결과가 𝐶C 행렬이 된다고 하자. 𝐶C 𝑖i번째 , 𝑗j번째 열의 원소 𝑐𝑖𝑗cij 값은 𝐴A 행렬의 𝑖i번째 벡터 𝑎𝑇𝑖aiT 𝐵B 행렬의 𝑗j번째 벡터 𝑏𝑗bj 곱이다.

𝐶=𝐴𝐵→𝑐𝑖𝑗=𝑎𝑇𝑖𝑏𝑗(2.2.39)(2.2.39)C=AB→cij=aiTbj

정의가 성립하려면 앞의 행렬 𝐴A 열의 수가 뒤의 행렬 𝐵B 행의 수와 일치해야만 한다.

𝐴∈𝐑𝑁×𝐿,𝐵∈𝐑𝐿×𝑀→𝐴𝐵∈𝐑𝑁×𝑀(2.2.40)(2.2.40)A∈RN×L,B∈RL×M→AB∈RN×M

다음은 4×34×3 행렬과 3×23×2 곱하여 4×24×2 계산하는 예다.

⎡⎣⎢⎢⎢⎢𝑎11𝑎21𝑎31𝑎41𝑎12𝑎22𝑎32𝑎42𝑎13𝑎23𝑎33𝑎43⎤⎦⎥⎥⎥⎥⎡⎣⎢⎢𝑏11𝑏21𝑏31𝑏12𝑏22𝑏32⎤⎦⎥⎥=⎡⎣⎢⎢⎢⎢(𝑎11𝑏11+𝑎12𝑏21+𝑎13𝑏31)(𝑎21𝑏11+𝑎22𝑏21+𝑎23𝑏31)(𝑎31𝑏11+𝑎32𝑏21+𝑎33𝑏31)(𝑎41𝑏11+𝑎42𝑏21+𝑎43𝑏31)(𝑎11𝑏12+𝑎12𝑏22+𝑎13𝑏32)(𝑎21𝑏12+𝑎22𝑏22+𝑎23𝑏32)(𝑎31𝑏12+𝑎32𝑏22+𝑎33𝑏32)(𝑎41𝑏12+𝑎42𝑏22+𝑎43𝑏32)⎤⎦⎥⎥⎥⎥(2.2.41)(2.2.41)[a11a12a13a21a22a23a31a32a33a41a42a43][b11b12b21b22b31b32]=[(a11b11+a12b21+a13b31)(a11b12+a12b22+a13b32)(a21b11+a22b21+a23b31)(a21b12+a22b22+a23b32)(a31b11+a32b21+a33b31)(a31b12+a32b22+a33b32)(a41b11+a42b21+a43b31)(a41b12+a42b22+a43b32)]

다음은 실제 행렬을 사용한 곱셈의 예다.

𝐴=[142536](2.2.42)(2.2.42)A=[123456]

𝐵=⎡⎣⎢⎢135246⎤⎦⎥⎥(2.2.43)(2.2.43)B=[123456]

𝐶=𝐴𝐵=[22492864](2.2.44)(2.2.44)C=AB=[22284964]

넘파이를 이용하여 행렬의 곱을 구할 때도 @ 연산자 또는 dot() 명령을 사용한다.

In [13]:

A = np.array([[1, 2, 3], [4, 5, 6]])

B = np.array([[1, 2], [3, 4], [5, 6]])

C = A @ B

C

array([[22, 28],

    [49, 64]])

연습 문제 2.2.4
(1) 𝐴A 𝐵B 위와 같을 𝐴𝐵AB 연습장에 손으로 계산하고 넘파이의 계산 결과와 맞는지 확인한다.
(2) 순서를 바꾸어 𝐵𝐴BA 손으로 계산하고 넘파이의 계산 결과와 맞는지 확인한다. 𝐵𝐴BA 𝐴𝐵AB 같은가?
(3) 𝐴A, 𝐵B 다음과 같을 , 𝐴𝐵AB, 𝐵𝐴BA (계산이 가능하다면) 손으로 계산하고 넘파이의 계산 결과와 맞는지 확인한다. 𝐴𝐵AB, 𝐵𝐴BA 모두 계산 가능한가?
𝐴=[123](2.2.45)(2.2.45)A=[123]
𝐵=⎡⎣⎢⎢456789⎤⎦⎥⎥(2.2.46)(2.2.46)B=[475869]
(4) 𝐴A, 𝐵B 다음과 같을 , 𝐴𝐵AB, 𝐵𝐴BA (계산이 가능하다면) 손으로 계산하고 넘파이의 계산 결과와 맞는지 확인한다. 𝐴𝐵AB, 𝐵𝐴BA 모두 계산 가능한가? 𝐵𝐴BA 결과가 𝐴𝐵AB 같은가?
𝐴=[1324](2.2.47)(2.2.47)A=[1234]
𝐵=[5768](2.2.48)(2.2.48)B=[5678]
(5) 𝐴A 다음과 같을 , 𝐴𝐴𝑇AAT 𝐴𝑇𝐴ATA 손으로 계산하고 넘파이의 계산 결과와 맞는지 확인한다. 𝐴𝐴𝑇AAT 𝐴𝑇𝐴ATA 크기는 어떠한가? 항상 정방행렬이 되는가?
𝐴=⎡⎣⎢⎢135246⎤⎦⎥⎥(2.2.49)(2.2.49)A=[123456]
(6) 𝑥x 다음과 같을 , 𝑥𝑇𝑥xTx 𝑥𝑥𝑇xxT 손으로 계산하고 넘파이의 계산 결과와 맞는지 확인한다. 𝑥𝑇𝑥xTx 𝑥𝑥𝑇xxT 크기는 어떠한가? 어떤 것이 스칼라이고 어떤 것이 정방행렬인가?
𝑥=⎡⎣⎢⎢123⎤⎦⎥⎥(2.2.50)(2.2.50)x=[123]

인공 신경망은 내부적으로 다음과 같이 여러 개의 선형회귀 모형을 사용한다. 구조는 행렬과 벡터의 곱으로 나타낼 있다.

그림 2.2.2 인공신경망의 기본 구조

그림을 행렬식으로 표현하면 다음과 같다.

[𝑦̂ 1𝑦̂ 2]=[𝑤11𝑤21𝑤12𝑤22𝑤13𝑤23]⎡⎣⎢⎢𝑥1𝑥2𝑥3⎤⎦⎥⎥(2.2.51)(2.2.51)[y^1y^2]=[w11w12w13w21w22w23][x1x2x3]

𝑦̂ =𝑊𝑥(2.2.52)(2.2.52)y^=Wx

교환 법칙과 분배 법칙

행렬의 곱셈은 곱하는 행렬의 순서를 바꾸는 교환 법칙이 성립하지 않는다. 그러나 덧셈에 대한 분배 법칙은 성립한다.

𝐴𝐵≠𝐵𝐴(2.2.53)(2.2.53)AB≠BA

𝐴(𝐵+𝐶)=𝐴𝐵+𝐴𝐶(2.2.54)(2.2.54)A(B+C)=AB+AC

(𝐴+𝐵)𝐶=𝐴𝐶+𝐵𝐶(2.2.55)(2.2.55)(A+B)C=AC+BC

𝐴A, 𝐵B, 𝐶C 다음과 같을 법칙을 넘파이로 살펴보자.

𝐴=[1324](2.2.56)(2.2.56)A=[1234]

𝐵=[5768](2.2.57)(2.2.57)B=[5678]

𝐶=[9786](2.2.58)(2.2.58)C=[9876]

In [14]:

A = np.array([[1, 2], [3, 4]])

B = np.array([[5, 6], [7, 8]])

C = np.array([[9, 8], [7, 6]])

𝐴𝐵AB 𝐵𝐴BA 값은 다음처럼 다른 값이 나오므로 교환법칙이 성립하지 않음을 있다.

In [15]:

A @ B

array([[19, 22],

    [43, 50]])

In [16]:

B @ A

array([[23, 34],

    [31, 46]])

분배법칙은 다음과 같이 성립한다.

In [17]:

A @ (B + C)

array([[42, 42],

    [98, 98]])

In [18]:

A @ B + A @ C

array([[42, 42],

    [98, 98]])

In [19]:

(A + B) @ C

array([[110,  96],

    [174, 152]])

In [20]:

A @ C + B @ C

array([[110,  96],

    [174, 152]])

전치 연산도 마찬가지로 덧셈/뺄셈에 대해 분배 법칙이 성립한다.

(𝐴+𝐵)𝑇=𝐴𝑇+𝐵𝑇(2.2.59)(2.2.59)(A+B)T=AT+BT

전치 연산과 곱셈의 경우에는 분배 법칙이 성립하기는 하지만 전치 연산이 분배되면서 곱셈의 순서가 바뀐다.

(𝐴𝐵)𝑇=𝐵𝑇𝐴𝑇(2.2.60)(2.2.60)(AB)T=BTAT

(𝐴𝐵𝐶)𝑇=𝐶𝑇𝐵𝑇𝐴𝑇(2.2.61)(2.2.61)(ABC)T=CTBTAT

마찬가지로 넘파이로 법칙이 성립하는지 살펴보자.

In [21]:

(A + B).T

array([[ 6, 10],

    [ 8, 12]])

In [22]:

A.T + B.T

array([[ 6, 10],

    [ 8, 12]])

In [23]:

(A @ B).T

array([[19, 43],

    [22, 50]])

In [24]:

B.T @ A.T

array([[19, 43],

    [22, 50]])

연습 문제 2.2.5
(1) 길이가 같은 일벡터 1𝑁𝐑𝑁1N∈RN 행벡터 𝑥∈𝐑𝑁x∈RN 곱은 행벡터 𝑥x 반복하여 가지는 행렬과 같음을 보여라.
1𝑁𝑥𝑇=⎡⎣⎢⎢⎢⎢𝑥𝑇𝑥𝑇⋮𝑥𝑇⎤⎦⎥⎥⎥⎥(2.2.62)(2.2.62)1NxT=[xTxT⋮xT]
(2) 행렬 𝑋(𝑋∈𝐑𝑁×𝑀)X(X∈RN×M) 있을 , 행렬의 열의 평균으로 이루어진 벡터 𝑥¯(𝑥¯∈𝐑𝑀)x¯(x¯∈RM) 다음과 같음을 보여라.
𝑥¯=1𝑁𝑋𝑇1𝑁(2.2.63)(2.2.63)x¯=1NXT1N
(3) 행렬 𝑋¯ (𝑋¯∈𝐑𝑁×𝑀)X¯ (X¯∈RN×M) 동일한 벡터 𝑥¯𝑇x¯T 𝑁N 누적하여 만든 행렬이다. 열의 모든 값이 열의 평균으로 이루어진 행렬이다.
𝑋¯=⎡⎣⎢⎢⎢⎢𝑥¯𝑇𝑥¯𝑇⋮𝑥¯𝑇⎤⎦⎥⎥⎥⎥(2.2.64)(2.2.64)X¯=[x¯Tx¯T⋮x¯T]
이때 𝑋¯ 다음과 같음을 보여라.
𝑋¯=1𝑁1𝑁1𝑇𝑁𝑋(2.2.65)(2.2.65)X¯=1N1N1NTX
(4) 다음 코드를 실행하면 붓꽃 전체 데이터를 모두 벡터로 변환하여 하나의 넘파이 행렬 X 만든다.
from sklearn.datasets import load_iris
X = load_iris().data
데이터로 행렬 𝑋¯ 값을 계산하라. 행렬은 번째 열의 값이 모두 같은 값으로 붓꽃의 꽃받침의 길이(sepal length) 평균이고 번째 열의 값이 모두 같은 값으로 붓꽃의 꽃받침의 (sepal width) 평균, 이런 식으로 계산된 행렬이다.

곱셈의 연결

연속된 행렬의 곱셈은 계산 순서를 임의의 순서로 해도 상관없다.

𝐴𝐵𝐶=(𝐴𝐵)𝐶=𝐴(𝐵𝐶)(2.2.66)(2.2.66)ABC=(AB)C=A(BC)

𝐴𝐵𝐶𝐷=((𝐴𝐵)𝐶)𝐷=(𝐴𝐵)(𝐶𝐷)=𝐴(𝐵𝐶𝐷)=𝐴(𝐵𝐶)𝐷(2.2.67)(2.2.67)ABCD=((AB)C)D=(AB)(CD)=A(BCD)=A(BC)D

연습 문제 2.2.6
다음 행렬의 곱셈을 순서를 바꾸어 가지 방법으로 해본다.
[12][1324][56](2.2.68)(2.2.68)[12][1234][56]

항등행렬의 곱셈

어떤 행렬이든 항등행렬을 곱하면 행렬의 값이 변하지 않는다.

𝐴𝐼=𝐼𝐴=𝐴(2.2.69)(2.2.69)AI=IA=A

넘파이로 다음과 같이 확인한다.

In [25]:

A = np.array([[1, 2], [3, 4]])

I = np.eye(2)

In [26]:

A @ I

array([[1., 2.],

    [3., 4.]])

In [27]:

I @ A

array([[1., 2.],

    [3., 4.]])

행렬과 벡터의

그럼 이러한 행렬의 곱셈은 데이터 분석에서 어떤 경우에 사용될까? 행렬의 곱셈 가장 널리 쓰이는 것은 다음과 같은 형태의 행렬 𝑀M 벡터 𝑣v 곱이다.

𝑀𝑣(2.2.70)(2.2.70)Mv

벡터와 행렬의 크기를 직사각형으로 표시하면 다음과 같다.

𝑀𝑣=𝑀𝑣(2.2.71)(2.2.71)M(v(=Mv

행렬과 벡터의 곱을 사용하는 몇가지 예를 살펴보자.

벡터의 선형조합

행렬 𝑋X 벡터 𝑤w 곱은 행렬 𝑋X 이루는 열벡터 𝑐1,𝑐2,…,𝑐𝑀c1,c2,…,cM 뒤에 곱해지는 벡터 𝑤w 성분 𝑤1,𝑤2,…,𝑤𝑀w1,w2,…,wM으로 선형조합(linear combination) 결과 벡터와 같다.

𝑋𝑤=[𝑐1𝑐2⋯𝑐𝑀]⎡⎣⎢⎢⎢⎢𝑤1𝑤2⋮𝑤𝑀⎤⎦⎥⎥⎥⎥=𝑤1𝑐1+𝑤2𝑐2+⋯+𝑤𝑀𝑐𝑀(2.2.72)(2.2.72)Xw=[c1c2⋯cM][w1w2⋮wM]=w1c1+w2c2+⋯+wMcM

벡터의 크기를 직사각형으로 표시하면 다음과 같다.

⎡⎣⎢⎢⎢⎢⎢𝑐1𝑐2⋯𝑐𝑀⎤⎦⎥⎥⎥⎥⎥⎡⎣⎢⎢⎢⎢𝑤1𝑤2⋮𝑤𝑀⎤⎦⎥⎥⎥⎥=𝑤1𝑐1+𝑤2𝑐2+⋯+𝑤𝑀𝑐𝑀(2.2.73)(2.2.73)[(c11((c21(⋯(cM(][w1w2⋮wM]=w1(c11(+w2(c21(+⋯+wM(cM(

연습 문제 2.2.7
다음 행렬 𝑋X 벡터 𝑤w 대해 𝑋𝑤Xw 열벡터 𝑐1,𝑐2,𝑐3c1,c2,c3 선형조합 𝑤1𝑐1+𝑤2𝑐2+𝑤3𝑐3w1c1+w2c2+w3c3 됨을 실제 계산으로 증명하라.
𝑋=[142536],𝑤=⎡⎣⎢⎢234⎤⎦⎥⎥(2.2.74)(2.2.74)X=[123456],w=[234]
연습 문제 2.2.8
벡터 𝑣1,𝑣2,𝑣3v1,v2,v3 이루어진 행렬 𝑉V 벡터 𝜆λ 대해 다음 식이 성립함을 증명하라. 식에서 𝜆1λ1 스칼라이다.
𝑉𝜆=[𝑣1𝑣2𝑣3]⎡⎣⎢⎢𝜆100⎤⎦⎥⎥=𝜆1𝑣1(2.2.75)(2.2.75)Vλ=[v1v2v3][λ100]=λ1v1

벡터의 선형조합은 다양한 분야에 응용된다. 예를 들어 이미지 벡터의 선형조합은 이미지를 섞어놓은 모핑(morphing) 효과를 얻는 사용할 있다.

In [28]:

from sklearn.datasets import fetch_olivetti_faces

 

faces = fetch_olivetti_faces()

 

f, ax = plt.subplots(1, 3)

 

ax[0].imshow(faces.images[6], cmap=plt.cm.bone)

ax[0].grid(False)

ax[0].set_xticks([])

ax[0].set_yticks([])

ax[0].set_title("image 1: $x_1$")

 

ax[1].imshow(faces.images[10], cmap=plt.cm.bone)

ax[1].grid(False)

ax[1].set_xticks([])

ax[1].set_yticks([])

ax[1].set_title("image 2: $x_2$")

 

new_face = 0.7 * faces.images[6] + 0.3 * faces.images[10]

ax[2].imshow(new_face, cmap=plt.cm.bone)

ax[2].grid(False)

ax[2].set_xticks([])

ax[2].set_yticks([])

ax[2].set_title("image 3: $0.7x_1 + 0.3x_2$")

 

plt.show()

여러 개의 벡터에 대한 가중합 동시 계산

벡터 하나의 가중합은 𝑤𝑇𝑥wTx 또는 𝑥𝑇𝑤xTw 표시할 있다는 것을 배웠다. 그런데 만약 이렇게 𝑤w 가중치를 사용한 가중합을 하나의 벡터 𝑥x 아니라 여러 벡터 𝑥1,⋯,𝑥𝑀x1,⋯,xM 개에 대해서 모두 계산해야 한다면 어떻게 해야 할까? 예를 들어 위와 같이 선형 회귀 모형을 사용하여 여러 데이터 𝑥1,𝑥2,𝑥3,⋯,𝑥𝑁x1,x2,x3,⋯,xN 개의 데이터 모두에 대해 예측값 𝑦1,𝑦2,𝑦3,⋯,𝑦𝑁y1,y2,y3,⋯,yN 한꺼번에 계산하고 싶다면 다음처럼 데이터 행렬 𝑋X 사용하여 𝑦̂ =𝑋𝑤y^=Xw라는 수식으로 간단하게 표시할 있다.

𝑦̂ =⎡⎣⎢⎢⎢⎢𝑦̂ 1𝑦̂ 2⋮𝑦̂ 𝑀⎤⎦⎥⎥⎥⎥=⎡⎣⎢⎢⎢⎢𝑤1𝑥1,1+𝑤2𝑥1,2+⋯+𝑤𝑁𝑥1,𝑁𝑤1𝑥2,1+𝑤2𝑥2,2+⋯+𝑤𝑁𝑥2,𝑁⋮𝑤1𝑥𝑀,1+𝑤2𝑥𝑀,2+⋯+𝑤𝑁𝑥𝑀,𝑁⎤⎦⎥⎥⎥⎥=⎡⎣⎢⎢⎢⎢𝑥1,1𝑥2,1⋮𝑥𝑀,1𝑥1,2𝑥2,2⋮𝑥𝑀,2⋯⋯⋮⋯𝑥1,𝑁𝑥2,𝑁⋮𝑥𝑀,𝑁⎤⎦⎥⎥⎥⎥⎡⎣⎢⎢⎢⎢𝑤1𝑤2⋮𝑤𝑁⎤⎦⎥⎥⎥⎥=⎡⎣⎢⎢⎢⎢⎢𝑥𝑇1𝑥𝑇2⋮𝑥𝑇𝑀⎤⎦⎥⎥⎥⎥⎥⎡⎣⎢⎢⎢⎢𝑤1𝑤2⋮𝑤𝑁⎤⎦⎥⎥⎥⎥=𝑋𝑤(2.2.76)(2.2.76)y^=[y^1y^2⋮y^M]=[w1x1,1+w2x1,2+⋯+wNx1,Nw1x2,1+w2x2,2+⋯+wNx2,N⋮w1xM,1+w2xM,2+⋯+wNxM,N]=[x1,1x1,2⋯x1,Nx2,1x2,2⋯x2,N⋮⋮⋮⋮xM,1xM,2⋯xM,N][w1w2⋮wN]=[x1Tx2T⋮xMT][w1w2⋮wN]=Xw

.

𝑦̂ =𝑋𝑤(2.2.77)(2.2.77)y^=Xw

연습 문제 2.2.9
𝑥1x1, 𝑥2x2 다음과 같을 ,
𝑥1=⎡⎣⎢⎢𝑥11𝑥21𝑥31⎤⎦⎥⎥𝑥2=⎡⎣⎢⎢𝑥12𝑥22𝑥32⎤⎦⎥⎥(2.2.78)(2.2.78)x1=[x11x21x31]x2=[x12x22x32]
다음 등식이 성립함을 보인다.
𝑋𝑤=[𝑥𝑇1𝑥𝑇2]⎡⎣⎢⎢𝑤1𝑤2𝑤3⎤⎦⎥⎥=[𝑥𝑇1𝑤𝑥𝑇2𝑤](2.2.79)(2.2.79)Xw=[x1Tx2T][w1w2w3]=[x1Twx2Tw]

잔차

선형 회귀분석(linear regression) 결과는 가중치 벡터 𝑤w라는 형태로 나타나고 예측치는 가중치 벡터를 사용한 독립변수 데이터 레코드 , 벡터 𝑥𝑖xi 가중합 𝑤𝑇𝑥𝑖wTxi 된다고 했다. 예측치와 실젯값(target) 𝑦𝑖yi 차이를 오차(error) 혹은 잔차(residual) 𝑒𝑖ei라고 한다. 이러한 잔찻값을 모든 독립변수 벡터에 대해 구하면 잔차 벡터 𝑒e 된다.

𝑒𝑖=𝑦𝑖−𝑦̂ 𝑖=𝑦𝑖−𝑤𝑇𝑥𝑖(2.2.80)(2.2.80)ei=yi−y^i=yi−wTxi

잔차 벡터는 다음처럼 𝑦−𝑋𝑤y−Xw 간단하게 표기할 있다.

𝑒=⎡⎣⎢⎢⎢⎢𝑒1𝑒2⋮𝑒𝑀⎤⎦⎥⎥⎥⎥=⎡⎣⎢⎢⎢⎢𝑦1𝑦2⋮𝑦𝑀⎤⎦⎥⎥⎥⎥−⎡⎣⎢⎢⎢⎢⎢𝑥𝑇1𝑤𝑥𝑇2𝑤⋮𝑥𝑇𝑀𝑤⎤⎦⎥⎥⎥⎥⎥=𝑦−𝑋𝑤(2.2.81)(2.2.81)e=[e1e2⋮eM]=[y1y2⋮yM]−[x1Twx2Tw⋮xMTw]=y−Xw

𝑒=𝑦−𝑋𝑤(2.2.82)(2.2.82)e=y−Xw

잔차 제곱합

잔차의 크기는 잔차 벡터의 원소를 제곱한 더한 잔차 제곱합(RSS: Residual Sum of Squares) 이용하여 구한다. 값은 𝑒𝑇𝑒eTe 간단하게 있으며 값은 다음처럼 계산한다.

𝑖=1𝑁𝑒2𝑖=∑𝑖=1𝑁(𝑦𝑖−𝑤𝑇𝑥𝑖)2=𝑒𝑇𝑒=(𝑦−𝑋𝑤)𝑇(𝑦−𝑋𝑤)(2.2.83)(2.2.83)∑i=1Nei2=∑i=1N(yi−wTxi)2=eTe=(y−Xw)T(y−Xw)

연습 문제 2.2.10
분배 법칙을 사용하여 (𝑦−𝑋𝑤)𝑇(𝑦−𝑋𝑤)(y−Xw)T(y−Xw) 풀어쓰면 다음과 같아짐을 보여라.
(𝑦−𝑋𝑤)𝑇(𝑦−𝑋𝑤)=𝑦𝑇𝑦−𝑤𝑇𝑋𝑇𝑦−𝑦𝑇𝑋𝑤+𝑤𝑇𝑋𝑇𝑋𝑤(2.2.84)(2.2.84)(y−Xw)T(y−Xw)=yTy−wTXTy−yTXw+wTXTXw

이차형식

위의 연습 문제에서 마지막 항은 𝑤𝑇𝑋𝑇𝑋𝑤wTXTXw라는 형태다. 식에서 𝑋𝑇𝑋XTX 정방행렬이 되므로 정방행렬을 𝐴A라고 이름 붙이면 마지막 항은 𝑤𝑇𝐴𝑤wTAw 같은 형태가 된다.

벡터의 이차형식(Quadratic Form)이란 이처럼 어떤 벡터와 정방행렬이 '행벡터 x 정방행렬 x 열벡터' 형식으로 되어 있는 것을 말한다.

수식을 풀면 𝑖=1,…,𝑁,𝑗=1,…,𝑁i=1,…,N,j=1,…,N 대해 가능한 모든 𝑖,𝑗i,j 쌍의 조합을 구한 다음 𝑖i, 𝑗j 해당하는 원소 𝑥𝑖xi, 𝑥𝑗xj 가중치 𝑎𝑖,𝑗ai,j 같이 곱한 𝑎𝑖,𝑗𝑥𝑖𝑥𝑗ai,jxixj 총합이 된다.

𝑥𝑇𝐴𝑥=[𝑥1𝑥2⋯𝑥𝑁]⎡⎣⎢⎢⎢⎢𝑎1,1𝑎2,1⋮𝑎𝑁,1𝑎1,2𝑎2,2⋮𝑎𝑁,2⋯⋯⋱⋯𝑎1,𝑁𝑎2,𝑁⋮𝑎𝑁,𝑁⎤⎦⎥⎥⎥⎥⎡⎣⎢⎢⎢⎢𝑥1𝑥2⋮𝑥𝑁⎤⎦⎥⎥⎥⎥=∑𝑖=1𝑁𝑗=1𝑁𝑎𝑖,𝑗𝑥𝑖𝑥𝑗(2.2.85)(2.2.85)xTAx=[x1x2⋯xN][a1,1a1,2⋯a1,Na2,1a2,2⋯a2,N⋮⋮⋱⋮aN,1aN,2⋯aN,N][x1x2⋮xN]=∑i=1N∑j=1Nai,jxixj

연습 문제 2.2.11
다음 3차원 벡터와 행렬에 대해 이차형식을 쓰고 값을 계산하라.
𝑥=⎡⎣⎢⎢𝑥1𝑥2𝑥3⎤⎦⎥⎥(2.2.86)(2.2.86)x=[x1x2x3]
𝐴=⎡⎣⎢⎢𝑎11𝑎21𝑎31𝑎12𝑎22𝑎32𝑎13𝑎23𝑎33⎤⎦⎥⎥(2.2.87)(2.2.87)A=[a11a12a13a21a22a23a31a32a33]

예를 들어 𝑥=[1,2,3]𝑇x=[1,2,3]T 이고 A 다음과 같다면

𝐴=⎡⎣⎢⎢147258369⎤⎦⎥⎥(2.2.88)(2.2.88)A=[123456789]

넘파이 에서 벡터의 이차형식은 다음처럼 계산한다.

In [29]:

x = np.array([1, 2, 3])

x

array([1, 2, 3])

In [30]:

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

A

array([[1, 2, 3],

    [4, 5, 6],

    [7, 8, 9]])

In [31]:

x.T @ A @ x

228

연습 문제 2.2.12
다음 식이 성립함을 증명하라.
𝑥𝑇𝐴𝑥=12𝑥𝑇(𝐴+𝐴𝑇)𝑥(2.2.89)(2.2.89)xTAx=12xT(A+AT)x

부분행렬

다음과 같은 2차원 정방행렬 𝐴A, 𝐵B 있다.

𝐴=[𝑎11𝑎21𝑎12𝑎22],𝐵=[𝑏11𝑏21𝑏12𝑏22](2.2.90)(2.2.90)A=[a11a12a21a22],B=[b11b12b21b22]

이때 행렬의 𝐴𝐵AB 𝐴A, 𝐵B 부분행렬(submatrix) 이용하여 여러 방법으로 계산할 있다.

(1) 우선 앞에 곱해지는 행렬을 행벡터로 나누어 계산해도 된다.

𝐴=⎡⎣⎢⎢𝑎𝑇1𝑎𝑇2⎤⎦⎥⎥(2.2.91)(2.2.91)A=[a1Ta2T]

,

𝑎𝑇1=[𝑎11𝑎12],𝑎𝑇2=[𝑎21𝑎22](2.2.92)(2.2.92)a1T=[a11a12],a2T=[a21a22]

이면

𝐴𝐵=⎡⎣⎢⎢𝑎𝑇1𝑎𝑇2⎤⎦⎥⎥𝐵=⎡⎣⎢⎢𝑎𝑇1𝐵𝑎𝑇2𝐵⎤⎦⎥⎥(2.2.93)(2.2.93)AB=[a1Ta2T]B=[a1TBa2TB]

(2) 아니면 뒤에 곱해지는 행렬을 열벡터로 나누어 계산해도 된다.

𝐵=⎡⎣⎢⎢⎢𝑏1𝑏2⎤⎦⎥⎥⎥(2.2.94)(2.2.94)B=[(b1((b2(]

,

𝑏1=[𝑏11𝑏21],𝑏2=[𝑏21𝑏22](2.2.95)(2.2.95)b1=[b11b21],b2=[b21b22]

이면

𝐴𝐵=𝐴⎡⎣⎢⎢⎢𝑏1𝑏2⎤⎦⎥⎥⎥=⎡⎣⎢⎢⎢𝐴𝑏1𝐴𝑏2⎤⎦⎥⎥⎥(2.2.96)(2.2.96)AB=A[(b1((b2(]=[(Ab1((Ab2(]

(3) 앞에 곱해지는 행렬을 열벡터로, 뒤에 곱해지는 행렬을 행벡터로 나누어 스칼라처럼 계산해도 된다.

𝐴𝐵=[𝑎1𝑎2][𝑏𝑇1𝑏𝑇2]=𝑎1𝑏𝑇1+𝑎2𝑏𝑇2(2.2.97)(2.2.97)AB=[a1a2][b1Tb2T]=a1b1T+a2b2T

벡터의 크기를 직사각형으로 표시하면 다음과 같다.

𝐴𝐵=⎡⎣⎢⎢⎢𝑎1𝑎2⎤⎦⎥⎥⎥⎡⎣⎢⎢𝑏𝑇1𝑏𝑇2⎤⎦⎥⎥=𝑎1𝑏𝑇1+𝑏1𝑏𝑇2(2.2.98)(2.2.98)AB=[(a1((a2(][b1Tb2T]=(a1(b1T+(b1(b2T

여기에서는 2차원 행렬의 예를 들었지만 일반적인 𝑁N차원 행렬에서도 관계는 성립한다.

연습 문제 2.2.13
행렬 𝑉V 열벡터 𝑣𝑖(𝑖=1,…,𝑁)vi(i=1,…,N) 이루어진 정방행렬이다. 𝑉V 크기가 같은 다른 정방행렬 𝐴A, ΛΛ 있을 다음 식이 성립한다.
𝐴𝑉=𝐴[𝑣1⋯𝑣𝑁]=[𝐴𝑣1⋯𝐴𝑣𝑁](2.2.99)(2.2.99)AV=A[v1⋯vN]=[Av1⋯AvN]
𝑉Λ=[𝑣1⋯𝑣𝑁]⎡⎣⎢⎢⎢⎢𝜆10⋮00𝜆2⋮0⋯⋯⋱⋯00⋮𝜆𝑁⎤⎦⎥⎥⎥⎥=[𝜆1𝑣1⋯𝜆𝑁𝑣𝑁](2.2.100)(2.2.100)VΛ=[v1⋯vN][λ10⋯00λ2⋯0⋮⋮⋱⋮00⋯λN]=[λ1v1⋯λNvN]
𝑁=3N=3 경우에 식이 성립함을 보여라.
연습 문제 2.2.14
부분행렬 공식 (3)으로부터 𝐴A 행벡터 𝑎𝑇𝑖(𝑖=1,…,𝑁)aiT(i=1,…,N) 이루어진 𝑁N 정방행렬일
𝐴=⎡⎣⎢⎢⎢⎢⎢𝑎𝑇1𝑎𝑇2⋮𝑎𝑇𝑁⎤⎦⎥⎥⎥⎥⎥(2.2.101)(2.2.101)A=[a1Ta2T⋮aNT]
다음 관계가 성립한다.
𝐴𝑇𝐴=[𝑎1𝑎2⋯𝑎𝑁]⎡⎣⎢⎢⎢⎢⎢𝑎𝑇1𝑎𝑇2⋮𝑎𝑇𝑁⎤⎦⎥⎥⎥⎥⎥=∑𝑖=1𝑁𝑎𝑖𝑎𝑇𝑖(2.2.102)(2.2.102)ATA=[a1a2⋯aN][a1Ta2T⋮aNT]=∑i=1NaiaiT
𝑁=3N=3 경우에 식이 성립함을 보여라.

질문/덧글

dot연산된 2차원 배열 벡터 hamj*** 2017 3 24 9:42 오후 답변

안녕하세요. numpy 관련 문서를 찾다가 압도적인 튜토리얼을 발견했네요 ! 요새 딥러닝관련 문서들을 보는데, 문꽈 출신으로 첩첩산중이라 애로사항이 많슴다... 위에서 2차원 벡터의 dot 연산된 "결과값이 스칼라가 아닌 2차원 배열이라는 점에 유의한다."

array([[32]]) 이게 무슨 의미인지 이해하기가 힘듭니다. 얼마 전에 수학교과서에서는 "내적(inner product = dot product)연산은 결과값이 스칼라이므로 scalar product라고도 부른다"라고 봤거든요. 외적은 결과값도 벡터이므로 벡터곱이라고 부른다고 하구요. 수학적인 결과값은 스칼라이지만, 파이썬의 자료형으로 2차원 배열이라는 의미인지요 ?

답변: dot연산된 2차원 배열 벡터 관리자 2017 3 27 8:29 오후 답변

, 말씀하신대로 수학적인 결과값은 스칼라이지만, 파이썬의 자료형으로 2차원 배열이라는 의미입니다.

본문의 평균 부분 beom*** 2017 9 3 8:22 오후 답변

본문의 평균 부분에서 N = len(x) np.dot(np.ones(N), x) / N 아래에 나오는 결과값이 잘못 같습니다. x.mean() 결과값과 동일하게 4.5 수정되어야 같습니다.

답변: 본문의 평균 부분 관리자 2017 9 4 1:38 오후 답변

수정하였습니다. 지적 감사드립니다.

본문의 문장 '벡터로 표현된 N 개의 데이터의 단순 평균은 가중치값이 모두 1/N 가중 평균과 같다'에서 가중 평균이 가중 합으로 바뀌어하는게 아닌지요? beom*** 2017 9 8 4:25 오후 답변

답변: 본문의 문장 '벡터로 표현된 N 개의 데이터의 단순 평균은 가중치값이 모두 1/N 가중 평균과 같다'에서 가중 평균이 가중 합으로 바뀌어하는게 아닌지요? 관리자 2017 9 8 5:56 오후 답변

수정하였습니다. 지적 감사드립니다.

사용자에 의해 삭제되었습니다. eddy*** 2017 9 23 8:12 오후 답변

사용자에 의해 삭제되었습니다.

교열맨 roh.*** 2018 9 18 9:37 오전 답변

행렬과 행렬의 곱셈) 다음은 실제 행렬을 사용한 '곱셍' 예이다. -> 곱셈

벡터의 선형조합) 이미지를 섞어놓은 모핑(morhping) 효과 -> morphing 감사합니다!!

답변: 교열맨 관리자 2018 9 19 9:49 오전 답변

지적 감사드립니다. 수정하겠습니다.

사용자에 의해 삭제되었습니다. shul*** 2019 5 6 8:48 오후 답변

사용자에 의해 삭제되었습니다.

사용자에 의해 삭제되었습니다. shul*** 2019 5 6 9:13 오후 답변

사용자에 의해 삭제되었습니다.

의문 혹은 질문들 shul*** 2019 5 6 11:27 오후 답변

· 내적을 표현할 각괄호<> 사용하는데, 각괄호는 위치벡터를 표현할 때도 사용하는 걸로 압니다. 혹시 사이에 어떤 연관성이 있기에 같은 기호를 사용하는 걸까요?

· 절에서 Numpy에서는 1차원 배열의 전치 연산이 계산되지 않는다고 했는데, 내적은 행벡터와 열벡터를 가정해가면서까지 자동으로 구할 있게 해놨네요. 그렇게 만들어진 걸까요?

· 문서와 연습문제들로 , 행렬간의 곱셈에서는 교환법칙이 성립하지 않지만, 벡터와 행렬의 곱셈에서는 교환법칙이 성립한다고 이해했는데 맞을까요?

답변: 의문 혹은 질문들 관리자 2019 5 10 9:32 오전 답변

(1) 참고 자료나 링크를 제시해주시면 좋겠습니다. (2) 사용자 편의를 위한 것입니다. (3) 아닙니다. 벡터도 행렬이므로 교환법칙이 일반적으로 성립하지 않습니다.

연습문제 해설을 보다가 질문 드립니다. sgus*** 2020 3 18 2:03 오후 답변

연습문제 2.2.1에서 내적 곱을 , p.T @ n으로 끝나지 않고, p.T @ n [0][0] 들어가 있는 확인하였습니다. [0][0] 넣은 것은 2차원 배열을 1차원 배열로 변형하기 위해서인가요?

답변: 연습문제 해설을 보다가 질문 드립니다. 관리자 2020 3 25 7:12 오후 답변

2차원 배열에서 스칼라를 뽑기 위해서입니다.

 


+ Recent posts