Repository: statsmodels/statsmodels

Issue:
use RandomState for random numbers
We should follow sklearn's example and use RandomState for any random variable or random process generation.

makes it easier to initialize with seed and will work better with parallel processing.



Discussion:
What's the difference to calling seed? Could you explain the parallel part or point to some discussions? I have written a decorator to do parallel monte carlo (will be in public soon) and at first I ran into some issues with setting the seeds for the workers.

Mostly guessing:

If we don't use RandomState, then it uses the global numpy RandomState and different processes might influence each other. I don't understand whether this is correct, or what the effects would be, but sklearn has more experience in this and I would just imitate them.

My tendency so far was to rely on the global state and just to np.random.seed(...)

Ah, well this is good to know then. I will have a look around. Thanks.


Resolving patch:
diff --git a/statsmodels/genmod/cov_struct.py b/statsmodels/genmod/cov_struct.py
--- a/statsmodels/genmod/cov_struct.py
+++ b/statsmodels/genmod/cov_struct.py
@@ -1266,8 +1266,8 @@ def _make_pairs(self, i, j):
         except TypeError:
             # workaround for old numpy that can't call unique with complex
             # dtypes
-            np.random.seed(4234)
-            bmat = np.dot(mat, np.random.uniform(size=mat.shape[1]))
+            rs = np.random.RandomState(4234)
+            bmat = np.dot(mat, rs.uniform(size=mat.shape[1]))
             _, idx = np.unique(bmat, return_index=True)
         mat = mat[idx, :]
 
diff --git a/statsmodels/tsa/vector_ar/util.py b/statsmodels/tsa/vector_ar/util.py
--- a/statsmodels/tsa/vector_ar/util.py
+++ b/statsmodels/tsa/vector_ar/util.py
@@ -186,9 +186,8 @@ def varsim(coefs, intercept, sig_u, steps=100, initvalues=None, seed=None):
     Simulate simple VAR(p) process with known coefficients, intercept, white
     noise covariance, etc.
     """
-    if seed is not None:
-        np.random.seed(seed=seed)
-    from numpy.random import multivariate_normal as rmvnorm
+    rs = np.random.RandomState(seed=seed)
+    rmvnorm = rs.multivariate_normal
     p, k, k = coefs.shape
     ugen = rmvnorm(np.zeros(len(sig_u)), sig_u, steps)
     result = np.zeros((steps, k))
diff --git a/statsmodels/tsa/vector_ar/var_model.py b/statsmodels/tsa/vector_ar/var_model.py
--- a/statsmodels/tsa/vector_ar/var_model.py
+++ b/statsmodels/tsa/vector_ar/var_model.py
@@ -1105,7 +1105,8 @@ def irf_errband_mc(self, orth=False, repl=1000, T=10,
 
         for i in range(repl):
             #discard first hundred to eliminate correct for starting bias
-            sim = util.varsim(coefs, intercept, sigma_u, steps=nobs+burn)
+            sim = util.varsim(coefs, intercept, sigma_u,
+                              seed=seed, steps=nobs+burn)
             sim = sim[burn:]
             ma_coll[i,:,:,:] = fill_coll(sim)
 
@@ -1156,8 +1157,6 @@ def irf_resim(self, orth=False, repl=1000, T=10,
         intercept = self.intercept
         df_model = self.df_model
         nobs = self.nobs
-        if seed is not None:
-            np.random.seed(seed=seed)
 
         ma_coll = np.zeros((repl, T+1, neqs, neqs))
 
@@ -1176,7 +1175,8 @@ def irf_resim(self, orth=False, repl=1000, T=10,
 
         for i in range(repl):
             #discard first hundred to eliminate correct for starting bias
-            sim = util.varsim(coefs, intercept, sigma_u, steps=nobs+burn)
+            sim = util.varsim(coefs, intercept, sigma_u,
+                              seed=seed, steps=nobs+burn)
             sim = sim[burn:]
             ma_coll[i,:,:,:] = fill_coll(sim)
 


Test patch: