你好,我尝试使用一个基于向量的神经网络来拟合一个非常简单的x**2函数。这个网络有一个输入节点,一个输出节点,以及两个隐藏层,每层各有3个节点 – 只是为了验证其功能。因此,我使用了下面的代码。结果我得到了橙色线,蓝色线是真实线。
如你所见,某些地方出了问题。我尝试过更改迭代次数和学习率的值,但没有成功。如果我绘制损失随迭代的变化,我在100次迭代后得到了以下图形:
我还没有添加偏置,但我认为这个简单的函数应该可以在没有额外偏置节点的情况下拟合。此外,我认为代码中最可能出现错误的地方是在“计算相对于权重的梯度”部分…
所以原则上我有两个问题:
- 我的代码中是否存在基本错误,导致代码无法工作
- 如果没有,为什么我的模型无法拟合简单的数据
提前感谢你的帮助!
这里是代码 – 已经准备好运行:
class Neural_Net: """ """ def __init__(self, activation_function, learning_rate, runs): self.activation_function = activation_function self.X_train = np.linspace(0,1,1000) self.y_train = self.X_train**2 plt.plot(self.X_train, self.y_train) self.y_pred = None self.W_input = np.random.randn(1, 3) self.Partials_W_input = np.random.randn(1, 3) self.W_hidden = np.random.randn(3,3) self.Partials_W_hidden = np.random.randn(3,3) self.W_output = np.random.randn(3,1) self.Partials_W_output = np.random.randn(3,1) self.Activations = np.ones((3,2)) self.Partials = np.ones((3,2)) self.Output_Gradient = None self.Loss = 0 self.learning_rate = learning_rate self.runs = runs self.Losses = [] self.i = 0 def apply_activation_function(self, activation_vector): return 1/(1+np.exp(-activation_vector)) def forward_pass(self, training_instance): for layer in range(len(self.Activations[0])): # For the first layer between X and the first hidden layer pre_activation_first = self.W_input.T @ training_instance.reshape(1,1) # print('pre activation: ', pre_activation) # Apply the activation function self.Activations[:,0] = self.apply_activation_function(pre_activation_first).ravel() else: pre_activation_hidden = self.W_hidden.T @ self.Activations[:, layer-1] self.Activations[:, layer] = self.apply_activation_function(pre_activation_hidden) # print('Activations: ', self.Activations) output = self.W_output.T @ self.Activations[:, -1] # print('output: ', output) return output def backpropagation(self, y_true, training_instance): if self.activation_function == 'linear': # Calculate the ouput gradient self.Output_Gradient = -(y_true-self.y_pred) # print('Output Gradient: ', self.Output_Gradient) # Calculate the partial gradients of the Error with respect to the pre acitvation values in the nodes self.Partials[:, 1] = self.Activations[:, 1]*(1-self.Activations[:, 1])*(self.W_output @ self.Output_Gradient) self.Partials[:, 0] = self.Activations[:, 0]*(1-self.Activations[:, 0])*(self.W_hidden @ self.Partials[:, 1]) # print('Partials: ', self.Partials) # Calculate the Gradients with respect to the weights self.Partials_W_output = self.Output_Gradient * self.Activations[:, -1] # print('Partials_W_output: ', self.Partials_W_output) self.Partials_W_hidden = self.Partials[:, -1].reshape(3,1) * self.Activations[:, 0].reshape(1,3) # print('Partials_W_hidden: ',self.Partials_W_hidden) self.Partials_W_input = (self.Partials[:, 0].reshape(3,1) * training_instance.T).T # print('Partials_W_input: ', self.Partials_W_input) def weight_update(self, training_instance, learning_rate): # Output Layer weights w_output_old = self.W_output.copy() self.W_output = w_output_old - learning_rate*self.Output_Gradient # Hidden Layer weights w_hidden_old = self.W_hidden.copy() self.W_hidden = w_hidden_old - learning_rate * self.W_hidden # print('W_hidden new: ', self.W_hidden) # Input Layer weights w_input_old = self.W_input.copy() self.W_input = w_input_old - learning_rate * self.W_input # print('W_input new: ', self.W_input) def train_model(self): for _ in range(self.runs): for instance in range(len(self.X_train)): # forward pass self.y_pred = self.forward_pass(self.X_train[instance]) # Calculate loss self.Loss = self.calc_loss(self.y_pred, self.y_train[instance]) # print('Loss: ', self.Loss) # Calculate backpropagation self.backpropagation(self.y_train[instance], self.X_train[instance]) # Update weights self.weight_update(self.X_train[instance], self.learning_rate) # print(self.Losses) # plt.plot(range(len(self.Losses)), self.Losses) # plt.show() # Make predictions on training data to check if the model is basically able to fit the training data predictions = [] for i in np.linspace(0,1,1000): predictions.append(self.make_prediction(i)) plt.plot(np.linspace(0,1,1000), predictions) def make_prediction(self, X_new): return self.forward_pass(X_new) def calc_loss(self, y_pred, y_true): loss = (1/2)*(y_true-y_pred)**2 self.Losses.append(loss[0]) return (1/2)*(y_true-y_pred)**2 def accuracy(self): passNeural_Net('linear', 0.0001, 10).train_model()
回答: