필립 클라인의 저서 코딩 더 매트릭스 9장 내적
norm과 내적의 정의와 성질을 이해합니다.
직교의 의미를 이해합니다.
투영을 이용해 벡터를 분해하고 분해한 성분이 어떤 의미를 가지는지 알아봅니다.
내적을 이용해 간단한 기계 학습을 배워봅니다.
norm과 내적
두 벡터 u u u 와 v v v 의 거리는 차분 v − u v - u v − u 의 길이로 정의할 수 있습니다. 벡터에 대해서는 "길이"라는 용어 대신 보통 norm을 사용합니다. 벡터 v v v 의 norm은 ∥ v ∥ \parallel v \parallel ∥ v ∥ 로 씁니다. norm은 다음 성질들을 만족합니다.
임의의 벡터 v v v 에 대해 ∥ v ∥ \parallel v\parallel ∥ v ∥ 은 영이 아닌 실수이다.
임의의 벡터 v v v 에 대해 ∥ v ∥ \parallel v\parallel ∥ v ∥ 이 영이 될 필요충분조건은 v v v 가 영벡터인 것이다.
임의의 벡터 v v v 와 스칼라 α \alpha α 에 대해 ∥ α v ∥ = ∣ α ∣ ∥ v ∥ \parallel{\alpha v}\parallel = |\alpha| \parallel v\parallel ∥ α v ∥ = ∣ α ∣ ∥ v ∥ 이다.
임의의 벡터 u u u 와 v v v 에 대해 ∥ u + v ∥ ≤ ∥ u ∥ + ∥ v ∥ \parallel{u + v}\parallel \le \parallel u\parallel + \parallel v\parallel ∥ u + v ∥ ≤ ∥ u ∥ + ∥ v ∥ 이다.
마지막 성질은 아래 삼각형을 보면 쉽게 이해할 수 있습니다. 삼각형의 한변의 길이는 절대 다른 두변의 길이의 합보다 크지 않습니다.
실수 벡터들에 대한 내적
R \Bbb{R} R 상의 벡터들에 대한 내적은 도트곱으로 정의됩니다.
⟨ u , v ⟩ = u ⋅ v \langle u,v \rangle = u \cdot v ⟨ u , v ⟩ = u ⋅ v
실수 벡터들에 대한 내적은 도트곱의 성질들을 따릅니다.
⟨ u + v , w ⟩ = ⟨ u , w ⟩ + ⟨ v , w ⟩ \langle u + v, w \rangle = \langle u, w \rangle + \langle v, w \rangle ⟨ u + v , w ⟩ = ⟨ u , w ⟩ + ⟨ v , w ⟩
⟨ u , v ⟩ = ⟨ v , u ⟩ \langle u, v\rangle = \langle v, u\rangle ⟨ u , v ⟩ = ⟨ v , u ⟩
⟨ α u , v ⟩ = α ⟨ u , v ⟩ \langle \alpha u, v \rangle = \alpha \langle u, v \rangle ⟨ α u , v ⟩ = α ⟨ u , v ⟩
벡터 v v v 의 norm은 벡터들의 내적으로 다음과 같이 쓸 수 있습니다.
∥ v ∥ = ⟨ v , v ⟩ \parallel v \parallel = \sqrt{\langle v, v \rangle} ∥ v ∥ = ⟨ v , v ⟩
v = [ v 1 , v 2 , . . . , v n ] v = [v_1, v_2, ..., v_n] v = [ v 1 , v 2 , . . . , v n ] 이라 하면
∥ v ∥ 2 = ⟨ v , v ⟩ = v 1 2 + v 2 2 + . . . + v n 2 = ∑ i ∈ D v i 2 \begin{aligned}
\parallel v \parallel^2 & = \langle v, v \rangle \\
& = {v_1}^2 + {v_2}^2 + ... + {v_n}^2 \\
& = \sum_{i \in D} {v_i}^2
\end{aligned} ∥ v ∥ 2 = ⟨ v , v ⟩ = v 1 2 + v 2 2 + . . . + v n 2 = i ∈ D ∑ v i 2
따라서 ∥ v ∥ = ∑ i ∈ D v i 2 \parallel v \parallel = \sqrt{\sum_{i \in D} {v_i}^2} ∥ v ∥ = ∑ i ∈ D v i 2 입니다.
직교성 Orthogonality
직교(Orthogonal)는 수직(perpendicular)에 대한 수학적인 용어입니다. 직교의 정의에 대해 알아보기 전에 피타고라스의 정리를 이용해 그 동기를 살펴보겠습니다.
위 삼각형에서 빗변 u + v u + v u + v 의 제곱의 길이는 다음과 같습니다.
∥ u + v ∥ 2 = ⟨ u + v , u + v ⟩ = ⟨ u + v , u ⟩ + ⟨ u + v , v ⟩ = ⟨ u , u ⟩ + ⟨ v , u ⟩ + ⟨ u , v ⟩ + ⟨ v , v ⟩ = ∥ u ∥ 2 + 2 ⟨ u , v ⟩ + ∥ v ∥ 2 \begin{aligned}
{\parallel u + v \parallel}^2 & = \langle u + v, u + v \rangle \\
& = \langle u + v, u \rangle + \langle u + v, v \rangle \\
& = \langle u, u \rangle + \langle v, u \rangle + \langle u, v \rangle + \langle v, v \rangle \\
& = {\parallel u \parallel}^2 + 2 \langle u, v \rangle + {\parallel v \parallel}^2
\end{aligned} ∥ u + v ∥ 2 = ⟨ u + v , u + v ⟩ = ⟨ u + v , u ⟩ + ⟨ u + v , v ⟩ = ⟨ u , u ⟩ + ⟨ v , u ⟩ + ⟨ u , v ⟩ + ⟨ v , v ⟩ = ∥ u ∥ 2 + 2 ⟨ u , v ⟩ + ∥ v ∥ 2
마지막 표현이 ∥ u ∥ 2 + ∥ v ∥ 2 {\parallel u \parallel}^2 + {\parallel v \parallel}^2 ∥ u ∥ 2 + ∥ v ∥ 2 가 되기 위한 필요충분조건은 ⟨ u , v ⟩ = 0 \langle u, v \rangle = 0 ⟨ u , v ⟩ = 0 이 될 때입니다. 이때 u u u 와 v v v 는 직교합니다.
피타고라스 정리의 a 2 = b 2 + c 2 a^2 = b^2 + c^2 a 2 = b 2 + c 2 은 직각삼각형에 대해 성립하므로 만약 벡터 u u u , v v v 가 직교하면 다음이 성립합니다.
∥ u + v ∥ 2 = ∥ u ∥ 2 + ∥ v ∥ 2 {\parallel u + v \parallel}^2 = {\parallel u \parallel}^2 + {\parallel v \parallel}^2 ∥ u + v ∥ 2 = ∥ u ∥ 2 + ∥ v ∥ 2
직교의 몇가지 성질을 알아보겠습니다.
u u u 와 v v v 가 직교할 때 u u u 는 모든 스칼라 α \alpha α 에 대해 α v \alpha v α v 와 직교합니다.
∵ ⟨ u , α v ⟩ = α ⟨ u , v ⟩ = α 0 = 0 \because \langle u, \alpha v \rangle = \alpha \langle u, v \rangle = \alpha 0 = 0 ∵ ⟨ u , α v ⟩ = α ⟨ u , v ⟩ = α 0 = 0
u u u 와 v v v 둘 다 w w w 와 직교할때 u + v u + v u + v 는 w w w 와 직교합니다.
∵ ⟨ u + v , w ⟩ = ⟨ u , w ⟩ + ⟨ v , w ⟩ = 0 + 0 = 0 \because \langle u + v, w \rangle = \langle u, w \rangle + \langle v, w \rangle = 0 + 0 = 0 ∵ ⟨ u + v , w ⟩ = ⟨ u , w ⟩ + ⟨ v , w ⟩ = 0 + 0 = 0
평행 및 수직 성분으로의 벡터 분해
임의의 벡터 b b b 와 v v v 에 대해 b ∥ v b^{\parallel v} b ∥ v 는 b b b 의 v v v 를 따른 투영(projection), b ⊥ v b^{\perp v} b ⊥ v 를 b b b 의 v v v 에 직교하는 투영이라고 정의합니다.
b = b ∥ v + b ⊥ v b = b^{\parallel v} + b^{\perp v} b = b ∥ v + b ⊥ v
b ∥ v b^{\parallel v} b ∥ v 는 v v v 와 방향이 같거나 반대이고 크기가 다른 벡터이므로 다음과 같이 쓸 수 있습니다. 어떤 스칼라 σ ∈ R \sigma \in R σ ∈ R 에 대해,
b ∥ v = σ v b^{\parallel v} = \sigma v b ∥ v = σ v
그리고 b ⊥ v b^{\perp v} b ⊥ v 는 v v v 에 직교합니다.
벡터 b b b 와 v v v 에 대해 b b b 에 가장 가까운 S p a n { v } Span\{v\} S p a n { v } 내의 점은 b ∥ v b^{\parallel v} b ∥ v 이고 그 거리는 b ⊥ v b^{\perp v} b ⊥ v 입니다. 이를 증명하기 위해 S p a n { v } Span\{v\} S p a n { v } 내의 벡터 p p p 를 두고 다음과 같이 그려보겠습니다.
세 점 b b b , b ∥ v b^{\parallel v} b ∥ v , p p p 는 삼각형을 형성하고 있습니다. 여기서 피타고라스의 정리에 의해 세 점을 다음과 같이 쓸 수 있습니다.
∥ b − p ∥ 2 = ∥ b ∥ v − p ∥ 2 + ∥ b − b ∥ v ∥ 2 {\parallel b - p \parallel}^2 = {\parallel b^{\parallel v} - p \parallel}^2 + {\parallel b - b^{\parallel v} \parallel}^2 ∥ b − p ∥ 2 = ∥ b ∥ v − p ∥ 2 + ∥ b − b ∥ v ∥ 2
만약 b ∥ v ≠ p b^{\parallel v} \neq p b ∥ v = p 이면 ∥ b ∥ v − p ∥ 2 > 0 {\parallel b^{\parallel v} - p \parallel}^2 > 0 ∥ b ∥ v − p ∥ 2 > 0 입니다. 따라서
∥ b − b ∥ v ∥ 2 < ∥ b ∥ v − p ∥ 2 + ∥ b − b ∥ v ∥ 2 {\parallel b - b^{\parallel v} \parallel}^2 < {\parallel b^{\parallel v} - p \parallel}^2 + {\parallel b - b^{\parallel v} \parallel}^2 ∥ b − b ∥ v ∥ 2 < ∥ b ∥ v − p ∥ 2 + ∥ b − b ∥ v ∥ 2 이므로 ∥ b − b ∥ v ∥ < ∥ b − p ∥ \parallel b - b^{\parallel v}\parallel < \parallel b - p \parallel ∥ b − b ∥ v ∥ < ∥ b − p ∥ 입니다. 이는 b b b 에 가장 가까운 S p a n { v } Span\{v\} S p a n { v } 내의 벡터는 b ∥ v b^{\parallel v} b ∥ v 임을 의미하고 이 때 거리 ∥ b − b ∥ v ∥ \parallel b - b^{\parallel v} \parallel ∥ b − b ∥ v ∥ 는 ∥ b ⊥ v ∥ \parallel b^{\perp v} \parallel ∥ b ⊥ v ∥ 입니다.
투영 및 가장 가까운 점 찾기
b ∥ v = σ v b^{\parallel v} = \sigma v b ∥ v = σ v 에서 σ \sigma σ 는 어떻게 구할 수 있을까요? 직교하는 두 벡터 b ⊥ v b^{\perp v} b ⊥ v 와 v v v 를 내적하면 0이므로 다음과 같이 쓸 수 있습니다.
⟨ b ⊥ v , v ⟩ = 0 \langle b^{\perp v}, v \rangle = 0 ⟨ b ⊥ v , v ⟩ = 0
b ⊥ v = b − b ∥ v b^{\perp v} = b - b^{\parallel v} b ⊥ v = b − b ∥ v 이므로 다음과 같이 바꿔 쓸 수 있습니다.
⟨ b − b ∥ v , v ⟩ = ⟨ b , v ⟩ − ⟨ b ∥ v , v ⟩ = ⟨ b , v ⟩ − ⟨ σ v , v ⟩ = ⟨ b , v ⟩ − σ ⟨ v , v ⟩ \begin{aligned}
\langle b - b^{\parallel v}, v \rangle & = \langle b, v \rangle - \langle b^{\parallel v}, v \rangle \\
& = \langle b, v \rangle - \langle \sigma v, v \rangle \\
& = \langle b, v \rangle - \sigma \langle v, v \rangle
\end{aligned} ⟨ b − b ∥ v , v ⟩ = ⟨ b , v ⟩ − ⟨ b ∥ v , v ⟩ = ⟨ b , v ⟩ − ⟨ σ v , v ⟩ = ⟨ b , v ⟩ − σ ⟨ v , v ⟩
σ \sigma σ 에 대해 풀면 다음을 얻습니다.
σ = ⟨ b , v ⟩ ⟨ v , v ⟩ \sigma = \frac{\langle b, v \rangle}{\langle v, v \rangle} σ = ⟨ v , v ⟩ ⟨ b , v ⟩
위의 정리를 기반으로 b ∥ v b^{\parallel v} b ∥ v 와 b ⊥ v b^{\perp v} b ⊥ v 를 구하는 프로시저 project_along
, project_orthogonal_1
를 작성해 보겠습니다.
def project_along ( b, v) :
sigma = ( b * v) / ( v * v) if v * v != 0 else 0
return sigma * v
def project_orthogonal_1 ( b, v) :
return b - project_along( b, v)
외적과 투영
벡터 u u u 와 v v v 의 외적은 행렬-행렬 곱 u v T uv^T u v T 으로 정의됩니다.
[ u ] [ v T ] \begin{bmatrix}
\text{ } \\
u \\
\text{ }
\end{bmatrix}
\begin{bmatrix}
\text{ } & v^T & \text{ }
\end{bmatrix} ⎣ ⎢ ⎡ u ⎦ ⎥ ⎤ [ v T ]
외적을 이용해 v v v 를 따른 b b b 의 투영 b ∥ v b^{\parallel v} b ∥ v 를 표현할 수 있습니다. b ∥ v = σ v b^{\parallel v} = \sigma v b ∥ v = σ v 이고 σ = ⟨ v , v ⟩ ⟨ b , v ⟩ \sigma = \frac{\langle v, v \rangle}{\langle b, v \rangle} σ = ⟨ b , v ⟩ ⟨ v , v ⟩ 이므로 다음과 같이 쓸 수 있습니다.
b ∥ v = b ⋅ v ⟨ v , v ⟩ v b^{\parallel v} = \frac{b \cdot v}{\langle v, v \rangle}v b ∥ v = ⟨ v , v ⟩ b ⋅ v v
위 식을 행렬-행렬 곱셈으로 표현하면 다음과 같습니다.
1 ⟨ v , v ⟩ [ v ] ( [ v T ] [ b ] ) = 1 ⟨ v , v ⟩ ( [ v ] [ v T ] ) ⏟ 행렬 [ b ] \begin{aligned}
\frac{1}{\langle v, v \rangle}
\begin{bmatrix}
\text{ }\\
v \\
\text{ }
\end{bmatrix}
\begin{pmatrix}
\begin{bmatrix}
\text{ } & v^T & \text{ }
\end{bmatrix}
\begin{bmatrix}
\text{ }\\
b \\
\text{ }
\end{bmatrix}
\end{pmatrix}
= \frac{1}{\langle v, v \rangle}
\underbrace{
\begin{pmatrix}
\begin{bmatrix}
\text{ }\\
v \\
\text{ }
\end{bmatrix}
\begin{bmatrix}
\text{ } & v^T & \text{ }
\end{bmatrix}
\end{pmatrix}
}_{행렬}
\begin{bmatrix}
\text{ }\\
b \\
\text{ }
\end{bmatrix}
\end{aligned} ⟨ v , v ⟩ 1 ⎣ ⎢ ⎡ v ⎦ ⎥ ⎤ ⎝ ⎛ [ v T ] ⎣ ⎢ ⎡ b ⎦ ⎥ ⎤ ⎠ ⎞ = ⟨ v , v ⟩ 1 행 렬 ⎝ ⎛ ⎣ ⎢ ⎡ v ⎦ ⎥ ⎤ [ v T ] ⎠ ⎞ ⎣ ⎢ ⎡ b ⎦ ⎥ ⎤
다음은 위 식의 행렬을 찾는 프로시저 projection_matrix
입니다.
from matutil import zero_mat
from vecutil import list2vec
def projection_matrix ( v) :
M = zero_mat( ( v. D, v. D) )
norm = v * v
for r in v. D:
for c in v. D:
M[ r, c] = v[ r] * v[ c]
return M * ( 1 / norm)
기계학습
직교와 투영에 기반에 간단한 기계학습을 살펴보겠습니다. 데이터는 유방암 진단에 대한 각각의 피쳐벡터를 행으로 가지는 행렬과 결과벡터입니다. 행렬 방정식 M x = b Mx = b M x = b 의 행렬 M M M 과 벡터 b b b 를 cancer_data.py
의 프로시저 read_training_data
로 가져올 수 있습니다.
from cancer_data import read_training_data
M, b = read_training_data( '../assets/train.data' )
기계학습을 통해 M x = b Mx = b M x = b 를 최대한 만족하는 x ˉ \bar{x} x ˉ 를 찾게 될 것입니다. 이 때 M x ˉ = b ˉ M\bar{x} = \bar{b} M x ˉ = b ˉ 라 하면 학습한 데이터를 바탕으로 도출한 결과와 실제 데이터와의 차이, 즉 에러를 ( b ˉ − b ) 2 (\bar{b} - b)^2 ( b ˉ − b ) 2 으로 나타냅니다. 기계학습을 이미 배웠다면 익숙할 것입니다. 가설 벡터 w w w 와 피쳐벡터 a i a_i a i 에 대해 함수 h h h 를 다음과 같이 쓰겠습니다.
h ( a i ) = w ⋅ a i h(a_i) = w \cdot a_i h ( a i ) = w ⋅ a i
앞서 M x ˉ = b ˉ M\bar{x} = \bar{b} M x ˉ = b ˉ 의 b ˉ \bar{b} b ˉ 의 한 엔트리는 h ( a i ) h(a_i) h ( a i ) 입니다. 따라서 전체 에러를 다음과 같이 쓸 수 있습니다.
( h ( a 1 ) − b 1 ) 2 + ( h ( a 2 ) − b 2 ) 2 + . . . + ( h ( a m ) − b m ) 2 (h(a_1) - b_1)^2 + (h(a_2) - b_2)^2 + ... + (h(a_m) - b_m)^2 ( h ( a 1 ) − b 1 ) 2 + ( h ( a 2 ) − b 2 ) 2 + . . . + ( h ( a m ) − b m ) 2
행렬A
와 결과벡터 b
, 가설 벡터 w
를 인수로 받아 전체 에러를 구하는 프로시저 loss
를 작성해 보겠습니다.
def loss ( A, b, w) :
diff = A * w - b
return diff * diff
제곱의 합은 내적임을 이용해 반복문 없이 간단하게 프로시저를 작성할 수 있었습니다.
전체 에러의 최소화를 위해 경사하강법(그래디언트 디센트)를 알아볼 필요가 있습니다. 만약 솔루션 공간을 평면으로 그릴 수 있다면 다음과 같은 입체 평면이 그려집니다.
솔루션의 초기값이 위 평면의 임의의 지점에 있다고 가정하겠습니다. 최솟값에 도달하기 위해 지금의 점에서 가장 경사가 급한 지점으로 하강하고 다시 이동한 지점에서 경사가 가장 급한 지점으로 하강하면 최솟값에 도달하리라 예상할 수 있습니다. (실제로 전체 평면의 최소지점이 아닌 국지적인 최소지점에 도달할 수도 있습니다.) 이를 위해 그래디언트 ∇ f \nabla f ∇ f 를 이용합니다. 그래디언트는 미적분학에서 쓰는 용어로 함수 f ( [ x 1 , . . . , x n ] ) f([x_1, ..., x_n]) f ( [ x 1 , . . . , x n ] ) 의 그래디언트는 다음과 같이 정의됩니다.
[ ∂ f ∂ x 1 , . . . , ∂ f ∂ x n ] [\frac{\partial f}{\partial x_1}, ..., \frac{\partial f}{\partial x_n}] [ ∂ x 1 ∂ f , . . . , ∂ x n ∂ f ]
전체 에러를 구하는 손실함수를 L ( x ) L(x) L ( x ) 라 하면 L ( x ) L(x) L ( x ) 를 다음과 같이 쓸 수 있습니다.
L ( x ) = ∑ i = 1 m ( a i ⋅ x − b i ) 2 L(x) = \sum_{i=1}^{m}(a_i \cdot x - b_i)^2 L ( x ) = i = 1 ∑ m ( a i ⋅ x − b i ) 2
L ( x ) L(x) L ( x ) 를 x j x_j x j 에 대해 편미분하면
∂ L ∂ x j = ∑ i = 1 m ∂ ∂ x j ( a i ⋅ x − b i ) 2 = ∑ i = 1 m 2 ( a i ⋅ x − b i ) a i j \begin{aligned}
\frac{\partial L}{\partial x_j} & = \sum_{i=1}^{m}\frac{\partial}{\partial x_j}(a_i \cdot x - b_i)^2 \\
& = \sum_{i=1}^{m}2 (a_i \cdot x - b_i) a_{ij}
\end{aligned} ∂ x j ∂ L = i = 1 ∑ m ∂ x j ∂ ( a i ⋅ x − b i ) 2 = i = 1 ∑ m 2 ( a i ⋅ x − b i ) a i j
여기서 a i j a_{ij} a i j 는 x ⋅ a i x \cdot a_i x ⋅ a i 에서 x j x_j x j 와 곱해지는 a i a_i a i 의 엔트리입니다. 각각의 편미분을 구하면 그래디언트 값인 벡터가 구해집니다.
∇ L ( x ) = [ ∑ i = 1 m 2 ( a i ⋅ x − b i ) a i 1 , ∑ i = 1 m 2 ( a i ⋅ x − b i ) a i 2 , . . . , ∑ i = 1 m 2 ( a i ⋅ x − b i ) a i j ] \nabla L(x) = [\sum_{i=1}^{m}2 (a_i \cdot x - b_i) a_{i1}, \sum_{i=1}^{m}2 (a_i \cdot x - b_i) a_{i2}, ..., \sum_{i=1}^{m}2 (a_i \cdot x - b_i) a_{ij}] ∇ L ( x ) = [ i = 1 ∑ m 2 ( a i ⋅ x − b i ) a i 1 , i = 1 ∑ m 2 ( a i ⋅ x − b i ) a i 2 , . . . , i = 1 ∑ m 2 ( a i ⋅ x − b i ) a i j ]
그래디언트를 찾는 프로시저 find_grad
를 작성해보겠습니다. 연산 과정을 떠올려 보면 벡터-행렬 곱셈을 이용해 간단하게 구현할 수 있습니다.
def find_grad ( A, b, w) :
return 2 * ( A * w - b) * A
그래디언트 디센트는 find_grad
를 통해 찾은 그래디언트에 작은 스칼라를 곱한 값을 원래의 w w w 에서 뺌으로서 w w w 를 업데이트 합니다. 이 것은 솔루션 평면에서 한 스텝 하강하는 과정과 같습니다. 이 때 곱하는 작은 스칼라는 스텝 크기라 하고 σ \sigma σ 로 나타냅니다.
def gradient_descent_step ( A, b, w, sigma) :
return w - sigma * find_grad( A, b, w)
프로시저 gradient_descent_step
를 사용해 주어진 이터레이션 수만큼 하강을 반복하는 프로시저 gradient_descent
를 작성해 보겠습니다.
def gradient_descent ( A, b, w, sigma, T) :
for i in range ( T) :
w = gradient_descent_step( A, b, w, sigma)
if i % 30 == 0 :
print ( loss( A, b, w) )
return w
위 프로시저에서는 이터레이션의 매 30번마다 현재 전체 에러를 출력합니다.
이제 유방암 진단 데이터를 이용해 가설 벡터를 구할 수 있도록 학습하고 validate.data
에 적용해 보겠습니다.
from vecutil import list2vec
from vec import Vec
A, b = read_training_data( '../assets/train.data' )
w = Vec( A. D[ 1 ] , { } )
sigma = 10e - 10
T = 300
w = gradient_descent( A, b, w, sigma, T)
A_val, b_val = read_training_data( '../assets/validate.data' )
print ( loss( A_val, b_val, w) )
>> >
204.03071938964135
전체 에러만으로는 실제 결과와 얼마나 다른지 직관적으로 보기가 어렵습니다. 아래는 실제 데이터와 예측한 데이터가 얼마나 다른지 보여주고자 만든 프로시저입니다.
from vecutil import zero_vec
def signum ( u) :
v = zero_vec( u. D)
for d in u. D:
if u[ d] >= 0 :
v[ d] = 1
else :
v[ d] = - 1
return v
def fraction_wrong ( A, b, w) :
r = signum( A * w)
diff = ( r - b) / 2
return ( diff * diff) / len ( b. D)
프로시저 signum
은 양수는 모두 1에 음수는 모두 -1에 매핑합니다. fraction_wrong
는 벡터의 엔트리 값이 항상 1 또는 -1임을 이용해 실제와 예측이 얼마나 다른지 보여줍니다.
print ( fraction_wrong( A_val, b_val, w) )
>> >
0.1