![](/img/trans.png)
[英]How would I get frames from a .mp4 file without importing large modules in python?
[英]How would I create a matrix in python without importing modules? How would I make a tensor without importing modules?
我正在尝试在 python 中创建矩阵和张量,而不导入任何模块,例如 numpy。 有办法做到这一点吗?
矩阵只是列表的列表。 您可以这样做:
x = [[0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[3, 4, 5, 6, 7]]
至于在没有 numpy 的情况下执行操作,这将取决于您创建可能使用嵌套循环的函数。
这将是一个列表列表,例如:
matrix = [
[1, 0, 0],
[0, 1, 0],
[0, 0, 0],
]
然后,您必须在该数据结构之上实现所有数学运算(矩阵乘法等)。
Python 为矩阵乘法保留方法名__matmul__
class Matrix:
def __mul__(left, right):
print("__mul__ was called")
def __matmul__(left, right):
print("__MATMUL__ WAS CALLED")
def __rmatmul__(right, left):
print(40*"#")
print("__rmatmul__")
print("left == ", left)
print("right == ", right)
print(40 * "#")
def __imatmul__(total, step):
print("__imatmul__")
a = Matrix()
b = Matrix()
a * b # scalar multiplication __mul__
a @ b # matrix multiplication __matmul__
3 @ b # matrix multiplication __rmatmul__
a @= b
__imatmul__
类似于以下内容:
x = 5
x += 2 # __iadd__(x, 2) `x = x + 2`
x *= 1 # __imul__(x, 3) `x = x * 3`
每当您编写x * y
python 时,都会首先尝试从左侧参数中获取乘法的定义。 也就是说, x * y
最初是type(x).__add__(x, y)
然而,有时左边的东西不知道如何将自己与右边的东西相乘。
class K:
pass
a = K()
result = 55*a
result = type(55).__mul__(55, a)
int
class 不知道如何将55
和 class K
的实例相乘。 如果type(left).__mul__(left, right)
失败,则调用备份机制type(right).__rmul__(right, left)
。 如果您编写自己的矩阵 class,那么当您将标量倍数(如 88)放在前面时,将调用 3 __rmatmul__
和__rmul__
。
m = Matrix()
88 * m # __rmul__(m, 88)
88 @ m # __rmatmul__(m, 88)
实现矩阵的一种方法是作为列表列表:
matrix = [
[1, 0, 0],
[0, 1, 0],
[0, 0, 0],
]
这有几个显着的缺点。 一个是容易select一行的矩阵:
matrix[1] == [0, 1, 0]
但是,选择列的效率会非常低:
def get_column(coli:int):
coli = 1
column = list()
for rowi in range(len(matrix)):
column.append(matrix[rowi][coli])
return column
一种解决方案是有两个不同的列表列表:
row_then_col = [
[[("r0", "c0")], [("r0", "c1")], [("r0", "c2")]],
[[("r1", "c0")], [("r1", "c1")], [("r1", "c2")]],
[[("r2", "c0")], [("r2", "c1")], [("r2", "c2")]],
]
ncols = 3
nrows = 3
col_then_row = list()
for coli in range(ncols):
col_then_row.append([None]*ncols)
for rowi in range(nrows):
col_then_row[coli]
col_then_row[coli][rowi] = row_then_col[rowi][coli]
然后col_then_row[coli]
将返回一整列, row_then_col[rowi]
将返回一整行。 您可以使用包含一个元素的列表来伪造“指针”。 这将允许row_then_col
col_then_row
可见,反之亦然,无需更新任何内容。
row_then_col[1][2][0] = "happy"
print(col_then_row[2][1][0]) # "happy"
矩阵乘法有很多算法。 我建议实施Strassen 算法。 它不是世界上最快的,但它比真正快速的更容易理解。
有很多方法可以实现矩阵。 一种实现的开始如下所示:
import io
import math
import abc
def flatten(container):
for elem in container:
if not hasattr(elem, "__iter__"):
yield elem
else:
it_elem = iter(elem)
subelem = next(it_elem)
if subelem != elem:
yield subelem
for j in flatten(it_elem):
yield j
class MatrixNodeState(abc.ABC):
"""
Abstract Base Class
"""
pass
MatrixNodeState.MatrixNodeState = MatrixNodeState
class MatrixNodeStateNullNullNullClass(MatrixNodeState):
@classmethod
def ERR(cls):
with io.StringIO() as string_stream:
print(
"YOU ARE OFF THE EDGE OF THE MAP!",
"STOP ITERATING!",
file=string_stream
)
msg = string_stream.getvalue()
raise cls.OFF_THE_EDGE_OF_THE_MAP(msg)
class OFF_THE_EDGE_OF_THE_MAP(Exception):
pass
def __getattribute__(self, *args):
type(self).ERR()
def __setattr__(self, *args):
type(self).ERR()
MatrixNodeState.nullnullnull = MatrixNodeStateNullNullNullClass()
class MatrixNodeStateNullNullClass(MatrixNodeState):
def __setattr__(*args):
pass
def __getattribute__(self, *args):
return type(self).nullnullnull
MatrixNodeState.nullnull = MatrixNodeStateNullNullClass()
class MatrixNodeStateNullClass(MatrixNodeState):
"""
This class exists because `None.left = n`
would produce an error
`null.left = k` -----`no operation`.
Does nothing
Does not set the `left` attribute
of the nullnull node.
`x = node.left` returns `nullnull`
"""
def __setattr__(*args):
pass
def __getattribute__(self, *args):
return type(self).nullnull
MatrixNodeState.null = MatrixNodeStateNullClass()
class MatrixNodeStateNonNullNull(MatrixNodeState):
def __init__(self, data):
self.data = data
self.up = type(self).null
self.right = type(self).null
self.down = type(self).null
self.left = type(self).null
def __setattr__(self, key, value):
if isinstance(value, type(self).nullnull):
value = type(self).null
elif isinstance(value, type(self).nullnullnull):
value = type(self).null
super().__setattr__(self, key, value)
MatrixNodeState.MatrixNodeStateNonNullNull = MatrixNodeStateNonNullNull
class MatrixNode:
def __init__(self, data=None):
MatrixNodeState = type(self)
if data:
self.state = MatrixNodeState.MatrixNodeStateNonNullNull(data)
else:
self.state = MatrixNodeState.nullnull
def __getattr__(self, attrname):
return self.state.attrname
def __setattr__(self, attr_name, attr_value):
try:
object.__getattr__(self)
super().__setattr__(self, attr_name, attr_value)
except AttributeError:
setattr(self.state, attr_name, attr_value)
MatrixNode.MatrixNodeState = MatrixNodeState
class Matrix:
"""
"""
MatrixNode = MatrixNode
def __init__(self, xdims, xelems):
"""
Example 1:
m = Matrix([3, 3], [1, 0, 0, 0, 1, 0, 0, 0, 1])
Example 2
m = Matrix([3, 3], [[1, 0, 0], [0, 1, 0], [0, 0, 1]])
"""
MatrixNode = type(self).MatrixNode
idims = tuple(map(int, xdims))
ielems = iter(flatten(xelems))
nrows = idims[0]
ncols = idims[1]
self.d = dict()
try:
elem_count = 0
left_node = MatrixNode.nullnull
up_node = MatrixNode.nullnull
for rowi in range(nrows):
for coli in range(ncols):
ielem = next(ielem)
elem_count += 1
up_node = left_node.up.right
node = MatrixNode(ielem)
self.d[(rowi, coli)] = node
node.left = left_node
left_node.right = node
node.up = up_node
up_node.down = node
left_node = node
except StopIteration:
with io.StringIO() as string_stream:
print(
"Dimensions", idims, "indicated",
"that there should be", math.prod(idims),
"elements.", "Instead, only ", elem_count,
"elements were found.",
file=string_stream
)
msg = string_stream.getvalue()
raise TypeError(msg)
def __getitem__(self, xkey):
ikey = tuple(map(int, iter(flatten(xkey))))
return self.d[ikey].data
def __setitem__(self, xkey, xval):
ikey = tuple(map(int, iter(flatten(xkey))))
self.d[ikey].data = xval
return
def get_column(self, coli):
coli = int(str(coli))
def get_row(self, rowi):
rowi = int(str(rowi))
def __mul__(left, right):
print("__mul__ was called")
raise NotImplementedError()
def __rmul__(right, left):
"""
m = Matrix([1, 2, 3])
88 * m
"""
print("__rmul__ was called")
raise NotImplementedError()
def __matmul__(left, right):
print("__MATMUL__ WAS CALLED")
raise NotImplementedError()
def __rmatmul__(right, left):
print(40*"#")
print("__rmatmul__")
print("left == ", left)
print("right == ", right)
print(40 * "#")
raise NotImplementedError()
def __imatmul__(total, step):
print("__imatmul__")
raise NotImplementedError()
def __str__(self):
raise NotImplementedError()
def __repr__(self):
return type(self) + str(self)
row_then_col = [
[[("r0", "c0")], [("r0", "c1")], [("r0", "c2")]],
[[("r1", "c0")], [("r1", "c1")], [("r1", "c2")]],
[[("r2", "c0")], [("r2", "c1")], [("r2", "c2")]],
]
a = Matrix([3, 3], row_then_col)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.