我正在实现神经网络,其输入和输出矩阵非常大,所以我使用dask数组来存储它们。
std::priority_queue
是32000 x 7500的输入矩阵,X
是相同维度的输出矩阵。
下面是具有1个隐藏层的神经网络代码:
y
现在我尝试降低功能成本,如下所示:
class Neural_Network(object):
def __init__(self,i,j,k):
#define hyperparameters
self.inputLayerSize = i
self.outputLayerSize = j
self.hiddenLayerSize = k
#weights
self.W1 = da.random.normal(0.5,0.5,size =(self.inputLayerSize,self.hiddenLayerSize),chunks=(1000,1000))
self.W2 = da.random.normal(0.5,0.5,size =(self.hiddenLayerSize,self.outputLayerSize),chunks=(1000,1000))
self.W1 = self.W1.astype('float96')
self.W2 = self.W2.astype('float96')
def forward(self,X):
self.z2 = X.dot(self.W1)
self.a2 = self.z2.map_blocks(self.sigmoid)
self.z3 = self.a2.dot(self.W2)
yhat = self.z3.map_blocks(self.sigmoid)
return yhat
def exp(z):
return np.exp(z)
def sigmoid(self,z):
#sigmoid function
## return 1/(1+np.exp(-z))
return 1/(1+(-z).map_blocks(self.exp))
def sigmoidprime(self,z):
ez = (-z).map_blocks(self.exp)
return ez/(1+ez**2)
def costFunction (self,X,y):
self.yHat = self.forward(X)
return 1/2*sum((y-self.yHat)**2)
def costFunctionPrime (self,X,y):
self.yHat = self.forward(X)
self.error = -(y - self.yHat)
self.delta3 = self.error*self.z3.map_blocks(self.sigmoidprime)
dJdW2 = self.a2.transpose().dot(self.delta3)
self.delta2 = self.delta3.dot(self.W2.transpose())*self.z2.map_blocks(self.sigmoidprime)
dJdW1 = X.transpose().dot(self.delta2)
return dJdW1 , dJdW2
但是当>>> n = Neural_Network(7420,7420,5000)
>>> for i in range(0,500):
cost1,cost2 = n.costFunctionPrime(X,y)
n.W1 = n.W1 -3*cost1
n.W2 = n.W2 -3*cost2
if i%5==0:
print (i*100/500,'%')
达到120左右时,它会给我一个错误:
i
当我执行 File "<pyshell#127>", line 3, in <module>
n.W1 = n.W1 -3*cost1
File "c:\python34\lib\site-packages\dask\array\core.py", line 1109, in __sub__
return elemwise(operator.sub, self, other)
File "c:\python34\lib\site-packages\dask\array\core.py", line 2132, in elemwise
dtype=dt, name=name)
File "c:\python34\lib\site-packages\dask\array\core.py", line 1659, in atop
return Array(merge(dsk, *dsks), out, chunks, dtype=dtype)
File "c:\python34\lib\site-packages\toolz\functoolz.py", line 219, in __call__
return self._partial(*args, **kwargs)
File "c:\python34\lib\site-packages\toolz\curried\exceptions.py", line 20, in merge
return toolz.merge(*dicts, **kwargs)
File "c:\python34\lib\site-packages\toolz\dicttoolz.py", line 39, in merge
rv.update(d)
MemoryError
MemoryError
答案 0 :(得分:0)
这看起来像是在构建图形时失败,而不是在计算过程中。我想到了两件事:
for循环的每次迭代都可能将数百万个任务转储到任务图中。每项任务可能占用100B到1kB之类的东西。当这些加起来时,它们很容易淹没你的机器。
在像Theano这样的典型深度学习库中,您可以使用scan
操作来执行此类操作。 Dask.array没有这样的操作。
您在自己调用map_blocks的函数上调用map_blocks。
self.delta2 = self.delta3.dot(self.W2.transpose())*self.z2.map_blocks(self.sigmoidprime)
def sigmoidprime(self,z):
ez = (-z).map_blocks(self.exp)
return ez/(1+ez**2)
相反,你可能只是制作一个sigmoid prime函数
def sigmoidprime(z):
ez = np.exp(-z)
return ez / (1 + ez ** 2)
然后映射该功能
self.z2.map_blocks(sigmoidprime)
一般来说,深度学习往往需要专业化。设计得很好的图书馆通常不是一般目的。像dask.array 这样的通用库可能很有用,但可能永远无法实现像Theano这样的库的平滑操作。
您可以尝试构建仅需一步的功能。它将从磁盘读取,执行所有点积,转置和正常计算,然后显式存储到磁盘数据集中。然后,您将多次调用此函数。即使这样,我也不相信dask.array背后的调度策略可以做得很好。