Сигмоидная функция возвращает 1 для больших положительных входов - PullRequest
0 голосов
/ 20 сентября 2018

Я написал следующую функцию в Python для вычисления сигмоидальной функции скаляра, вектора или матрицы.

def sigmoid(z):
    sig = 1.0/(1.0 + np.exp(-z))
    return sig

Для относительно больших положительных значений z, e^-z возвращает очень маленькое значение, близкое к нулю(0) и, следовательно, значение sig округляется до 1. Моя конечная цель - определить функцию стоимости алгоритма логистической регрессии.Поскольку сигмоид возвращает ровно 1, log(1-1) возвращает 'nan'.Как я могу решить проблему таким образом, чтобы моя функция sigmoid () вернула правильное значение, а не округлила от e^-z до 0?

Когда я нормализовал входные функции, используя среднее и стандартное отклонение, онработал нормально.Но есть ли способ заставить его работать с большими значениями z?

Кроме того, я попробовал то же самое на Matlab, и он работал нормально без нормализации.

>>> Z = np.array([[60, 100],[20, 80]])
>>> Z
array([[ 60, 100],
       [ 20,  80]])
>>> np.exp(-Z)
array([[8.75651076e-27, 3.72007598e-44],
       [2.06115362e-09, 1.80485139e-35]])
>>> 1.0/(1.0 + np.exp(-Z))
array([[1., 1.],
       [1., 1.]])

Ответы [ 2 ]

0 голосов
/ 26 марта 2019

Я преодолел эту проблему, обернув сигмовидную функцию np.minimum & np.maximum:

def sigmoid(x):
    sig = 1 / (1 + np.exp(-x))     # Define sigmoid function
    sig = np.minimum(sig, 0.9999)  # Set upper bound
    sig = np.maximum(sig, 0.0001)  # Set lower bound
    return sig

В результате мои потери стали выглядеть так

this

Но потери как при обучении, так и при тестировании хорошо сходились, и я получил ~ 90% точности для крошечного набора данных с использованием логистической регрессии.

0 голосов
/ 20 сентября 2018

Как уже упоминалось jdehesa, ваша проблема связана с точностью.Вы можете прочитать больше здесь: https://docs.python.org/2/tutorial/floatingpoint.html

Вы можете попробовать использовать класс Decimal, который избегает округления:

from decimal import Decimal
import numpy as np
import math

def sigmoid(z):
    sig = Decimal(1.0)/(Decimal(1.0) + Decimal(np.exp(-z)))
    return sig


math.log(Decimal(1)-sigmoid(60))
>>> -59.97257293350302

, но это будет работать только до некоторой точки (я вижу, что это уже терпит неудачуза 80).Я немного читал, и если вам действительно нужно больше точности, вы можете изменить точность десятичного объекта, увеличив значение по умолчанию по сравнению со значением по умолчанию 28:

from decimal import *
getcontext().prec = 28 

Подробнее здесь:

https://docs.python.org/2/library/decimal.html

Тем не менее, в большинстве случаев предложение ручной обработки небольших результатов с помощью логической проверки, вероятно, будет наилучшим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...