Search code examples
pythonnumpyscipy-optimize

Error: 'numpy.ndarray' object has no attribute 'exp'


I am using the scipy.optimize.fsolve function with the following code:

I am trying to solve the obj function for the value of x_1 keeping the value of x_2 constant. It should be noted that value of x_1 and x_2 are between 0 and 1. I am adding the value of w_xx, b_xx and y_test.

import numpy as np
from scipy.optimize import fsolve
y_test = np.array([3.448 ,11.071,3.602 ,11.838,3.512 ,13.78,4.013,15.209,3.339,13.15,3.387,17.419,3.793,15.303,3.92,11.683,3.655 ,14.317]).reshape(9,2)
#weight matrix
w_01 = np.array([0.5524624,0.72511494,0.51372594,-0.6308459]).reshape(2,2)
w_T2 = np.array([[-0.59752214, -0.5804831,   1.4108963,  -0.2634158,  -0.5614638,  -1.0390981, 0.65243214,  0.7106961, -0.5652963,  -0.0601576,   0.90772694, -1.3798463,  -0.40833127, -0.7003734, -0.21786042,  0.27037245]]).reshape(2,8)
w_02 = np.transpose(w_T2)
w_03 = np.array([[-1.0097426,0.32732514,0.24015452,-1.0950012,0.24607354,-0.21128657,-0.89929247,0.5828309,-1.4573368,-1.0770408,0.62045175,-1.2865094,-1.3986484,-1.2846812, 0.9638692 ,1.5144163]]).reshape(2,8)
#Bais matrix
b_01 = np.array([0.859291,0.59829414]).reshape(2,1)
b_02 = np.array([-0.5619188,-0.57078356,0.5717453,-0.5602762,-0.61745477,-0.6130685,0.56874627,0.55697656]).reshape(8,1)
b_03 = np.array([0.23421602,0.48550755]).reshape(2,1)
def sigmoid(x):
    return 1 / (1 + np.exp(-x))
### Defining Obj function
### inp is 2x1 matrix and out is also 2x1 matrix
def objfunction(x1,x2,y):
    inp = np.array([x1,x2]).reshape(2,1)
    out = y.reshape(2,1)
    f = (np.dot(w_03,(np.dot(w_02,(sigmoid(np.dot(w_01,inp) + b_01))) + b_02)) + b_03) - out # value of y
    return f.flatten()
### Calculating Solution
x_1 = 0 ### Inital guess
x_2 = 0.5 
sol = np.zeros((len(y_test),2))
for i,value in enumerate(y_test):
    sol[i] = fsolve(objfunction,x_1,args=(x_2,value))

Error:

p:\python\mimo_fsolve.py:46: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
  inp = np.array([x1,x2]).reshape(2,1)

AttributeError: 'numpy.ndarray' object has no attribute 'exp'

loop of ufunc does not support argument 0 of type numpy.ndarray which has no callable exp method

Solution

  • To answer your main question, the reason you're getting this error is because fsolve is providing objfunction with a numpy array that looks like np.array([x1]) for x1. When you try and combine this with x2, which is a float, to make inp, you create a ragged array since the first element is an array and the second element is just a number. Numpy doesn't like that so it turns the array into an object data type. You can see this if you try the following code:

    print(np.array([np.array([0]), 0]).dtype) # object
    

    When you then try and do np.exp on the object array (because inp is an object data type, np.dot(w_01, inp) + b_01 will also be), numpy throws an error because there is no implementation for np.exp on object arrays (reread the error and you'll see that that is what the error says).

    To fix this, you can replace x1 in your inp definition with x1[0]. But you'll end up with another issue because you're returning f.flatten(), which will be of shape (2,) since it contains x2 while fsolve was expecting the return to be (1,) since that's what it gave the function. You can fix that by taking the first element (i.e. f.flatten()[0]). The last issue is that you defined sol to be (n,2), but you only seem to want to store x_1, so just make it a 1D array.

    def objfunction(x1, x2, y):
        inp = np.array([x1[0], x2]).reshape(2, 1)
        out = y.reshape(2, 1)
        f = (np.dot(w_03, (np.dot(w_02, (sigmoid(np.dot(w_01, inp) + b_01))) +
             b_02)) + b_03) - out  # value of y
        return f.flatten()[0]
    
    
    x_1 = 0  # Inital guess
    x_2 = 0.5
    sol = np.zeros((len(y_test)))
    for i, value in enumerate(y_test):
        sol[i] = fsolve(objfunction, x_1, args=(x_2, value))