
上次笔记,完成了第十八章Numpy关于爱因斯坦求和约定的基础学习。这是一个极其强大且简洁的工具,可以用一种统一的语法完成数组的求和、转置、乘法等操作,可理解为线性代数与张量运算的瑞士军刀。
今天的学习内容,继续深入探索Numpy的“爱因斯坦求和约定”,包括:
18.3 二维、三维数组转置
18.4 矩阵乘法(格拉姆矩阵、分类矩阵乘法)
# 代码18.1 利用爱因斯坦求和约定求和import numpy as npfrom sklearn.datasets import load_iris# 加载鸢尾花数据集iris = load_iris()X = iris.data # 形状 (150, 4)y = iris.target# 每一列求和:等价于 np.sum(X, axis=0)col_sum = np.einsum('ij->j', X)# 字符串'ij->j'含义:# - 输入X有两个维度:i(行)、j(列)# - 输出只保留j维度,对i维度求和(压缩i)# - 结果是一维数组,长度为4(列数)# 每一行求和:等价于 np.sum(X, axis=1)row_sum = np.einsum('ij->i', X)# 'ij->i':压缩j维度,保留i维度# 所有元素求和:等价于 np.sum(X, axis=(0,1)) 或 np.sum(X)total_sum = np.einsum('ij->', X)# 'ij->':压缩所有维度,输出标量图示辅助理解

# 代码18.2 利用爱因斯坦求和约定完成转置# 二维数组转置:等价于 X.T 或 np.transpose(X)X_T = np.einsum('ij->ji', X)# 'ij->ji':调换输入的两个维度索引



# 首先创建一个三维数组,例如将三类鸢尾花数据堆叠X_setosa = X[y == 0] # 第一类样本X_versicolor = X[y == 1]X_virginica = X[y == 2]X_3d = np.stack([X_setosa, X_versicolor, X_virginica]) # 形状 (3, 50, 4)# 三维数组转置:保持第一个维度不变,交换后两个维度X_transposed = np.einsum('ijk->ikj', X_3d)# 等价于 np.transpose(X_3d, (0, 2, 1))
# 计算格拉姆矩阵 G = X^T XG = np.einsum('ij,ik->jk', X, X)# 等价于 X.T @ X# 字符串'ij,ik->jk'含义:# - 第一个输入X维度为(i,j),第二个输入X维度为(i,k)# - 输出维度为(j,k),对公共维度i求和



# 假设我们有一个类别标签向量y,想对每个类别分别计算格拉姆矩阵# 这里以三类鸢尾花为例,X_3d形状(3, 50, 4)代表三类样本# 对每个类别切片计算格拉姆矩阵G_per_class = np.einsum('bij,bik->bjk', X_3d, X_3d)# 字符串'bij,bik->bjk':# - b: 类别维度,i: 样本维度,j/k: 特征维度# - 对每个类别b,计算其内部样本i的格拉姆矩阵# 结果形状(3, 4, 4),即每个类别一个4x4的格拉姆矩阵



---
笔记写于:2026年4月29日13:04:29
结束于:2026年4月29日13:55
用时:约50分钟
--