HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Defensive programming type-checking

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
typeprogrammingcheckingdefensive

Problem

I have issues with dynamically typed languages, and I tend to worry about type a lot.

Numpy has different behaviour depending on if something is a matrix or a plain ndarray, or a list. I didn't originally have all these asserts, but I inserted them while trying to debug a type error.

from numpy import *
sigmoid = vectorize(lambda(x): 1.0/(1.0+exp(-x)))

def prob_hOn_givenV (v,b,w):
    assert isinstance(v,matrix)
    assert isinstance(w,matrix)
    assert isinstance(b,matrix)
    assert shape(v)[1]==shape(w)[0]
    #print("|v|="+str(shape(v)) +"|w|="+str(shape(w)) )
    return sigmoid(b+v*w) #sum up rows (v is a column vector)

def prob_vOn_givenH (h,a,w):
    assert isinstance(h,matrix)
    assert isinstance(a,matrix)
    assert isinstance(w,matrix)

    assert shape(h)[1]==shape(w.T)[0]

    return sigmoid(a+h*w.T) #sum up columns. (h is a row vector)


Is there a better way? Perhaps a defensive programming toolkit? There is also duplication in the code, but I can't see a nice way of removing it while maintaining meaning. People familiar with Restricted Boltzman Machines will recognise the conditional formula used for Gibbs sampling for contrastive divergence.

Solution

First, I recommend avoiding the matrix type altogether. The problems it causes outweighs the minor syntactical convenience it provides, in my (and quite a few others') opinion.

Second, the idiomatic way to do this kind of thing in numpy is not to assert that the inputs are particular types, but to coerce them to an ndarray. np.asarray() does this efficiently; if the input is an ndarray, the input passes through untouched; if it is an ndarray subclass, then a new ndarray will be created but only as a view on the original data so no data will be copied.

import numpy as np

def sigmoid(x):
    # No need to use vectorize() for this. It's already vectorized.
    return 1.0 / (1.0 + np.exp(-x))

def prob_hOn_givenV(v, b, w):
    v = np.asarray(v)
    b = np.asarray(b)
    w = np.asarray(w)
    # Don't bother checking the shape. `np.dot()` will do that for us.
    # Strictly speaking, the `asarray(v)` and `asarray(w)` aren't necessary
    # since `np.dot(v, w)` already does that internally. But it does no harm.
    return sigmoid(b + np.dot(v, w))

Code Snippets

import numpy as np

def sigmoid(x):
    # No need to use vectorize() for this. It's already vectorized.
    return 1.0 / (1.0 + np.exp(-x))

def prob_hOn_givenV(v, b, w):
    v = np.asarray(v)
    b = np.asarray(b)
    w = np.asarray(w)
    # Don't bother checking the shape. `np.dot()` will do that for us.
    # Strictly speaking, the `asarray(v)` and `asarray(w)` aren't necessary
    # since `np.dot(v, w)` already does that internally. But it does no harm.
    return sigmoid(b + np.dot(v, w))

Context

StackExchange Code Review Q#39125, answer score: 2

Revisions (0)

No revisions yet.