【问题标题】:Python ReLu activation function desn't workPython ReLu 激活函数不起作用
【发布时间】:2018-05-23 09:40:30
【问题描述】:

我的第一个神经网络使用了 sigmoid 激活函数并且运行良好。现在我想切换到更高级的激活函数(ReLu)。但是使用 ReLu,我的 NN 根本不起作用。 90% 的错误,而使用 sigmoid 有 4% 的错误。我在代码中找不到错误。帮帮我。

class NeuralNetwork:
    def __init__(self, input_nodes, hidden_nodes, output_nodes, learning_rate = 0.1):
        self.input_nodes = input_nodes
        self.hidden_nodes = hidden_nodes
        self.output_nodes = output_nodes
        self.learning_rate = learning_rate

        self.weights_ih = np.random.normal(0.0, pow(input_nodes, -0.5), (hidden_nodes, input_nodes))
        self.weights_ho = np.random.normal(0.0, pow(hidden_nodes, -0.5), (output_nodes, hidden_nodes))
        self.bias_h = np.random.normal(0.0, pow(1, -0.5), (hidden_nodes, 1))
        self.bias_o = np.random.normal(0.0, pow(1, -0.5), (output_nodes, 1))

    def activation_function(self, x):
        return x * (x > 0)

    def activation_function_d(self, x):
        return 1 * (x >= 0)

    def train(self, inputs_list, targets_list):
        inputs = np.array(inputs_list, ndmin=2).T
        targets = np.array(targets_list, ndmin=2).T

        # Feedforward
        hidden_inputs = np.dot(self.weights_ih, inputs) + self.bias_h
        hidden = self.activation_function(hidden_inputs)
        output_inputs = np.dot(self.weights_ho, hidden) + self.bias_o
        outputs = self.activation_function(output_inputs)

        # Calculate errors
        output_errors = targets - outputs
        hidden_errors = np.dot(self.weights_ho.T, output_errors)

        # Calculate gradients
        output_gradient = output_errors * self.activation_function_d(output_inputs) * self.learning_rate
        hidden_gradient = hidden_errors * self.activation_function_d(hidden_inputs) * self.learning_rate

        # Calculate deltas
        output_deltas = np.dot(output_gradient, hidden.T)
        hidden_deltas = np.dot(hidden_gradient, inputs.T)

        # Adjust weights and biases by deltas and gradients
        self.weights_ho += output_deltas
        self.weights_ih += hidden_deltas
        self.bias_o     += output_gradient
        self.bias_h     += hidden_gradient

    def predict(self, inputs_list):
        inputs = np.array(inputs_list, ndmin=2).T
        hidden = self.activation_function(np.dot(self.weights_ih, inputs) + self.bias_h)
        outputs = self.activation_function(np.dot(self.weights_ho, hidden) + self.bias_o)
        return outputs.flatten().tolist()

以及训练代码:

with open('mnist_train.csv') as train_file:
    for str in train_file:
        data = [int(char) for char in str.split(',')]
        inputs = data[1:]
        targets = [1 if i == data[0] else 0 for i in range(10)]
        nn.train(inputs, targets)

【问题讨论】:

    标签: python numpy neural-network relu


    【解决方案1】:

    无论您尝试做什么,最后一层都应始终使用 sigmoid(在二进制情况下)。

    sigmoid函数用于估计一个例子在给定类中的概率,一个例子的预测是这个例子最有可能在的那个类。

    总之,改变这个:

    def predict(self, inputs_list):
        inputs = np.array(inputs_list, ndmin=2).T
        hidden = self.activation_function(np.dot(self.weights_ih, inputs) + self.bias_h)
        outputs = self.activation_function(np.dot(self.weights_ho, hidden) + self.bias_o)
        return outputs.flatten().tolist()
    

    到这里

    def predict(self, inputs_list):
        inputs = np.array(inputs_list, ndmin=2).T
        hidden = self.activation_function(np.dot(self.weights_ih, inputs) + self.bias_h)
        outputs = sigmoid(np.dot(self.weights_ho, hidden) + self.bias_o) // create a sigmoid function
        return outputs.flatten().tolist()
    

    在训练中:

        # Feedforward
        hidden_inputs = np.dot(self.weights_ih, inputs) + self.bias_h
        hidden = self.activation_function(hidden_inputs)
        output_inputs = np.dot(self.weights_ho, hidden) + self.bias_o
        outputs = self.activation_function(output_inputs)
    

    到:

        # Feedforward
        hidden_inputs = np.dot(self.weights_ih, inputs) + self.bias_h
        hidden = self.activation_function(hidden_inputs)
        output_inputs = np.dot(self.weights_ho, hidden) + self.bias_o
        outputs = sigmoid(output_inputs)
    

        # Calculate gradients
        output_gradient = output_errors * self.activation_function_d(output_inputs) * self.learning_rate
        hidden_gradient = hidden_errors * self.activation_function_d(hidden_inputs) * self.learning_rate
    

           # Calculate gradients
        output_gradient = output_errors * sigmoid_d(output_inputs) * self.learning_rate
        hidden_gradient = hidden_errors * self.activation_function_d(hidden_inputs) * self.learning_rate
    

    【讨论】:

    • 为什么在计算梯度时,隐藏层使用sigmoid,输出层使用relu?
    • 如果我使用 sigmoid,那么我应该将目标标准化为范围 (0, 1),对吗?如果我使用 ReLu,我应该将输入标准化到某个范围吗?
    • 尝试相同的范围,根据我的经验,它运行良好,但我认为 ReLU 不需要规范化到特定范围
    • 我在输出层用 sigmoid 替换了 ReLu,但得到了 30% 的错误,在第二次训练后,我得到了 50% 的错误。然后再次切换到 sigmoid,得到了 6% 的错误。你能看看我的代码吗?还是谢谢你。 GitHub
    猜你喜欢
    • 2021-08-31
    • 2019-11-16
    • 1970-01-01
    • 2017-05-23
    • 2018-04-17
    • 2021-02-10
    • 2021-07-30
    • 2017-05-06
    • 2018-01-12
    相关资源
    最近更新 更多