输入为一个矩阵(ndarray格式),输出为分解后的2个(特征分解)或3个(SVD)矩阵不能调用numpy库或其他库中已有的矩阵分解方法/函数。
时间: 2024-02-17 14:01:08 浏览: 68
svd.zip_svd分解
好的,那我来编写两个不使用numpy库中的矩阵分解函数的特征分解和奇异值分解函数。
特征分解函数:
```python
def eigen_decomposition(matrix):
n = matrix.shape[0]
eigenvalues = np.zeros(n)
eigenvectors = np.zeros((n, n))
for i in range(n):
# 取出当前列向量
v = matrix[:, i]
# 初始化特征向量为列向量
q = v
for j in range(50):
# 迭代计算特征向量
q = matrix @ q
q = q / np.linalg.norm(q)
# 计算特征值
eigenvalues[i] = q @ matrix @ q
# 将特征向量作为矩阵的一列
eigenvectors[:, i] = q
# 返回特征值和特征向量的转置
return np.diag(eigenvalues), eigenvectors.T
```
在这个函数中,我们采用了幂迭代法来计算特征向量和特征值。具体而言,我们从矩阵的某个列向量开始,进行迭代计算,得到一个逼近于最大特征向量的向量。然后,我们计算该向量在矩阵下的变换,并将其归一化,得到一个新的向量。我们不断重复这个过程,直到收敛。最终,我们得到的向量就是最大特征向量,而对应的特征值即为向量在矩阵下的变换后的长度。
奇异值分解函数:
```python
def singular_value_decomposition(matrix):
n, m = matrix.shape
# 计算矩阵的转置和矩阵乘积
mtm = matrix.T @ matrix
mmt = matrix @ matrix.T
# 计算对称矩阵的特征分解
eigenvalues_u, eigenvectors_u = eigen_decomposition(mtm)
eigenvalues_v, eigenvectors_v = eigen_decomposition(mmt)
# 计算奇异值和左奇异向量
s = np.sqrt(eigenvalues_u)
u = eigenvectors_u / s
# 计算右奇异向量
v = np.zeros((m, n))
for i in range(m):
v[:, i] = (1 / s[i]) * matrix.T @ u[:, i]
# 返回左奇异向量、奇异值和右奇异向量
return u, np.diag(s), v.T
```
在这个函数中,我们首先计算了矩阵的转置和矩阵乘积,然后分别对它们进行了特征分解。接着,我们根据特征分解得到的特征向量和特征值计算了奇异值和左奇异向量。最后,我们使用左奇异向量和矩阵的转置计算右奇异向量。需要注意的是,我们在计算左奇异向量时,需要将特征值的平方根作为奇异值,而不是特征值本身。
阅读全文