ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ Python ] 선형대수학 X 파이썬 | 벡터의 외적과 직교벡터 분해
    Study/Python 2025. 3. 7. 23:28

    군 내에서 아이패드, 사지방 컴퓨터를 이용하여 작성함. 본 내용은 자기개발 목적으로 책 '개발자를 위한 실전 선형대수학-한빛미디어', 유튜브 등을 참고하였음. 그래프는 Google Colab에서 작성함.


    벡터의 외적


     외적열벡터행벡터를 사용하여 행렬을 만든다. 외적 행렬의 각 행은 행벡터 스칼라에 대응되는 열벡터 원소를 곱한 값이고, 각 열은 열벡터 스칼라에 대응되는 행벡터 원소를 곱한 값이다.
    벡터의 외적은 내적의 차이가 있는데, 외적은 스칼라 대신 행렬을 생성한다. 또 외적은 두 벡터의 차원이 달라도 되지만 내적은 같아야 한다.

    벡터의 외적 예시


    벡터의 외적을 앞으로 다음과 같이 표기하겠다.

    벡터의 외적 표기 방법

     
     외적은 브로드캐스팅과 비슷하지만 두 벡터를 곱하는 기법이므로 산술 연산을 벡터로 확장한 브로드캐스팅과는 다르다.
    각각 열과 행 방향인 벡터가 존재할 때 np.outer(), np.cross() 두 함수를 통해 외적을 계산할 수 있다.


    직교벡터 분해


     벡터와 행렬을 분해하면, 여러 조각으로 나뉘게 된다. 이를 통해 행렬을 분석하거나 변형하여 목적에 맞게 사용할 수 있다.

    직교 투영

    직교벡터 분해를 통해 직교 투영의 식을 유도할 수 있다.
    표준 위치에 두 벡터 a, b가 있을 때, b벡터의 머리가 a벡터와 가장 가까운 점을 찾는다고 하자. b벡터를 a벡터에 투영한 거리가 최소가 되도록 한 지점을 βa라 할 때 b에서 βa까지의 선을 ba라고 정의할 수 있다.

    위의 내용을 그림으로 표현한 것

    ba와 βa는 직교하는 걸 알 수 있으므로 둘의 내적의 값은 0이 되어야 한다.
    따라서 다음과 같은 식을 유도할 수 있다.

    이와 같은 β를 직교 투영(orthographic projection 또는 정사영)이라고 한다.


    직교벡터 분해

    위에서 한 것처럼, 벡터를 분해하기 위해서는 목표벡터기준벡터를 설정해야 된다.(목표벡터를 두 개의 다른 벡터로 분해하려는 목적이다.)
    이는 두 가지를 만족해야 된다.

    1. 분해된 두 벡터의 합이 목표벡터가 되어야 한다.
    2. 한 벡터는 기준벡터와 직교하고, 다른 벡터는 평행해야 된다.

    목표벡터t, 기준벡터r이라 할 때, 주어진 상황은 다음과 같다.

    따라서 직교 투영에서 구한 식을 이용하면 평행 성분을 찾을 수 있다.


    직교 투영에서 구한 식은 스칼라 β값만 구했으나 이 식에서는 벡터 βr을 구할 수 있다. 이 벡터가 평행 성분이다.
    수직 성분은 목표 벡터에서 평행 성분을 뺀 값으로 구할 수 있다.

     


    파이썬으로 구현하기

     

    np.cross()np.outer()의 차이

     np.cross()np.outer()는 외적을 계산하는 데 있어 차이점이 존재한다. 
    벡터의 외적을 계산할 때는 np.cross()를 사용한다. 같이 외적이라고 불리는 np.outer()는 텐서곱이다.

    # np.cross()을 이용한 벡터의 외적 예시
    import numpy as np
    
    Vec_a=np.array([1, 2, 3])
    Vec_b=np.array([4, 5, 6])
    
    cross_product = np.cross(Vec_a,Vec_b)
    print(cross_product)
    
    
    '''
    >> [-3  6 -3]
    '''

     

    # np.outer()을 이용한 벡터의 외적(텐서곱) 예시
    import numpy as np
     
    Vec_a = np.array([1, 2, 3])
    Vec_b = np.array([4, 5, 6])
    
    outer_product= np.outer(Vec_a, Vec_b)
    print(outer_product)
    
    
    '''
    >> [[ 4  5  6]
     [ 8 10 12]
     [12 15 18]]
    '''

     
     

    직교벡터 분해

     다음 코드는 두 난수 벡터 tr이 있을 때 두 성분의 합이 t이고 trt || r(수직 성분과 평행 성분)이 직교하는지 확인하는 것이다.

    import numpy as np
    import matplotlib.pyplot as plt
    
    # 난수 벡터 t, 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 )
    
    # 직교임을 확인하기(내적의 값은 0)
    print( np.dot(t_para,t_perp) )
    
    
    # 그래프 틀 그리기
    plt.figure(figsize=(6,6))
    
    # 두 메인 벡터 그리기
    plt.plot([0,t[0]],[0,t[1]],color='k',linewidth=3,label=r't')
    plt.plot([0,r[0]],[0,r[1]],color=[.7,.7,.7],linewidth=3,label=r'r')
    
    # 벡터의 두 구성요소 그리기
    plt.plot([0,t_para[0]],[0,t_para[1]],'k--',linewidth=3,label=r't para')
    plt.plot([0,t_perp[0]],[0,t_perp[1]],'k:',linewidth=3,label=r't perp')
    
    plt.axis('equal')
    plt.legend()
    plt.savefig('Figure_01_08.png',dpi=300)
    plt.show()
    
    
    '''
    >>[-1.19004149  0.34705056]
     [-1.19004149  0.34705056]
     0
     (아래 사진 참고)
    '''

제목 없는 코딩 블로그