python - NumPy - 是否可以提高相互递归数组计算的性能
问题描述
考虑以下模块 -
""" simple nn """
import numpy as np
TRAINING_SET = np.array([[0, 0, 1], [0, 1, 1], [1, 0, 1], [1, 1, 1]])
OUTPUT = np.array([[0, 0, 1, 1]]).T
def train(epochs=100000):
""" train a single layer neural network """
rng = np.random.default_rng()
weights = 2 * rng.random((3, 1)) - 1
for _ in range(epochs):
layer = 1 /(1 + np.exp(-np.dot(TRAINING_SET, weights)))
weights += np.dot(TRAINING_SET.T, (OUTPUT - layer) * layer * (1 - layer))
print("Number of epochs:", epochs)
print("layer\n", layer)
print("weights\n", weights)
因为layer
和weights
是相互递归的,所以我不得不使用for
循环来计算它们。有没有更有效的方法?
解决方案
这是一种完全摆脱for
循环的方法。请注意,weights
不需要为这个问题唯一定义最优值,但layer
可以恢复最优值。
我假设 as趋于epochs
无穷大,weights
并layer
收敛到一些极限值(就像这个特定示例的情况一样)。如果是这样,我们期望增量weights
为零。因此,我们有以下方程组:
0 == np.dot(TRAINING_SET.T, (OUTPUT - layer) * layer * (1 - layer))
layer == 1 /(1 + np.exp(-np.dot(TRAINING_SET, weights)))
使用一点代数,我们得到
OUTPUT == 1/(1 + np.exp(-TRAINING_SET @ weights))
请注意,这个方程不能完全成立,因为OUTPUT
有一些零元素。我们可以得到如下数值近似:
err = 1e-8
w = np.linalg.pinv(TRAINING_SET) @ -np.log(err + 1/(err + OUTPUT)-1)
比较结果layer
:
ws, lr = train(100000)
err = 1e-8
ws2 = np.linalg.pinv(TRAINING_SET) @ -np.log(err + 1/(err + OUTPUT)-1)
lr2 = 1 /(1 + np.exp(-np.dot(TRAINING_SET, ws2)))
print(lr - lr2)
# [[ 0.00301781]
# [ 0.00246096]
# [-0.00200824]
# [-0.0024629 ]]
推荐阅读
- node.js - 如何在 circleci 上运行 websocket 测试
- c++ - 对两个链表求和
- php - 将临时表中的值导入另一个表?
- python - 在 Azure DevOps Pipelines 中将变量从 Python 传递到 YAML
- spring-boot - Keycloak:使用 SpringBoot 进行访问令牌验证
- python - 如何使用 pytest 测试 python 控制台脚本输出?
- apache-kafka - 异常发生时Kafka Event收到10次
- mule - 有没有办法在 DataWeave 2.0 中修剪数字中不必要的零?
- python - 将数据帧索引移动一定数量
- python - 根据条件使用多索引更新熊猫数据框