Изменение пороговых значений при активации сигмоида в нейронных сетях - PullRequest
0 голосов
/ 21 апреля 2020

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

Я знаю, что значение сигмовидной функции находится в диапазоне [0; 1], 0,5 принимается за порог, если h (theta) <0.5, мы предполагаем, что это значение равно 0, если h (theta)> = 0.5, то это 1.

Пороги используются только на выходном слое сети и только при классификации. Итак, если вы пытаетесь классифицировать 3 класса, можете ли вы дать разные пороги для каждого класса (0,2,0,4,0,4 - для каждого класса)? Или вы можете указать другой порог в целом, например, 0,8? Я не уверен, как определить это в коде ниже. Любое руководство приветствуется.

# Hyper Parameters
input_size = 14
hidden_size = 40
hidden_size2 = 30
num_classes = 3
num_epochs = 600
batch_size = 34
learning_rate = 0.01


class Net(torch.nn.Module):
    def __init__(self, n_input, n_hidden, n_hidden2, n_output):
        super(Net, self).__init__()
        # define linear hidden layer output
        self.hidden = torch.nn.Linear(n_input, n_hidden)
        self.hidden2 = torch.nn.Linear(n_hidden, n_hidden2)
        # define linear output layer output
        self.out = torch.nn.Linear(n_hidden, n_output)

    def forward(self, x):
        """
            In the forward function we define the process of performing
            forward pass, that is to accept a Variable of input
            data, x, and return a Variable of output data, y_pred.
        """
        # get hidden layer input
        h_input1 = self.hidden(x)
        # define activation function for hidden layer
        h_output1 = torch.sigmoid(h_input1)

        # get hidden layer input
        h_input2 = self.hidden2(h_output1)
        # define activation function for hidden layer
        h_output2 = torch.sigmoid(h_input2)

        # get output layer output
        out = self.out(h_output2)

        return out


net = Net(input_size, hidden_size, hidden_size, num_classes)

criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=learning_rate)

all_losses = []

for epoch in range(num_epochs):
    total = 0
    correct = 0
    total_loss = 0
    for step, (batch_x, batch_y) in enumerate(train_loader):
        X = batch_x
        Y = batch_y.long()

    # Forward + Backward + Optimize
    optimizer.zero_grad()  # zero the gradient buffer
    outputs = net(X)
    loss = criterion(outputs, Y)
    all_losses.append(loss.item())
    loss.backward()
    optimizer.step()

    if epoch % 50 == 0:
        _, predicted = torch.max(outputs, 1)
        # calculate and print accuracy
        total = total + predicted.size(0)
        correct = correct + sum(predicted.data.numpy() == Y.data.numpy())
        total_loss = total_loss + loss
    if epoch % 50 == 0:
        print(
            "Epoch [%d/%d], Loss: %.4f, Accuracy: %.2f %%"
            % (epoch + 1, num_epochs, total_loss, 100 * correct / total)
        )

train_input = train_data.iloc[:, :input_size]
train_target = train_data.iloc[:, input_size]

inputs = torch.Tensor(train_input.values).float()
targets = torch.Tensor(train_target.values - 1).long()

outputs = net(inputs)
_, predicted = torch.max(outputs, 1)

Ответы [ 2 ]

1 голос
/ 21 апреля 2020

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

Известно, что нейронные сети часто чрезмерно уверены (например, применяя 0.95 к одному из 50 классов), поэтому может быть полезно использовать другой порог в вашем случае.

С вашей тренировкой все в порядке, но вы должны изменить прогнозы (две последние строки) и использовать torch.nn.softmax следующим образом:

outputs = net(inputs) 
probabilities = torch.nn.functional.softmax(outputs, 1)

Как упоминалось в другом ответе, вы получит каждую строку с вероятностями, суммирующими 1 (ранее у вас были ненормализованные вероятности или логиты).

Теперь просто используйте желаемый порог для этих вероятностей:

predictions = probabilities > 0.8

Обратите внимание, что в некоторых случаях вы можете получить только нули (например, [0.2, 0.3, 0.5]).

Это будет означать, что нейронная сеть недостаточно уверена в соответствии с вашими стандартами и, вероятно, отбросит количество неверных положительных прогнозов ( абстрактно, но, скажем, вы предсказываете, нет ли у пациента одного из взаимоисключающих 3 заболеваний. Лучше сказать так, только если вы действительно уверены). * 10 23 *

Различные пороговые значения для каждого класса

Это можно сделать так же, как это:

thresholds = torch.tensor([0.1, 0.1, 0.8]).unsqueeze(0)
predictions = probabilities > thresholds

Заключительные комментарии

Обратите внимание, в случае softmax только один класс должен быть ответом (как указано в другом ответе), и этот подход (и упоминание о сигмоиде) может указывать, что вы после многолинейной классификации .

Если вы хотите тренировать свой сеть, чтобы он мог одновременно предсказать классы, которые вы должны использовать sigmoid и изменить свой убыток на torch.nn.BCEWithLogitsLoss.

0 голосов
/ 21 апреля 2020

В классификации нескольких классов вы должны иметь выходные данные для каждого класса. Затем вы можете использовать функцию softmax , чтобы нормализовать вывод, поэтому сумма всех их равна 1. Выход с наибольшим значением - это тот, который выбран в качестве классификации.

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