Batch Gradient Descent running too slowly
dot() gets called three million times.

I changed it from:

def dot(v,w):
    return sum(v_i * w_i for v_i, w_i in zip(v,w))


to:

def dot(v,w):
    return (v[0] * w[0]) + (v[1] * w[1])


And the runtime dropped from 7.09 seconds to 2.89 seconds, with the same results.