如何使用感知器找到近似多项式

问题描述 投票:0回答:1

我想使用二次多项式将 cos(x) 从 0 近似到 pi/4。

我相信我可以使用我的范围内的(比如 1000)个点,训练输入 (x^2, x, 1) 和训练输出 sigmoid(cos(x)) 来训练感知器。然后,神经元的权重将是多项式的系数(即 w1x^2 + w2x + w3)

这是我的尝试(但它没有收敛)

import numpy
import matplotlib.pyplot as plt
import random
import math
#Generate random points in range
R = [random.uniform(0, math.pi/4) for i in range(1000)]

def sigmoid(x):
    return 1.0/(1.0 + numpy.exp(-x))

def sigmoid_prime(x):
    return sigmoid(x)*(1 - sigmoid(x))

#Generate training inputs
training_inputs = numpy.ones((len(R), 3))
for index, x in enumerate(R):
    training_inputs[index, 0] = x**2
    training_inputs[index, 1] = x

#Generate training outputs
training_outputs = numpy.array([sigmoid(math.cos(i)) for i in R]).reshape(len(R), 1)

#Arbitrary weights
weights = numpy.ones((3, 1))

#Neural Network
def train_nn(training_inputs, training_outputs, initial_weights, niter, errors_data):
    w = initial_weights
    for ii in range(niter):
        #forward propagation
        outputs = sigmoid(numpy.dot(training_inputs, w))
        #backward propagation
        errors = training_outputs - outputs
        deltaw = errors*sigmoid_prime(outputs)
        deltaw = numpy.dot(training_inputs.T, deltaw)
        w += deltaw
        #save errors
        errors_data[ii] = errors.reshape(len(R),)
    return outputs, w


NITER = 5000
errors = numpy.zeros((NITER, len(R)))
outputs, weights = train_nn(training_inputs, training_outputs, weights, NITER, errors)

#coefficients
print(weights)


python polynomials approximation perceptron
1个回答
0
投票

您似乎错过了一些学习率,这意味着在您的情况下它是 1。这太高了。当学习率设置得太高时,优化算法(在您的情况下是梯度下降)可能会发散、超过最小值或振荡。 所以通过一些因素更新你的权重< 1, like this:

w += 0.01*deltaw

# how intensive update the weights
learning_rate = 0.01

#Neural Network
def train_nn(training_inputs, training_outputs, initial_weights, niter, errors_data):
    w = initial_weights
    for ii in range(niter):
        #forward propagation
        outputs = sigmoid(numpy.dot(training_inputs, w))
        #backward propagation
        errors = training_outputs - outputs
        deltaw = errors*sigmoid_prime(outputs)
        deltaw = numpy.dot(training_inputs.T, deltaw)
        w += learning_rate*deltaw # updated line
        #save errors
        errors_data[ii] = errors.reshape(len(R),)
    return outputs, w

建议:

  1. 从数学上讲,你应该移动到梯度的负方向,而不是正方向,但由于其中一个梯度是负的,所以从技术上来说它是正确的。每行都有正确的数学公式会更清楚,如下所示:

    deltaw = -numpy.dot(training_inputs.T, deltaw)

    w -= deltaw

  2. 如果你想将其扩展到 cos(x) 的全范围,即从 0 到 pi 的近似值,那么 sigmoid 激活函数还不够,因为它的范围是 0 到 1,但 cos(x) 的范围是 - 1 比 1,所以你可以尝试使用双曲正切函数。

  3. 所得权重将与泰勒多项式的二阶不同。如果没有 sigmoid 函数,您不能单独使用它们(如果这是您的最初意图)。相反,您可以简单地使用线性回归和多项式特征。

© www.soinside.com 2019 - 2024. All rights reserved.