【发布时间】:2014-12-09 21:00:33
【问题描述】:
假设我们有一个“神经网络”类
- 每个神经网络都由层组成
- 每一层都由神经元组成
-
每个神经元由权重、偏差和激活函数组成
class Neuron: def __init__(self,weights,bias,activation): self._weights = weights self._bias = bias self._activation = activation def activate(self,input): return self._activation.compute(self._weights.dot(input)+self._bias) class Layer: def __init__(self,neurons): self._neurons = neurons def compute(self,input): output = [] for neuron in self._neurons: output.append(neuron.activate(input)) return output class NeuralNetwork: def __init__(self,layers): self._layers = layers def compute(self,input): output = input for layer in self._layers: output = layer.compute(output) return output def train(self,dataset): # do some training # changes the neurons inside the layers
NeuralNetwork 有一个方法 train() 可以改变其内部表示。 但这意味着可以访问 Layer 对象的内部。它需要访问单个神经元,这违反了得墨忒耳定律。 例如
layers[0].getNeuron(0).compute(input)
layer[0].getNeuron(0).changeBias(2)
我能想到的唯一解决方案是在“层”中提供额外的方法并将其委托给神经元。这也将允许我使用 Layer 接口的不同实现。一种更灵活,一种性能更好。
但这似乎很麻烦。没有更好的方法来建模吗?
【问题讨论】:
-
train如何选择要修改的神经元还不是很清楚。但除此之外,我怀疑观察者模式可以提供一种可能的替代方案。神经元会订阅层上的事件,train会将事件发布到层。这样,层将成为“转储”中间体,即神经元中的实际处理,同时保持 demeter 定律。 -
但这会引入循环依赖,因为层仍然需要了解神经元来计算其输出。因此,由于所有内容都发布到该层,因此我认为简单的提供委托方法没有优势。我添加了一个图表来描述我的问题。我想要删除的是 Network 和 Neuron 之间的依赖关系。 train 方法的工作原理无关紧要。它基本上会进行一些计算并更改所有单个神经元的权重。
-
神经元不知道层。层会订阅它们并调用它们的事件处理方法,就像它现在在您的代码中调用它们的
activate()方法一样。Network和Neuron之间的链接将被破坏,Layer不需要提供任何包装方法,只需一个用于将事件委托给神经元。 -
这样的?
train()组装具有特定神经元“地址”的Event对象并将其发布到层layer.publish(event)。现在层可能会将其广播给所有神经元或对其进行部分解析,发现地址并将其发送到正确的神经元neuron.parse(event)。 -
如果你违反了得墨忒耳法则怎么办?这只是一个指导方针。过度依赖/耦合(违反 Demeter 定律)是不好的,因为对其他事物所依赖的事物的更改可能会有害地传播。
Neuron有多“不稳定”?如果你愿意忍受它是稳定的,那么不要担心得墨忒耳法则。
标签: python oop design-patterns