I tend to see code where it is not clear where you are in the computation when looking at an individual line. For example:
def forward(self, X):
X = layer(X)
X = activation(X)
X = layer(X)
X = activation(X)
return X
Clearly, lines 2 and 4 as well as 3 and 5, are indistinguishable from eachother.
I would much rather write more readable code, where it is clear where you are in the computation when looking at a particular line of code. For example (using Andrew Ng's notation):
def forward(self, X):
A0 = X
Z1 = layer(A0)
A1 = activation(Z1)
Z2 = layer(A1)
A2 = activation(Z2)
return A2
But this could cause memory errors given large variables, so it may be necessary to do the following...
def forward(self, X):
A0 = X
Z1 = layer(A0); del A0
A1 = activation(Z1); del Z1
Z2 = layer(A1); del A1
A2 = activation(Z2); del Z2
return A2
However, this compromizes the readability does not take advantage of garbage collector properties. I'm not sure if this alternative makes a difference.
If A0, Z1, A1, Z2, A2 were all the same size, there would ideally be a solution that only took up the size of at most two of the variables in memory.
Is there a pythonic way to delete all the variables used on the right-hand side after calculating the left-hand side, or have some similar effect? Alternatively, could you create a function that does the deletion and assignment (given scoping limitations) and what's the efficiency tradeoff there?