Repository: tensorlayer/TensorLayer

Issue:
save_npz sometimes fails
Hi,

`save_npz` sometimes fails because of [this line of code](https://github.com/zsdonghao/tensorlayer/blob/master/tensorlayer/files.py#L552), where `params` is a `list` of numpy arrays. When the first dimension of arrays in `params` is the same but other dimensions may be not, numpy would raise a broadcast error.

Here is a piece of code for reproducing the numpy error.

> import numpy as np
> t1 = np.arange(8).reshape((2, 2, 2))
> t2 = np.arange(12).reshape((2, 2, 3))
> t3 = np.arange(16).reshape((2, 2, 4))
> np.savez('test.npz', params=[t1, t2, t3])

I use python 3.5 and numpy 1.12. I googled around and it seems to be an implementation problem in numpy, as suggested by [this](https://stackoverflow.com/questions/25552741/python-numpy-not-saving-array). A possible solution is not to use a list of numpy arrays for the `params`.



Discussion:
thank you for reporting this.

Could we set all params to list before saving them?

`np.savez('test.npz', [list(t1),list(t2),list(t3)])`
@zsdonghao the error would still be raised. 

Resolving patch:
diff --git a/tensorlayer/files.py b/tensorlayer/files.py
--- a/tensorlayer/files.py
+++ b/tensorlayer/files.py
@@ -561,6 +561,40 @@ def save_npz(save_list=[], name='model.npz', sess=None):
     # np.savez(name, **rename_dict)
     # print('Model is saved to: %s' % name)
 
+def save_npz_dict(save_list=[], name='model.npz', sess=None):
+    """Input parameters and the file name, save parameters as a dictionary into .npz file. Use tl.utils.load_npz_dict() to restore.
+
+    Parameters
+    ----------
+    save_list : a list
+        Parameters want to be saved.
+    name : a string or None
+        The name of the .npz file.
+    sess : None or Session
+
+    Notes
+    -----
+    This function tries to avoid a potential broadcasting error raised by numpy.
+
+    """
+    ## save params into a list
+    save_list_var = []
+    if sess:
+        save_list_var = sess.run(save_list)
+    else:
+        try:
+            for k, value in enumerate(save_list):
+                save_list_var.append(value.eval())
+        except:
+            print(" Fail to save model, Hint: pass the session into this function, save_npz_dict(network.all_params, name='model.npz', sess=sess)")
+    save_var_dict = {str(idx):val for idx, val in enumerate(save_list_var)}
+    np.savez(name, **save_var_dict)
+    save_list_var = None
+    save_var_dict = None
+    del save_list_var
+    del save_var_dict
+    print("[*] %s saved" % name)
+
 def load_npz(path='', name='model.npz'):
     """Load the parameters of a Model saved by tl.files.save_npz().
 
@@ -602,6 +636,25 @@ def load_npz(path='', name='model.npz'):
     # exit()
     # return d.items()[0][1]['params']
 
+def load_npz_dict(path='', name='model.npz'):
+    """Load the parameters of a Model saved by tl.files.save_npz_dict().
+
+    Parameters
+    ----------
+    path : a string
+        Folder path to .npz file.
+    name : a string or None
+        The name of the .npz file.
+
+    Returns
+    --------
+    params : list
+        A list of parameters in order.
+    """
+    d = np.load( path+name )
+    saved_list_var = [val[1] for val in sorted(d.items(), key=lambda tup: int(tup[0]))]
+    return saved_list_var
+
 def assign_params(sess, params, network):
     """Assign the given parameters to the TensorLayer network.
 


Test patch: