1.线性代数基础概念:标量、向量、矩阵、张量
标量
定义:
标量是只有大小没有方向的量。在数学中,它通常是一个实数或复数。
通俗:
想象你有5个苹果。这个数字 “5” 就是一个标量。它只告诉你有多少苹果,但不告诉你这些苹果放在哪里。
向量
定义:
向量是具有大小和方向的量。在数学中,它通常表示为一个有序的数字列表,如二维或三维空间中的点。
通俗:
想象你在一个大房间里,你想告诉你的朋友一个宝藏的位置。你可以说:“从门口开始,走5步向前,然后走3步向右” 。这个 “5步向前和3步向右” 就像一个向量,它有方向和距离。
矩阵
定义:
矩阵是一个二维数组,其中的每个元素都是一个标量。它可以表示线性变换。
通俗:
想象你有一个秘密地图,上面有很多宝藏的位置。为了整齐的记录所有的位置,你决定用一个网格或表格来写下所有的 “向前和向右” 的步数。这个表格就像一个矩阵,它帮助你整齐地记录信息。
张量
定义:
张量是一个可以在多个方向上有分量的数学对象。标量是零阶张量,向量是一阶张量,矩阵是二阶张量。更高阶的张量可以看做是多维数组。
通俗:
想象你不仅在一个房间里找宝藏,而且在一个大楼里。这是,你不仅要告诉你的朋友向前多少步、向右多少步,还要告诉他上或下走多少楼梯。如果你用一个更大的表格来记录这些信息,其中包括向前、向右和上下的步数,这就像一个张量。张量就是一个更高级的表格,可以记录更多的信息。
2.向量(矩阵)的范数与单位向量
向量的范数
定义:
向量的范数是一个函数,它将向量映射到一个非负值。直观地说,范数表示向量的“长度”或“大小”。对于向量 (v),其范数通常表示为 (∣∣v∣∣)。
通俗:
想象你在一个城市的地图上,从你家走到一个公园。这条路线就像一个向量。范数就是你需要走的距离,也就是从家到公园的实际步数。
矩阵的范数
单位向量
定义:
单位向量是长度(或范数)为1的向量。对于任何非零向量 (v),其对应的单位向量
可以通过将 (v)除以其L2范数得到:
通俗解释:
假设你不关心走多远,只想知道公园的方向。你拿出一个指南针,它指向公园的方向,但不告诉你有多远。这个指南针的指向就像一个单位向量。
3.案例实战:创建向量、矩阵、张量
- import numpy as np
-
- # 创建向量(一维)
- vector = np.array([1, 2, 3, 4, 5])
- vector_norm = np.linalg.norm(vector) # 矩阵或向量的范数
- print(f"Vector:\n{vector}")
- print(f"Vector L2 Norm: {vector_norm}")
-
- # 创建矩阵(二维)
- matrix = np.array([
- [1, 2, 3],
- [4, 5, 6],
- [7, 8, 9]
- ])
- matrix_norm = np.linalg.norm(matrix)
- print(f"Matrix:\n{matrix}")
- print(f"Matrix L2 Norm: {matrix_norm}")
-
- # 创建张量(三维)
- tensor = np.array([
- [[1, 2], [3, 4]],
- [[5, 6], [7, 8]],
- [[9, 10], [11, 12]]
- ])
- tensor_norm = np.linalg.norm(tensor)
- print(f"Tensor:\n{tensor}")
- print(f"Tensor L2 Norm: {tensor_norm}")
4.案例实战:将Numpy矩阵保存成本地图像
- import numpy as np
- import cv2
-
- # 创建一个大小为224X224的二维矩阵,值为0~255之间
- two_d_matrix = np.random.randint(0, 256, (224, 224), dtype=np.uint8)
-
- # 创建一个大小为3X224X224的三维矩阵,值为0~255之间
- three_d_matrix = np.random.randint(0, 256, (3, 224, 224), dtype=np.uint8)
-
- # 在 OpenCv 中,图像的通道顺序为 高 X 宽 X 通道数
- three_d_matrix_transposed = three_d_matrix.transpose(1, 2, 0)
-
- # 将画面显示出来
- cv2.imshow("two_d_matrix", two_d_matrix)
- cv2.imshow("three_d_matrix", three_d_matrix_transposed)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
-
- # 使用 OpenCv 将图片保存到本地
- cv2.imwrite("two_d_matrix.jpg", two_d_matrix)
- cv2.imwrite("three_d_matrix.jpg", three_d_matrix_transposed)
5.案例实战:图像增强(调整对比度)
矩阵基础运算
矩阵的加法
标量与矩阵的乘法
案例实践
- import numpy as np
-
- # 定义矩阵A和B
- matrix_a = np.array([
- [1, 2],
- [3, 4]
- ])
-
- matrix_b = np.array([
- [5, 6],
- [7, 8]
- ])
-
- # 定义标量C
- scalar_c = 3
-
- # 标量与矩阵的乘法
- scalar_mult_matrix = matrix_a * scalar_c
-
- # 矩阵的加法
- matrix_add = matrix_a + matrix_b
-
- print(scalar_mult_matrix)
- print(matrix_add)
图像增强(调整对比度)
- import numpy as np
- import cv2
-
- # 读取图像
- image = cv2.imread("robot(1).jpg")
-
- # 增加对比度
- # 为了避免溢出,使用cv2.convertScaleAbs而不是直接乘法
- increased_contrast = cv2.convertScaleAbs(image, alpha=1.5) # 表示对 image 每个像素值在原来基础上乘1.5
-
- # 减少对比度
- decreased_contrast = cv2.convertScaleAbs(image, alpha=0.5)
-
- # 将图片进行横向拼接
- combined_image = cv2.hconcat([image, increased_contrast, decreased_contrast])
-
- # 显示图片
- cv2.imshow("Original - Increased Contrast - Decreased Contrast", combined_image)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
图像增强(调整亮度)
- import cv2
- import numpy as np
-
- # 读取图片
- image = cv2.imread('robot(1).jpg') # 替换为你的图片路径
-
- # 增加亮度
- # 为了避免溢出,使用cv2.add而不是直接加法
- brighter_image = cv2.add(image, np.array([50.0])) # 增加亮度
-
- # 减少亮度
- # 同样,使用cv2.subtract避免溢出
- darker_image = cv2.subtract(image, np.array([50.0])) # 减少亮度
-
- # 将原图、增亮后的图和减暗后的图横向拼接
- combined_image = cv2.hconcat([image, brighter_image, darker_image])
-
- # 显示图片
- cv2.imshow('Original - Brighter - Darker', combined_image)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
6.Python实现解方程组
矩阵的逆
对于一个方阵(即行数和列数相同的矩阵)A,如果存在另一个矩阵 B 使得 A 和 B 相乘的结果是单位矩阵(对角线上都是 1,其他位置都是 0 的矩阵),那么 B 就是 A 的逆矩阵,通常表示为
不是所有的矩阵都有逆。只有当矩阵的行列式不为 0 时,矩阵才有逆。
行列式
行列式是一个与方阵相关的标量值。对于 2 X 2 的矩阵,其行列式计算相对简单。但对于更大的矩阵,计算会更复杂。
行列式有很多重要的性质和应用,其中之一是:一个矩阵是可逆的当且仅当起行列式不为0。
行列式常用符号
或
矩阵的秩
矩阵的秩描述了矩阵的 “大小” 或 “维度”。更具体地说,它是矩阵中线性对立的行或列的最大数量。
例如,如果一个矩阵的所有行都是其他行的倍数,那么这个矩阵的秩是 1,因为只有一个线性独立的行。
矩阵的秩对于解决线性方程组很有用,因为它可以帮助我们判断方程组是否有解,以及解的数量。
解方程
使用代码解方程
- import numpy as np
-
- # 创建系数矩阵
- A = np.array([
- [1, 2, 3],
- [1, 6, 7],
- [1, 10, 6]
- ])
-
- # 创建常数向量
- B = np.array([5, 9, 8])
-
- # 解方程
- x = np.linalg.solve(A, B) # 求解线性矩阵方程或线性标量方程组。
-
- # 打印结果
- print(f"解:{x}")
7.特征向量与特征值实操
特征值
定义:
与特征向量相对应的标量 λ 称为特征值。它表示在特定的特征向量方向上,变换的缩放比例。
想象一个拉伸机,你放入一根箭头,拉伸机的作用下,这根箭头可能会被拉长、缩短或者保持原长,但方向不变。这个 “拉伸” 或者 “缩短” 的倍数,就是特征值。特征值反映了这个变换增强或减弱了向量的程度。
特征向量
定义:
如果一个非零向量 v 在一个线性变换下的效果仅仅是被伸缩(缩放或拉伸),而方向不变,那么这个向量被称为特征向量。
那根被拉伸后方向不变的箭头,就是特征向量。它是一个特殊的向量,它在矩阵变换下只是被伸缩,但不改变其方向。可以指明变换的主要方向。
特征值和特征向量求解
- import numpy as np
-
- # 定义矩阵A
- A = np.array([
- [4, 1],
- [2, 3]
- ])
-
- # 使用 numpy 求特征值和特征向量
- eigenvalues, eigenvectors = np.linalg.eig(A)
-
- print(f"特征值:{eigenvalues}")
- print(f"特征向量:\n{eigenvectors}")
8.案例实战:图像的SVD分解
在数学上,对于一幅图像的SVD分解,我们可以将其分解为三个部分:
- U 矩阵:这个矩阵包含了所谓的“左奇异向量”,可以想象成是一组基础的图像模式。
- Σ(Sigma)矩阵:这个对角矩阵包含了所谓的“奇异值”,这些值表明了每个图像模式的重要性或权重。较大的奇异值对应于图像中更重要的特征。
- V 矩阵:这个矩阵包含了“右奇异向量”,它与U矩阵类似,但从不同的角度描述了图像的特征。
通过这种分解,一幅图像就被转化成了一系列的模式和对应的权重。你可以通过仅仅结合前几个最重要的模式(即权重最大的那些)来近似重构原始图像。这种方法在图像压缩和降噪中非常有用,因为它允许我们用较少的数据来描述一幅图像,同时保留其关键特征。
- import cv2
- import numpy as np
-
- # 读取图片
- image = cv2.imread("robot(1).jpg", 0) # 自动图片转变为灰度图像
-
- # 对图像进行 SVD 分解
- U, S, V = np.linalg.svd(image.astype(np.float64), full_matrices=False)
- # image.astype(np.float64) 将图片格式转换为浮点型
-
- # 定义要保留的奇异值数量
- k = 50
- s_k = np.diag(S[:k]) # 提取对角线或构造对角线数组。
-
- # 重构图像
- compressed_image = np.dot(U[:, :k], np.dot(s_k, V[:k, :])) # dot 两个阵列的点积。
- compressed_image = np.clip(compressed_image, 0, 255).astype(np.uint8) # clip 剪切(限制)数组中的值。
-
- # 显示图像
- cv2.imshow("Original Image", image)
- cv2.imshow("Compress Image", compressed_image)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
评论记录:
回复评论: