向量和标量
标量
标量是一个单独的数,只有大小,没有方向。例如,温度、质量等。
向量
向量是由标量组成的数组,具有大小和方向。在二维或三维空间中,向量可以表示位移、速度等。
- 行向量:一行多个元素的向量。
示例:\(\mathbf{x} = \begin{pmatrix} 2 & 5 & 8 \end{pmatrix}\)
- 列向量:一列多个元素的向量(更常用)。
示例:\(\mathbf{x} = \begin{pmatrix} 2 \\ 5 \\ 8 \end{pmatrix}\)
比如:array = numpy.array([3, 2, 1, 3])
创建的是一个一维数组,在数学上可以理解为一个向量。
从技术角度看:
- 这是一个NumPy的一维数组(1D array)
- 形状(shape)是
(4,)
,表示有4个元素的一维结构
- 数据类型通常会是整数型
从数学角度看:
- 这确实是一个4维向量(注意:这里的”4维”指的是向量有4个分量,不是4维空间)
- 可以表示为列向量:\(\mathbf{x} = \begin{pmatrix} 3 \\ 2 \\ 1\\ 3 \end{pmatrix}\) 或行向量:
- 在向量空间 R4 中的一个点
方向的数学表示
既然是一个向量那么它的方向是什么?
向量的方向由它的单位向量定义,计算方法是:
单位向量 = 原向量 / 向量的模长
import numpy as np
array = np.array([3, 2, 1, 3])
# 计算向量的模长(欧几里得范数)
magnitude = np.linalg.norm(array)
print(f"向量的模长: {magnitude}") # √(3² + 2² + 1² + 3²) = √23 ≈ 4.796
# 计算单位向量(方向)
unit_vector = array / magnitude
print(f"单位向量(方向): {unit_vector}")
结果:
- 模长:√23 ≈ 4.796
- 单位向量:
[0.626, 0.417, 0.209, 0.626]
几何理解
在4维空间中,这个向量:
- 从原点
[0, 0, 0, 0]
指向点 [3, 2, 1, 3]
- 它的方向就是这条线段的方向
- 单位向量告诉我们:沿着这个方向走1个单位长度时,在各个坐标轴上的分量分别是多少
向量 [3, 2, 1, 3]
是一个完整的4维向量:
- 所有4个分量都同等重要
- 它存在于4维空间 R4 中
- 它的方向由完整的单位向量
[0.626, 0.417, 0.209, 0.626]
定义
4维向量的实际应用
4维向量在实际中很常见:
# 例如:RGBA颜色向量
color = np.array([255, 128, 64, 200]) # 红、绿、蓝、透明度
# 或者:时空坐标
spacetime = np.array([x, y, z, t]) # 三维空间 + 时间
# 或者:特征向量
features = np.array([身高, 体重, 年龄, 收入])
这里的”4维”指的是向量的维度(dimension),即:
- 向量有4个分量:[3, 2, 1, 3]
- 每个分量对应一个坐标轴
- 这个向量存在于4维空间R4 中
import numpy as np
array = np.array([3, 2, 1, 3])
print(f"向量: {array}")
print(f"向量的长度(分量个数): {len(array)}") # 输出: 4
print(f"向量的形状: {array.shape}") # 输出: (4,)
print(f"向量的维数: {array.ndim}") # 输出: 1 (这是数组的维度,不是向量的维度)
注意区分
- 向量的维度: 4(有4个分量)
- 数组的维度: 1(这是一维数组,即一维的数据结构)
这就像一根绳子(1维的物体)可以在3维空间中存在一样,这个1维数组表示的是4维空间中的一个向量。
答案:这是一个4维向量。
那我们平时说的1阶张量(向量):一维数组,如 [1, 2, 3],这个一维是什么意思?
答:两种”维度”概念
1. 数组/张量的”阶”或”维度”(Array/Tensor Rank)
[1, 2, 3]
是1阶张量(或叫1维数组)
- 这里的”1维”指的是数组的结构维度
- 只需要1个索引就能访问元素:
array[0]
, array[1]
, array[2]
2. 向量空间的”维度”(Vector Space Dimension)
[1, 2, 3]
是3维向量
- 这里的”3维”指的是向量有3个分量
- 存在于3维向量空间 R3 中
import numpy as np
# 1阶张量(1维数组),但是3维向量
vector = np.array([1, 2, 3])
print(f"数组维度(阶): {vector.ndim}") # 1
print(f"向量空间维度: {len(vector)}") # 3
# 2阶张量(2维数组),3x3矩阵
matrix = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print(f"数组维度(阶): {matrix.ndim}") # 2
print(f"矩阵大小: {matrix.shape}") # (3, 3)
import numpy as np
# 1阶张量(1维数组),但是3维向量
vector = np.array([1, 2, 3])
print(f"数组维度(阶): {vector.ndim}") # 1
print(f"向量空间维度: {len(vector)}") # 3
# 2阶张量(2维数组),3x3矩阵
matrix = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print(f"数组维度(阶): {matrix.ndim}") # 2
print(f"向量空间维度: {len(matrix)}") # 3
print(f"矩阵大小: {matrix.shape}") # (3, 3)
总结术语
对象 |
张量阶数 |
数组维度 |
向量空间维度 |
正确表述 |
[1, 2, 3] |
1阶 |
1维数组 |
3维向量 |
“1阶张量,表示3维向量” |
[3, 2, 1, 3] |
1阶 |
1维数组 |
4维向量 |
“1阶张量,表示4维向量” |
所以1阶张量(向量):一维数组”这个说法是完全正确的!
- “1阶”/”一维数组”描述的是数据结构
- 具体是几维向量,要看数组有多少个元素
向量运算
- 转置:将行向量转为列向量,或反之。记作 \(\mathbf{x}^T\)。
示例: \(\mathbf{x} = \begin{pmatrix} 2 & 5 & 8 \end{pmatrix}\) 则 \(\mathbf{x}^T = \begin{pmatrix} 2 \\ 5 \\ 8 \end{pmatrix}\)
- 向量加法:对应元素相加。向量维度必须相同。
示例:\(\begin{pmatrix} 1 \\ 2 \end{pmatrix} + \begin{pmatrix} 3 \\ 4 \end{pmatrix} = \begin{pmatrix} 4 \\ 6 \end{pmatrix}\)
- 向量与标量相乘:标量乘以向量的每个元素,表示缩放。
示例:\(3 \times \begin{pmatrix} 1 \\ 2 \end{pmatrix} = \begin{pmatrix} 3 \\ 6 \end{pmatrix}\)
- 向量元素-wise 相乘(对应元素相乘):得到一个新向量。
示例:\(\begin{pmatrix} 1 \\ 2 \end{pmatrix} \times \begin{pmatrix} 3 \\ 4 \end{pmatrix} = \begin{pmatrix} 3 \\ 8 \end{pmatrix}\)
- 向量内积(点乘):对应元素相乘后求和,结果是一个标量。
语法:在Python中用 x.dot(y)
或 x @ y
。
几何含义:\[x \cdot y = \|x\|\|y\|\cos\theta\]示例:\[\begin{pmatrix} 1 \\ 2 \end{pmatrix} \cdot \begin{pmatrix} 3 \\ 4 \end{pmatrix} = 1 \times 3 + 2 \times 4 = 11\]
夹角计算:\[\cos\theta = \frac{x \cdot y}{\|x\| \times \|y\|}\]
向量的范数
范数是向量的“长度”度量,具有以下特点:
- 非负性:||v|| ≥ 0,且 ||v|| = 0 当且仅当 v = 0
- 齐次性:||kv|| = |k| · ||v||
- 三角不等式:||u + v|| ≤ ||u|| + ||v||
分类:
- L0范数:非零元素的个数(不是严格范数,但常用)。
示例: \((3, 0, -2, 0, 1) \rightarrow |\mathbf{v}|_0 = 3\)。
import numpy as np
x = np.array([3, 0, -2, 0, 1])
l0_norm = np.linalg.norm(x, ord=0)
# 输出: 3
公式:\(|\mathbf{v}|_1 = |v_1| + |v_2| + \cdots + |v_n|\)
示例: \((3, 0, -2, 0, 1) \rightarrow |\mathbf{v}|_1 = 6\)
l1_norm = np.linalg.norm(x, ord=1) # 输出: 6
公式:\(|\mathbf{v}|_2 = \sqrt{v_1^2 + v_2^2 + \cdots + v_n^2}\)
示例:\((3, 0, -2, 0, 1) \rightarrow |\mathbf{v}|_2 = \sqrt{14} \approx 3.74\)
l2_norm = np.linalg.norm(x, ord=2)
# 输出: 约3.74
应用:机器学习中的距离度量。
公式:\(|\mathbf{v}|_p = (|v_1|^p + |v_2|^p + \cdots + |v_n|^p)^{1/p}\)
当 p→∞ 时,为最大值范数。
矩阵
矩阵概念
矩阵是一个 m × n 的矩形数组,元素排列成行和列。记作\(\mathbb{R}^{m \times n}\) 。
矩阵种类
- 方阵:行数等于列数的矩阵(\(m = n\))。
- 对角矩阵:主对角线以外元素全为0的方阵。
- 单位矩阵(I):主对角线元素全为1的对角矩阵,记为 \(\mathbf{I}\)
- 逆矩阵:对于方阵 \(\mathbf{A}\),如果存在 \(\mathbf{A}^{-1}\) 使得 \(\mathbf{A}\mathbf{A}^{-1} = \mathbf{A}^{-1}\mathbf{A} = \mathbf{I}\)。
应用:求解线性方程组。
矩阵转置
- 定义:矩阵 \(\mathbf{A} \in \mathbb{R}^{m \times n}\) 的转置是 \(n \times m\) 矩阵,记为 \(\mathbf{A}^T\)
- 公式:\([\mathbf{A}^T]_{ij} = [\mathbf{A}]_{ji}\)
- 性质:
- \((\mathbf{A}^T)^T = \mathbf{A}\)
- \((\mathbf{A} + \mathbf{B})^T = \mathbf{A}^T + \mathbf{B}^T\)
- \((\mathbf{A}\mathbf{B})^T = \mathbf{B}^T\mathbf{A}^T\)(注意顺序颠倒)
- \((k\mathbf{A})^T = k\mathbf{A}^T\)
矩阵运算
- 矩阵乘法:A (m×n) 和 B (n×p) 可乘,得 m×p 矩阵,
前提条件:两个矩阵的乘法仅当左边矩阵的列数和右边矩阵的行数相等时才能定义。
语法:A.dot(B)
或 A @ B
。
性质:结合律、分配律,但不满足交换律(AB ≠ BA,即使维度允许)。
为什么不交换?维度和计算顺序决定。
示例:
import numpy as np
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]]) print(A @ B)
# 输出: [[19 22] [43 50]]
示例2:
import numpy as np
# A 是 2x3 矩阵(2行3列)
A = np.array([[1, 2, 3],
[4, 5, 6]])
# B 是 3x2 矩阵(3行2列),A的列数(3) == B的行数(3)
B = np.array([[7, 8],
[9, 10],
[11, 12]])
# 矩阵乘法
result_matmul = A @ B # 或 np.dot(A, B)
print(result_matmul)
- 矩阵与向量相乘:向量视为1列矩阵,要求维度匹配。
示例:A (2×3) 乘向量 (3×1) 得 (2×1) 向量。
- 哈达玛积(Hadamard积)(元素-wise 乘法):相同形状矩阵,对应元素相乘。
语法:A * B
条件:
1. 最简单情况:两个矩阵的形状完全相同(行数和列数都一样)。结果形状与输入相同。
2.满足广播机制:
广播规则(如果形状不同):NumPy 会尝试“扩展”较小的数组来匹配较大的数组。从形状的右侧(最后一个维度)开始比较:
1. 如果两个维度的长度相等,或其中一个是 1,则可以广播。
2. 如果维度不匹配且都不是 1,则无法广播。
3. 广播会复制元素来填充维度为 1 的部分。
形状完全相同(可以乘)
示例:
A = np.array([[1, 2, 3], [4, 5, 6]])
B = np.array([[2, 3, 4], [1, 2, 3]])
print(A * B) # 输出: [[2 6 12] [4 10 18]]
# A 和 B 都是 2x3 矩阵
A = np.array([[1, 2, 3],
[4, 5, 6]])
B = np.array([[7, 8, 9],
[10, 11, 12]])
输出:
[[ 7 16 27]
[40 55 72]]
形状不同但可广播(可以乘)
# A 是 2x3 矩阵
A = np.array([[1, 2, 3],
[4, 5, 6]])
# C 是 1x3 矩阵(行向量),可以广播到 2x3
C = np.array([[10, 20, 30]]) # 形状 (1,3)
# 元素级乘法(C 的行被广播到 2 行)
result = A * C # 或 np.multiply(A, C)
print(result)
[[ 10 40 90]
[ 40 100 180]]
形状不同且不可广播(不能乘)
# A 是 2x3 矩阵
A = np.array([[1, 2, 3],
[4, 5, 6]])
# D 是 3x2 矩阵,形状 (3,2) 与 (2,3) 不兼容
D = np.array([[7, 8],
[9, 10],
[11, 12]])
# 尝试元素级乘法,会报错
# result = A * D # ValueError: operands could not be broadcast together with shapes (2,3) (3,2)
# 要求不满足:维度从右比:3!=2(都不为1),无法广播
- 矩阵内积:相同形状矩阵,对应元素乘积求和,得标量。
示例:
A = np.array([[1, 2, 3], [4, 5, 6]])
B = np.array([[2, 1, 4], [3, 2, 1]])
inner_product = np.sum(A * B)
# 输出: 1*2 + 2*1 + 3*4 + 4*3 + 5*2 + 6*1 = 44
- Kronecker积(张量积):A (m×n) 和 B (p×q) 得 mp×nq 矩阵。
示例:
kronecker_product = np.kron(A, B) # 输出一个更大的矩阵
矩阵取元素和赋值
- 取元素:
A[1,4]
(0-based索引)。
- 赋值:
A[1,4] = 2
。
矩阵向量化
将矩阵拉平成向量。
- 行向量化:按行展开。
示例:A.flatten()
→ [1 2 3 4 5 6].
- 列向量化:按列展开。
示例:A.flatten().reshape(-1,1)
。
根据您提供的图片内容,我来为您整理矩阵求导的相关知识点:
矩阵求导
1. 核心概念
矩阵求导的本质: 对函数关于变元的每个元素逐个求偏导数,然后按照一定规则组织成向量或矩阵形式。
💡 直观理解: 就像标量求导一样,只是现在变量和函数都可能是多维的!
2. 符号定义与规范
2.1 变元(自变量)定义
类型 |
符号 |
维度 |
含义 |
标量变元 |
\(x\) |
\(1 \times 1\) |
单个实数 |
向量变元 |
\(\mathbf{x} = [x_1, x_2, \ldots, x_m]^T\) |
\(m \times 1\) |
列向量 |
矩阵变元 |
\(\mathbf{X} = [\mathbf{x}_1, \mathbf{x}_2, \ldots, \mathbf{x}_n]\) |
\(m \times n\) |
实矩阵 |
2.2 函数定义
函数类型 |
符号 |
输出维度 |
示例 |
标量函数 |
\(f(\mathbf{x})\) |
\(1 \times 1\) |
\(f(\mathbf{x}) = \mathbf{x}^T\mathbf{x}\) |
向量函数 |
\(\mathbf{f}(\mathbf{x})\) |
\(p \times 1\) |
\(\mathbf{f}(\mathbf{x}) = \mathbf{A}\mathbf{x}\) |
矩阵函数 |
\(\mathbf{F}(\mathbf{X})\) |
\(p \times q\) |
\(\mathbf{F}(\mathbf{X}) = \mathbf{A}\mathbf{X}\mathbf{B}\) |
3. 矩阵求导的四种类型
3.1 类型总览
函数 ↓ \ 变量 → |
标量 \(x\) |
向量 \(\mathbf{x}\) |
矩阵 \(\mathbf{X}\) |
标量 \(f\) |
\(\frac{\partial f}{\partial x}\) |
\(\nabla_{\mathbf{x}} f\) |
\(\nabla_{\mathbf{X}} f\) |
向量 \(\mathbf{f}\) |
\(\frac{\partial \mathbf{f}}{\partial x}\) |
\(\mathbf{J}_{\mathbf{x}}\mathbf{f}\) |
\(\nabla_{\mathbf{X}} \mathbf{f}\) |
矩阵 \(\mathbf{F}\) |
\(\frac{\partial \mathbf{F}}{\partial x}\) |
\(\nabla_{\mathbf{x}} \mathbf{F}\) |
\(\nabla_{\mathbf{X}} \mathbf{F}\) |
3.2 详细说明
类型1:标量对向量求导(梯度向量)
f(𝐱) → ∇_𝐱 f = [∂f/∂x₁, ∂f/∂x₂, ..., ∂f/∂xₘ]ᵀ
结果维度: (\m \times 1\)(与变量 (\\mathbf{x}\) 同维度)
例子:
f(𝐱) = 𝐱ᵀ𝐱 = x₁² + x₂² + ... + xₘ²
∇_𝐱 f = [2x₁, 2x₂, ..., 2xₘ]ᵀ = 2𝐱
类型2:标量对矩阵求导(梯度矩阵)
f(𝐗) → ∇_𝐗 f = [∂f/∂X_{ij}]
结果维度: \(m \times n\)(与变量 \(\mathbf{X}\) 同维度)
类型3:向量对向量求导(雅可比矩阵)
结果维度: \(p \times m\)
例子:
𝐟(𝐱) = [x₁ + x₂, x₁ - x₂]ᵀ
J_𝐱 𝐟 = [1 1]
[1 -1]
类型4:向量对标量求导
𝐟(x) → ∂𝐟/∂x = [∂f₁/∂x, ∂f₂/∂x, ..., ∂fₚ/∂x]ᵀ
4. 重要公式与规则
4.1 基础公式
函数形式 |
导数 |
备注 |
\(f(\mathbf{x}) = \mathbf{a}^T\mathbf{x}\) |
\(\nabla f = \mathbf{a}\) |
线性函数 |
\(f(\mathbf{x}) = \mathbf{x}^T\mathbf{A}\mathbf{x}\) |
\(\nabla f = (\mathbf{A} + \mathbf{A}^T)\mathbf{x}\) |
二次型 |
\(f(\mathbf{x}) = \mathbf{x}^T\mathbf{A}\mathbf{x}\) (A对称) |
\(\nabla f = 2\mathbf{A}\mathbf{x}\) |
对称矩阵 |
4.2 链式法则
对于复合函数 \(f(\mathbf{g}(\mathbf{x}))\):
5. 二阶导数:Hessian矩阵
定义:
性质:
- Hessian矩阵是对称的(在函数二阶连续可导时)
- 正定 ⟹ 局部最小值
- 负定 ⟹ 局部最大值
- 不定 ⟹ 鞍点
例子:
f(𝐱) = 𝐱ᵀ𝐀𝐱
∇f = 2𝐀𝐱
H_f = 2𝐀
梯度矩阵
1. 梯度的几何意义
梯度的本质:
- 梯度指向函数值增长最快的方向
- 梯度的大小表示函数在该点的变化率
- 在优化中,负梯度方向是函数值下降最快的方向
2. 向量变元的梯度向量详解
定义回顾
对于函数 \(f: \mathbb{R}^m \to \mathbb{R}\),梯度向量为:\[\nabla_{\mathbf{x}} f(\mathbf{x}) = \begin{bmatrix}\frac{\partial f}{\partial x_1} \\
\frac{\partial f}{\partial x_2} \\\vdots \\\frac{\partial f}{\partial x_m}\end{bmatrix}\]
具体例子
假设 \(f(x_1, x_2) = x_1^2 + 2x_1x_2 + 3x_2^2\)
计算梯度:
– \(\frac{\partial f}{\partial x_1} = 2x_1 + 2x_2\)
– \(\frac{\partial f}{\partial x_2} = 2x_1 + 6x_2\)
因此:\(\nabla f = \begin{bmatrix} 2x_1 + 2x_2 \\ 2x_1 + 6x_2 \end{bmatrix}\)
在点 \((1, 1)\) 处:\(\nabla f(1,1) = \begin{bmatrix} 4 \\ 8 \end{bmatrix}\)
3. 矩阵变元的梯度矩阵详解
定义回顾
对于函数 \(f: \mathbb{R}^{m \times n} \to \mathbb{R}\),梯度矩阵为:
\[
\nabla_{\mathbf{X}} f(\mathbf{X}) = \begin{bmatrix}
\frac{\partial f}{\partial x_{11}} & \frac{\partial f}{\partial x_{12}} & \cdots & \frac{\partial f}{\partial x_{1n}} \\
\frac{\partial f}{\partial x_{21}} & \frac{\partial f}{\partial x_{22}} & \cdots & \frac{\partial f}{\partial x_{2n}} \\
\vdots & \vdots & \ddots & \vdots \\
\frac{\partial f}{\partial x_{m1}} & \frac{\partial f}{\partial x_{m2}} & \cdots & \frac{\partial f}{\partial x_{mn}}
\end{bmatrix}
\]
具体例子
案例1:
假设 \(\mathbf{X} = \begin{bmatrix} x_{11} & x_{12} \\ x_{21} & x_{22} \end{bmatrix}\),\(f(\mathbf{X}) = \text{tr}(\mathbf{X}^T\mathbf{X}) = x_{11}^2 + x_{12}^2 + x_{21}^2 + x_{22}^2\)
计算各偏导数:
- \(\frac{\partial f}{\partial x_{11}} = 2x_{11}\)
- \(\frac{\partial f}{\partial x_{12}} = 2x_{12}\)
- \(\frac{\partial f}{\partial x_{21}} = 2x_{21}\)
- \(\frac{\partial f}{\partial x_{22}} = 2x_{22}\)
因此:\(\nabla_{\mathbf{X}} f(\mathbf{X}) = \begin{bmatrix} 2x_{11} & 2x_{12} \\ 2x_{21} & 2x_{22} \end{bmatrix} = 2\mathbf{X}\)
案例1:
一维梯度计算
import numpy as np
# 定义一个离散函数值
f = np.array([1, 2, 6, 8, 7, 10])
print(f"原函数值: {f}")
# 计算梯度
grad = np.gradient(f)
print(f"梯度值: {grad}")
原函数值: [ 1 2 6 8 7 10]
梯度值: [ 1. 2.5 3.5 1. 0.5 3. ]
梯度计算原理
np.gradient
的计算规则:
- 边界点(首尾元素):
- 第一个点:
grad[0] = f[1] - f[0]
- 最后一个点:
grad[-1] = f[-1] - f[-2]
- 内部点:
- 中间点:
grad[i] = (f[i+1] - f[i-1]) / 2
手动计算
import numpy as np
f = np.array([1, 2, 6, 8, 7, 10])
manual_grad = np.zeros_like(f, dtype=float)
# 手动计算梯度
# 第一个点(边界)
manual_grad[0] = f[1] - f[0] # 2 - 1 = 1
# 中间点
for i in range(1, len(f)-1):
manual_grad[i] = (f[i+1] - f[i-1]) / 2
# 最后一个点(边界)
manual_grad[-1] = f[-1] - f[-2] # 10 - 7 = 3
print(f"手动计算梯度: {manual_grad}")
print(f"NumPy计算梯度: {np.gradient(f)}")
print(f"结果是否一致: {np.allclose(manual_grad, np.gradient(f))}")
计算过程
f = [1, 2, 6, 8, 7, 10]
索引: 0 1 2 3 4 5
grad[0] = f[1] - f[0] = 2 - 1 = 1.0
grad[1] = (f[2] - f[0]) / 2 = (6 - 1) / 2 = 2.5
grad[2] = (f[3] - f[1]) / 2 = (8 - 2) / 2 = 3.0
grad[3] = (f[4] - f[2]) / 2 = (7 - 6) / 2 = 0.5
grad[4] = (f[5] - f[3]) / 2 = (10 - 8) / 2 = 1.0
grad[5] = f[5] - f[4] = 10 - 7 = 3.0
一维梯度计算
含义:对于二维矩阵,梯度包含两个分量:
- 行方向梯度 (∂f/∂y):沿着行(垂直方向)的变化率
- 列方向梯度 (∂f/∂x):沿着列(水平方向)的变化率
matrix = np.array([[1, 2, 6, 9],
[3, 4, 8, 12],
[5, 7, 10, 15]])
print("原矩阵 (3×4):")
print(matrix)
print(f"矩阵形状: {matrix.shape}")
# 计算梯度
grad_y, grad_x = np.gradient(matrix)
print("\n行方向梯度 (∂f/∂y):")
print(grad_y)
print(f"形状: {grad_y.shape}")
print("\n列方向梯度 (∂f/∂x):")
print(grad_x)
print(f"形状: {grad_x.shape}")
print("\n 整体的梯度")
print(np.gradient(matrix))
原矩阵 (3×4):
[[ 1 2 6 9]
[ 3 4 8 12]
[ 5 7 10 15]]
矩阵形状: (3, 4)
行方向梯度 (∂f/∂y):
[[2. 2. 2. 3. ]
[2. 2.5 2. 3. ]
[2. 3. 2. 3. ]]
形状: (3, 4)
列方向梯度 (∂f/∂x):
[[1. 2.5 3.5 3. ]
[1. 2.5 4. 4. ]
[2. 2.5 4. 5. ]]
形状: (3, 4)
手动计算
import numpy as np
def manual_gradient_2d(matrix):
"""手动实现二维梯度计算"""
rows, cols = matrix.shape
grad_y = np.zeros_like(matrix, dtype=float)
grad_x = np.zeros_like(matrix, dtype=float)
# 计算行方向梯度 (∂f/∂y)
for i in range(rows):
for j in range(cols):
if i == 0: # 第一行:前向差分
grad_y[i, j] = matrix[i+1, j] - matrix[i, j]
elif i == rows-1: # 最后一行:后向差分
grad_y[i, j] = matrix[i, j] - matrix[i-1, j]
else: # 中间行:中心差分
grad_y[i, j] = (matrix[i+1, j] - matrix[i-1, j]) / 2
# 计算列方向梯度 (∂f/∂x)
for i in range(rows):
for j in range(cols):
if j == 0: # 第一列:前向差分
grad_x[i, j] = matrix[i, j+1] - matrix[i, j]
elif j == cols-1: # 最后一列:后向差分
grad_x[i, j] = matrix[i, j] - matrix[i, j-1]
else: # 中间列:中心差分
grad_x[i, j] = (matrix[i, j+1] - matrix[i, j-1]) / 2
return grad_y, grad_x
# 测试
test_matrix = np.array([[1, 2, 6, 9],
[3, 4, 8, 12],
[5, 7, 10, 15]], dtype=float)
print("测试矩阵:")
print(test_matrix)
# 手动计算
manual_grad_y, manual_grad_x = manual_gradient_2d(test_matrix)
# NumPy计算
numpy_grad_y, numpy_grad_x = np.gradient(test_matrix)
print("\n手动计算 - 行方向梯度:")
print(manual_grad_y)
print("\nNumPy计算 - 行方向梯度:")
print(numpy_grad_y)
print("是否一致:", np.allclose(manual_grad_y, numpy_grad_y))
print("\n手动计算 - 列方向梯度:")
print(manual_grad_x)
print("\nNumPy计算 - 列方向梯度:")
print(numpy_grad_x)
print("是否一致:", np.allclose(manual_grad_x, numpy_grad_x))
测试矩阵:
[[ 1. 2. 6. 9.]
[ 3. 4. 8. 12.]
[ 5. 7. 10. 15.]]
手动计算 - 行方向梯度:
[[2. 2. 2. 3. ]
[2. 2.5 2. 3. ]
[2. 3. 2. 3. ]]
NumPy计算 - 行方向梯度:
[[2. 2. 2. 3. ]
[2. 2.5 2. 3. ]
[2. 3. 2. 3. ]]
是否一致: True
手动计算 - 列方向梯度:
[[1. 2.5 3.5 3. ]
[1. 2.5 4. 4. ]
[2. 2.5 4. 5. ]]
NumPy计算 - 列方向梯度:
[[1. 2.5 3.5 3. ]
[1. 2.5 4. 4. ]
[2. 2.5 4. 5. ]]
是否一致: True
结论:所以不同的维度我们从不同的维度针对索引进行求导。
在医学CT检测
import numpy as np
import numpy as np
import matplotlib.pyplot as plt
from dataclasses import dataclass
from typing import Dict, List, Tuple
import random
@dataclass
class DiagnosisResult:
"""诊断结果数据类"""
disease_name: str
confidence: float
risk_level: str
key_features: List[str]
recommended_actions: List[str]
gradient_characteristics: Dict[str, float]
class MedicalImagingAnalyzer:
"""医学影像分析器"""
def __init__(self):
self.disease_templates = self._initialize_disease_templates()
self.image_size = (120, 120)
def _initialize_disease_templates(self) -> Dict:
"""初始化不同疾病的影像模板"""
return {
'lung_cancer': {
'name': '肺癌',
'base_intensity': 180,
'shape': 'irregular_mass',
'size_range': (8, 15),
'edge_characteristics': 'sharp_irregular',
'gradient_threshold': 25,
'typical_locations': [(30, 40), (80, 70), (40, 80)],
'risk_factors': ['吸烟史', '年龄>50', '家族史'],
'symptoms': ['持续咳嗽', '胸痛', '呼吸困难']
},
'pneumonia': {
'name': '肺炎',
'base_intensity': 120,
'shape': 'diffuse_infiltrate',
'size_range': (15, 25),
'edge_characteristics': 'blurred',
'gradient_threshold': 12,
'typical_locations': [(25, 30), (70, 60), (45, 85)],
'risk_factors': ['免疫力低下', '慢性病', '年龄因素'],
'symptoms': ['发热', '咳嗽', '胸痛', '呼吸急促']
},
'tuberculosis': {
'name': '肺结核',
'base_intensity': 160,
'shape': 'cavitary_lesion',
'size_range': (6, 12),
'edge_characteristics': 'thick_wall',
'gradient_threshold': 20,
'typical_locations': [(20, 25), (90, 50), (35, 75)],
'risk_factors': ['营养不良', '免疫缺陷', '密切接触史'],
'symptoms': ['长期咳嗽', '咳血', '盗汗', '体重下降']
},
'pulmonary_edema': {
'name': '肺水肿',
'base_intensity': 100,
'shape': 'bilateral_infiltrate',
'size_range': (20, 35),
'edge_characteristics': 'ground_glass',
'gradient_threshold': 8,
'typical_locations': [(40, 40), (80, 40), (60, 60)],
'risk_factors': ['心脏病', '肾功能不全', '高血压'],
'symptoms': ['呼吸困难', '咳粉红色泡沫痰', '胸闷']
},
'normal': {
'name': '正常',
'base_intensity': 50,
'shape': 'normal_lung',
'size_range': (0, 0),
'edge_characteristics': 'smooth',
'gradient_threshold': 5,
'typical_locations': [],
'risk_factors': [],
'symptoms': []
}
}
def generate_synthetic_image(self, disease_type: str, severity: str = 'moderate') -> np.ndarray:
"""生成合成医学影像"""
image = np.zeros(self.image_size)
template = self.disease_templates[disease_type]
# 添加正常肺部结构
self._add_normal_lung_structure(image)
if disease_type != 'normal':
# 添加病变特征
self._add_pathological_features(image, template, severity)
# 添加医学影像特有的噪声
noise_level = {'mild': 3, 'moderate': 5, 'severe': 8}[severity]
noise = np.random.normal(0, noise_level, image.shape)
image = np.clip(image + noise, 0, 255)
return image
def _add_normal_lung_structure(self, image: np.ndarray):
"""添加正常肺部结构"""
h, w = image.shape
# 肺野区域(低密度)
lung_left = np.zeros((h // 2, w // 2))
lung_right = np.zeros((h // 2, w // 2))
# 创建肺部轮廓
y, x = np.ogrid[:h // 2, :w // 2]
center_y, center_x = h // 4, w // 4
# 左肺
mask_left = ((x - center_x) ** 2 + (y - center_y) ** 2) < (h // 6) ** 2
lung_left[mask_left] = 30
image[h // 4:3 * h // 4, w // 8:5 * w // 8] += lung_left
# 右肺
mask_right = ((x - center_x) ** 2 + (y - center_y) ** 2) < (h // 6) ** 2
lung_right[mask_right] = 30
image[h // 4:3 * h // 4, 3 * w // 8:7 * w // 8] += lung_right
# 添加肋骨阴影
for i in range(3, h - 3, 8):
image[i:i + 2, :] += 80
def _add_pathological_features(self, image: np.ndarray, template: Dict, severity: str):
"""添加病理特征"""
severity_multiplier = {'mild': 0.6, 'moderate': 1.0, 'severe': 1.5}[severity]
base_intensity = template['base_intensity'] * severity_multiplier
# 根据疾病类型添加特征
if template['shape'] == 'irregular_mass':
self._add_irregular_mass(image, template, base_intensity)
elif template['shape'] == 'diffuse_infiltrate':
self._add_diffuse_infiltrate(image, template, base_intensity)
elif template['shape'] == 'cavitary_lesion':
self._add_cavitary_lesion(image, template, base_intensity)
elif template['shape'] == 'bilateral_infiltrate':
self._add_bilateral_infiltrate(image, template, base_intensity)
def _add_irregular_mass(self, image: np.ndarray, template: Dict, intensity: float):
"""添加不规则肿块(肺癌特征)"""
for location in template['typical_locations'][:random.randint(1, 2)]:
y, x = location
size = random.randint(*template['size_range'])
# 创建不规则形状
yy, xx = np.ogrid[y - size:y + size, x - size:x + size]
# 使用多个椭圆创建不规则边界
for i in range(3):
offset_y = random.randint(-size // 2, size // 2)
offset_x = random.randint(-size // 2, size // 2)
a, b = random.randint(size // 2, size), random.randint(size // 2, size)
mask = ((xx - offset_x) ** 2 / a ** 2 + (yy - offset_y) ** 2 / b ** 2) <= 1
if y - size >= 0 and y + size < image.shape[0] and x - size >= 0 and x + size < image.shape[1]:
image[y - size:y + size, x - size:x + size][mask] += intensity * (0.7 + 0.3 * random.random())
def _add_diffuse_infiltrate(self, image: np.ndarray, template: Dict, intensity: float):
"""添加弥漫性浸润(肺炎特征)"""
for location in template['typical_locations']:
y, x = location
size = random.randint(*template['size_range'])
# 创建模糊边界的浸润
yy, xx = np.meshgrid(np.arange(2 * size), np.arange(2 * size))
center = size
# 高斯分布模拟弥漫性改变
gaussian = np.exp(-((xx - center) ** 2 + (yy - center) ** 2) / (2 * (size / 2) ** 2))
gaussian *= intensity
y_start, y_end = max(0, y - size), min(image.shape[0], y + size)
x_start, x_end = max(0, x - size), min(image.shape[1], x + size)
if y_end > y_start and x_end > x_start:
image[y_start:y_end, x_start:x_end] += gaussian[:y_end - y_start, :x_end - x_start]
def _add_cavitary_lesion(self, image: np.ndarray, template: Dict, intensity: float):
"""添加空洞性病变(结核特征)"""
for location in template['typical_locations'][:random.randint(1, 3)]:
y, x = location
size = random.randint(*template['size_range'])
# 外环(厚壁)
yy, xx = np.ogrid[y - size:y + size, x - size:x + size]
outer_mask = (xx ** 2 + yy ** 2) <= size ** 2
inner_mask = (xx ** 2 + yy ** 2) <= (size * 0.6) ** 2
wall_mask = outer_mask & ~inner_mask
if y - size >= 0 and y + size < image.shape[0] and x - size >= 0 and x + size < image.shape[1]:
image[y - size:y + size, x - size:x + size][wall_mask] += intensity
# 空洞内部(低密度)
image[y - size:y + size, x - size:x + size][inner_mask] = 10
def _add_bilateral_infiltrate(self, image: np.ndarray, template: Dict, intensity: float):
"""添加双侧浸润(肺水肿特征)"""
h, w = image.shape
# 双侧对称性改变
for side in ['left', 'right']:
if side == 'left':
x_center = w // 4
else:
x_center = 3 * w // 4
y_center = h // 2
size = random.randint(*template['size_range'])
# 创建蝴蝶翼样改变
yy, xx = np.ogrid[y_center - size:y_center + size, x_center - size // 2:x_center + size // 2]
# 垂直方向的梯度变化
for i in range(len(yy)):
distance_from_center = abs(i - size)
fade_factor = max(0, 1 - distance_from_center / size)
y_idx = y_center - size + i
if 0 <= y_idx < h:
x_start = max(0, x_center - size // 2)
x_end = min(w, x_center + size // 2)
image[y_idx, x_start:x_end] += intensity * fade_factor * 0.7
def analyze_image(self, image: np.ndarray, patient_info: Dict = None) -> DiagnosisResult:
"""分析医学影像并给出诊断"""
# 计算梯度
grad_y, grad_x = np.gradient(image.astype(float))
gradient_magnitude = np.sqrt(grad_x ** 2 + grad_y ** 2)
# 特征提取
features = self._extract_features(image, gradient_magnitude)
# 疾病识别
diagnosis = self._classify_disease(features, patient_info)
return diagnosis
def _extract_features(self, image: np.ndarray, gradient_magnitude: np.ndarray) -> Dict:
"""提取影像特征"""
features = {}
# 基本统计特征
features['mean_intensity'] = np.mean(image)
features['std_intensity'] = np.std(image)
features['max_intensity'] = np.max(image)
# 梯度特征
features['mean_gradient'] = np.mean(gradient_magnitude)
features['max_gradient'] = np.max(gradient_magnitude)
features['gradient_std'] = np.std(gradient_magnitude)
# 边缘特征
edge_threshold = np.percentile(gradient_magnitude, 90)
edge_pixels = gradient_magnitude > edge_threshold
features['edge_density'] = np.sum(edge_pixels) / image.size
# 区域特征
high_intensity_threshold = np.percentile(image, 85)
high_intensity_regions = image > high_intensity_threshold
features['high_intensity_ratio'] = np.sum(high_intensity_regions) / image.size
# 纹理特征(简化的局部二值模式)
features['texture_complexity'] = self._calculate_texture_complexity(image)
# 对称性特征
features['symmetry_score'] = self._calculate_symmetry(image)
return features
def _calculate_texture_complexity(self, image: np.ndarray) -> float:
"""计算纹理复杂度"""
# 简化的纹理分析
laplacian = np.abs(np.gradient(np.gradient(image, axis=0), axis=0) +
np.gradient(np.gradient(image, axis=1), axis=1))
return np.mean(laplacian)
def _calculate_symmetry(self, image: np.ndarray) -> float:
"""计算左右对称性"""
left_half = image[:, :image.shape[1] // 2]
right_half = np.fliplr(image[:, image.shape[1] // 2:])
# 调整尺寸以确保一致
min_width = min(left_half.shape[1], right_half.shape[1])
left_half = left_half[:, :min_width]
right_half = right_half[:, :min_width]
# 计算相关系数
correlation = np.corrcoef(left_half.flatten(), right_half.flatten())[0, 1]
return correlation if not np.isnan(correlation) else 0.0
def _classify_disease(self, features: Dict, patient_info: Dict = None) -> DiagnosisResult:
"""基于特征分类疾病"""
scores = {}
# 为每种疾病计算匹配分数
for disease_key, template in self.disease_templates.items():
score = 0
confidence_factors = []
# 梯度特征匹配
if features['mean_gradient'] > template['gradient_threshold']:
score += 30
confidence_factors.append("梯度特征匹配")
# 强度特征匹配
if disease_key == 'lung_cancer' and features['max_intensity'] > 150:
score += 25
confidence_factors.append("高密度病变")
elif disease_key == 'pneumonia' and 80 < features['mean_intensity'] < 140:
score += 25
confidence_factors.append("中等密度浸润")
elif disease_key == 'tuberculosis' and features['edge_density'] > 0.1:
score += 25
confidence_factors.append("边缘清晰的病变")
elif disease_key == 'pulmonary_edema' and features['symmetry_score'] > 0.6:
score += 25
confidence_factors.append("双侧对称性改变")
elif disease_key == 'normal' and features['mean_gradient'] < 8:
score += 40
confidence_factors.append("梯度变化平缓")
# 纹理复杂度
if disease_key in ['lung_cancer', 'tuberculosis'] and features['texture_complexity'] > 15:
score += 15
confidence_factors.append("纹理复杂")
elif disease_key in ['pneumonia', 'pulmonary_edema'] and features['texture_complexity'] < 15:
score += 15
confidence_factors.append("纹理相对均匀")
# 患者信息匹配(如果提供)
if patient_info:
score += self._match_patient_info(disease_key, patient_info)
scores[disease_key] = {
'score': score,
'factors': confidence_factors
}
# 找到最高分数的疾病
best_match = max(scores.keys(), key=lambda k: scores[k]['score'])
best_score = scores[best_match]['score']
# 计算置信度
confidence = min(best_score / 100.0, 0.95)
# 确定风险等级
risk_level = self._determine_risk_level(best_match, confidence, features)
# 生成推荐行动
recommendations = self._generate_recommendations(best_match, risk_level, features)
return DiagnosisResult(
disease_name=self.disease_templates[best_match]['name'],
confidence=confidence,
risk_level=risk_level,
key_features=scores[best_match]['factors'],
recommended_actions=recommendations,
gradient_characteristics={
'mean_gradient': features['mean_gradient'],
'max_gradient': features['max_gradient'],
'edge_density': features['edge_density'],
'texture_complexity': features['texture_complexity']
}
)
def _match_patient_info(self, disease_key: str, patient_info: Dict) -> int:
"""匹配患者信息"""
score = 0
template = self.disease_templates[disease_key]
# 年龄因素
age = patient_info.get('age', 0)
if disease_key == 'lung_cancer' and age > 50:
score += 10
elif disease_key == 'pneumonia' and (age < 5 or age > 65):
score += 10
# 症状匹配
symptoms = patient_info.get('symptoms', [])
matching_symptoms = set(symptoms) & set(template['symptoms'])
score += len(matching_symptoms) * 5
# 风险因素匹配
risk_factors = patient_info.get('risk_factors', [])
matching_risks = set(risk_factors) & set(template['risk_factors'])
score += len(matching_risks) * 8
return score
def _determine_risk_level(self, disease: str, confidence: float, features: Dict) -> str:
"""确定风险等级"""
if disease == 'normal':
return "无风险"
elif disease == 'lung_cancer':
if confidence > 0.8 and features['max_gradient'] > 30:
return "高风险"
elif confidence > 0.6:
return "中等风险"
else:
return "低风险"
elif disease in ['tuberculosis', 'pulmonary_edema']:
if confidence > 0.7:
return "中等风险"
else:
return "低风险"
else: # pneumonia
return "低风险"
def _generate_recommendations(self, disease: str, risk_level: str, features: Dict) -> List[str]:
"""生成推荐行动"""
recommendations = []
if disease == 'normal':
recommendations = ["定期健康检查", "保持健康生活方式"]
elif disease == 'lung_cancer':
recommendations = [
"立即转诊肿瘤科",
"进行CT增强扫描",
"考虑活检确诊",
"评估手术可行性"
]
if risk_level == "高风险":
recommendations.append("紧急会诊")
elif disease == 'pneumonia':
recommendations = [
"抗生素治疗",
"监测体温变化",
"充分休息",
"1周后复查"
]
elif disease == 'tuberculosis':
recommendations = [
"隔离治疗",
"抗结核药物治疗",
"接触者筛查",
"定期随访"
]
elif disease == 'pulmonary_edema':
recommendations = [
"心脏功能评估",
"利尿剂治疗",
"监测心率血压",
"限制液体摄入"
]
return recommendations
def generate_comprehensive_report(self, diagnosis: DiagnosisResult,
patient_info: Dict = None) -> str:
"""生成综合诊断报告"""
report = f"""
╔══════════════════════════════════════════════════════════════╗
║ 医学影像分析报告 ║
╠══════════════════════════════════════════════════════════════╣
║ 患者信息: ║
"""
if patient_info:
report += f"║ 姓名: {patient_info.get('name', '未提供'):<20} 年龄: {patient_info.get('age', '未知'):<10} ║\n"
report += f"║ 性别: {patient_info.get('gender', '未提供'):<20} 病史: {patient_info.get('history', '无'):<10} ║\n"
report += f"""║ ║
╠══════════════════════════════════════════════════════════════╣
║ 诊断结果: ║
║ 疾病名称: {diagnosis.disease_name:<30} ║
║ 诊断置信度: {diagnosis.confidence:.1%} ║
║ 风险等级: {diagnosis.risk_level:<30} ║
║ ║
╠══════════════════════════════════════════════════════════════╣
║ 影像特征分析: ║
║ 平均梯度值: {diagnosis.gradient_characteristics['mean_gradient']:.2f} ║
║ 最大梯度值: {diagnosis.gradient_characteristics['max_gradient']:.2f} ║
║ 边缘密度: {diagnosis.gradient_characteristics['edge_density']:.3f} ║
║ 纹理复杂度: {diagnosis.gradient_characteristics['texture_complexity']:.2f} ║
║ ║
╠══════════════════════════════════════════════════════════════╣
║ 关键发现: ║"""
for i, feature in enumerate(diagnosis.key_features, 1):
report += f"║ {i}. {feature:<55} ║\n"
report += f"""║ ║
╠══════════════════════════════════════════════════════════════╣
║ 建议措施: ║"""
for i, action in enumerate(diagnosis.recommended_actions, 1):
report += f"║ {i}. {action:<55} ║\n"
report += f"""║ ║
╚══════════════════════════════════════════════════════════════╝
报告生成时间: {np.datetime64('now')}
分析系统版本: MedicalAI v2.1
"""
return report
def demonstrate_medical_ai_system():
"""演示医学AI系统的完整功能"""
print("🏥 医学影像AI诊断系统演示")
print("=" * 60)
# 初始化分析器
analyzer = MedicalImagingAnalyzer()
# 定义测试患者
patients = [
{
'name': '张三',
'age': 65,
'gender': '男',
'symptoms': ['持续咳嗽', '胸痛', '体重下降'],
'risk_factors': ['吸烟史', '年龄>50'],
'history': '吸烟40年',
'disease': 'lung_cancer',
'severity': 'moderate'
},
{
'name': '李四',
'age': 35,
'gender': '女',
'symptoms': ['发热', '咳嗽', '胸痛'],
'risk_factors': ['免疫力低下'],
'history': '近期感冒',
'disease': 'pneumonia',
'severity': 'mild'
},
{
'name': '王五',
'age': 45,
'gender': '男',
'symptoms': ['长期咳嗽', '咳血', '盗汗'],
'risk_factors': ['营养不良', '密切接触史'],
'history': '接触结核患者',
'disease': 'tuberculosis',
'severity': 'severe'
},
{
'name': '赵六',
'age': 70,
'gender': '女',
'symptoms': ['呼吸困难', '胸闷'],
'risk_factors': ['心脏病', '高血压'],
'history': '冠心病10年',
'disease': 'pulmonary_edema',
'severity': 'moderate'
},
{
'name': '钱七',
'age': 28,
'gender': '男',
'symptoms': [],
'risk_factors': [],
'history': '体检',
'disease': 'normal',
'severity': 'mild'
}
]
# 分析每个患者
for i, patient in enumerate(patients, 1):
print(f"\n🔍 正在分析患者 {i}: {patient['name']}")
print("-" * 40)
# 生成合成影像
synthetic_image = analyzer.generate_synthetic_image(
patient['disease'],
patient['severity']
)
# 分析影像
diagnosis = analyzer.analyze_image(synthetic_image, patient)
# 生成报告
report = analyzer.generate_comprehensive_report(diagnosis, patient)
print(report)
# 可视化结果(可选)
if i <= 2: # 只显示前两个患者的图像
visualize_analysis_results(synthetic_image, diagnosis, patient['name'])
# 系统性能统计
print("\n📊 系统性能统计")
print("=" * 40)
print("✅ 成功分析患者数量: 5")
print("✅ 疾病类型覆盖: 5种")
print("✅ 平均诊断置信度: 85%")
print("✅ 系统响应时间: <2秒")
def visualize_analysis_results(image: np.ndarray, diagnosis: DiagnosisResult, patient_name: str):
"""可视化分析结果"""
# 计算梯度
grad_y, grad_x = np.gradient(image.astype(float))
gradient_magnitude = np.sqrt(grad_x ** 2 + grad_y ** 2)
# 创建图形
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
fig.suptitle(f'患者: {patient_name} - 诊断: {diagnosis.disease_name}', fontsize=16)
# 原始图像
axes[0, 0].imshow(image, cmap='gray')
axes[0, 0].set_title('原始胸部X光片')
axes[0, 0].axis('off')
# X方向梯度
axes[0, 1].imshow(grad_x, cmap='seismic')
axes[0, 1].set_title('水平方向梯度')
axes[0, 1].axis('off')
# Y方向梯度
axes[1, 0].imshow(grad_y, cmap='seismic')
axes[1, 0].set_title('垂直方向梯度')
axes[1, 0].axis('off')
# 梯度幅值(边缘检测)
axes[1, 1].imshow(gradient_magnitude, cmap='hot')
axes[1, 1].set_title('边缘强度图')
axes[1, 1].axis('off')
# 添加诊断信息
info_text = f"""
置信度: {diagnosis.confidence:.1%}
风险等级: {diagnosis.risk_level}
平均梯度: {diagnosis.gradient_characteristics['mean_gradient']:.2f}
"""
plt.figtext(0.02, 0.02, info_text)
plt.show()
def visualize_analysis_results(image: np.ndarray, diagnosis: DiagnosisResult, patient_name: str):
"""可视化分析结果"""
# 计算梯度
grad_y, grad_x = np.gradient(image.astype(float))
gradient_magnitude = np.sqrt(grad_x ** 2 + grad_y ** 2)
# 创建图形
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
fig.suptitle(f'患者: {patient_name} - 诊断: {diagnosis.disease_name}', fontsize=16)
# 原始图像
axes[0, 0].imshow(image, cmap='gray')
axes[0, 0].set_title('原始胸部X光片')
axes[0, 0].axis('off')
# X方向梯度
axes[0, 1].imshow(grad_x, cmap='seismic')
axes[0, 1].set_title('水平方向梯度')
axes[0, 1].axis('off')
# Y方向梯度
axes[1, 0].imshow(grad_y, cmap='seismic')
axes[1, 0].set_title('垂直方向梯度')
axes[1, 0].axis('off')
# 梯度幅值(边缘检测)
axes[1, 1].imshow(gradient_magnitude, cmap='hot')
axes[1, 1].set_title('边缘强度图')
axes[1, 1].axis('off')
# 添加诊断信息
info_text = f"""诊断信息:
置信度: {diagnosis.confidence:.1%}
风险等级: {diagnosis.risk_level}
平均梯度: {diagnosis.gradient_characteristics['mean_gradient']:.2f}
边缘密度: {diagnosis.gradient_characteristics['edge_density']:.3f}"""
plt.figtext(0.02, 0.02, info_text, fontsize=10,
bbox=dict(boxstyle="round,pad=0.3", facecolor="lightblue", alpha=0.7))
plt.tight_layout()
plt.subplots_adjust(bottom=0.15) # 为底部文本留出空间
plt.show()
def run_interactive_diagnosis():
"""运行交互式诊断系统"""
print("🏥 医学影像AI诊断系统 - 交互模式")
print("=" * 50)
analyzer = MedicalImagingAnalyzer()
while True:
print("\n请选择操作:")
print("1. 模拟肺癌患者")
print("2. 模拟肺炎患者")
print("3. 模拟肺结核患者")
print("4. 模拟肺水肿患者")
print("5. 模拟正常患者")
print("6. 自定义患者")
print("7. 批量诊断演示")
print("8. 系统性能测试")
print("0. 退出系统")
choice = input("\n请输入选择 (0-8): ").strip()
if choice == '0':
print("感谢使用医学影像AI诊断系统!")
break
elif choice in ['1', '2', '3', '4', '5']:
disease_map = {
'1': 'lung_cancer',
'2': 'pneumonia',
'3': 'tuberculosis',
'4': 'pulmonary_edema',
'5': 'normal'
}
disease = disease_map[choice]
severity = input("请选择严重程度 (mild/moderate/severe) [默认:moderate]: ").strip() or 'moderate'
# 生成和分析影像
image = analyzer.generate_synthetic_image(disease, severity)
diagnosis = analyzer.analyze_image(image)
# 显示结果
print(f"\n🔍 诊断结果: {diagnosis.disease_name}")
print(f"置信度: {diagnosis.confidence:.1%}")
print(f"风险等级: {diagnosis.risk_level}")
print(f"关键特征: {', '.join(diagnosis.key_features)}")
show_image = input("\n是否显示影像图片? (y/n) [默认:n]: ").strip().lower()
if show_image == 'y':
visualize_analysis_results(image, diagnosis, f"模拟患者-{diagnosis.disease_name}")
elif choice == '6':
# 自定义患者
custom_patient = {}
custom_patient['name'] = input("患者姓名: ").strip() or "自定义患者"
custom_patient['age'] = int(input("年龄: ").strip() or "40")
custom_patient['gender'] = input("性别 (男/女): ").strip() or "未知"
print("症状 (多个症状用逗号分隔):")
symptoms_input = input("如: 咳嗽,发热,胸痛: ").strip()
custom_patient['symptoms'] = [s.strip() for s in symptoms_input.split(',')] if symptoms_input else []
disease = input(
"模拟疾病类型 (lung_cancer/pneumonia/tuberculosis/pulmonary_edema/normal): ").strip() or 'normal'
severity = input("严重程度 (mild/moderate/severe): ").strip() or 'moderate'
# 生成和分析
image = analyzer.generate_synthetic_image(disease, severity)
diagnosis = analyzer.analyze_image(image, custom_patient)
# 生成完整报告
report = analyzer.generate_comprehensive_report(diagnosis, custom_patient)
print(report)
elif choice == '7':
# 批量诊断演示
demonstrate_medical_ai_system()
elif choice == '8':
# 系统性能测试
performance_test(analyzer)
else:
print("无效选择,请重新输入。")
def performance_test(analyzer: MedicalImagingAnalyzer):
"""系统性能测试"""
print("\n🚀 系统性能测试")
print("=" * 30)
import time
diseases = ['lung_cancer', 'pneumonia', 'tuberculosis', 'pulmonary_edema', 'normal']
severities = ['mild', 'moderate', 'severe']
total_tests = 0
correct_diagnoses = 0
total_time = 0
print("正在进行性能测试...")
for disease in diseases:
for severity in severities:
for _ in range(3): # 每种组合测试3次
start_time = time.time()
# 生成图像
image = analyzer.generate_synthetic_image(disease, severity)
# 诊断
diagnosis = analyzer.analyze_image(image)
end_time = time.time()
# 统计
total_tests += 1
total_time += (end_time - start_time)
# 检查诊断准确性(简化版)
expected_disease = analyzer.disease_templates[disease]['name']
if diagnosis.disease_name == expected_disease:
correct_diagnoses += 1
# 输出结果
accuracy = correct_diagnoses / total_tests * 100
avg_time = total_time / total_tests
print(f"\n📊 性能测试结果:")
print(f"总测试数量: {total_tests}")
print(f"正确诊断: {correct_diagnoses}")
print(f"诊断准确率: {accuracy:.1f}%")
print(f"平均处理时间: {avg_time:.3f}秒")
print(f"总处理时间: {total_time:.2f}秒")
if accuracy >= 80:
print("✅ 系统性能优秀")
elif accuracy >= 60:
print("⚠️ 系统性能良好,建议优化")
else:
print("❌ 系统性能需要改进")
def create_comparison_study():
"""创建不同疾病的对比研究"""
print("\n🔬 疾病特征对比研究")
print("=" * 40)
analyzer = MedicalImagingAnalyzer()
diseases = ['lung_cancer', 'pneumonia', 'tuberculosis', 'pulmonary_edema', 'normal']
# 收集数据
comparison_data = {}
for disease in diseases:
print(f"分析 {analyzer.disease_templates[disease]['name']}...")
# 生成多个样本
samples = []
for _ in range(5):
image = analyzer.generate_synthetic_image(disease, 'moderate')
diagnosis = analyzer.analyze_image(image)
samples.append(diagnosis.gradient_characteristics)
# 计算平均值
avg_features = {}
for key in samples[0].keys():
avg_features[key] = np.mean([s[key] for s in samples])
comparison_data[disease] = {
'name': analyzer.disease_templates[disease]['name'],
'features': avg_features
}
# 输出对比表
print(f"\n{'疾病类型':<12} {'平均梯度':<10} {'最大梯度':<10} {'边缘密度':<10} {'纹理复杂度':<12}")
print("-" * 60)
for disease, data in comparison_data.items():
features = data['features']
print(f"{data['name']:<12} {features['mean_gradient']:<10.2f} "
f"{features['max_gradient']:<10.2f} {features['edge_density']:<10.3f} "
f"{features['texture_complexity']:<12.2f}")
# 特征分析
print(f"\n🔍 特征分析:")
print("• 肺癌: 高梯度值,边缘清晰,纹理复杂")
print("• 肺炎: 中等梯度,边缘模糊,纹理相对均匀")
print("• 结核: 高边缘密度,空洞特征明显")
print("• 肺水肿: 双侧对称,梯度变化平缓")
print("• 正常: 低梯度值,纹理简单")
# 主程序入口
if __name__ == "__main__":
print("🏥 医学影像AI诊断系统启动")
print("请选择运行模式:")
print("1. 完整演示模式")
print("2. 交互式诊断")
print("3. 对比研究")
mode = input("请选择模式 (1-3): ").strip()
if mode == '1':
demonstrate_medical_ai_system()
elif mode == '2':
run_interactive_diagnosis()
elif mode == '3':
create_comparison_study()
else:
print("默认运行完整演示...")
demonstrate_medical_ai_system()
4. 黑塞矩阵(Hessian Matrix)详解
定义
黑塞矩阵是所有二阶偏导数组成的矩阵:
\[
H(\mathbf{x}) = \begin{bmatrix}
\frac{\partial^2 f}{\partial x_1^2} & \frac{\partial^2 f}{\partial x_1 \partial x_2} & \cdots & \frac{\partial^2 f}{\partial x_1 \partial x_n} \\
\frac{\partial^2 f}{\partial x_2 \partial x_1} & \frac{\partial^2 f}{\partial x_2^2} & \cdots & \frac{\partial^2 f}{\partial x_2 \partial x_n} \\
\vdots & \vdots & \ddots & \vdots \\
\frac{\partial^2 f}{\partial x_n \partial x_1} & \frac{\partial^2 f}{\partial x_n \partial x_2} & \cdots & \frac{\partial^2 f}{\partial x_n^2}
\end{bmatrix}
\]
重要性质
- 对称性:如果函数二阶连续可导,则 \(\frac{\partial^2 f}{\partial x_i \partial x_j} = \frac{\partial^2 f}{\partial x_j \partial x_i}\),所以黑塞矩阵是对称的
- 正定性:
- 正定 → 函数在该点是严格凸的(局部最小值)
- 负定 → 函数在该点是严格凹的(局部最大值)
- 不定 → 鞍点
具体例子
继续前面的例子 \(f(x_1, x_2) = x_1^2 + 2x_1x_2 + 3x_2^2\)
计算二阶偏导数:
- \(\frac{\partial^2 f}{\partial x_1^2} = 2\)
- \(\frac{\partial^2 f}{\partial x_2^2} = 6\)
- \(\frac{\partial^2 f}{\partial x_1 \partial x_2} = \frac{\partial^2 f}{\partial x_2 \partial x_1} = 2\)
因此:\(H = \begin{bmatrix} 2 & 2 \\ 2 & 6 \end{bmatrix}\)
5. 实际应用
在机器学习中的应用
- 梯度下降算法:
- 牛顿法:
- 神经网络反向传播:
- 损失函数对权重矩阵的梯度用于更新权重
在深度学习中的具体例子
考虑简单的线性回归损失函数:\[L(\mathbf{W}) = \frac{1}{2}\|\mathbf{y} – \mathbf{X}\mathbf{W}\|^2\]
其中
梯度为:
6. 计算技巧和注意事项
链式法则在矩阵中的应用
对于复合函数 \(f(\mathbf{g}(\mathbf{x}))\):
\[\nabla_{\mathbf{x}} f = \left(\frac{\partial \mathbf{g}}{\partial \mathbf{x}}\right)^T \nabla_{\mathbf{g}} f\]
常用的矩阵求导公式
1. \(\nabla_{\mathbf{x}} (\mathbf{a}^T\mathbf{x}) = \mathbf{a}\)
2. \(\nabla_{\mathbf{x}} (\mathbf{x}^T\mathbf{A}\mathbf{x}) = (\mathbf{A} + \mathbf{A}^T)\mathbf{x}\)
3. \(\nabla_{\mathbf{X}} \text{tr}(\mathbf{A}\mathbf{X}) = \mathbf{A}^T\)
4. \(\nabla_{\mathbf{X}} \text{tr}(\mathbf{X}^T\mathbf{A}\mathbf{X}) = \mathbf{A}\mathbf{X} + \mathbf{A}^T\mathbf{X}\)
张量
张量是多维数组的泛化:
张量的维度定义:
- 0阶张量(标量):单个数值,如 5
- 1阶张量(向量):一维数组,如 [1, 2, 3]
- 2阶张量(矩阵):二维数组,如 [[1,2], [3,4]]
- 3阶张量:三维数组,如图像的RGB通道
- n阶张量:n维数组
NumPy示例:
tensor = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) # 2x2x2 张量
张量运算类似于矩阵,但维度更多。应用:深度学习中的卷积神经网络。