【发布时间】:2017-03-29 20:09:31
【问题描述】:
我过去曾成功编写过一些神经网络。我编写了一个具有完全连接层(任何大小和数量)的多层感知器,并使用反向传播对其进行了训练。我做了一个卷积网络,并用手写/计算的数学找到了它的梯度。我现在正试图变得更笼统。我想本着 Theano 的精神为任何计算图编写反向传播。
考虑一下这个 Python 代码:
from __future__ import division
from pylab import *
class Node(object):
def __init__(self):
self.children = []
self.parents = []
self.state = []
def forward_prop(self):
for child in self.children:
child.forward_prop()
class Static(Node):
def __init__(self, *shape):
super(Static, self).__init__()
state = zeros(shape)
class MatrixProduct(Node):
def __init__(self, w, x):
super(MatrixProduct, self).__init__()
self.w = w
self.x = x
self.state = [0]*len(x.state)
def forward_prop(self):
self.state = self.w.state.dot(self.x.state)
for child in self.children:
child.forward_prop()
class Doubler(Node):
def __init__(self):
super(Doubler, self).__init__()
def forward_prop(self):
self.state = [s*2 for s in self.state]
for child in self.children:
child.forward_prop()
a = Static()
a.state = array([2,3])
w = Static()
w.state = array([[1,2],[3,4]])
x = MatrixProduct(w, a)
a.children.append(x)
d = Doubler()
d.state.append(3)
x.children.append(d)
a.forward_prop()
print a.state
print d.state
我主要了解如何将其移植到 C++。我的问题是我不知道如何让孩子的前向传播在 C++ 中工作。在 Python 中,这很容易,因为 children 是一个潜在异构类型的列表,每个类型都有自己的 forward_propagate 行为。在 C++ 中,我该怎么办?
我觉得答案是继承,但如果它们都是一些基类,那么它会调用基类向前传播,而不是子类。
我试图避免冗余。节点知道将其输入转换为输出的操作。但是,只要它们的形状相同,它们就可以接受不同类型的输入。 IE,ElementwiseVectorDoubler 节点可以将任何类型的处理向量的节点作为输入并作为输出。可以从矩阵乘法等中获取输入...但我不想为每个特定类型的 1d 向量输入单独的 ElementwiseVectorDoubler 类输入我们的输出。
【问题讨论】:
-
“如果它们都是一些基类,那么它调用基类前向传播,而不是子类。” - 你听说过虚函数吗?
-
是的,但几乎没有。我会去阅读并尝试应用它。谢谢!
-
防范 X/Y 问题:您这样做是为了个人学习吗?有几个很好的 NN 框架可以大大加快您的开发时间——如果模型本身是您的实际目标,而不是教育。
-
更清楚一点 - 您使用类和
forward_prop方法的方式本质上就是您在 C++(以及其他一些语言,如 C#)中的方式,除非您需要添加方法的virtual(和override,自 C++11 起)关键字。 -
虚拟函数绝对可以解决问题。这个页面对我很有帮助:cplusplus.com/doc/tutorial/polymorphism
标签: python c++ vector neural-network