无法逼近具有 1 个隐藏层的神经网络中的简单乘法函数
Can't approximate simple multiplication function in neural network with 1 hidden layer
我只是想测试神经网络逼近乘法函数(回归任务)的效果如何。
我正在使用 Azure 机器学习工作室。我有 6500 个样本,1 个隐藏层
(我已经测试了每个隐藏层 5 /30 /100 个神经元),没有归一化。和默认参数
学习率 - 0.005,学习迭代次数 - 200,初始学习权重 - 0.1,
动量 - 0 [描述]。我的准确性非常差,接近于 0。
同时提升决策森林回归显示出非常好的近似。
我做错了什么?这个任务对NN来说应该很容易。
一些要检查的东西:
- 你的输出层应该有一个线性激活函数。如果它是 sigmoidal,它将无法表示超出其范围的值(例如 -1 到 1)
- 您应该使用适合回归的损失函数(例如平方误差)
- 如果您的隐藏层使用 sigmoidal 激活函数,请检查您没有使它们饱和。乘法可以作用于任意 small/large 个值。而且,如果您将大量数字作为输入传递,您可能会饱和,这会丢失信息。如果使用 ReLU,请确保它们不会在所有示例中都停留在 0(尽管在任何给定示例中激活通常都是稀疏的)。
- 检查您的培训程序是否按预期进行。绘制训练期间随时间变化的误差。它看起来如何?您的梯度表现良好还是正在爆炸?问题的来源之一可能是学习率设置得太高(不稳定的错误,梯度爆炸)或太低(进展非常缓慢,错误没有足够快地减少)。
大乘法函数梯度迫使网络几乎立即进入某种可怕的状态,其中所有隐藏节点的梯度都为零。
我们可以使用两种方法:
1) 按常数除法。我们只是在学习之前除掉一切,然后乘以。
2) 进行对数归一化。它将乘法变成加法:
m = x*y => ln(m) = ln(x) + ln(y).
m = x*y => ln(m) = ln(x) + ln(y), 但前提是 x, y > 0
"Two approaches: divide by constant, or make log normalization"
两种方法我都试过了。当然,日志规范化是有效的,因为正如您正确指出的那样,它会强制执行加法。除以常数——或类似地在任何范围内标准化——在我的广泛测试中似乎没有成功。
对数方法很好,但如果您有两个数据集,其中包含一组输入和一个目标 y 值,其中:
在数据集一中,目标始终是两个输入的总和
在数据集二中,目标始终是两个输入的乘积
那么我不清楚如何设计一个使用反向传播在两个数据集中找到目标 y 的神经网络。如果这不可能,那么我发现神经网络找到 "an approximation to any function" 的能力存在令人惊讶的限制。但是我是这个游戏的新手,我的期望可能不切实际。
这是一种使用一个隐藏层来近似乘法函数的方法。它在隐藏层使用 sigmoidal 激活,并且在一定范围内的数字之前效果很好。这是gist link
这是我用神经网络做乘法的方法:
import numpy as np
from keras import layers
from keras import models
model = models.Sequential()
model.add(layers.Dense(150, activation='relu', input_shape=(2,)))
model.add(layers.Dense(1, activation='relu'))
data = np.random.random((10000, 2))
results = np.asarray([a * b for a, b in data])
model.compile(optimizer='sgd', loss='mae')
model.fit(data, results, epochs=1, batch_size=1)
model.predict([[0.8, 0.5]])
有效。
我只是想测试神经网络逼近乘法函数(回归任务)的效果如何。 我正在使用 Azure 机器学习工作室。我有 6500 个样本,1 个隐藏层 (我已经测试了每个隐藏层 5 /30 /100 个神经元),没有归一化。和默认参数 学习率 - 0.005,学习迭代次数 - 200,初始学习权重 - 0.1, 动量 - 0 [描述]。我的准确性非常差,接近于 0。 同时提升决策森林回归显示出非常好的近似。
我做错了什么?这个任务对NN来说应该很容易。
一些要检查的东西:
- 你的输出层应该有一个线性激活函数。如果它是 sigmoidal,它将无法表示超出其范围的值(例如 -1 到 1)
- 您应该使用适合回归的损失函数(例如平方误差)
- 如果您的隐藏层使用 sigmoidal 激活函数,请检查您没有使它们饱和。乘法可以作用于任意 small/large 个值。而且,如果您将大量数字作为输入传递,您可能会饱和,这会丢失信息。如果使用 ReLU,请确保它们不会在所有示例中都停留在 0(尽管在任何给定示例中激活通常都是稀疏的)。
- 检查您的培训程序是否按预期进行。绘制训练期间随时间变化的误差。它看起来如何?您的梯度表现良好还是正在爆炸?问题的来源之一可能是学习率设置得太高(不稳定的错误,梯度爆炸)或太低(进展非常缓慢,错误没有足够快地减少)。
大乘法函数梯度迫使网络几乎立即进入某种可怕的状态,其中所有隐藏节点的梯度都为零。 我们可以使用两种方法:
1) 按常数除法。我们只是在学习之前除掉一切,然后乘以。
2) 进行对数归一化。它将乘法变成加法:
m = x*y => ln(m) = ln(x) + ln(y).
m = x*y => ln(m) = ln(x) + ln(y), 但前提是 x, y > 0
"Two approaches: divide by constant, or make log normalization"
两种方法我都试过了。当然,日志规范化是有效的,因为正如您正确指出的那样,它会强制执行加法。除以常数——或类似地在任何范围内标准化——在我的广泛测试中似乎没有成功。
对数方法很好,但如果您有两个数据集,其中包含一组输入和一个目标 y 值,其中:
在数据集一中,目标始终是两个输入的总和
在数据集二中,目标始终是两个输入的乘积
那么我不清楚如何设计一个使用反向传播在两个数据集中找到目标 y 的神经网络。如果这不可能,那么我发现神经网络找到 "an approximation to any function" 的能力存在令人惊讶的限制。但是我是这个游戏的新手,我的期望可能不切实际。
这是一种使用一个隐藏层来近似乘法函数的方法。它在隐藏层使用 sigmoidal 激活,并且在一定范围内的数字之前效果很好。这是gist link
这是我用神经网络做乘法的方法:
import numpy as np
from keras import layers
from keras import models
model = models.Sequential()
model.add(layers.Dense(150, activation='relu', input_shape=(2,)))
model.add(layers.Dense(1, activation='relu'))
data = np.random.random((10000, 2))
results = np.asarray([a * b for a, b in data])
model.compile(optimizer='sgd', loss='mae')
model.fit(data, results, epochs=1, batch_size=1)
model.predict([[0.8, 0.5]])
有效。