3 层神经网络陷入局部最小值
3-Layer Neural Network Getting Stuck in Local Minima
我在 Python 中编写了一个基于 this tutorial 的 3 层神经网络来玩剪刀石头布,样本数据使用 -1 rock,0 用于 paper,1 用于 scissors,以及与教程中类似的数组。我的功能似乎在每个 运行 时都陷入了相对最小值,我正在寻找一种方法来解决这个问题。程序如下。
#math module
import numpy as np
#sigmoid function converts numbers to percentages(between 0 and 1)
def nonlin(x, deriv = False):
if (deriv == True): #sigmoid derivative is just
return x*(1-x)#output * (output - 1)
return 1/(1+np.exp(-x)) #print the sigmoid function
#input data: using MOCK RPS DATA, -1:ROCK, 0:PAPER, 1:SCISSORS
input_data = np.array([[1, 1, 1],
[0, 0, 0],
[-1, -1, -1],
[-1, 1, -1]])
#also for training
output_data = np.array([[1],
[0],
[-1],
[1]])
#random numbers to not get stuck in local minima for fitness
np.random.seed(1)
#create random weights to be trained in loop
firstLayer_weights = 2*np.random.random((3, 4)) - 1 #size of matrix
secondLayer_weights = 2*np.random.random((4, 1)) - 1
for value in xrange(60000): # loops through training
#pass input through weights to output: three layers
layer0 = input_data
#layer1 takes dot product of the input and weight matrices, then maps them to sigmoid function
layer1 = nonlin(np.dot(layer0, firstLayer_weights))
#layer2 takes dot product of layer1 result and weight matrices, then maps the to sigmoid function
layer2 = nonlin(np.dot(layer1, secondLayer_weights))
#check computer predicted result against actual data
layer2_error = output_data - layer2
#if value is a factor of 10,000, so six times (out of 60,000),
#print how far off the predicted value was from the data
if value % 10000 == 0:
print "Error:" + str(np.mean(np.abs(layer2_error))) #average error
#find out how much to re-adjust weights based on how far off and how confident the estimate
layer2_change = layer2_error * nonlin(layer2, deriv = True)
#find out how layer1 led to error in layer 2, to attack root of problem
layer1_error = layer2_change.dot(secondLayer_weights.T)
#^^sends error on layer2 backwards across weights(dividing) to find original error: BACKPROPAGATION
#same thing as layer2 change, change based on accuracy and confidence
layer1_change = layer1_error * nonlin(layer1, deriv=True)
#modify weights based on multiplication of error between two layers
secondLayer_weights = secondLayer_weights + layer1.T.dot(layer2_change)
firstLayer_weights = firstLayer_weights + layer0.T.dot(layer1_change)
可以看到,这部分是涉及到的数据:
input_data = np.array([[1, 1, 1],
[0, 0, 0],
[-1, -1, -1],
[-1, 1, -1]])
#also for training
output_data = np.array([[1],
[0],
[-1],
[1]])
权重在这里:
firstLayer_weights = 2*np.random.random((3, 4)) - 1 #size of matrix
secondLayer_weights = 2*np.random.random((4, 1)) - 1
似乎在第一千代之后,权重在剩余的编译过程中以最低效率纠正,这让我相信它们已经达到了相对最小值,如下所示:
纠正此问题的快速有效替代方法是什么?
每次迭代后给权重添加一点噪声。这将使您的程序脱离局部最小值并进行改进(如果可能)。有很多关于这方面的文献。在 http://paper.ijcsns.org/07_book/200705/20070513.pdf.
中查找示例
您的网络的一个问题是输出(layer2
的元素的值)只能在 0 和 1 之间变化,因为您使用的是 S 型非线性。由于您的四个目标值之一是 -1,而最接近的可能预测是 0,因此总会有至少 25% 的误差。这里有一些建议:
对输出使用 one-hot 编码:即具有三个输出节点——每个节点对应 ROCK
、PAPER
和 SCISSORS
——并训练网络计算这些输出的概率分布(通常使用 softmax 和 cross-entropy 损失)。
将网络的输出层设为线性层(应用权重和偏差,但不是非线性层)。添加另一层,或从当前输出层中移除非线性。
您可以尝试的其他事情,但不太可能可靠地工作,因为您实际上是在处理分类数据而不是连续输出:
缩放数据,使训练数据中的所有输出都在 0 和 1 之间。
使用 non-linearity 生成介于 -1 和 1 之间的值(例如 tanh)。
我在 Python 中编写了一个基于 this tutorial 的 3 层神经网络来玩剪刀石头布,样本数据使用 -1 rock,0 用于 paper,1 用于 scissors,以及与教程中类似的数组。我的功能似乎在每个 运行 时都陷入了相对最小值,我正在寻找一种方法来解决这个问题。程序如下。
#math module
import numpy as np
#sigmoid function converts numbers to percentages(between 0 and 1)
def nonlin(x, deriv = False):
if (deriv == True): #sigmoid derivative is just
return x*(1-x)#output * (output - 1)
return 1/(1+np.exp(-x)) #print the sigmoid function
#input data: using MOCK RPS DATA, -1:ROCK, 0:PAPER, 1:SCISSORS
input_data = np.array([[1, 1, 1],
[0, 0, 0],
[-1, -1, -1],
[-1, 1, -1]])
#also for training
output_data = np.array([[1],
[0],
[-1],
[1]])
#random numbers to not get stuck in local minima for fitness
np.random.seed(1)
#create random weights to be trained in loop
firstLayer_weights = 2*np.random.random((3, 4)) - 1 #size of matrix
secondLayer_weights = 2*np.random.random((4, 1)) - 1
for value in xrange(60000): # loops through training
#pass input through weights to output: three layers
layer0 = input_data
#layer1 takes dot product of the input and weight matrices, then maps them to sigmoid function
layer1 = nonlin(np.dot(layer0, firstLayer_weights))
#layer2 takes dot product of layer1 result and weight matrices, then maps the to sigmoid function
layer2 = nonlin(np.dot(layer1, secondLayer_weights))
#check computer predicted result against actual data
layer2_error = output_data - layer2
#if value is a factor of 10,000, so six times (out of 60,000),
#print how far off the predicted value was from the data
if value % 10000 == 0:
print "Error:" + str(np.mean(np.abs(layer2_error))) #average error
#find out how much to re-adjust weights based on how far off and how confident the estimate
layer2_change = layer2_error * nonlin(layer2, deriv = True)
#find out how layer1 led to error in layer 2, to attack root of problem
layer1_error = layer2_change.dot(secondLayer_weights.T)
#^^sends error on layer2 backwards across weights(dividing) to find original error: BACKPROPAGATION
#same thing as layer2 change, change based on accuracy and confidence
layer1_change = layer1_error * nonlin(layer1, deriv=True)
#modify weights based on multiplication of error between two layers
secondLayer_weights = secondLayer_weights + layer1.T.dot(layer2_change)
firstLayer_weights = firstLayer_weights + layer0.T.dot(layer1_change)
可以看到,这部分是涉及到的数据:
input_data = np.array([[1, 1, 1],
[0, 0, 0],
[-1, -1, -1],
[-1, 1, -1]])
#also for training
output_data = np.array([[1],
[0],
[-1],
[1]])
权重在这里:
firstLayer_weights = 2*np.random.random((3, 4)) - 1 #size of matrix
secondLayer_weights = 2*np.random.random((4, 1)) - 1
似乎在第一千代之后,权重在剩余的编译过程中以最低效率纠正,这让我相信它们已经达到了相对最小值,如下所示:
纠正此问题的快速有效替代方法是什么?
每次迭代后给权重添加一点噪声。这将使您的程序脱离局部最小值并进行改进(如果可能)。有很多关于这方面的文献。在 http://paper.ijcsns.org/07_book/200705/20070513.pdf.
中查找示例您的网络的一个问题是输出(layer2
的元素的值)只能在 0 和 1 之间变化,因为您使用的是 S 型非线性。由于您的四个目标值之一是 -1,而最接近的可能预测是 0,因此总会有至少 25% 的误差。这里有一些建议:
对输出使用 one-hot 编码:即具有三个输出节点——每个节点对应
ROCK
、PAPER
和SCISSORS
——并训练网络计算这些输出的概率分布(通常使用 softmax 和 cross-entropy 损失)。将网络的输出层设为线性层(应用权重和偏差,但不是非线性层)。添加另一层,或从当前输出层中移除非线性。
您可以尝试的其他事情,但不太可能可靠地工作,因为您实际上是在处理分类数据而不是连续输出:
缩放数据,使训练数据中的所有输出都在 0 和 1 之间。
使用 non-linearity 生成介于 -1 和 1 之间的值(例如 tanh)。