改进张量流中的异或神经网络并使用密集作为输入层
improving xor neural network in tensorflow and using dense as an input layer
我正在尝试在 tf 中构建一个神经网络作为初学者的挑战,我的模型不是很好,这意味着很多时候它不会很准确(虽然有时准确度是 1,但大多数时候它不是' t,即使那样损失也很大。
所以我有两个问题:
- 我该如何改进这个 NN?
- 使用
Input
作为输入层和使用Dense
有什么区别?
代码如下:
import tensorflow as tf
from tensorflow import keras
model = keras.Sequential()
model.add(tf.keras.Input(shape=(2,)))
#model.add(keras.layers.Dense(2))
model.add(keras.layers.Dense(4, activation='relu'))
model.add(keras.layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam',
loss=tf.losses.BinaryCrossentropy(),
metrics=['accuracy'])
# X_train, Y_train = ([[0, 0], [0, 1], [1, 0], [1, 1]], [[0], [1], [1], [0]])
X_train = tf.cast([[0, 0], [0, 1], [1, 0], [1, 1]], tf.float32)
Y_train = tf.cast([0, 1, 1, 0], tf.float32)
model.fit(X_train, Y_train, epochs=500, steps_per_epoch=1)
print(model.predict([[0, 1]]))
print(model.predict([[1, 1]]))
print(model.predict([[1, 0]]))
print(model.predict([[0, 0]]))
你应该尝试在你的隐藏层中放置更多的神经元。我试过 64 并且工作正常。
model.add(keras.layers.Dense(64, activation='relu'))
输入层配置为接收您的初始数据,这意味着您可以自定义神经网络的输入形状数据,它会明确要求输入的形状。当你使用 dense 时,你可以配置层中需要多少个神经元,此外你还可以在那里自定义激活函数。
请注意,您使用 dense 来设置输出层,其中神经元的数量是您要预测的 类 的数量(在本例中为一个)。
以上代码有几个明显的问题:
首先,steps_per_epoch=1
参数意味着对于每个 epoch,您的模型只会看到 1 个示例。非常低效。删除该参数。
接下来,500 个纪元还远远不够。如果没有预训练,NN-s 需要花费大量时间进行训练,即使是在最简单的问题上也是如此。我只是 运行 你的代码,在大约 3500 个迭代后,它收敛到最优解。
没试过,不过你也可以试试更高的学习率,像这样:
optimizer = keras.optimizers.Adam(lr=5e-2) #for example
model.compile(optimizer=optimzer, ...)
此外,如果您知道如何使用回调,您可以随时使用 EarlyStopping
回调来制作模型 运行 直到找到最佳模型。
关于提前停止:
如果您使用提前停止,您 必须 还使用单独的验证集。是验证集告诉你什么时候该停止训练了。提前停止是当今该领域最简单且(在我看来)最有用的正则化技术之一。
因此,如果与验证集一起使用,则不会出现过早停止的问题。默认参数只是为了技巧。
此外,如果您有很多 (+50) 个纪元,请尝试绘制历史以获取见解。
像这样:
hist = model.fit(...)
plt.plot(hist.history['loss'])
如果线路在最后跳动,您可能需要 EarlyStopping
甚至 Learning rate decay。
问我是否还有其他问题。
干杯。
我正在尝试在 tf 中构建一个神经网络作为初学者的挑战,我的模型不是很好,这意味着很多时候它不会很准确(虽然有时准确度是 1,但大多数时候它不是' t,即使那样损失也很大。
所以我有两个问题:
- 我该如何改进这个 NN?
- 使用
Input
作为输入层和使用Dense
有什么区别?
代码如下:
import tensorflow as tf
from tensorflow import keras
model = keras.Sequential()
model.add(tf.keras.Input(shape=(2,)))
#model.add(keras.layers.Dense(2))
model.add(keras.layers.Dense(4, activation='relu'))
model.add(keras.layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam',
loss=tf.losses.BinaryCrossentropy(),
metrics=['accuracy'])
# X_train, Y_train = ([[0, 0], [0, 1], [1, 0], [1, 1]], [[0], [1], [1], [0]])
X_train = tf.cast([[0, 0], [0, 1], [1, 0], [1, 1]], tf.float32)
Y_train = tf.cast([0, 1, 1, 0], tf.float32)
model.fit(X_train, Y_train, epochs=500, steps_per_epoch=1)
print(model.predict([[0, 1]]))
print(model.predict([[1, 1]]))
print(model.predict([[1, 0]]))
print(model.predict([[0, 0]]))
你应该尝试在你的隐藏层中放置更多的神经元。我试过 64 并且工作正常。
model.add(keras.layers.Dense(64, activation='relu'))
输入层配置为接收您的初始数据,这意味着您可以自定义神经网络的输入形状数据,它会明确要求输入的形状。当你使用 dense 时,你可以配置层中需要多少个神经元,此外你还可以在那里自定义激活函数。
请注意,您使用 dense 来设置输出层,其中神经元的数量是您要预测的 类 的数量(在本例中为一个)。
以上代码有几个明显的问题:
首先,steps_per_epoch=1
参数意味着对于每个 epoch,您的模型只会看到 1 个示例。非常低效。删除该参数。
接下来,500 个纪元还远远不够。如果没有预训练,NN-s 需要花费大量时间进行训练,即使是在最简单的问题上也是如此。我只是 运行 你的代码,在大约 3500 个迭代后,它收敛到最优解。
没试过,不过你也可以试试更高的学习率,像这样:
optimizer = keras.optimizers.Adam(lr=5e-2) #for example
model.compile(optimizer=optimzer, ...)
此外,如果您知道如何使用回调,您可以随时使用 EarlyStopping
回调来制作模型 运行 直到找到最佳模型。
关于提前停止: 如果您使用提前停止,您 必须 还使用单独的验证集。是验证集告诉你什么时候该停止训练了。提前停止是当今该领域最简单且(在我看来)最有用的正则化技术之一。
因此,如果与验证集一起使用,则不会出现过早停止的问题。默认参数只是为了技巧。
此外,如果您有很多 (+50) 个纪元,请尝试绘制历史以获取见解。
像这样:
hist = model.fit(...)
plt.plot(hist.history['loss'])
如果线路在最后跳动,您可能需要 EarlyStopping
甚至 Learning rate decay。
问我是否还有其他问题。 干杯。