Python - 使用 NumPy 从零开始的神经网络 - 在 Softmax 方面需要帮助
Python - Neural Network from Scratch using NumPy - Need help in Softmax
post看起来很长其实不是,因为我不善于解释:)
我正在尝试制作一个神经网络来分类 O
和 X
字母。每个字母都是 6x6
像素(36 个输入),我使用卷积层将字母最大汇集到 2x2
像素(4 个输入)。在我的 NN 架构中我只有 1 个输出节点,如果输出接近 0
那么字母是 "O",如果它更接近 1
那么字母就是 "X".
- 第一个神经网络架构:
我的第一个 NN 架构的训练数据:
x= [[0.46931818, 0.44129729, 0.54988949, 0.54295118], #O Letter Max Pooled from 6x6 to 2x2
[0.54976771, 0.54295118, 0.50129169, 0.54988949]] #X Letter Max Pooled from 6x6 to 2x2
y=[[0],[1]]
如您所见,O 字母的标签 为零,X 字母的标签为 1。因此,如果输出更接近 0,那么它将输入分类为 O Letter
,如果它更接近 1,那么它将输入分类为 X Letter
。
这对我来说工作得很好,但是当我决定将我的架构更改为 2 个输出时,我开始遇到问题,所以我阅读了有关 Softmax 的内容,但我认为我实施它是错误的。这是我的新 NN 的照片:
- 第二种神经网络架构
这是我的问题:
1.我是否应该更改 y
变量 y=[[0],[1]]
因为我
认为我的新架构没有将其分类为接近 0
或 1,因为每个字母都有自己的输出节点。
2。我的代码如何知道 o1
节点是 O 字母和
o2
节点为X字母
3。我在前馈时是否在我的代码中正确实施了 yPred?
在第一个架构中,我的 y_pred 是这样的:y_pred = o1
因为我只有 1 个输出节点。我应该将 o1 和 o2 作为
softmax函数的胜利者并获得最高价值? (我真的
认为我正在接近这个错误)这是我写的代码:
sum_o1 = (self.w9 * h1 + self.w10 * h2)
o1 = sigmoid(sum_o1)
sum_o2 = (self.w11 * h1 + self.w12 * h2)
o2 = sigmoid(sum_o2)
#Check this later, might be implemented wrong ######################
y_pred = softmax([o1, o2])
y_pred = max(y_pred)
我认为我实施错误的原因是我的 loss rate
有时会变得更高,有时甚至在 40000
个时代之后它也不会改变!这是我检查损失的方法:
if epoch % 1000 == 0:
y_preds = np.apply_along_axis(self.feedforward, 1, data)
loss = mse_loss(all_y_trues, y_preds)
print("Epoch %d loss: %.3f" % (epoch, loss))
- 在第一个NN架构中,我是用来计算partial的
像这样推导:
d_L_d_ypred = -2 * (y_true - y_pred)
,如何
我应该用我的新架构来计算吗?因为现在我不
认为我的 y_true 将不再是 0 和 1。因为我已经有2
节点(o1 和 o2),每个代表一个字母。
我知道我是初学者,所以有一些误解,但我希望有人能给我解释一下。
即使我不希望有人回答这个问题(因为有时 Whosebug 就是这样工作的,这让我很烦),但真的非常感谢帮助!!提前致谢!
注意:添加代码使我关于形状问题的问题更清楚:
class OurNeuralNetwork:
def __init__(self):
# Weights for h1 (First Node in the Hidden Layer)
self.w1 = np.random.normal()
self.w2 = np.random.normal()
self.w3 = np.random.normal()
self.w4 = np.random.normal()
# Weights for h2 (Second Node in the Hidden Layer)
self.w5 = np.random.normal()
self.w6 = np.random.normal()
self.w7 = np.random.normal()
self.w8 = np.random.normal()
# Biases in the hidden layer
self.b1 = np.random.normal() #First Node
self.b2 = np.random.normal() #Second Node
self.w9 = np.random.normal()
self.w10 = np.random.normal()
self.w11 = np.random.normal()
self.w12 = np.random.normal()
def testForward(self, x):
h1 = sigmoid(self.w1 * x[0] + self.w2 * x[1] + self.w3 * x[2] + self.w4 * x[3] + self.b1)
h2 = sigmoid(self.w5 * x[0] + self.w6 * x[1] + self.w7 * x[2] + self.w8 * x[3] + self.b2)
o1 = sigmoid(self.w9 * h1 + self.w10 * h2)
o2 = sigmoid(self.w11 * h1 + self.w12 * h2)
output = softmax([o1, o2])
return output
def feedforward(self, x):
h1 = sigmoid(self.w1 * x[0] + self.w2 * x[1] + self.w3 * x[2] + self.w4 * x[3] + self.b1)
h2 = sigmoid(self.w5 * x[0] + self.w6 * x[1] + self.w7 * x[2] + self.w8 * x[3] + self.b2)
o1 = sigmoid(self.w9 * h1 + self.w10 * h2)
o2 = sigmoid(self.w11 * h1 + self.w12 * h2)
output = softmax([o1, o2])
return output
def train(self, data, all_y_trues):
learn_rate = 0.01
epochs = 20000
for epoch in range(epochs):
for x, y_true in zip(data, all_y_trues):
#Feedforward
sum_h1 = self.w1 * x[0] + self.w2 * x[1] + self.w3 * x[2] + self.w4 * x[3] + self.b1
h1 = sigmoid(sum_h1)
sum_h2 = self.w5 * x[0] + self.w6 * x[1] + self.w7 * x[2] + self.w8 * x[3] + self.b2
h2 = sigmoid(sum_h2)
sum_o1 = (self.w9 * h1 + self.w10 * h2)
o1 = sigmoid(sum_o1)
sum_o2 = (self.w11 * h1 + self.w12 * h2)
o2 = sigmoid(sum_o2)
#Check this later, might be implemented wrong ######################
y_pred = softmax([o1, o2])
## Partial Derivates ->
d_L_d_ypred = -2 * (y_true - y_pred)
# Node o1
d_ypred_d_w9 = h1 * deriv_sigmoid(sum_o1)
d_ypred_d_w10 = h2 * deriv_sigmoid(sum_o1)
#Node o2
d_ypred_d_w11 = h1 * deriv_sigmoid(sum_o2)
d_ypred_d_w12 = h2 * deriv_sigmoid(sum_o2)
d_ypred_d_h1_o1 = self.w9 * deriv_sigmoid(sum_o1)
d_ypred_d_h2_o1 = self.w10 * deriv_sigmoid(sum_o1)
d_ypred_d_h1_o2 = self.w11 * deriv_sigmoid(sum_o2)
d_ypred_d_h2_o2 = self.w12 * deriv_sigmoid(sum_o2)
# Node h1
d_h1_d_w1 = x[0] * deriv_sigmoid(sum_h1)
d_h1_d_w2 = x[1] * deriv_sigmoid(sum_h1)
d_h1_d_w3 = x[2] * deriv_sigmoid(sum_h1)
d_h1_d_w4 = x[3] * deriv_sigmoid(sum_h1)
d_h1_d_b1 = deriv_sigmoid(sum_h1)
# Node h2
d_h2_d_w5 = x[0] * deriv_sigmoid(sum_h2)
d_h2_d_w6 = x[1] * deriv_sigmoid(sum_h2)
d_h2_d_w7 = x[2] * deriv_sigmoid(sum_h2)
d_h2_d_w8 = x[3] * deriv_sigmoid(sum_h2)
d_h2_d_b2 = deriv_sigmoid(sum_h2)
# Update weights and biases
# Node h1
self.w1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1_o1 * d_h1_d_w1
self.w2 -= learn_rate * d_L_d_ypred * d_ypred_d_h1_o1 * d_h1_d_w2
self.w3 -= learn_rate * d_L_d_ypred * d_ypred_d_h1_o1 * d_h1_d_w3
self.w4 -= learn_rate * d_L_d_ypred * d_ypred_d_h1_o1 * d_h1_d_w4
self.b1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1_o1 * d_h1_d_b1
# Node h2
self.w5 -= learn_rate * d_L_d_ypred * d_ypred_d_h2_o2 * d_h2_d_w5
self.w6 -= learn_rate * d_L_d_ypred * d_ypred_d_h2_o2 * d_h2_d_w6
self.w7 -= learn_rate * d_L_d_ypred * d_ypred_d_h2_o2 * d_h2_d_w7
self.w8 -= learn_rate * d_L_d_ypred * d_ypred_d_h2_o2 * d_h2_d_w8
self.b2 -= learn_rate * d_L_d_ypred * d_ypred_d_h2_o2 * d_h2_d_b2
# Node o1
self.w9 -= learn_rate * d_L_d_ypred * d_ypred_d_w9
self.w10 -= learn_rate * d_L_d_ypred * d_ypred_d_w10
#Node o2
self.w11 -= learn_rate * d_L_d_ypred * d_ypred_d_w11
self.w12 -= learn_rate * d_L_d_ypred * d_ypred_d_w12
#Check this later after fixing the softmax issue #################################
if epoch % 10000 == 0:
y_preds = np.apply_along_axis(self.feedforward, 1, data)
loss = mse_loss(all_y_trues, y_preds)
print("Epoch %d loss: %.3f" % (epoch, loss))
1.我应该改变我的 y 变量,它是 y=[[0],] 因为我认为我的新架构没有 class 将它变成接近 0 或 1 因为每个字母都有自己的输出节点.
Ans 您应该从 y=[[0],[1]]
更改为 one-hot 矢量点赞 y=[[1,0],[0,1]]
。这意味着如果输入图像为 0,我们希望索引 0(您的第一个输出节点)的输出为 1。如果输入图像为 x,则索引 1(您的第二个输出节点)的输出为 1。
2。我的代码如何知道 o1 节点用于 O 字母而 o2 节点用于 X 字母
Ans 您的模型将从 onehot 标签中学习 y=[[1,0],[0,1]]
。在模型训练过程中,你的模型会意识到,如果它想要最小化损失函数,当输入图像为 0 时,它应该从第一个输出节点触发值 1
,反之亦然。
3。我在前馈时是否在我的代码中正确实施了 yPred?在第一个架构中,我的 y_pred 是这样的: y_pred = o1 因为我只有一个输出节点。我应该将 o1 和 o2 作为胜利者发送到 softmax 函数并获得最高值吗? (我真的认为我正在接近这个错误)这是我写的代码:
Ans 在训练过程中,我们只需要 class 0
和 x
的概率来做 back-propagation用于更新权重。因此,不需要 y_pred = max(y_pred)
。
4.在第一个NN架构中,我曾经这样计算偏导数:d_L_d_ypred = -2 * (y_true - y_pred),我的新架构应该怎么计算呢?因为现在我认为我的 y_true 不再是 0 和 1。因为我已经有2个节点(o1和o2),每个节点代表一个字母。
答案也许这个可以帮到你
post看起来很长其实不是,因为我不善于解释:)
我正在尝试制作一个神经网络来分类 O
和 X
字母。每个字母都是 6x6
像素(36 个输入),我使用卷积层将字母最大汇集到 2x2
像素(4 个输入)。在我的 NN 架构中我只有 1 个输出节点,如果输出接近 0
那么字母是 "O",如果它更接近 1
那么字母就是 "X".
- 第一个神经网络架构:
我的第一个 NN 架构的训练数据:
x= [[0.46931818, 0.44129729, 0.54988949, 0.54295118], #O Letter Max Pooled from 6x6 to 2x2
[0.54976771, 0.54295118, 0.50129169, 0.54988949]] #X Letter Max Pooled from 6x6 to 2x2
y=[[0],[1]]
如您所见,O 字母的标签 为零,X 字母的标签为 1。因此,如果输出更接近 0,那么它将输入分类为 O Letter
,如果它更接近 1,那么它将输入分类为 X Letter
。
这对我来说工作得很好,但是当我决定将我的架构更改为 2 个输出时,我开始遇到问题,所以我阅读了有关 Softmax 的内容,但我认为我实施它是错误的。这是我的新 NN 的照片:
- 第二种神经网络架构
这是我的问题:
1.我是否应该更改 y
变量 y=[[0],[1]]
因为我
认为我的新架构没有将其分类为接近 0
或 1,因为每个字母都有自己的输出节点。
2。我的代码如何知道 o1
节点是 O 字母和
o2
节点为X字母
3。我在前馈时是否在我的代码中正确实施了 yPred?
在第一个架构中,我的 y_pred 是这样的:y_pred = o1
因为我只有 1 个输出节点。我应该将 o1 和 o2 作为
softmax函数的胜利者并获得最高价值? (我真的
认为我正在接近这个错误)这是我写的代码:
sum_o1 = (self.w9 * h1 + self.w10 * h2)
o1 = sigmoid(sum_o1)
sum_o2 = (self.w11 * h1 + self.w12 * h2)
o2 = sigmoid(sum_o2)
#Check this later, might be implemented wrong ######################
y_pred = softmax([o1, o2])
y_pred = max(y_pred)
我认为我实施错误的原因是我的 loss rate
有时会变得更高,有时甚至在 40000
个时代之后它也不会改变!这是我检查损失的方法:
if epoch % 1000 == 0:
y_preds = np.apply_along_axis(self.feedforward, 1, data)
loss = mse_loss(all_y_trues, y_preds)
print("Epoch %d loss: %.3f" % (epoch, loss))
- 在第一个NN架构中,我是用来计算partial的
像这样推导:
d_L_d_ypred = -2 * (y_true - y_pred)
,如何 我应该用我的新架构来计算吗?因为现在我不 认为我的 y_true 将不再是 0 和 1。因为我已经有2 节点(o1 和 o2),每个代表一个字母。
我知道我是初学者,所以有一些误解,但我希望有人能给我解释一下。
即使我不希望有人回答这个问题(因为有时 Whosebug 就是这样工作的,这让我很烦),但真的非常感谢帮助!!提前致谢!
注意:添加代码使我关于形状问题的问题更清楚:
class OurNeuralNetwork:
def __init__(self):
# Weights for h1 (First Node in the Hidden Layer)
self.w1 = np.random.normal()
self.w2 = np.random.normal()
self.w3 = np.random.normal()
self.w4 = np.random.normal()
# Weights for h2 (Second Node in the Hidden Layer)
self.w5 = np.random.normal()
self.w6 = np.random.normal()
self.w7 = np.random.normal()
self.w8 = np.random.normal()
# Biases in the hidden layer
self.b1 = np.random.normal() #First Node
self.b2 = np.random.normal() #Second Node
self.w9 = np.random.normal()
self.w10 = np.random.normal()
self.w11 = np.random.normal()
self.w12 = np.random.normal()
def testForward(self, x):
h1 = sigmoid(self.w1 * x[0] + self.w2 * x[1] + self.w3 * x[2] + self.w4 * x[3] + self.b1)
h2 = sigmoid(self.w5 * x[0] + self.w6 * x[1] + self.w7 * x[2] + self.w8 * x[3] + self.b2)
o1 = sigmoid(self.w9 * h1 + self.w10 * h2)
o2 = sigmoid(self.w11 * h1 + self.w12 * h2)
output = softmax([o1, o2])
return output
def feedforward(self, x):
h1 = sigmoid(self.w1 * x[0] + self.w2 * x[1] + self.w3 * x[2] + self.w4 * x[3] + self.b1)
h2 = sigmoid(self.w5 * x[0] + self.w6 * x[1] + self.w7 * x[2] + self.w8 * x[3] + self.b2)
o1 = sigmoid(self.w9 * h1 + self.w10 * h2)
o2 = sigmoid(self.w11 * h1 + self.w12 * h2)
output = softmax([o1, o2])
return output
def train(self, data, all_y_trues):
learn_rate = 0.01
epochs = 20000
for epoch in range(epochs):
for x, y_true in zip(data, all_y_trues):
#Feedforward
sum_h1 = self.w1 * x[0] + self.w2 * x[1] + self.w3 * x[2] + self.w4 * x[3] + self.b1
h1 = sigmoid(sum_h1)
sum_h2 = self.w5 * x[0] + self.w6 * x[1] + self.w7 * x[2] + self.w8 * x[3] + self.b2
h2 = sigmoid(sum_h2)
sum_o1 = (self.w9 * h1 + self.w10 * h2)
o1 = sigmoid(sum_o1)
sum_o2 = (self.w11 * h1 + self.w12 * h2)
o2 = sigmoid(sum_o2)
#Check this later, might be implemented wrong ######################
y_pred = softmax([o1, o2])
## Partial Derivates ->
d_L_d_ypred = -2 * (y_true - y_pred)
# Node o1
d_ypred_d_w9 = h1 * deriv_sigmoid(sum_o1)
d_ypred_d_w10 = h2 * deriv_sigmoid(sum_o1)
#Node o2
d_ypred_d_w11 = h1 * deriv_sigmoid(sum_o2)
d_ypred_d_w12 = h2 * deriv_sigmoid(sum_o2)
d_ypred_d_h1_o1 = self.w9 * deriv_sigmoid(sum_o1)
d_ypred_d_h2_o1 = self.w10 * deriv_sigmoid(sum_o1)
d_ypred_d_h1_o2 = self.w11 * deriv_sigmoid(sum_o2)
d_ypred_d_h2_o2 = self.w12 * deriv_sigmoid(sum_o2)
# Node h1
d_h1_d_w1 = x[0] * deriv_sigmoid(sum_h1)
d_h1_d_w2 = x[1] * deriv_sigmoid(sum_h1)
d_h1_d_w3 = x[2] * deriv_sigmoid(sum_h1)
d_h1_d_w4 = x[3] * deriv_sigmoid(sum_h1)
d_h1_d_b1 = deriv_sigmoid(sum_h1)
# Node h2
d_h2_d_w5 = x[0] * deriv_sigmoid(sum_h2)
d_h2_d_w6 = x[1] * deriv_sigmoid(sum_h2)
d_h2_d_w7 = x[2] * deriv_sigmoid(sum_h2)
d_h2_d_w8 = x[3] * deriv_sigmoid(sum_h2)
d_h2_d_b2 = deriv_sigmoid(sum_h2)
# Update weights and biases
# Node h1
self.w1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1_o1 * d_h1_d_w1
self.w2 -= learn_rate * d_L_d_ypred * d_ypred_d_h1_o1 * d_h1_d_w2
self.w3 -= learn_rate * d_L_d_ypred * d_ypred_d_h1_o1 * d_h1_d_w3
self.w4 -= learn_rate * d_L_d_ypred * d_ypred_d_h1_o1 * d_h1_d_w4
self.b1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1_o1 * d_h1_d_b1
# Node h2
self.w5 -= learn_rate * d_L_d_ypred * d_ypred_d_h2_o2 * d_h2_d_w5
self.w6 -= learn_rate * d_L_d_ypred * d_ypred_d_h2_o2 * d_h2_d_w6
self.w7 -= learn_rate * d_L_d_ypred * d_ypred_d_h2_o2 * d_h2_d_w7
self.w8 -= learn_rate * d_L_d_ypred * d_ypred_d_h2_o2 * d_h2_d_w8
self.b2 -= learn_rate * d_L_d_ypred * d_ypred_d_h2_o2 * d_h2_d_b2
# Node o1
self.w9 -= learn_rate * d_L_d_ypred * d_ypred_d_w9
self.w10 -= learn_rate * d_L_d_ypred * d_ypred_d_w10
#Node o2
self.w11 -= learn_rate * d_L_d_ypred * d_ypred_d_w11
self.w12 -= learn_rate * d_L_d_ypred * d_ypred_d_w12
#Check this later after fixing the softmax issue #################################
if epoch % 10000 == 0:
y_preds = np.apply_along_axis(self.feedforward, 1, data)
loss = mse_loss(all_y_trues, y_preds)
print("Epoch %d loss: %.3f" % (epoch, loss))
1.我应该改变我的 y 变量,它是 y=[[0],
Ans 您应该从 y=[[0],[1]]
更改为 one-hot 矢量点赞 y=[[1,0],[0,1]]
。这意味着如果输入图像为 0,我们希望索引 0(您的第一个输出节点)的输出为 1。如果输入图像为 x,则索引 1(您的第二个输出节点)的输出为 1。
2。我的代码如何知道 o1 节点用于 O 字母而 o2 节点用于 X 字母
Ans 您的模型将从 onehot 标签中学习 y=[[1,0],[0,1]]
。在模型训练过程中,你的模型会意识到,如果它想要最小化损失函数,当输入图像为 0 时,它应该从第一个输出节点触发值 1
,反之亦然。
3。我在前馈时是否在我的代码中正确实施了 yPred?在第一个架构中,我的 y_pred 是这样的: y_pred = o1 因为我只有一个输出节点。我应该将 o1 和 o2 作为胜利者发送到 softmax 函数并获得最高值吗? (我真的认为我正在接近这个错误)这是我写的代码:
Ans 在训练过程中,我们只需要 class 0
和 x
的概率来做 back-propagation用于更新权重。因此,不需要 y_pred = max(y_pred)
。
4.在第一个NN架构中,我曾经这样计算偏导数:d_L_d_ypred = -2 * (y_true - y_pred),我的新架构应该怎么计算呢?因为现在我认为我的 y_true 不再是 0 和 1。因为我已经有2个节点(o1和o2),每个节点代表一个字母。
答案也许这个