1

I am working on Dictionary Learning by using SPAMS in Python.

Here is my code =>

import spams
import numpy as np
from PIL import Image
import time
import matplotlib.pyplot as plt

img_file = 'gray-car.jpg'
try:
    img = Image.open(img_file)
except:
    print("Cannot load image %s : skipping test" %img_file)
I = np.array(img) / 255.

print('Shape : ',I.shape)

if I.ndim == 3:
    A = np.asfortranarray(I.reshape((I.shape[0],I.shape[1] * I.shape[2])))
    rgb = True
else:
    A = np.asfortranarray(I)
    rgb = False

m = 8;n = 8;
X = spams.im2col_sliding(A,m,n,rgb)

X = X - np.tile(np.mean(X,0),(X.shape[0],1))
X = np.asfortranarray(X / np.tile(np.sqrt((X * X).sum(axis=0)),(X.shape[0],1)),dtype=np.float64)
param = { 'K' : 100, # learns a dictionary with 100 elements
          'lambda1' : 0.15, 'numThreads' : 4, 'batchsize' : 400,
          'iter' : 1000}

tic = time.time()
D = spams.trainDL(X,**param)
tac = time.time()
t = tac - tic
print('time of computation for Dictionary Learning: %f' %t)

##param['approx'] = 0
# save dictionnary as dict.png
plt.imshow(D)
plt.show()
_objective(X,D,param,'dict')

Here the error that I am getting during learning =>

noise.py:27: RuntimeWarning: invalid value encountered in true_divide 
X = np.asfortranarray(X / np.tile(np.sqrt((X *
X).sum(axis=0)),(X.shape[0],1)),dtype=np.float64)
/usr/local/lib/python3.4/dist-packages/numpy/core/fromnumeric.py:2699:
VisibleDeprecationWarning: `rank` is deprecated; use the `ndim`
attribute or function instead. To find the rank of a matrix see
`numpy.linalg.matrix_rank`.   VisibleDeprecationWarning)

Input Image that I have used here =>

enter image description here

Sudip Das
  • 1,178
  • 1
  • 9
  • 24
  • 1
    I think you have a zero (or nan/inf) in the divisor. I don't think this has anything to do with `np.asfortranarray`. Please also share some sample input so we can _actually_ verify the code. – MSeifert Mar 08 '17 at 18:53
  • @MSeifert I am uploading the pic that i Have used there – Sudip Das Mar 08 '17 at 18:57
  • Tell us about the expression inside the `asfortran`, `X / np.tile(np.sqrt((X * X).sum(axis=0))`. shape, dtype, whether it runs, etc. – hpaulj Mar 08 '17 at 20:31

1 Answers1

2

Let's guess the X somehow represents an image, and has a 'white' border:

In [127]: X=np.zeros((10,10))
In [128]: X[3:8,3:8]=1
 ....
In [130]: np.sqrt(X*X).sum(axis=0)
Out[130]: array([ 0.,  0.,  0.,  5.,  5.,  5.,  5.,  5.,  0.,  0.])

The tiled division could easily contain 0s, and produce the runtime warning:

In [134]: X/np.tile(np.sqrt((X * X).sum(axis=0)),(X.shape[0],1))
/usr/local/bin/ipython3:1: RuntimeWarning: invalid value encountered in true_divide
  #!/usr/bin/python3
Out[134]: 
array([[       nan,        nan,        nan,  0.       ,  0.       ,
         0.       ,  0.       ,  0.       ,        nan,        nan],
       [       nan,        nan,        nan,  0.       ,  0.       ,
         0.       ,  0.       ,  0.       ,        nan,        nan],
            ...     ,
         0.       ,  0.       ,  0.       ,        nan,        nan]])

I don't know why it's using asfortranarray(), but I don't get any further errors from that.

VisibleDeprecationWarning in python

is an example of posts asking about this VisibleDeprecationWarning. Theres is a np.rank function:

In [138]: np.rank(X)
/usr/local/bin/ipython3:1: VisibleDeprecationWarning: `rank` is deprecated; use the `ndim` attribute or function instead. To find the rank of a matrix see `numpy.linalg.matrix_rank`.
  #!/usr/bin/python3

Some old or obscure piece of code is using rank instead of ndim.

I'm tempted to blame asfortranarray, which I haven't seen used before. But its current code is only:

return array(a, dtype, copy=False, order='F', ndmin=1)

which shouldn't have obscure corners hiding a rank call.

I think we need to know more about X, esp it's shape and dtype. Maybe also its strides. im2col_sliding suggests it's a sliding window array generated with as_strided.

Community
  • 1
  • 1
hpaulj
  • 221,503
  • 14
  • 230
  • 353