在逻辑回归的背景下理解 np.where()

Understanding np.where() in the context of Logistic Regression

我目前正在学习 Andrew Ng 在 Coursera 上教授的深度学习专业。在第一个作业中,我必须定义一个预测函数,并想知道我的替代解决方案是否与实际解决方案一样有效。

请告诉我我对 np.where() 函数的理解是否正确,因为我在 "ALTERNATIVE SOLUTION COMMENTS" 下的代码中对此进行了评论。另外,如果我在 "ACTUAL SOLUTION COMMENTS" 下的理解也能得到检查,我们将不胜感激。

当我尝试将 X 当前数量 (m = 3) 中 examples/inputs 的数量增加到 4、5 和时,使用 np.where() 的替代解决方案也有效依此类推

让我知道您的想法,以及两种解决方案是否一样好!谢谢。

def predict(w, b, X):
    '''
    Predict whether the label is 0 or 1 using learned logistic regression parameters (w, b)

    Arguments:
    w -- weights, a numpy array of size (num_px * num_px * 3, 1)
    b -- bias, a scalar
    X -- data of size (num_px * num_px * 3, number of examples)

    Returns:
    Y_prediction -- a numpy array (vector) containing all predictions (0/1) for the examples in X
    '''

    m = X.shape[1]
    Y_prediction = np.zeros((1,m))    # Initialize Y_prediction as an array of zeros 
    w = w.reshape(X.shape[0], 1)

    # Compute vector "A" predicting the probabilities of a cat being present in the picture
    ### START CODE HERE ### (≈ 1 line of code)
    A = sigmoid(np.dot(w.T, X) + b)   # Note: The shape of A will always be a (1,m) row vector
    ### END CODE HERE ###

    for i in range(A.shape[1]):       # for i in range(# of examples in A = # of examples in our set)

        # Convert probabilities A[0,i] to actual predictions p[0,i]
        ### START CODE HERE ### (≈ 4 lines of code)
        Y_prediction[0, i] = 1 if A[0, i] > 0.5 else 0

        ''' 
        ACTUAL SOLUTION COMMENTS: 

        The above reads as:

        Change/update the i-th value of Y_prediction to 1 if the corresponding i-th value in A is > 0.5. 
        Otherwise, change/update the i-th value of Y_prediction to 0. 

        '''


        ''' 
        ALTERNATIVE SOLUTION COMMENTS:

        To condense this code, you could delete the for loop and Y_prediction var from the top, 
        and then use the following one line: 

        return np.where(A > 0.5, np.ones((1,m)), np.zeros((1,m))) 

        This reads as: 
        Given the condition > 0.5, return np.ones((1,m)) if True, 
        or return np.zeros((1,m)) if False. 

        Another way to understand this is as follows:
        Tell me where in the array A, entries satisfies the condition A > 0.5,
        At those positions, give me np.ones((1,m)), otherwise, give me 
        np.zeros((1,m))

        '''
        ### END CODE HERE ###

    assert(Y_prediction.shape == (1, m))

    return Y_prediction

w = np.array([[0.1124579],[0.23106775]])
b = -0.3
X = np.array([[1.,-1.1,-3.2],[1.2,2.,0.1]])
print(sigmoid(np.dot(w.T, X) + b))
print ("predictions = " + str(predict(w, b, X)))   # Output gives 1,1,0 as expected

您的替代方法似乎不错。作为说明,我要补充一点,您甚至不需要 np.onesnp.zeros,您可以直接指定整数 01。使用 np.where 时,只要 Xy(根据条件替换的值)和相同的条件可广播,它应该可以正常工作。 这是一个简单的例子:

y_pred = np.random.rand(1,6).round(2)
# array([[0.53, 0.54, 0.68, 0.34, 0.53, 0.46]])
np.where(y_pred> 0.5, np.ones((1,6)), np.zeros((1,6)))
# array([[1., 1., 1., 0., 1., 0.]])

并使用整数:

np.where(y_pred> 0.5,1,0)
# array([[1, 1, 1, 0, 1, 0]])

根据您对函数工作原理的评论,它确实按照您描述的那样工作。也许只是代替 To condense this code,我认为使用 numpy 可以使其更高效,并且在这种情况下也更容易理解。