我的编程空间,编程开发者的网络收藏夹
学习永远不晚

使用python实现矩阵

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

使用python实现矩阵

文章目录

矩阵

使用python构建一个类,模拟矩阵,可以进行各种矩阵的计算,与各种方便的用法

init

from array import arrayclass Matrix:    def __init__(self, matrix: 'a list of one dimension', shape: 'a tuple of shape' = None,                  dtype: 'data type code' = 'd'):        # matrix一个包含所有元素的列表,shape指定形状,默认为列向量,dtype是数据类型        # 使用一个数组模拟矩阵,通过操作这个数组完成矩阵的运算        self.shape = (len(matrix), 1)        if shape:            self.shape = shape        self.array = array(dtype, matrix)

getitem

由于矩阵是一个二维数组,应当支持诸如matrix[1, 2],matrix[1:3, 2],matrix[1:3, 2:4]之类的取值
所以我们需要使用slice类的indice方法实现__getitem__,并支持切片

    def __getitem__(self, item: 'a index of two dimensions'):        # 使用slice类的indices方法,实现二维切片        rows, cols = item        # 下面对传入的指针或者切片进行处理,使其可以统一处理        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)))  # 新矩阵的形状        # 通过遍历按照顺序将元素加入新的矩阵        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:        # 若是数则返回数            return res[0]        # 若是矩阵则返回矩阵        return Matrix(res, shape)

由于要支持切片,所以需要在方法中新建一个矩阵用于返回值

setitem

由于没有序列协议的支持,我们需要自己实现__setitem__

    def __setitem__(self, key: 'a index or slice of two dimensions', value):        # 使用slice类的indices方法,实现二维切片的广播赋值        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):            # 对于传入的值是矩阵,则需要判断形状            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是一个数,这里的逻辑基本与__getitem__相同,实现了广播。
而若传入的是一个矩阵,则需要判断形状,对对应的元素进行赋值,这是为了方便LU分解。

reshape

reshape用于改变形状,对于上面的实现方法,只需要改变matrix.shape就可以了
注意改变前后的总元素数应当一致

    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

实现__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])) + "]"

addmul

对于加法与乘法的支持,这里的乘法是元素的乘法,不是矩阵的乘法
同样的,实现广播

    def __add__(self, other):        shape = self.shape        res = zeros(shape)  # 创建一个新的零矩阵,用于返回        if isinstance(other, Matrix):            # 实现同样形状的矩阵元素之间的加法            if self.shape != other.shape:                # 如果矩阵的形状对不上,就返回错误                raise ShapeError            for i in range(shape[0]):                for j in range(shape[1]):                    res[i, j] = self[i, j] + other[i, j]        else:            # 实现广播            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)  # 创建一个新的零矩阵,用于返回        if isinstance(other, Matrix):            # 实现同样形状的矩阵元素之间的乘法            if self.shape != other.shape:                # 如果矩阵的形状对不上,就返回错误                raise ShapeError            for i in range(shape[0]):                for j in range(shape[1]):                    res[i, j] = self[i, j] * other[i, j]        else:            # 实现广播            for i in range(shape[0]):                for j in range(shape[1]):                    res[i, j] = self[i, j] * other        return res

matmul

matmul矩阵乘法,运算符为@

    def __matmul__(self, other):        # 实现矩阵的乘法        if self.shape[1] != other.shape[0]:            # 对形状进行判断            raise ShapeError        if self.shape[0] == 1 and other.shape[1] == 1:            # 行向量与列向量的乘积,就是它们的数量积            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]):                # 将两个矩阵分别按行向量与列向量分块,然后相乘                try:                    # 由于切片返回的可能是数,而数不支持'@'运算符,所以使用异常处理语句                    res.append(self[i, :] @ other[:, j])                except TypeError:                    res.append(self[i, :] * other[:, j])        return Matrix(res, shape)

将矩阵分成向量进行矩阵乘法

LU分解

用属性self._lu,构建一个新的矩阵,作为LU分解表。self._lu并不会在初始化时创建,而是在需要用到LU分解表时计算。
同时,我们维护一个self.changed属性,用来判断在需要用到LU分解表时是否需要重新进行LU分解

    def __init__(self, matrix: 'a list of one dimension', shape: 'a tuple of shape' = None,                 dtype: 'data type code' = "d"):        # matrix一个包含所有元素的列表,shape指定形状默认为列向量,dtype是数据类型        # 使用一个数组模拟矩阵,通过操作这个数组完成矩阵的运算        self.shape = (len(matrix), 1)        if shape:            self.shape = shape        self.array = array(dtype, matrix)        self._changed = True        self._primary = list(range(shape[0])) # 只进行行交换

显然,当我们修改了矩阵的元素后就需要重新进行LU分解,重写 setitem ,在开始时修改self.changed属性

    def __setitem__(self, key: 'a index or slice of two dimensions', value):        # 使用slice类的indices方法,实现二维切片的广播赋值        self._change = True        ...

在lu分解中需要选择主元,用属性self._primary储存当前矩阵的主元表,因此我们要重写 getitemsetitem

...row = self._primary[row]  # 通过主元表进行赋值,将行换为index = row * self.shape[1] + col...

下面,我们来实现LU分解

    def _primary_update(self, k):        # 选择绝对值最大的数作为主元        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) # 新建一个矩阵储存LU分解表        rows, cols = self.shape        _lu = self._lu        step = min(rows, cols)        for k in range(step):            if _lu[k, k] == 0:                # 如果当前对角元素为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]

转置

用一个方法实现转置,而不是维护一个属性

    def trans(self):        shape = self.shape[::-1]        res = zeros(shape) # 创建一个零矩阵用于返回        for i in range(shape[0]):            for j in range(shape[1]):                res[i, j] = self[j, i]        return res

利用LU分解求行列式

原矩阵的行列式就是L与U的对角元素的乘积

    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))

来源地址:https://blog.csdn.net/A2233776/article/details/129492455

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

使用python实现矩阵

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎么使用Python实现生成对角矩阵和对角块矩阵

这篇文章主要介绍了怎么使用Python实现生成对角矩阵和对角块矩阵的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么使用Python实现生成对角矩阵和对角块矩阵文章都会有所收获,下面我们一起来看看吧。对角矩阵s
2023-07-06

Python实现生成对角矩阵和对角块矩阵

这篇文章主要为大家详细介绍了如何利用Python实现生成对角矩阵和对角块矩阵,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下
2023-05-15

python共现矩阵怎么实现

本篇内容主要讲解“python共现矩阵怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“python共现矩阵怎么实现”吧!什么是共现矩阵比如我们有两句话:ls = [我永远喜欢三上悠亚, 三
2023-07-06

python如何实现矩阵乘法

小编给大家分享一下python如何实现矩阵乘法,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!矩阵相乘需要前面矩阵的行数与后面矩阵的列数相同方可相乘。第一步,先将前面矩阵的每一行分别与后面矩阵的列相乘,作为结果矩阵的行列;第
2023-06-26

python二维矩阵怎么实现

Python中可以使用列表(list)来表示二维矩阵。可以通过嵌套列表的方式来表示二维矩阵的行和列。以下是几种创建二维矩阵的方法:使用列表生成式:matrix = [[0 for _ in range(cols)] for _ in ra
2023-10-22

python旋转矩阵怎么实现

要实现矩阵的旋转,可以使用numpy库中的rot90函数。下面是一个简单的示例代码:import numpy as np# 创建一个2x3的矩阵matrix = np.array([[1, 2, 3],[4, 5, 6]])# 将矩阵逆
2023-10-21

使用Python怎么求逆矩阵

使用Python怎么求逆矩阵?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。import numpy as np kernel = np.array([1, 1,
2023-06-08

Python使用邻接矩阵实现图及Dijkstra算法问题

这篇文章主要介绍了Python使用邻接矩阵实现图及Dijkstra算法问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2022-12-16

使用Matlab怎么实现矩阵复制扩充

使用Matlab怎么实现矩阵复制扩充?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。考虑这个问题:定义一个简单的行向量a如何复制10行呢?即:同理,对于一个列向量,如何复制
2023-06-15

mat矩阵和npy矩阵怎么实现互相转换

这篇“mat矩阵和npy矩阵怎么实现互相转换”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“mat矩阵和npy矩阵怎么实现互相
2023-07-02

python实现邻接表转邻接矩阵

这篇文章主要介绍了python实现邻接表转邻接矩阵,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2022-12-16

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录