欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python實(shí)現(xiàn)矩陣的示例代碼

 更新時(shí)間:2023年07月07日 10:34:51   作者:星火流明  
本文主要介紹了python實(shí)現(xiàn)矩陣的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

矩陣

使用python構(gòu)建一個(gè)類,模擬矩陣,可以進(jìn)行各種矩陣的計(jì)算,與各種方便的用法

init

from array import array
class Matrix:
    def __init__(self, matrix: 'a list of one dimension', shape: 'a tuple of shape' = None, 
                 dtype: 'data type code' = 'd'):
        # matrix一個(gè)包含所有元素的列表,shape指定形狀,默認(rèn)為列向量,dtype是數(shù)據(jù)類型
        # 使用一個(gè)數(shù)組模擬矩陣,通過操作這個(gè)數(shù)組完成矩陣的運(yùn)算
        self.shape = (len(matrix), 1)
        if shape:
            self.shape = shape
        self.array = array(dtype, matrix)

getitem

由于矩陣是一個(gè)二維數(shù)組,應(yīng)當(dāng)支持諸如matrix[1, 2],matrix[1:3, 2],matrix[1:3, 2:4]之類的取值
所以我們需要使用slice類的indice方法實(shí)現(xiàn)__getitem__,并支持切片

    def __getitem__(self, item: 'a index of two dimensions'):
        # 使用slice類的indices方法,實(shí)現(xiàn)二維切片
        rows, cols = item
        # 下面對(duì)傳入的指針或者切片進(jìn)行處理,使其可以統(tǒng)一處理
        if isinstance(rows, slice):
            rows = rows.indices(self.shape[0])
        else:
            rows = (rows, rows + 1)
        if isinstance(cols, slice):
            cols = cols.indices(self.shape[1])
        else:
            cols = (cols, cols + 1)
        res = []
        shape = (len(range(*rows)), len(range(*cols)))  # 新矩陣的形狀
        # 通過遍歷按照順序?qū)⒃丶尤胄碌木仃?
        for row in range(*rows):
            for col in range(*cols):
                index = row * self.shape[1] + col
                res.append(self.array[index])
        if len(res) == 1:
        # 若是數(shù)則返回?cái)?shù)
            return res[0]
        # 若是矩陣則返回矩陣
        return Matrix(res, shape)

由于要支持切片,所以需要在方法中新建一個(gè)矩陣用于返回值

setitem

由于沒有序列協(xié)議的支持,我們需要自己實(shí)現(xiàn)__setitem__

    def __setitem__(self, key: 'a index or slice of two dimensions', value):
        # 使用slice類的indices方法,實(shí)現(xiàn)二維切片的廣播賦值
        rows, cols = key
        if isinstance(rows, slice):
            rows = rows.indices(self.shape[0])
        else:
            rows = (rows, rows + 1)
        if isinstance(cols, slice):
            cols = cols.indices(self.shape[1])
        else:
            cols = (cols, cols + 1)
        if isinstance(value, Matrix):
            # 對(duì)于傳入的值是矩陣,則需要判斷形狀
            if value.shape != (len(range(*rows)), len(range(*cols))):
                raise ShapeError
            # 使用x,y指針取出value中的值賦給矩陣
            x = -1
            for row in range(*rows):
                x += 1
                y = -1
                for col in range(*cols):
                    y += 1
                    index = row * self.shape[1] + col
                    self.array[index] = value[x, y]
        else:
            for row in range(*rows):
                for col in range(*cols):
                    index = row * self.shape[1] + col
                    self.array[index] = value

若傳入的value是一個(gè)數(shù),這里的邏輯基本與__getitem__相同,實(shí)現(xiàn)了廣播。

而若傳入的是一個(gè)矩陣,則需要判斷形狀,對(duì)對(duì)應(yīng)的元素進(jìn)行賦值,這是為了方便LU分解。

reshape

reshape用于改變形狀,對(duì)于上面的實(shí)現(xiàn)方法,只需要改變matrix.shape就可以了
注意改變前后的總元素?cái)?shù)應(yīng)當(dāng)一致

    def reshape(self, shape: 'a tuple of shape'):
        if self.shape[0] * self.shape[1] != shape[0] * shape[1]:
            raise ShapeError
        self.shape = shape

repr

實(shí)現(xiàn)__repr__方法,較為美觀的打印矩陣

    def __repr__(self):
        shape = self.shape
        _array = self.array
        return "[" + ",\n".join(str(list(_array[i * shape[1]:(i + 1) * shape[1]])) for i in range(shape[0])) + "]"

add 與 mul

對(duì)于加法與乘法的支持,這里的乘法是元素的乘法,不是矩陣的乘法
同樣的,實(shí)現(xiàn)廣播

? ? def __add__(self, other):
? ? ? ? shape = self.shape
? ? ? ? res = zeros(shape) ?# 創(chuàng)建一個(gè)新的零矩陣,用于返回
? ? ? ? if isinstance(other, Matrix):
? ? ? ? ? ? # 實(shí)現(xiàn)同樣形狀的矩陣元素之間的加法
? ? ? ? ? ? if self.shape != other.shape:
? ? ? ? ? ? ? ? # 如果矩陣的形狀對(duì)不上,就返回錯(cuò)誤
? ? ? ? ? ? ? ? raise ShapeError
? ? ? ? ? ? for i in range(shape[0]):
? ? ? ? ? ? ? ? for j in range(shape[1]):
? ? ? ? ? ? ? ? ? ? res[i, j] = self[i, j] + other[i, j]
? ? ? ? else:
? ? ? ? ? ? # 實(shí)現(xiàn)廣播
? ? ? ? ? ? for i in range(shape[0]):
? ? ? ? ? ? ? ? for j in range(shape[1]):
? ? ? ? ? ? ? ? ? ? res[i, j] = self[i, j] + other
? ? ? ? return res
? ? def __mul__(self, other):
? ? ? ? shape = self.shape
? ? ? ? res = zeros(shape) ?# 創(chuàng)建一個(gè)新的零矩陣,用于返回
? ? ? ? if isinstance(other, Matrix):
? ? ? ? ? ? # 實(shí)現(xiàn)同樣形狀的矩陣元素之間的乘法
? ? ? ? ? ? if self.shape != other.shape:
? ? ? ? ? ? ? ? # 如果矩陣的形狀對(duì)不上,就返回錯(cuò)誤
? ? ? ? ? ? ? ? raise ShapeError
? ? ? ? ? ? for i in range(shape[0]):
? ? ? ? ? ? ? ? for j in range(shape[1]):
? ? ? ? ? ? ? ? ? ? res[i, j] = self[i, j] * other[i, j]
? ? ? ? else:
? ? ? ? ? ? # 實(shí)現(xiàn)廣播
? ? ? ? ? ? for i in range(shape[0]):
? ? ? ? ? ? ? ? for j in range(shape[1]):
? ? ? ? ? ? ? ? ? ? res[i, j] = self[i, j] * other
? ? ? ? return res

matmul

matmul矩陣乘法,運(yùn)算符為@

    def __matmul__(self, other):
        # 實(shí)現(xiàn)矩陣的乘法
        if self.shape[1] != other.shape[0]:
            # 對(duì)形狀進(jìn)行判斷
            raise ShapeError
        if self.shape[0] == 1 and other.shape[1] == 1:
            # 行向量與列向量的乘積,就是它們的數(shù)量積
            length = self.shape[1]
            return sum(self[0, i] * self[i, 0] for i in range(length))
        res = []
        shape = (self.shape[0], other.shape[1])
        for i in range(shape[0]):
            for j in range(shape[1]):
                # 將兩個(gè)矩陣分別按行向量與列向量分塊,然后相乘
                try:
                    # 由于切片返回的可能是數(shù),而數(shù)不支持'@'運(yùn)算符,所以使用異常處理語句
                    res.append(self[i, :] @ other[:, j])
                except TypeError:
                    res.append(self[i, :] * other[:, j])
        return Matrix(res, shape)

將矩陣分成向量進(jìn)行矩陣乘法

LU分解

用屬性self._lu,構(gòu)建一個(gè)新的矩陣,作為L(zhǎng)U分解表。self._lu并不會(huì)在初始化時(shí)創(chuàng)建,而是在需要用到LU分解表時(shí)計(jì)算。
同時(shí),我們維護(hù)一個(gè)self.changed屬性,用來判斷在需要用到LU分解表時(shí)是否需要重新進(jìn)行LU分解

? ? def __init__(self, matrix: 'a list of one dimension', shape: 'a tuple of shape' = None,
? ? ? ? ? ? ? ? ?dtype: 'data type code' = "d"):
? ? ? ? # matrix一個(gè)包含所有元素的列表,shape指定形狀默認(rèn)為列向量,dtype是數(shù)據(jù)類型
? ? ? ? # 使用一個(gè)數(shù)組模擬矩陣,通過操作這個(gè)數(shù)組完成矩陣的運(yùn)算
? ? ? ? self.shape = (len(matrix), 1)
? ? ? ? if shape:
? ? ? ? ? ? self.shape = shape
? ? ? ? self.array = array(dtype, matrix)
? ? ? ? self._changed = True
? ? ? ? self._primary = list(range(shape[0])) # 只進(jìn)行行交換

顯然,當(dāng)我們修改了矩陣的元素后就需要重新進(jìn)行LU分解,重寫 setitem ,在開始時(shí)修改self.changed屬性

    def __setitem__(self, key: 'a index or slice of two dimensions', value):
        # 使用slice類的indices方法,實(shí)現(xiàn)二維切片的廣播賦值
        self._change = True
        ...

在lu分解中需要選擇主元,用屬性self._primary儲(chǔ)存當(dāng)前矩陣的主元表,因此我們要重寫 getitem 與 setitem

...
row = self._primary[row]  # 通過主元表進(jìn)行賦值,將行換為
index = row * self.shape[1] + col
...

下面,我們來實(shí)現(xiàn)LU分解

? ? def _primary_update(self, k):
? ? ? ? # 選擇絕對(duì)值最大的數(shù)作為主元
? ? ? ? max_val = -777
? ? ? ? max_index = 0
? ? ? ? for i in range(k, self.shape[0]):
? ? ? ? ? ? x = abs(self[i, k])
? ? ? ? ? ? if x > max_val:
? ? ? ? ? ? ? ? max_val = x
? ? ? ? ? ? ? ? max_index = i
? ? ? ? self._primary[k], self._primary[max_index] = self._primary[max_index], self._primary[k]
? ? def _lu_factorization(self):
? ? ? ? self._lu = Matrix(self.array, self.shape) # 新建一個(gè)矩陣儲(chǔ)存LU分解表
? ? ? ? rows, cols = self.shape
? ? ? ? _lu = self._lu
? ? ? ? step = min(rows, cols)
? ? ? ? for k in range(step):
? ? ? ? ? ? if _lu[k, k] == 0:
? ? ? ? ? ? ? ? # 如果當(dāng)前對(duì)角元素為0,就需要更換主元
? ? ? ? ? ? ? ? _lu._primary_update(k)
? ? ? ? ? ? if _lu[k, k] == 0:
? ? ? ? ? ? ? ? # 如果更換主元之后仍然為0,就說明該列全為0,跳過
? ? ? ? ? ? ? ? break
? ? ? ? ? ? x = 1 / _lu[k, k]
? ? ? ? ? ? _lu[k + 1:, k] *= x
? ? ? ? ? ? for i in range(k + 1, rows):
? ? ? ? ? ? ? ? for j in range(k + 1, cols):
? ? ? ? ? ? ? ? ? ? _lu[i, j] = _lu[i, j] - _lu[i, k] * _lu[k, j]

轉(zhuǎn)置

用一個(gè)方法實(shí)現(xiàn)轉(zhuǎn)置,而不是維護(hù)一個(gè)屬性

    def trans(self):
        shape = self.shape[::-1]
        res = zeros(shape) # 創(chuàng)建一個(gè)零矩陣用于返回
        for i in range(shape[0]):
            for j in range(shape[1]):
                res[i, j] = self[j, i]
        return res

利用LU分解求行列式

原矩陣的行列式就是L與U的對(duì)角元素的乘積

    def det(self):
        if self.shape[0] != self.shape[1]:
            raise ShapeError
        if self._changed:
            self._lu_factorization()
            self._changed = False
        res = 1
        for i in range(self.shape[0]):
            res *= self[i, i]
        return res

利用LU分解解線性方程組

利用LU分解可以快速地解出線性方程組

    def linear_equation(self, y):
        # 利用LU分解表解方程
        if not self.det():
            # 不考慮扁平化的情況,即使可能有解
            raise DetError
        lu = self._lu
        length = self.shape[1]
        z = [0]*length # 先解 L @ z = y
        for i in range(length):
            z_i = y[i, 0]
            for j in range(i):
                z_i -= z[j] * lu[i, j]
            z[i] = z_i
        x = [0]*length # 再解 U @ x = z
        for i in range(length - 1, -1, -1):
            x_i = z[i]
            for j in range(length - 1, i, -1):
                x_i -= x[j] * lu[i, j]
            x[i] = x_i / lu[i, i]
        return Matrix(x, (length, 1))

到此這篇關(guān)于python實(shí)現(xiàn)矩陣的示例代碼的文章就介紹到這了,更多相關(guān)python 矩陣內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python實(shí)現(xiàn)確認(rèn)字符串是否包含指定字符串的實(shí)例

    Python實(shí)現(xiàn)確認(rèn)字符串是否包含指定字符串的實(shí)例

    下面小編就為大家分享一篇Python實(shí)現(xiàn)確認(rèn)字符串是否包含指定字符串的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • python反扒機(jī)制的5種解決方法

    python反扒機(jī)制的5種解決方法

    這篇文章主要介紹了python反扒機(jī)制的5種解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • python 循環(huán)數(shù)據(jù)賦值實(shí)例

    python 循環(huán)數(shù)據(jù)賦值實(shí)例

    今天小編就為大家分享一篇python 循環(huán)數(shù)據(jù)賦值實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • Django實(shí)現(xiàn)靜態(tài)文件緩存到云服務(wù)的操作方法

    Django實(shí)現(xiàn)靜態(tài)文件緩存到云服務(wù)的操作方法

    這篇文章主要介紹了Django實(shí)現(xiàn)靜態(tài)文件緩存到云服務(wù)的操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • 關(guān)于Python函數(shù)參數(shù)的進(jìn)階用法

    關(guān)于Python函數(shù)參數(shù)的進(jìn)階用法

    這篇文章主要給大家分享的是Python函數(shù)參數(shù)的進(jìn)階用法,Python函數(shù)的參數(shù)根據(jù)函數(shù) 在調(diào)用時(shí) 傳參的形式分為關(guān)鍵字參數(shù)和位置參數(shù),下面文章小編就來介紹相關(guān)資料,需要的朋友可以參考一下
    2021-10-10
  • Python并發(fā)執(zhí)行的幾種實(shí)現(xiàn)方法

    Python并發(fā)執(zhí)行的幾種實(shí)現(xiàn)方法

    在Python中多線程是實(shí)現(xiàn)并發(fā)的一種方式,多線程可以讓程序在同一時(shí)間內(nèi)進(jìn)行多個(gè)任務(wù),從而提高程序的效率和執(zhí)行速度,這篇文章主要給大家介紹了關(guān)于Python并發(fā)執(zhí)行的幾種實(shí)現(xiàn)方法,需要的朋友可以參考下
    2024-08-08
  • python獲取磁盤號(hào)下盤符步驟詳解

    python獲取磁盤號(hào)下盤符步驟詳解

    在本篇文章里小編給大家整理了關(guān)于python如何獲取磁盤號(hào)下盤符的操作步驟以及實(shí)例代碼,有興趣的朋友們學(xué)習(xí)下。
    2019-06-06
  • pandas的排序、分組groupby及cumsum累計(jì)求和方式

    pandas的排序、分組groupby及cumsum累計(jì)求和方式

    這篇文章主要介紹了pandas的排序、分組groupby及cumsum累計(jì)求和方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • Django中使用Whoosh進(jìn)行全文檢索的方法

    Django中使用Whoosh進(jìn)行全文檢索的方法

    這篇文章主要介紹了Django中使用Whoosh進(jìn)行全文檢索的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 舉例講解如何在Python編程中進(jìn)行迭代和遍歷

    舉例講解如何在Python編程中進(jìn)行迭代和遍歷

    這篇文章主要介紹了舉例講解如何在Python編程中進(jìn)行迭代和遍歷,是Python入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2016-01-01

最新評(píng)論