NumPy数组按行随机选10个元素的实现及plt.matshow()绘图方法
核心问题定位
你的代码存在两个根本性错误,是所有实现失败的原因:
- 自定义函数硬编码了
Xtrain[0,:],无论外部怎么遍历、怎么调用apply_along_axis,函数逻辑永远只会操作矩阵第一行,完全不会处理其他行 - 误将
np.random.choice的第一个参数传成了X的元素值,而非行内的列位置索引——你需要的是从每行的784个位置里随机挑10个位置取值,不是在第一行的数值里抽选重复值
可直接落地的正确实现方案
方案1:全向量化实现(无循环,适配3000行规模,运行速度最快)
这个方法不需要逐行调用函数,完全由numpy批量并行计算,不会出现循环/高阶函数调用的参数传递问题。
- 核心逻辑:对矩阵每一行生成无重复的随机列索引,再按索引批量取值
import numpy as np # 原始矩阵维度:(3000, 784),对应你的X n_samples, n_features = X.shape n_pick = 10 # 每行要抽取的元素数量 # 1. 为所有行生成随机列索引:给每个元素位置生成独立随机数,按行排序后取前10个位置的索引 # 生成的索引矩阵维度为(3000, 10),每行对应10个不重复的随机列位置 random_col_indices = np.argsort(np.random.rand(n_samples, n_features), axis=1)[:, :n_pick] # 2. 按索引抽取元素,得到的新矩阵维度为(3000, 10) X_picked = X[np.arange(n_samples)[:, None], random_col_indices]
方案2:修正后的apply_along_axis实现(和你最初尝试的思路匹配)
如果你一定要用np.apply_along_axis实现,只需要修正自定义函数的逻辑——让函数处理传入的单行数据,而非硬编码索引整个X矩阵的固定行:
def pick_single_row(row, pick_count): # 函数接收的row是arr的单行数据,直接在该行的长度范围内生成随机索引 col_indices = np.random.choice(len(row), pick_count, replace=False) return row[col_indices] # apply_along_axis会逐行把X的每一行传给pick_single_row,额外参数通过args传入 X_picked = np.apply_along_axis(pick_single_row, axis=1, arr=X, pick_count=10)
注:之前apply_along_axis调用失败,90%的概率是你在自定义函数里依然引用了全局的Xtrain[0,:],没有使用函数入参传入的单行数据,或是没有把pick_count作为额外参数传递给高阶函数
结合Y标签的matshow可视化实现
你可以先把抽取后的矩阵按Y标签排序,让同一类别的样本连续排列,可视化结果会更清晰:
import matplotlib.pyplot as plt # 按标签Y升序排序所有样本行 sort_order = np.argsort(Y.flatten()) X_vis = X_picked[sort_order] Y_vis = Y[sort_order] # 绘制热力图 plt.matshow(X_vis, aspect='auto', cmap='viridis') # 添加分类标注,避免分不清两类样本的边界 plt.yticks( ticks=np.arange(0, n_samples, 500), labels=[f"Sample Label: {Y_vis[i][0]}" for i in np.arange(0, n_samples, 500)] ) plt.xlabel("Randomly Picked Feature Position") plt.ylabel("Sample (Sorted by Label)") plt.colorbar(label="Original Feature Value") plt.show()
注意:如果你的X是MNIST类的图像数据集(784维对应28*28像素),直接抽10个随机像素位置做matshow的区分度会比较有限,建议可以结合不同类别的像素均值做差异筛选,再做随机抽样。
内容的提问来源于stack exchange,提问作者lambda
相关产品推荐
相关产品推荐

