Bagaimana Anda mengalikan dua matriks dengan python tanpa numpy?

Silakan temukan kode untuk posting ini di GitHub. Seperti biasa, saya harap Anda akan mengkloningnya dan menjadikannya milik Anda sendiri. Modul utama dalam repo yang menampung semua modul yang akan kita bahas diberi nama LinearAlgebraPurePython. py. Ada file python sederhana bernama BasicToolsPractice. py yang mengimpor modul utama itu dan mengilustrasikan fungsi modul. Alangkah baiknya jika Anda dapat mengkloning atau mengunduh yang pertama agar berguna saat kita membaca posting ini

Mengapa Posting Ini?

PENGINGAT. Tujuan kami adalah untuk lebih memahami prinsip-prinsip alat pembelajaran mesin dengan mengeksplorasi cara mengkodekannya sendiri …

Artinya, kami sedang mencari kode alat ini tanpa menggunakan modul python AWESOME yang tersedia untuk pembelajaran mesin

Upaya ini akan memberikan wawasan dan pemahaman yang lebih baik, tetapi wawasan tersebut kemungkinan besar tidak akan disampaikan kepada kami di setiap pos. Sebaliknya, kami sedang membangun fondasi yang akan mendukung wawasan tersebut di masa depan

Untuk merampingkan beberapa posting yang akan datang, saya ingin membahas beberapa fungsi dasar yang akan membuat posting mendatang lebih mudah. Jelas, jika kita menghindari penggunaan numpy dan scipy, kita harus membuat fungsi / alat kenyamanan kita sendiri. Posting ini mencakup alat-alat kenyamanan itu.  

Di salah satu ujung spektrum, jika Anda baru mengenal aljabar linier atau python atau keduanya, saya yakin Anda akan menemukan posting ini bermanfaat di antara, saya harap, sekelompok tautan tersimpan yang bagus

Di ujung lain spektrum, jika Anda memiliki latar belakang dengan python dan aljabar linier, alasan Anda membaca postingan ini adalah untuk membandingkan cara saya melakukannya dengan cara Anda melakukannya. Ulasan tersebut mungkin memberi Anda beberapa ide baru, atau mungkin mengonfirmasi bahwa Anda masih lebih menyukai cara Anda.  

Alat

Anda akan menemukan dokumentasi dan komentar di semua fungsi ini. Ketika lebih banyak deskripsi diperlukan, saya akan memberikan atau memberikan arahan ke sumber lain untuk menjelaskannya secara lebih rinci. Jika ada bagian tertentu yang tidak Anda mengerti, saya ingin Anda memahaminya dengan lebih baik. Apa cara terbaik untuk melakukannya?

Yang pertama adalah zeros_matrix. Saat kita hanya membutuhkan matriks baru, mari buat satu dan isi dengan nol

def zeros_matrix(rows, cols):
    """
    Creates a matrix filled with zeros.
        :param rows: the number of rows the matrix should have
        :param cols: the number of columns the matrix should have

        :return: list of lists that form the matrix
    """
    M = []
    while len(M) < rows:
        M.append([])
        while len(M[-1]) < cols:
            M[-1].append(0.0)

    return M

Seperti yang telah Anda lihat dari posting sebelumnya, matriks dan vektor keduanya ditangani dengan Python sebagai array dua dimensi. Jadi, larik baris berisi larik nilai kolom, dan setiap nilai kolom diinisialisasi ke 0. Perhatikan indeks -1 pada baris matriks pada while loop kedua. Ini adalah cara sederhana untuk mereferensikan elemen terakhir dari sebuah array, dan dalam hal ini, ini adalah array (baris) terakhir yang telah ditambahkan ke array

Fungsi penolong kedua kami adalah identity_matrix yang digunakan untuk membuat matriks identitas. Dan, seperti yang seharusnya dilakukan oleh programmer yang malas secara konstruktif, saya telah banyak memanfaatkan panggilan awal ke zeros_matrix. Yang tersisa setelah kita memiliki matriks identitas adalah mengganti elemen diagonal dengan 1

def identity_matrix(n):
    """
    Creates and returns an identity matrix.
        :param n: the square size of the matrix

        :return: a square identity matrix
    """
    IdM = zeros_matrix(n, n)
    for i in range(n):
        IdM[i][i] = 1.0

    return IdM
_

Ketiga adalah copy_matrix juga sangat bergantung pada zeros_matrix. Kami menginginkan ini untuk saat-saat di mana kami perlu mengerjakan salinan dan mempertahankan matriks asli. Di sini, kita hanya mendapatkan dimensi dari matriks asli dan menggunakan dimensi tersebut untuk membuat matriks nol dan kemudian menyalin elemen dari matriks asli ke elemen matriks baru dengan elemen.

def copy_matrix(M):
    """
    Creates and returns a copy of a matrix.
        :param M: The matrix to be copied

        :return: A copy of the given matrix
    """
    # Section 1: Get matrix dimensions
    rows = len(M)
    cols = len(M[0])

    # Section 2: Create a new matrix of zeros
    MC = zeros_matrix(rows, cols)

    # Section 3: Copy values of M into the copy
    for i in range(rows):
        for j in range(cols):
            MC[i][j] = M[i][j]

    return MC

Keempat adalah print_matrix sehingga kita bisa melihat apakah kita telah mengacaukan atau tidak dalam operasi aljabar linier kita. Di sini, kami hanya mencetak matriks, atau vektor, satu baris dalam satu waktu. "+0" dalam daftar pemahaman telah disebutkan di posting sebelumnya. Coba pemahaman daftar dengan dan tanpa "+0" itu dan lihat apa yang terjadi.  

def print_matrix(M, decimals=3):
    """
    Print a matrix one row at a time
        :param M: The matrix to be printed
    """
    for row in M:
        print([round(x,decimals)+0 for x in row])

Jika Anda belum mengetahui teknik pemahaman daftar python, itu layak dipelajari. Ada banyak sekali blog dan situs bagus yang mengajarkannya. Seperti biasa, saya merekomendasikan agar Anda merujuk ke setidaknya tiga sumber saat mempelajari keterampilan baru apa pun, terutama saat mempelajari keterampilan Python baru. Beberapa contoh singkatnya adalah…

some_new_list = [<method(x)> for x in list if <condition> else <other>]
# or
another_list = [s.method() for s in string_list if <condition>]
# or
one_more_list = [<method(x)> for x in list]
_

Tujuan menampilkan one_more_list adalah untuk membuatnya sangat jelas bahwa Anda sebenarnya tidak perlu memiliki persyaratan apa pun dalam pemahaman daftar, dan metode yang Anda terapkan bisa menjadi metode yang Anda tulis

Kelima adalah transpose. Mentranspos matriks hanyalah tindakan memindahkan elemen dari baris dan kolom asli yang diberikan ke baris = kolom asli dan kolom = baris asli. Artinya, jika elemen tertentu dari M adalah m_{i,j}, it will move to m_{j,i} in the transposed matrix, which is shown as

MT[j][i] = M[i][j]

dalam kode. Sehubungan dengan prinsip ini, perhatikan bahwa matriks nol dibuat dengan jumlah kolom matriks asli untuk jumlah baris matriks yang ditransposisikan dan jumlah baris matriks asli untuk jumlah kolom matriks yang ditransposisikan. Benar-benar seteguk

Perhatikan bahwa di bagian 1 di bawah ini, pertama-tama kita memastikan bahwa M adalah larik Python dua dimensi. Kemudian kami menyimpan dimensi M di bagian 2. Selanjutnya, di bagian 3, kami menggunakan dimensi tersebut untuk membuat matriks nol yang memiliki dimensi matriks yang ditransposisikan dan menyebutnya MT. Terakhir, di bagian 4, kami mentransfer nilai dari M ke MT dengan cara transposisi seperti yang dijelaskan sebelumnya

def transpose(M):
    """
    Returns a transpose of a matrix.
        :param M: The matrix to be transposed

        :return: The transpose of the given matrix
    """
    # Section 1: if a 1D array, convert to a 2D array = matrix
    if not isinstance(M[0],list):
        M = [M]

    # Section 2: Get dimensions
    rows = len(M)
    cols = len(M[0])

    # Section 3: MT is zeros matrix with transposed dimensions
    MT = zeros_matrix(cols, rows)

    # Section 4: Copy values from M to it's transpose MT
    for i in range(rows):
        for j in range(cols):
            MT[j][i] = M[i][j]

    return MT
_

Keenam dan Ketujuh adalah matrix_addition dan matrix_subtraction. Saya menjelaskannya pada saat yang sama, karena mereka pada dasarnya identik dengan pengecualian satu baris kode di mana elemen dengan penambahan atau pengurangan elemen terjadi. Di bagian 1 dari setiap fungsi, Anda melihat bahwa kami memeriksa bahwa setiap matriks memiliki dimensi yang identik, jika tidak, kami tidak dapat menjumlahkannya. Bagian 2 dari setiap fungsi membuat matriks nol untuk menampung matriks yang dihasilkan. Bagian 3 dari setiap fungsi melakukan operasi penjumlahan atau pengurangan elemen demi elemen.  

def matrix_addition(A, B):
    """
    Adds two matrices and returns the sum
        :param A: The first matrix
        :param B: The second matrix

        :return: Matrix sum
    """
    # Section 1: Ensure dimensions are valid for matrix addition
    rowsA = len(A)
    colsA = len(A[0])
    rowsB = len(B)
    colsB = len(B[0])
    if rowsA != rowsB or colsA != colsB:
        raise ArithmeticError('Matrices are NOT the same size.')

    # Section 2: Create a new matrix for the matrix sum
    C = zeros_matrix(rowsA, colsB)

    # Section 3: Perform element by element sum
    for i in range(rowsA):
        for j in range(colsB):
            C[i][j] = A[i][j] + B[i][j]

    return C

def matrix_subtraction(A, B):
    """
    Subtracts matrix B from matrix A and returns difference
        :param A: The first matrix
        :param B: The second matrix

        :return: Matrix difference
    """
    # Section 1: Ensure dimensions are valid for matrix subtraction
    rowsA = len(A)
    colsA = len(A[0])
    rowsB = len(B)
    colsB = len(B[0])
    if rowsA != rowsB or colsA != colsB:
        raise ArithmeticError('Matrices are NOT the same size.')

    # Section 2: Create a new matrix for the matrix difference
    C = zeros_matrix(rowsA, colsB)

    # Section 3: Perform element by element subtraction
    for i in range(rowsA):
        for j in range(colsB):
            C[i][j] = A[i][j] - B[i][j]

    return C

Kedelapan adalah matrix_multiply. Aturan pertama dalam perkalian matriks adalah jika ingin mengalikan matriks A kali matriks B, the number of columns of A MUST equal the number of rows of B. Thus, if A memiliki dimensi m baris dan n columns (m\,x\,n for short) B must have n rows and it can have 1 or more columns. Let’s say it has k kolom. Jadi, hasil perkalian kedua matriks tersebut adalah matriks m\,x\,k , atau matriks yang dihasilkan memiliki jumlah baris < . Oleh karena itu, kami membuat matriks nol untuk menampung produk yang dihasilkan dari dua matriks yang memiliki dimensi A and the number of columns of B.  Hence, we create a zeros matrix to hold the resulting product of the two matrices that has dimensions of rows_A \, x \, cols_B dalam kode. Juga, JIKA A dan B memiliki dimensi n rows and n columns, that is they are square matrices, A \cdot B does NOT equal B \cdot A. Remember that the order of multiplication matters when multiplying matrices. Finally, the result for each new element c_{i,j} di C, which will be the result of A \cdot B, is found as follows using a 3\,x\,3 matrix as an example:

c_{i,j} = a_{i,0} \cdot b_{0,j} + a_{i,1} \cdot b_{1,j} + a_{i,2} \cdot b_{2,j

Artinya, untuk mendapatkan c_{i,j} kita mengalikan setiap elemen kolom di setiap baris i of A times each row element in each column j of B and adding up those products. Phew!

def matrix_multiply(A, B):
    """
    Returns the product of the matrix A * B
        :param A: The first matrix - ORDER MATTERS!
        :param B: The second matrix

        :return: The product of the two matrices
    """
    # Section 1: Ensure A & B dimensions are correct for multiplication
    rowsA = len(A)
    colsA = len(A[0])
    rowsB = len(B)
    colsB = len(B[0])
    if colsA != rowsB:
        raise ArithmeticError(
            'Number of A columns must equal number of B rows.')

    # Section 2: Store matrix multiplication in a new matrix
    C = zeros_matrix(rowsA, colsB)
    for i in range(rowsA):
        for j in range(colsB):
            total = 0
            for ii in range(colsA):
                total += A[i][ii] * B[ii][j]
            C[i][j] = total

    return C

_

Kesembilan adalah fungsi, perkalian_matriks, untuk mengalikan daftar matriks menggunakan perkalian_matriks. Perhatikan bahwa kita hanya menetapkan produk yang berjalan sebagai matriks pertama dalam daftar, dan kemudian perulangan for dimulai pada elemen kedua (dari daftar matriks) untuk mengulang melalui matriks dan membuat produk yang berjalan, produk_matriks, dikali matriks berikutnya .  

def multiply_matrices(list):
    """
    Find the product of a list of matrices from first to last
        :param list: The list of matrices IN ORDER

        :return: The product of the matrices
    """
    # Section 1: Start matrix product using 1st matrix in list
    matrix_product = list[0]

    # Section 2: Loop thru list to create product
    for matrix in list[1:]:
        matrix_product = matrix_multiply(matrix_product, matrix)

    return matrix_product
_

Kesepuluh, dan saya akui saya tidak yakin kapan waktu terbaik untuk mempresentasikan yang ini, adalah check_matrix_equality. Akan ada saatnya memeriksa kesetaraan antara dua matriks adalah cara terbaik untuk memverifikasi hasil kami. Namun, operasi tersebut akan memiliki sejumlah kesalahan pembulatan di mana matriks tidak akan persis sama, tetapi pada dasarnya akan sama. Jadi, perhatikan bahwa ada tol (parameter toleransi), yang dapat diatur. Jika default yang digunakan, kedua matriks diharapkan sama persis. Jika toleransi diatur, nilai tol adalah jumlah desimal tempat nilai elemen dibulatkan untuk memeriksa keadaan yang pada dasarnya sama

def identity_matrix(n):
    """
    Creates and returns an identity matrix.
        :param n: the square size of the matrix

        :return: a square identity matrix
    """
    IdM = zeros_matrix(n, n)
    for i in range(n):
        IdM[i][i] = 1.0

    return IdM
_0

Hasil kali titik antara dua vektor atau matriks pada dasarnya adalah perkalian matriks dan harus mengikuti aturan yang sama. Penting untuk diperhatikan bahwa rutinitas perkalian matriks kita dapat digunakan untuk mengalikan dua vektor yang dapat menghasilkan matriks nilai tunggal. Dalam kasus seperti itu, hasil tersebut dianggap bukan vektor atau matriks, tetapi merupakan nilai tunggal, atau penskalaan. Namun, dengan menggunakan rutin kami, itu akan tetap menjadi array dengan array satu nilai di dalamnya. Untuk membaca referensi lain, centang , dan saya akan menyimpan tautan itu sebagai bookmark – ini adalah sumber yang bagus

Fungsi Kesebelas adalah fungsi unitize_vector. Mari kita telusuri bagian-bagiannya. Bagian 1 memastikan bahwa vektor adalah input yang berarti bahwa salah satu dimensinya harus 1. Juga, memastikan bahwa array adalah 2 dimensi. Kit alat ini menginginkan semua matriks dan vektor menjadi 2 dimensi untuk konsistensi. Bagian 2 menggunakan teorema Pythagoras untuk menemukan besarnya vektor. Bagian 3 membuat salinan dari vektor asli (fungsi copy_matrix bekerja dengan baik, karena masih bekerja pada array 2D), dan Bagian 4 membagi setiap elemen dengan besarnya vektor yang ditentukan untuk membuat vektor satuan.  

def identity_matrix(n):
    """
    Creates and returns an identity matrix.
        :param n: the square size of the matrix

        :return: a square identity matrix
    """
    IdM = zeros_matrix(n, n)
    for i in range(n):
        IdM[i][i] = 1.0

    return IdM
_1

Menggunakan Numpy Untuk Operasi Di Atas

Bagaimana kita melakukan semua tindakan ini dengan numpy? . Kode di bawah ini mengikuti urutan fungsi yang sama seperti yang baru saja kita bahas di atas, tetapi menunjukkan cara melakukannya masing-masing di numpy. Kode di bawah ini ada di file NumpyToolsPractice. py di repo. Salin kode di bawah ini atau dapatkan dari repo, tetapi saya sangat menganjurkan Anda untuk menjalankan dan memainkannya

def identity_matrix(n):
    """
    Creates and returns an identity matrix.
        :param n: the square size of the matrix

        :return: a square identity matrix
    """
    IdM = zeros_matrix(n, n)
    for i in range(n):
        IdM[i][i] = 1.0

    return IdM
_2

Penutupan

Itu saja untuk saat ini. Perpustakaan ini tentu saja akan tumbuh dengan setiap posting baru. Saya akan memperkenalkan fungsi pembantu baru jika dan ketika dibutuhkan di posting mendatang, dan memiliki posting terpisah untuk penambahan yang memerlukan penjelasan lebih lanjut. Tetapi fungsi-fungsi ini adalah yang paling dasar. Beberapa di antaranya juga mendukung pekerjaan untuk pos matriks invers dan untuk penyelesaian pos sistem persamaan.  

Bagaimana Anda memecahkan matriks dengan Python tanpa NumPy?

Kita ingin menyelesaikan X, jadi kita melakukan operasi baris pada A yang mengarahkannya ke matriks identitas. .
buat elemen di kolom-baris dengan fd sebuah scaler;
perbarui baris itu dengan … [baris saat ini] – scaler * [baris dengan fd];
nol sekarang akan berada di lokasi kolom fd untuk baris itu

Bagaimana Anda mengalikan dua matriks dengan Python?

Langkah 1. masukan dua matriks. Langkah 2. bersarang untuk loop untuk beralih melalui setiap baris dan setiap kolom. Langkah 3. ambil satu resultan matriks yang awalnya berisi semua 0. Kemudian kita mengalikan setiap elemen baris matriks pertama dengan setiap elemen matriks kedua, lalu menjumlahkan semua nilai yang dikalikan

Bagaimana Anda mengalikan matriks 2x2 dengan Python?

Misalnya, A= [ [1, 2], [3, 4]] adalah matriks 2x2. Baris pertama dapat dipilih sebagai A[0] dan elemen di baris pertama, kolom pertama dapat dipilih sebagai A[0][0]. Perkalian dua matriks hanya dapat dilakukan jika jumlah kolom pada matriks pertama sama dengan jumlah baris pada matriks kedua .

Bagaimana Anda mengalikan matriks secara manual?

Untuk mengalikan matriks dengan satu bilangan itu mudah. .
Ini perhitungannya. 2×4=8. 2×0=0. .
"Produk Dot" adalah tempat kami mengalikan anggota yang cocok, lalu menjumlahkannya. (1, 2, 3) • (7, 9, 11) = 1×7 + 2×9 + 3×11. = 58. .
(1, 2, 3) • (8, 10, 12) = 1×8 + 2×10 + 3×12. = 64. .
SELESAI. Mengapa Melakukannya Dengan Cara Ini?