这三个选项中,哪个对矩阵方程 `Wx + b` 最有效?

我在尝试从头开始编写神经网络程序,并对将每一层的偏置包含在相应层权重矩阵中的性能感到好奇:

# 对于前馈网络的单层 i:z = W[i] @ a[i-1] + b[i].reshape(-1,1)

与以下方法相比:

z = ((w[i] @ a[i-1]).T + b[i]).T

或者初始化权重,使偏置作为最后一列,每个激活矩阵添加一行对应的1:

ones = np.ones(len(X))z = w[i] @ a[i-1].append(ones)

提出这个问题的原因为,如果我想让X成为包含许多样本和许多变量的二维数组,第一个代码片段往往会产生广播错误,因为我试图将一维数组添加到二维数组的每一列(因此使用.reshape(-1,1))。

我希望 Stack Overflow 能够支持 LaTeX,但希望上述选项已经足够清晰。如果不够,请评论,我会尝试进一步解释。


回答:

在 numpy 中,像.T.reshape()这样的操作非常快,因为它们不会移动任何数据。第一个和第二个选项之间的性能差异不大。第三个选项(使用append(ones))通常应该避免,因为向 numpy 数组追加元素会导致分配一个新数组并复制所有值。

尽管.T.reshape速度很快,可能会有一些差异,这取决于原始数据是按行优先(’C’)还是按列优先(’F’)存储;请参阅numpy 数组文档。这将强烈依赖于底层的矩阵乘法代码,以及数组(至少是行和列)是否能适应 CPU 的缓存。如果您使用 Anaconda Python,那么幕后是 Intel MKL,它非常高效(只要您在 Intel CPU 上运行)。假设您使用单精度浮点数,并且 W 通常不超过 3500 个元素(14 kB 数据),整个数组很可能适合 L1 缓存。

如果a是一个二维数组,并且您一次选择一行a[i-1],那么如果a是以 C 顺序存储(numpy 的默认值),您使用的是在内存中连续的a元素。如果您从aa.T获得a,其中aa是一个 C 顺序数组,那么a[i-1]中的元素在内存中将不连续,这将导致额外的开销。我做了一些测试;看起来在实践中差异很小(小数组为 15%);我假设矩阵库会在必要时在内存中重新排列数组。

如果您使用 IPython(在 Jupyter Notebook 或 Spyder 中),那么您可以使用例如

%timeit -n 10 -r 10 a @ b

进行自己的速度测试(使用?timeit获取更多信息)。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注