矩阵:消除冗余
矩阵及其相关技术在现代科学计算、机器学习、图像处理、网络分析等领域有广泛应用,其优势在于强大的表达能力和高效的计算性能。然而,面对大规模数据时,存储和计算复杂度仍然是挑战。未来发展趋势包括进一步优化矩阵运算、智能 算法的引入、数据结构与存储方法的改进以及与其他技术的融合。
矩阵
基本概念
矩阵
(Matrix
)是一个按照行和列排列的元素的二维数组。具体来说,一个 的矩阵有 行和 列,表示为:
其中 是矩阵 的第 行第 列的元素。
矩阵性质
- 零矩阵:所有元素均为零的矩阵。
- 转置矩阵:将矩阵 的行列互换得到的矩阵为 。
- 对称矩阵::矩形的转置矩阵等于自身,即 。
- 单位矩阵:对角线元素为 1 其余元素为 0 的方阵。
- 逆矩阵:若矩阵 与 满足 ,则 为 的逆矩阵,记作 。
运算规则
- 加法:两个相同维数的矩阵相加,对应元素相加。
- 标量乘法:矩阵的每个元素和标量 相乘。
- 矩阵乘法: 矩阵 和 矩阵 乘积为 矩阵 。
- 转置:交换矩阵行和列的位置。
- 逆矩阵:若矩阵 可逆,则存在矩阵 使得 .
以下是一些简单的 Python 代码示例,帮助理解矩阵的基本操作:
import numpy as np
# 定义矩阵
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
# 矩阵加法
C = A + B
# 矩阵乘法
D = np.dot(A, B)
# 矩阵转置
E = A.T
# 矩阵的逆
F = np.linalg.inv(A)
print(f"A:\n{A}")
print(f"B:\n{B}")
print(f"A + B:\n{C}")
print(f"A * B:\n{D}")
print(f"A^T:\n{E}")
print(f"A^-1:\n{F}")
特殊矩阵
- 方阵:行数与列数相等的矩阵。
- 稀疏矩阵:大部分元素为零的矩阵。
- 对称矩阵:转置矩阵等于自身。
- 对角矩阵:非对角线元素全为零的方阵。
- 单位矩阵:对角线元素为 1,其他元素为 0 的方阵。
- 对称正定矩阵:所有特征值均为正的对称矩阵。
应用场景
- 线性方程组:矩阵可以表示线性方程组,有助于求解和分析。
- 图像处理:图像可以看作矩阵,通过矩阵运算实现图像滤波、变换等。
- 计算机图形学:通过矩阵运算实现三维图形的旋转、平移和缩放。
- 机器学习:数据集通常表示为矩阵,矩阵运算用于计算模型参数和预测。
- 物理学和工程学:描述和求解物理系统的状态和变化。
稀疏矩阵:一维三元组表示法
二维矩阵的一维三元组表示法(Triplet Representation)是一种稀疏矩阵
的存储方式,专为存储稀疏矩阵而设计。每个非零元素通过一个三元组 (i, j, value) 表示,其中 i 和 j 分别为矩阵元素的行和列索引,value 为元素的值。
基本概念
假设有一个稀疏矩阵:
0 0 3
4 0 0
0 0 5
用三元组表示法可以表示为:
[(0, 2, 3), (1, 0, 4), (2, 2, 5)]
大规模的科学计算、图像处理中的矩阵表示等都适用于稀疏矩阵的存储和计算。
矩阵的压缩存储
矩阵的压缩存储旨在减少存储空间和提高计算效率。常用的压缩存储格式包括:
-
压缩稀疏行
(CSR
,Compressed Sparse Row
)格式:值数组
(values
):存储所有非零元素的值。列索引数组
(col_indices
):存储每个非零元素所在列的索引。行指针数组
(row_ptr
):存储每一行在值数组values
中的起始位置。
-
压缩稀疏列
(CSC
,Compressed Sparse Column
)格式:- 列指针数组(
col_ptr
),存储每列的非零元素起始位置。 - 行索引数组(
row_indices
),存储非零元素在矩阵中的行索引。 - 值数组(
values
),存储非零元素值。
- 列指针数组(
CSR 表示
假设矩阵:
0 0 3
4 0 0
0 0 5
CSR 表示为:
values = [3, 4, 5]
col_indices = [2, 0, 2]
row_ptr = [0, 1, 2, 3]
CSR 表示法适用于大规模稀疏矩阵的存储和计算,如科学计算、机器学习中的特征矩阵等。
稀疏矩阵的转置
对于 CSR 格式的矩阵转置,将转换为 CSC 格式,基本步骤包括:
- 创建新矩阵的列指针数组:初始所有元素设为零,对原矩阵值进行累加。
- 利用行索引和列指针构建新值和行索引数组。
import numpy as np
from scipy.sparse import csr_matrix
def transpose_csr_to_csc(csr):
""" 将CSR格式的矩阵转置得到CSC格式 """
values = csr.data
row_indices = csr.indices
col_ptr = csr.indptr
n_rows = len(col_ptr) - 1
n_cols = len(values)
row_ptr = np.zeros(n_cols + 1, dtype=int)
for idx in row_indices:
row_ptr[idx + 1] += 1
np.cumsum(row_ptr, out=row_ptr)
new_values = np.zeros_like(values)
new_col_indices = np.zeros_like(row_indices)
for row in range(n_rows):
for idx in range(col_ptr[row], col_ptr[row + 1]):
col = row_indices[idx]
pos = row_ptr[col]
new_values[pos] = values[idx]
new_col_indices[pos] = row
row_ptr[col] += 1
for col in reversed(range(n_cols)):
row_ptr[col + 1] = row_ptr[col]
row_ptr[0] = 0
return csr_matrix((new_values, new_col_indices, row_ptr), shape=(n_cols, n_rows))
# 示例
A = csr_matrix([[0, 0, 3], [4, 0, 0], [0, 0, 5]])
A_t = transpose_csr_to_csc(A)
print(A_t)
这种稀疏矩阵的表示方式适用于图处理、机器 学习中的协作过滤等算法要求对高度稀疏矩阵进行频繁转置的场景。
稀疏矩阵的索引
根据压缩格式,执行索引。在 CSR 中,索引位置 (i, j)
时:
- 查找
row_ptr[i]
和row_ptr[i + 1]
之间的列索引col_indices
。 - 在
col_indices
中找到等于j
的索引位置,对应的值数组values
中索引即为A(i, j)
的值。
def get_element_csr(csr, i, j):
""" 获取CSR矩阵中的元素A(i, j) """
for idx in range(csr.indptr[i], csr.indptr[i + 1]):
if csr.indices[idx] == j:
return csr.data[idx]
return 0
# 示例
A = csr_matrix([[0, 0, 3], [4, 0, 0], [0, 0, 5]])
value = get_element_csr(A, 1, 0)
print(value)
在需要随机访问稀疏矩阵特定位置元素时,使用压缩存储格式可以进行高效索引。
稀疏矩阵的加法
加法运算要求同样格式,通过合并有效列索引和值数组实现。
def add_csr(csr1, csr2):
""" 两个CSR矩阵相加 """
return csr1 + csr2
# 示例
A = csr_matrix([[0, 0, 3], [4, 0, 0], [0, 0, 5]])
B = csr_matrix([[1, 0, 0], [0, 2, 0], [3, 0, 0]])
C = add_csr(A, B)
print(C)