Creating a Python class for the distance metric general formula and getting the error "NameError: name 'p' is not defined"

Creating a Python class for the distance metric general formula and getting the error "NameError: name 'p' is not defined"

我在 Python 中为距离度量通用公式创建了一个 class,但我收到错误:“NameError:名称 'p' 未定义”。 class 和测试的代码以及错误(“NameError:名称 'p' 未定义”)以及描述问题的内联注释如下。

这是 class 的代码:

class Lp_distance_metric_general_formula(object):
"""
This class takes the Lp distance metric general formula and sets p equal to a value provided by the user. 
This has the effect of deriving a distance metric for a specific metric space and calculating the distance 
of a vector in that metric space.

Example
-------
If the user sets p = 2, then the euclidean distance formula is derived.
If the user sets p = 1, then the taxicab distance formula is derived. 

Note
----
It is possible to use p values less than 1 but those are special cases that we will ignore. 
These special values are interesting for academic purposes but in practice you very likely won't need to know 
about them.
"""

def __init__(self, p=2, reg_strength = 1.0):
    
    """
    Parameters
    ----------
    
    p: int or float
        p value used for calculating the distance of a vector in a certain metric space
        
    reg_strength: int or float
        usually set to a value less than 1.0 to decrease the strength of the distance metric when used as a model regularizer
        keep this value at 1.0 when measureing vector norms (i.e. vector lengths)
    """
    
    assert p >=1 , "p value must be greater than or equal to 1"
    
    self.p = p
    self.reg_strength = reg_strength
            
def calc_squared_vector_comps(self):
    
    # raise each vector component in self.x to the power of p
    # save result to self.squared_vector_comps
    # YOUR CODE HERE
    self.squared_vector_comps = (self.x)**p
    
    # raise NotImplementedError()
    
def calc_sum_of_squared_comp(self):
    # take the sum of the squared components in self.squared_vector_comps
    # save to self.sum_of_squared_comp
    # hint: use tf.reduce_sum
    # YOUR CODE HERE
    self.sum_of_squared_comp = tf.reduce_sum(self.squared_vector_comps)
    
    #raise NotImplementedError()
    
def calc_vector_norm(self):
    
    # take the 1/p root of the self.sum_of_squared_comp in order to calculate the norm, i.e. ||x||
    
    # save result to self.vector_norm
    # YOUR CODE HERE
    self.vector_norm = (self.sum_of_squared_comp)**(1/p)
    
    # raise NotImplementedError()
    
    
def __call__(self, x):
    """
    This method calcualtes the distance (i.e. norm) for vector x in Lp space for a value p given by the use
    
    ‖‖ = (|_1|^ + |_2|^ + ⋯ +|_|^ )^1/
    
    Parameters
    ----------
    x: N-dimsional numpy array or tensorflow tensor of floats 
        x is our vector, could be a weight vector but any vector is valid 
        
        
    HINT
    -----
    You must use self.p when calculating squared_vector_comps and vector_norm
    """
    
    self.x = x
    

    
    # calculate these parts |_i|^
    self.calc_squared_vector_comps()
    
    # calcualte this |_1|^ + |_2|^ + ⋯ +|_|^
    self.calc_sum_of_squared_comp()
    
    # calculate this (|_1|^ + |_2|^ + ⋯ +|_|^ )^1/
    self.calc_vector_norm()
    
    # return the vector norm scaled by a regularization penality
    # we say penality because the value is usually less than 1.0 thereby scaling down the norm
    return self.reg_strength * self.vector_norm

测试代码如下:

# instantiate the unit test class that will check the calculates of Lp_distance_metric_general_formula's methods
tests = Test_distance_metric_solution()

# instantiate Lp_distance_metric_general_formula, set p = 2 in order to derive the euclidean distance metric

lp = Lp_distance_metric_general_formula(p=2, reg_strength = 1.0)

# don't change this test_vector
# Test_distance_metric_solution assumes that you're using ths exact test_vector
test_vector = np.array([1., 2.])
lp(test_vector)


# test the calculations that are perform in each of the following lp class methods 
tests.test_squared_vector_comps(lp.squared_vector_comps)
tests.test_sum_of_squared_comp(lp.sum_of_squared_comp)
tests.test_vector_norm(lp.vector_norm.numpy())

下面是整个错误:(最后一行最相关。)

NameError                                 Traceback (most recent call last)
<ipython-input-60-99f65ee9445b> in <module>
      9 # Test_distance_metric_solution assumes that you're using ths exact test_vector
     10 test_vector = np.array([1., 2.])
---> 11 lp(test_vector)
     12 
     13 '''

<ipython-input-59-68f0851b282b> in __call__(self, x)
     87 
     88         # calculate these parts |_i|^
---> 89         self.calc_squared_vector_comps()
     90 
     91         # calcualte this |_1|^ + |_2|^ + ⋯ +|_|^

<ipython-input-59-68f0851b282b> in calc_squared_vector_comps(self)
     41         # save result to self.squared_vector_comps
     42         # YOUR CODE HERE
---> 43         self.squared_vector_comps = (self.x)**p
     44 
     45         # raise NotImplementedError()

NameError: name 'p' is not defined

您的代码失败是因为当您调用 init 时您分配了 self.p = p。当 init 方法完成时,p 值从作用域中消失,但 self.p 仍然存在。

因此,当您需要参考您的 p 值时,您需要参考 self.p。

具体来说:

def calc_vector_norm(self):
    # take the 1/p root of the self.sum_of_squared_comp in order to calculate the norm, i.e. ||x||

    # save result to self.vector_norm
    # YOUR CODE HERE
    self.vector_norm = (self.sum_of_squared_comp) ** (1 / self.p)

def calc_squared_vector_comps(self):
    # raise each vector component in self.x to the power of p
    # save result to self.squared_vector_comps
    # YOUR CODE HERE
    self.squared_vector_comps = (self.x) ** self.p