メむンコンテンツぞスキップ
芋出し画像

numpyず、アダマヌル積

    はじめに

    皆さん、こんにちは。
    今回は、アダマヌル積ず、numpy 䞊でのアダマヌル積の実珟方法に぀いお、話をさせおいただこうず思いたす。


    numpyずは

    numpy は、プログラミング蚀語 python における特定の蚈算を、高速に実斜するためのラむブラリになりたす。

    先ず、python に぀いおは、別途以䞋の蚘事もありたすので、よかったら参照䞋さい。

    numpy に関しおは、以䞋の蚘事が numpy の高速化に぀いお觊れおいたすので、こちらもよかったら参照䞋さい。


    アダマヌル積ずは

    アダマヌル積に぀いおは、wikiに詳しい説明がありたした。

    䞀蚀で説明すれば、wiki䞭にある以䞋の画像のような圢になりたす。

    スクリヌンショット 2020-05-31 10.29.22

    芁するには、同じ芁玠数を持った行列、或いは、ベクトルに぀いお、同座暙同士の掛け合わせを行う蚈算の仕方になりたす。

    察しお、䞀般的な行列積は、異なる蚈算仕様になりたす。
    行列積や線圢代数の基本的な考え方に぀いおは、以䞋の蚘事を参照いただけたらず思いたす。

    アダマヌル積の蚈算仕様をむメヌゞにするず、以䞋の様になりたす。
    尚、アダマヌル積の蚘号は、○になりたす。

    スクリヌンショット 2020-05-31 10.48.33

    スクリヌンショット 2020-05-31 10.50.55

    同座暙の倀同士を掛け合わせお、その掛け算の結果を、同座暙にセットする圢です。

    䞀方、行列積の蚈算仕様は、以䞋むメヌゞずなりたす。

    スクリヌンショット 2020-05-31 11.05.18

    スクリヌンショット 2020-05-31 11.07.08


    numpyで実装するず、どうなるか

    䞊蚘の䟋を、numpy で実装するず、以䞋のようになりたす。

    import numpy as np
    
    A = np.array([[1, 4], 
                  [3, 6], 
                  [8, 2]])
    
    B = np.array([[3, 2], 
                  [5, 1], 
                  [7, 10]])
    
    print('A * B = ')
    print(A * B)
    print()
    print('A.T @ B = ')
    print(A.T @ B)

    出力結果は以䞋になりたす

    A * B =
    [[ 3 8]
     [15 6]
     [56 20]]

    A.T @ B =
    [[74 85]
     [56 34]]


    特殊なケヌスにおける、numpyのアダマヌル積的な蚈算仕様

    アダマヌル積は、基本的に芁玠数が等しい行列同士、ベクトル同士での蚈算が基本ではありたすが、実際には、もう少し拡匵したい時があったりしたす。

    䟋えば、行列ずベクトルずをアダマヌル積的に蚈算するケヌスです。
    ケヌスずしおは、ベクトルが瞊であるケヌスず、暪であるケヌスずの2぀がありたす。

    前者ケヌスのむメヌゞは以䞋です。
    numpy でアダマヌル積ず同様に

    スクリヌンショット 2020-05-31 14.05.33

    これは、芁するには、瞊のベクトルを、暪にコピヌしお、アダマヌル積を取るような圢です。

    スクリヌンショット 2020-05-31 14.10.14

    埌者ケヌスのむメヌゞは以䞋です。

    スクリヌンショット 2020-05-31 14.15.07

    こちらも、暪のベクトルを、瞊にコピヌしお、アダマヌル積を実斜しおくれたす。

    スクリヌンショット 2020-05-31 14.16.56

    或いは、行列ずスカラヌの掛け算の堎合は、行列の党芁玠に察しお、定数倍を実斜する圢になりたす。

    スクリヌンショット 2020-05-31 14.22.39

    こちらも、芁するには、スカラヌを瞊暪にコピヌしおから、アダマヌル積を実斜しおいる圢です。

    スクリヌンショット 2020-05-31 14.32.39

    尚、アダマヌル積、或いは、アダマヌル積的な蚈算をする堎合、掛け算蚘号の前埌の倉数が入れ替わっおも、蚈算結果は倉わりたせん。

    import numpy as np
    
    A = np.array([[1, 4], 
                  [3, 6], 
                  [8, 2]])
    
    b = np.array([[3], 
                  [5], 
                  [7]])
    
    c = np.array([[3, 2]])
    
    d = np.array([3])
    
    print('A * b = ')
    print(A * b)
    print()
    print('b * A = ')
    print(b * A)
    print()
    print('A * c = ')
    print(A * c)
    print()
    print('c * A = ')
    print(c * A)
    print()
    print('A * d = ')
    print(A * d)
    print()
    print('d * A = ')
    print(d * A)

    プログラムの出力結果は以䞋ずなりたす。

    A * b =
    [[ 3 12]
     [15 30]
     [56 14]]

    b * A =
    [[ 3 12]
     [15 30]
     [56 14]]

    A * c =
    [[ 3 8]
     [ 9 12]
     [24 4]]

    c * A =
    [[ 3 8]
     [ 9 12]
     [24 4]]

    A * d =
    [[ 3 12]
     [ 9 18]
     [24 6]]

    d * A =
    [[ 3 12]
     [ 9 18]
     [24 6]]

    䞀方、行列積の堎合は、䟋えば、行列 A ず行列 B に぀いお、AB ず BA の結果は異なりたす。

    A = np.array([[3, 2],
                  [1, 6]])
    B = np.array([[4, 3],
                  [2, 1]])
    
    print('A @ B = ')
    print(A @ B)
    print()
    print('B @ A = ')
    print(B @ A)

    プログラムの出力結果は、以䞋ずなりたす。

    A @ B =
    [[16 11]
     [16 9]]

    B @ A =
    [[15 26]
     [ 7 10]]


    解釈がややこしいので、いっそfor文にしおしたえば 

    䞊蚘、アダマヌル積的な蚈算に関しおは、解釈が若干難しいので、なんならfor文を䜿っお蚈算を衚珟した方が良いのではないか ず思えおくる方もいるこずでしょう。

    しかし、実は、python には、for 文によるパフォヌマンス䜎䞋の問題がありたす。
    numpy の機胜を甚いお、for 文を䜿わずに実装した方が、最適化されたラむブラリ機胜をフルに䜿うこずで、パフォヌマンスが栌段に向䞊するのです。

    その蟺りに぀いおは、以䞋の蚘事にたずめられおいたすので、参考にしお䞋さい。

    蚘事䞭に実斜した実隓では、1000䞇個の芁玠を持぀行列同士のアダマヌル積にお、250倍皋の高速化が実珟されおいたす。

    250倍の高速化ずいうず 。
    高速化のスケヌルずしお、「4分 → 1秒」、「4時間 → 1分」、「10日 → 1時間」ずいう具合です。
    スゎい違いですね。

    その為、仕様を理解しお、numpy を䜿ったアダマヌル積挔算を行うこずには、ずおも意味がありたす。


    おわりに

    以䞊で、アダマヌル積に関する蚘事を終えたす。
    ここたで読んでくださった方、本圓にありがずうございたした。🙇

     
     

    mucun_wuxian

     
     
    デヌタサむ゚ンティストずしお頑匵っおいたす。

    あなたぞのおすすめ