python定义矩阵函数_Python线性代数学习笔记——矩阵和矩阵的乘法,实现矩阵的乘法...

在上一篇文章中,有一个看待矩阵和向量乘法的视角,就是可以把矩阵理解成向量的函数,可以把一个向量,转换成另外的一个向量。

矩阵做这种向量间的转换,最典型的应用就是在图形中:

介绍矩阵数量乘的时候,举过这样的一个例子:有一个矩阵P,每一行都代表二维平面中的一个点的话,我们把这个矩阵P数量乘于2以后,得到的结果就相当于是把其中的每一个点的x坐标和y坐标都扩大2倍,画出图像化界面就是三角形扩大为原来的2倍

但是这里,换一个复杂的问题,我们要扩大,但是并不是x坐标和y坐标都扩大为原来的2倍,而是x坐标扩大为1.5倍,y坐标扩大为2倍,怎么做呢?

这里就是典型的,把一个向量,转换为另一个向量的问题

每一个点就是一个2维的列向量,通过矩阵T(向量函数的视角),转为另外一种的2维列向量

所以我们要找出这个矩阵T

由上图,根据矩阵乘于向量的定义,以及右边的向量,可以推导出:

矩阵T一定是有2列的,因为列向量(x,y)有2行,不然没法相乘

矩阵T一定是有2行的,因为右边的列向量(1.5x,2y)有2行

所以就有:(设a,b,c,d)

根据对应的关系,可以求出b=0,c=0

那么现在问题来了,上图的坐标轴上面,是有很多点的(3个点),一个点(向量)和这个矩阵T做乘法是完全可以的,但是有没有批量的操作呢???

我们只需要把所有的点(向量)集合在一起作为一个矩阵就可以了:矩阵中,使用列向量来表示

然后用矩阵T依次去乘于矩阵P中的每一个列向量即可(矩阵就是由一组向量组成的)

新矩阵就可以理解为:原来每一个点(向量),根据矩阵T,转换成新的向量组成的

基于矩阵和向量的乘法定义,就可以定义出矩阵和矩阵乘法的定义:

我们把两个矩阵的乘法,可以拆分另外一个矩阵(拆分为很多的列向量),然后矩阵再去分别乘于每一个列向量(一个矩阵和一个列向量相乘,还是得到另外一个列向量(函数视角))

两个矩阵相乘的条件:

所以:

实现矩阵的乘法

定义一个内部使用的文件_globals,用来存储全局使用的变量 EPSILON,用来判断精度用的

EPSILON = 1e-8

向量Vector类的代码:

import math

from ._globals import EPSILON

class Vector:

def __init__(self, lst):

self._values = list(lst)

@classmethod

def zero(cls, dim):

"""返回一个dim维的零向量"""

return cls([0] * dim)

def __add__(self, another):

"""向量加法,返回结果向量"""

assert len(self) == len(another), \

"Error in adding. Length of vectors must be same."

return Vector([a + b for a, b in zip(self, another)])

def __sub__(self, another):

"""向量减法,返回结果向量"""

assert len(self) == len(another), \

"Error in subtracting. Length of vectors must be same."

return Vector([a - b for a, b in zip(self, another)])

def norm(self):

"""返回向量的模"""

return math.sqrt(sum(e**2 for e in self))

def normalize(self):

"""返回向量的单位向量"""

if self.norm() < EPSILON:

raise ZeroDivisionError("Normalize error! norm is zero.")

return Vector(self._values) / self.norm()

def dot(self, another):

"""向量点乘,返回结果标量"""

assert len(self) == len(another), \

"Error in dot product. Length of vectors must be same."

return sum(a * b for a, b in zip(self, another))

def __mul__(self, k):

"""返回数量乘法的结果向量:self * k"""

return Vector([k * e for e in self])

def __rmul__(self, k):

"""返回数量乘法的结果向量:k * self"""

return self * k

def __truediv__(self, k):

"""返回数量除法的结果向量:self / k"""

return (1 / k) * self

def __pos__(self):

"""返回向量取正的结果向量"""

return 1 * self

def __neg__(self):

"""返回向量取负的结果向量"""

return -1 * self

def __iter__(self):

"""返回向量的迭代器"""

return self._values.__iter__()

def __getitem__(self, index):

"""取向量的第index个元素"""

return self._values[index]

def __len__(self):

"""返回向量长度(有多少个元素)"""

return len(self._values)

def __repr__(self):

return "Vector({})".format(self._values)

def __str__(self):

return "({})".format(", ".join(str(e) for e in self._values))

矩阵 Matrix类的代码:

from .Vector import Vector

class Matrix:

def __init__(self, list2d):

self._values = [row[:] for row in list2d]

@classmethod

def zero(cls, r, c):

"""返回一个r行c列的零矩阵"""

return cls([[0] * c for _ in range(r)])

def __add__(self, another):

"""返回两个矩阵的加法结果"""

assert self.shape() == another.shape(), \

"Error in adding. Shape of matrix must be same."

return Matrix([[a + b for a, b in zip(self.row_vector(i), another.row_vector(i))]

for i in range(self.row_num())])

def __sub__(self, another):

"""返回两个矩阵的减法结果"""

assert self.shape() == another.shape(), \

"Error in subtracting. Shape of matrix must be same."

return Matrix([[a - b for a, b in zip(self.row_vector(i), another.row_vector(i))]

for i in range(self.row_num())])

def dot(self, another):

"""返回矩阵乘法的结果"""

if isinstance(another, Vector):

# 矩阵和向量的乘法

assert self.col_num() == len(another), \

"Error in Matrix-Vector Multiplication."

return Vector([self.row_vector(i).dot(another) for i in range(self.row_num())])

if isinstance(another, Matrix):

# 矩阵和矩阵的乘法

assert self.col_num() == another.row_num(), \

"Error in Matrix-Matrix Multiplication."

return Matrix([[self.row_vector(i).dot(another.col_vector(j)) for j in range(another.col_num())]

for i in range(self.row_num())])

def __mul__(self, k):

"""返回矩阵的数量乘结果: self * k"""

return Matrix([[e * k for e in self.row_vector(i)]

for i in range(self.row_num())])

def __rmul__(self, k):

"""返回矩阵的数量乘结果: k * self"""

return self * k

def __truediv__(self, k):

"""返回数量除法的结果矩阵:self / k"""

return (1 / k) * self

def __pos__(self):

"""返回矩阵取正的结果"""

return 1 * self

def __neg__(self):

"""返回矩阵取负的结果"""

return -1 * self

def row_vector(self, index):

"""返回矩阵的第index个行向量"""

return Vector(self._values[index])

def col_vector(self, index):

"""返回矩阵的第index个列向量"""

return Vector([row[index] for row in self._values])

def __getitem__(self, pos):

"""返回矩阵pos位置的元素"""

r, c = pos

return self._values[r][c]

def size(self):

"""返回矩阵的元素个数"""

r, c = self.shape()

return r * c

def row_num(self):

"""返回矩阵的行数"""

return self.shape()[0]

__len__ = row_num

def col_num(self):

"""返回矩阵的列数"""

return self.shape()[1]

def shape(self):

"""返回矩阵的形状: (行数, 列数)"""

return len(self._values), len(self._values[0])

def __repr__(self):

return "Matrix({})".format(self._values)

__str__ = __repr__

测试代码:

from playLA.Vector import Vector

from playLA.Matrix import Matrix

if __name__ == "__main__":

matrix = Matrix([[1, 2], [3, 4]])

print(matrix)

print("matrix.shape ={}".format(matrix.shape()))

print("matrix.size ={}".format(matrix.size()))

print("len(matrix) ={}".format(len(matrix)))

print("matrix[0][0] ={}".format(matrix[0, 0]))

matrix2 = Matrix([[5, 6], [7, 8]])

print(matrix2)

print("add:{}".format(matrix + matrix2))

print("subtract:{}".format(matrix - matrix2))

print("scalar-mul:{}".format(2 * matrix))

print("scalar-mul:{}".format(matrix * 2))

print("zero_2_3:{}".format(Matrix.zero(2, 3)))

//测试矩阵和向量相乘

T = Matrix([[1.5, 0], [0, 2]])

p = Vector([5, 3])

print("T.dot(p) ={}".format(T.dot(p)))

//测试矩阵和矩阵相乘

P = Matrix([[0, 4, 5], [0, 0, 3]])

print("T.dot(P) ={}".format(T.dot(P)))

//验证两个矩阵的交换律

print("A.dot(B) ={}".format(matrix.dot(matrix2)))

print("B.dot(A) ={}".format(matrix2.dot(matrix)))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值