为距离度量通用公式创建 Python 类并收到错误“NameError: name 'p' is not defined”

时间:2021-07-30 17:10:01

标签: python undefined formula nameerror defined

我正在 Python 中为距离度量通用公式创建一个类,但出现错误:“NameError: name 'p' is not defined”。类和测试的代码和错误(“NameError: name 'p' is not defined”)如下以及描述问题的内联注释。

这是该类的代码:

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

1 个答案:

答案 0 :(得分:0)

您的代码失败,因为当您调用 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