- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
希望你能帮忙,因为这个让我很头疼。
我正在用 python(3.3) 开发一个小型捕食者-猎物模拟,它使用一个简单的前馈神经网络。今天,我将执行大脑每个“滴答声”的函数从纯 python 更改为 numpy 数组,以便在我使用更大的大脑时对其进行优化。
我用 cProfile 检查了(整个主程序“循环”的)性能速度,正如我所料,“tick”函数(在 brain 类中)更快。但是,在运行该程序时,我注意到实际上使用 numpy 的速度较慢(100 次循环在 ~12 秒内 vs 100 次循环在 ~9 秒内)。
为什么会这样?这是代码:
原始实现:
class Brain:
def __init__(self, inputs, hidden, outputs):
self.input_num = inputs
self.hidden_num = hidden
self.output_num = outputs
self.h_weight = []
self.o_weight = []
for _ in range(self.input_num * self.hidden_num):
self.h_weight.append(random.random()*2-1)
for _ in range(self.hidden_num * self.output_num):
self.o_weight.append(random.random()*2-1)
def tick(self):
input_num = self.input_num
hidden_num = self.hidden_num
output_num = self.output_num
hidden = [0]*hidden_num
output = [0]*output_num
inputs = self.input
h_weight = self.h_weight
o_weight = self.o_weight
e = math.e
count = -1
for x in range(hidden_num):
temp = 0
for y in range(input_num):
count += 1
temp -= inputs[y] * h_weight[count]
hidden[x] = 1/(1+e**(temp))
count = -1
for x in range(output_num):
temp = 0
for y in range(hidden_num):
count += 1
temp -= hidden[y] * o_weight[count]
output[x] = 1/(1+e**(temp))
self.output = output
新实现(使用 numpy):
class Brain:
def __init__(self, inputs, hidden, outputs):
self.input_num = inputs
self.hidden_num = hidden
self.output_num = outputs
self.h_weights = random.random((self.hidden_num, self.input_num))
self.o_weights = random.random((self.output_num, self.hidden_num))
self.h_activation = zeros((self.hidden_num, 1), dtype=float)
self.o_activation = zeros((self.output_num, 1), dtype=float)
self.i_output = zeros((self.input_num, 1), dtype=float)
self.h_output = zeros((self.hidden_num, 1), dtype=float)
self.o_output = zeros((self.output_num, 1), dtype=float)
def tick(self):
i_output = self.input
h_weights = self.h_weights
o_weights = self.o_weights
h_activation = dot(h_weights, i_output)
h_output = tanh(h_activation)
o_activation = dot(o_weights, h_output)
o_output = tanh(o_activation)
self.output = o_output
这里是程序的主循环,我已经计时(忽略其他函数,它们对“brain.tick()”函数没有影响)。它在另一个类中,这也是无关紧要的:
def update(self):
GUI.update()
if not self.pause:
self.tick += 1
if self.tick % 1000 == 0:
if self.globalSelection:
self.newGeneration(self.creatures)
else:
for specie in self.species:
if not specie.isPlant:
creatureList = [creature for creature in self.creatures if creature.specie == specie]
self.newGeneration(creatureList)
for creature in self.creatures:
if not creature.specie.isPlant:
if self.useHunger and creature.hunger < 1:
creature.hunger += 1/240
creature.setInputs()
creature.brain.tick()
creature.move(creature.brain.output[0]*50-25, creature.brain.output[1]*8)
creature.interactions()
threading.Timer(self.tickrate, self.update).start()
现在大脑设置为 5 个输入、200 个隐藏和 2 个输出,只是为了测试速度。以下是 cProfile 的结果:
原文:
3312 function calls in 0.094 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.094 0.094 <string>:1(<module>)
200 0.006 0.000 0.007 0.000 __init__.py:263(move)
200 0.024 0.000 0.024 0.000 __init__.py:286(setInputs)
200 0.001 0.000 0.001 0.000 __init__.py:360(interactions)
200 0.033 0.000 0.033 0.000 __init__.py:415(tick)
1 0.005 0.005 0.094 0.094 __init__.py:46(update)
1 0.007 0.007 0.020 0.020 __init__.py:471(update)
1 0.000 0.000 0.000 0.000 _weakrefset.py:79(add)
3 0.000 0.000 0.000 0.000 threading.py:127(__init__)
1 0.000 0.000 0.000 0.000 threading.py:160(_release_save)
1 0.000 0.000 0.000 0.000 threading.py:163(_acquire_restore)
1 0.000 0.000 0.000 0.000 threading.py:166(_is_owned)
1 0.000 0.000 0.000 0.000 threading.py:175(wait)
2 0.000 0.000 0.000 0.000 threading.py:297(__init__)
1 0.000 0.000 0.000 0.000 threading.py:305(is_set)
1 0.000 0.000 0.000 0.000 threading.py:325(wait)
1 0.000 0.000 0.000 0.000 threading.py:507(_newname)
1 0.000 0.000 0.000 0.000 threading.py:534(__init__)
1 0.000 0.000 0.000 0.000 threading.py:577(start)
1 0.000 0.000 0.000 0.000 threading.py:775(daemon)
1 0.000 0.000 0.000 0.000 threading.py:810(__init__)
1 0.000 0.000 0.000 0.000 threading.py:887(current_thread)
225 0.002 0.000 0.002 0.000 {built-in method aacircle}
200 0.001 0.000 0.001 0.000 {built-in method aaline}
200 0.000 0.000 0.000 0.000 {built-in method abs}
4 0.000 0.000 0.000 0.000 {built-in method allocate_lock}
200 0.001 0.000 0.001 0.000 {built-in method atan2}
400 0.001 0.000 0.001 0.000 {built-in method cos}
1 0.000 0.000 0.094 0.094 {built-in method exec}
225 0.001 0.000 0.001 0.000 {built-in method filled_circle}
4 0.000 0.000 0.000 0.000 {built-in method filled_polygon}
1 0.000 0.000 0.000 0.000 {built-in method get_ident}
1 0.000 0.000 0.000 0.000 {built-in method get_pressed}
1 0.000 0.000 0.000 0.000 {built-in method get}
2 0.000 0.000 0.000 0.000 {built-in method len}
200 0.000 0.000 0.000 0.000 {built-in method radians}
1 0.000 0.000 0.000 0.000 {built-in method round}
400 0.001 0.000 0.001 0.000 {built-in method sin}
1 0.000 0.000 0.000 0.000 {built-in method start_new_thread}
1 0.006 0.006 0.006 0.006 {built-in method update}
5 0.000 0.000 0.000 0.000 {method 'acquire' of '_thread.lock' objects}
1 0.000 0.000 0.000 0.000 {method 'add' of 'set' objects}
1 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
2 0.000 0.000 0.000 0.000 {method 'blit' of 'pygame.Surface' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.001 0.001 0.001 0.001 {method 'fill' of 'pygame.Surface' objects}
8 0.000 0.000 0.000 0.000 {method 'random_sample' of 'mtrand.RandomState' objects}
2 0.000 0.000 0.000 0.000 {method 'release' of '_thread.lock' objects}
3 0.000 0.000 0.000 0.000 {method 'render' of 'pygame.font.Font' objects}
新:
3322 function calls in 0.068 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.068 0.068 <string>:1(<module>)
200 0.005 0.000 0.006 0.000 __init__.py:265(move)
200 0.022 0.000 0.023 0.000 __init__.py:288(setInputs)
200 0.001 0.000 0.001 0.000 __init__.py:362(interactions)
200 0.005 0.000 0.014 0.000 __init__.py:417(tick)
1 0.005 0.005 0.068 0.068 __init__.py:47(update)
1 0.005 0.005 0.019 0.019 __init__.py:473(update)
1 0.000 0.000 0.000 0.000 _weakrefset.py:79(add)
3 0.000 0.000 0.000 0.000 threading.py:127(__init__)
1 0.000 0.000 0.000 0.000 threading.py:160(_release_save)
1 0.000 0.000 0.000 0.000 threading.py:163(_acquire_restore)
1 0.000 0.000 0.000 0.000 threading.py:166(_is_owned)
1 0.000 0.000 0.000 0.000 threading.py:175(wait)
2 0.000 0.000 0.000 0.000 threading.py:297(__init__)
1 0.000 0.000 0.000 0.000 threading.py:305(is_set)
1 0.000 0.000 0.000 0.000 threading.py:325(wait)
1 0.000 0.000 0.000 0.000 threading.py:507(_newname)
1 0.000 0.000 0.000 0.000 threading.py:534(__init__)
1 0.000 0.000 0.000 0.000 threading.py:577(start)
1 0.000 0.000 0.000 0.000 threading.py:775(daemon)
1 0.000 0.000 0.000 0.000 threading.py:810(__init__)
1 0.000 0.000 0.000 0.000 threading.py:887(current_thread)
225 0.002 0.000 0.002 0.000 {built-in method aacircle}
200 0.001 0.000 0.001 0.000 {built-in method aaline}
200 0.001 0.000 0.001 0.000 {built-in method abs}
4 0.000 0.000 0.000 0.000 {built-in method allocate_lock}
200 0.000 0.000 0.000 0.000 {built-in method atan2}
400 0.001 0.000 0.001 0.000 {built-in method cos}
400 0.008 0.000 0.008 0.000 {built-in method dot}
1 0.000 0.000 0.068 0.068 {built-in method exec}
225 0.001 0.000 0.001 0.000 {built-in method filled_circle}
4 0.000 0.000 0.000 0.000 {built-in method filled_polygon}
1 0.000 0.000 0.000 0.000 {built-in method get_ident}
1 0.000 0.000 0.000 0.000 {built-in method get_pressed}
1 0.000 0.000 0.000 0.000 {built-in method get}
2 0.000 0.000 0.000 0.000 {built-in method len}
200 0.000 0.000 0.000 0.000 {built-in method radians}
1 0.000 0.000 0.000 0.000 {built-in method round}
400 0.001 0.000 0.001 0.000 {built-in method sin}
1 0.000 0.000 0.000 0.000 {built-in method start_new_thread}
1 0.005 0.005 0.005 0.005 {built-in method update}
5 0.000 0.000 0.000 0.000 {method 'acquire' of '_thread.lock' objects}
1 0.000 0.000 0.000 0.000 {method 'add' of 'set' objects}
1 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
2 0.000 0.000 0.000 0.000 {method 'blit' of 'pygame.Surface' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.002 0.002 0.002 0.002 {method 'fill' of 'pygame.Surface' objects}
18 0.000 0.000 0.000 0.000 {method 'random_sample' of 'mtrand.RandomState' objects}
2 0.000 0.000 0.000 0.000 {method 'release' of '_thread.lock' objects}
3 0.000 0.000 0.000 0.000 {method 'render' of 'pygame.font.Font' objects}
如您所见,整个 update() 函数(模拟的核心)和 brain.tick() 似乎要快得多。那为什么程序运行的时候比较慢呢?
干杯。
最佳答案
在您的新实现中,您为每个 Brain
对象创建了 5 个 numpy 数组:
self.h_activation = zeros((self.hidden_num, 1), dtype=float)
self.o_activation = zeros((self.output_num, 1), dtype=float)
self.i_output = zeros((self.input_num, 1), dtype=float)
self.h_output = zeros((self.hidden_num, 1), dtype=float)
self.o_output = zeros((self.output_num, 1), dtype=float)
这些属性在代码的其他部分没有被引用。创建它们是一项可能代价高昂的操作,在原始实现中似乎没有直接对应的操作。我不确定它是否会超过更快的 numpy 计算的速度优势,但如果您正在创建大量 Brain
对象,那么它值得一看。
关于python - 它应该更快,cProfile说它更快,但程序实际上运行得更慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17778241/
我正在尝试在Elasticsearch中返回的值中考虑地理位置的接近性。我希望近距离比某些字段(例如legal_name)重要,但比其他字段重要。 从文档看来,当前的方法是使用distance_fea
我是Elasticsearch的初学者,今天在进行“多与或”查询时遇到问题。 我有一个SQL查询,需要在Elastic中进行转换: WHERE host_id = 999 AND psh_pid =
智能指针应该/可以在函数中通过引用传递吗? 即: void foo(const std::weak_ptr& x) 最佳答案 当然你可以通过const&传递一个智能指针。 这样做也是有原因的: 如果接
我想执行与以下MYSQL查询等效的查询 SELECT http_user, http_req_method, dst dst_port count(*) as total FROM my_table
我用这两个查询进行测试 用must查询 { "size": 200, "from": 0, "query": { "bool": { "must": [ { "mat
我仍在研究 Pro Android 2 的简短服务示例(第 304 页)同样,服务示例由两个类组成:如下所示的 BackgroundService.java 和如下所示的 MainActivity.j
给定标记 like this : header really_wide_table..........................................
根据 shouldJS 上的文档网站我应该能够做到这一点: ''.should.be.empty(); ChaiJS网站没有使用 should 语法的示例,但它列出了 expect 并且上面的示例似乎
我在 Stack Overflow 上读到一些 C 函数是“过时的”或“应该避免”。你能给我一些这种功能的例子以及原因吗? 这些功能有哪些替代方案? 我们可以安全地使用它们 - 有什么好的做法吗? 最
在 C++11 中,可变参数模板允许使用任意数量的参数和省略号运算符 ... 调用函数。允许该可变参数函数对每个参数做一些事情,即使每个参数的事情不是一样的: template void dummy(
我在我从事的项目之一上将Shoulda与Test::Unit结合使用。我遇到的问题是我最近更改了此设置: class MyModel :update end 以前,我的(通过)测试看起来像这样: c
我该如何做 or使用 chai.should 进行测试? 例如就像是 total.should.equal(4).or.equal(5) 或者 total.should.equal.any(4,5)
如果您要将存储库 B 中的更改 merge 到存储库 A 中,是否应该 merge .hgtags 中的更改? 存储库 B 可能具有 A 中没有的标签 1.01、1.02、1.03。为什么要将这些 m
我正在尝试执行X AND(y OR z)的查询 我需要获得该代理为上市代理或卖方的所有已售属性(property)。 我只用 bool(boolean) 值就可以得到9324个结果。当我添加 bool
我要离开 this教程,尝试使用 Mocha、Supertest 和 Should.js 进行测试。 我有以下基本测试来通过 PUT 创建用户接受 header 中数据的端点。 describe('U
我正在尝试为 Web 应用程序编写一些 UI 测试,但有一些复杂的问题希望您能帮助我解决。 首先,该应用程序有两种模式。其中一种模式是“训练”,另一种是“现场”。在实时模式下,数据直接从我们的数据库中
我有一个规范: require 'spec_helper' # hmm... I need to include it here because if I include it inside desc
我正在尝试用这个测试我在 Rails 中的更新操作: context "on PUT to :update" do setup do @countdown = Factory(:count
我还没有找到合适的答案: onclick="..." 中是否应该转义 &(& 符号)? (或者就此而言,在每个 HTML 属性中?) 我已经尝试在 jsFiddle 和 W3C 的验证器上运行转义和非
import java.applet.*; import java.awt.*; import java.awt.event.*; public class Main extends Applet i
我是一名优秀的程序员,十分优秀!