Задний план:
Я прошел курс машинного обучения и нейронных сетей, и в следующих случаях, когда я столкнулся с проблемой, нам требовалось вычислить функцию стоимости. Есть два способа сделать это, применив np.multiply и np.sum ИЛИ к np.dot. В этом примере я назвал их cost1 и cost2 соответственно. Они дают тот же результат.
Вопрос:
Моя проблема в том, что функция (которая для меня уже завершена) утверждает, что стоимость является плавающей, используя isinstance (). Первый метод выдает значение, которое проходит этот тест, а второй - нет. Однако, когда я печатаю оба значения и связанные с ними dtypes, они оба кажутся числами с плавающей запятой, хотя cost2 имеет большую точность. Почему cost2 не проходит тест на утверждение?
Код:
def compute_cost(A2, Y, parameters):
"""
Computes the cross-entropy cost given in equation (13)
Arguments:
A2 -- The sigmoid output of the second activation, of shape (1, number of examples)
Y -- "true" labels vector of shape (1, number of examples)
parameters -- python dictionary containing your parameters W1, b1, W2 and b2
Returns:
cost -- cross-entropy cost given equation (13)
"""
m = Y.shape[1] # number of example
# Compute the cross-entropy cost
### START CODE HERE ### (≈ 2 lines of code)
logprobs = np.multiply(np.log(A2), Y)
cost1 = -np.sum(logprobs)
cost2 = -np.dot(np.log(A2), Y.T)
### END CODE HERE ###
cost1 = np.squeeze(cost1) # makes sure cost is the dimension we expect.
cost2 = np.squeeze(cost2) # E.g., turns [[17]] into 17
# Troubleshooting
print(cost1.dtype,cost2.dtype)
print(cost1,cost2)
assert(isinstance(cost1, float))
assert(isinstance(cost2, float))
return cost1
A2, Y_assess, parameters = compute_cost_test_case()
print("cost = " + str(compute_cost(A2, Y_assess, parameters)))
Выход:
float64 float64
0.692685886972 0.6926858869721941
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-84-92a25de13cb3> in <module>()
1 A2, Y_assess, parameters = compute_cost_test_case()
2
----> 3 print("cost = " + str(compute_cost(A2, Y_assess, parameters)))
<ipython-input-83-411aa6cb57b7> in compute_cost(A2, Y, parameters)
30
31 assert(isinstance(cost1, float))
---> 32 assert(isinstance(cost2, float))
33
34 return cost1
AssertionError:
Числовые числа с плавающей запятой не являются подклассами Python с плавающей запятой.
np.squeeze вернет массив из многомерного массива. Таким образом, ваш cost2.dtype по-прежнему будет возвращать dtype членов массива, isinstance по-прежнему будет видеть его как массив.
Если cost1 - это массив с одним элементом или np.float64, то cost1.item() будет Python с плавающей запятой.






Хорошо, позвольте мне начать с самого начала.
Первый, и это касается не вопроса, который вы задали, а научного секретариата. np.dot() не всегда равен np.sum and np.multiply, теоретически они равны, но что касается расчета функции затрат, они не будут одинаковыми, так как расчеты np.dot будут отличаться от матрицы к вектору, не говоря уже о том, что это выдаст вам ошибку из-за несоответствия размеров. Поэтому на всякий случай используйте функции умножения и суммирования, и вы можете проверить этот пост для получения дополнительной информации по этому поводу. Реализация функции стоимости в логистической регрессии в Python: почему умножение точек в одном выражении, а поэлементное умножение в другом
Второй, и это ваш исходный вопрос, чтобы разобраться в проблеме, вы должны распечатать всю информацию о cost1 и cost2.
Например, после расчета уравнения стоимости с keepdims = True вы обнаружите, что cost.shape = (), cost.dtype = float64 и type(cost) = numpy.ndarray, которые являются scalar и это твоя проблема здесь.
Функция squeeze может успешно выполнить уменьшение размеров до точки, например, [[.364]] будет .364. Однако .364 будет иметь тип numpy.ndarray.
Итак, чтобы преобразовать scalar в float, вы можете просто сделать это
Решение:
cost = np.asscalar(cost) # make sure to convert scalar with shape () to normal float
Следовательно, ваше утверждение наверняка будет работать нормально.
Вы можете проверить этот вопрос Как преобразовать одноэлементный массив в скалярное значение в Python? и этот тоже Что такое ndarray shape (), возвращаемый после np.squeeze из shape (1,1)?
Показать вывод
print(type(cost1), type(cost2))