Python 如何通过从头开始的神经网络来提高预测的准确性?

Python 如何通过从头开始的神经网络来提高预测的准确性?,python,machine-learning,neural-network,Python,Machine Learning,Neural Network,我对机器学习比较陌生,作为一个入门项目,我决定使用NumPy从零开始在Python中实现我自己的神经网络。因此,我已经手动实现了正向传播、反向传播和计算函数导数的方法 对于我的测试数据,我编写了一个生成sin(x)值的函数。当我最终创建和训练我的人际网络时,我的输出在每次试验中波动很大,并且明显偏离真实值(尽管它们比最初的预测有了相当大的改进) 我尝试过调整很多设置,包括学习速率、神经元数量、层数、训练迭代次数和激活函数,但最终输入数据的平方成本仍在0.1左右 我认为我的导数函数和链式规则表达式

我对机器学习比较陌生,作为一个入门项目,我决定使用NumPy从零开始在Python中实现我自己的神经网络。因此,我已经手动实现了正向传播、反向传播和计算函数导数的方法

对于我的测试数据,我编写了一个生成sin(x)值的函数。当我最终创建和训练我的人际网络时,我的输出在每次试验中波动很大,并且明显偏离真实值(尽管它们比最初的预测有了相当大的改进)

我尝试过调整很多设置,包括学习速率、神经元数量、层数、训练迭代次数和激活函数,但最终输入数据的平方成本仍在0.1左右

我认为我的导数函数和链式规则表达式是正确的,因为当我只使用一个输入样本时,我得到了一个近乎完美的答案

然而,添加更多的输入数据会显著降低网络的准确性

你们对如何改善这个网络有什么建议吗?或者我目前有什么做错的地方吗

我的代码:

将numpy导入为np
#为网络生成输入数据
def inputgen():
输入=[]
输出=[]
i=0.01
对于范围(10000)内的x:
输入。追加([第(i,7)轮)])
outputs.append([np.sin(i)]#输出为sin(x)
i+=0.0001
返回[输入、输出]
#设置培训输入和输出
inputs=np.array(inputgen()[0])
outputs=np.array(inputgen()[1])
#sigmoid激活函数及其导数
def乙状结肠(x):
返回1/(1+np.exp(-x))
def S形导数(x):
返回S形(x)*(1-S形(x))
#tanh活化函数及其导数
def tanh(x):
返回np.tanh(x)
def tanh_导数(x):
返回1-((tanh(x))**2)
#层类
类别层:
def_uuuinit_uuu(self,num_神经元,num_输入,输入):
self.num_neurons=num_neurons#隐藏层中的神经元数
self.num_inputs=num_inputs#输入神经元数(测试数据为1)
self.inputs=输入
self.weights=np.rand.rand(num_输入,num_神经元)*np.sqrt(1/num_输入)#由Xavier函数初始化的权重
self.biases=np.zeros((1,num_神经元))#偏差初始化为0
self.z=np.dot(self.input,self.weights)+self.bias#Cacluate z
self.a=tanh(self.z)#计算激活
self.dcost_a=[]#与激活相关的成本衍生工具
self.da_z=[]激活对z的导数
self.dz_w=[]z对重量的导数
self.dcost_w=[]成本相对于重量的导数
self.dcost_b=[]#成本相对于偏差的导数
#前向传播中使用的函数
def compute_z(自):
self.z=np.dot(self.input,self.weights)+self.bias
返回self.z
def激活(自):
self.a=tanh(self.compute_z())
def转发(自):
自我激活()
#网络类
班级网络:
定义初始化(self、num层、num神经元、num输入、输入、num输出、输出):
自学习率=0.01#学习率
self.num_layers=num_layers#隐藏层数
self.num_neurons=num_neurons#隐藏层中的神经元数
self.num_inputs=num_inputs#输入神经元的数量
自我输入=输入
自身预期输出=输出
self.layers=[]
对于范围内的x(num_层):
如果x==0:
self.layers.append(层(num_神经元,num_输入,输入))#具有给定输入的初始层
其他:
#其他层有一个输入,它是前一层的激活
self.layers.append(层(num_neurons,len(self.layers[x-1].a[0]),self.layers[x-1].a))
self.prediction=层(num_输出,num_神经元,self.layers[-1].a)#预测
self.layers.append(self.prediction)
self.cost=(self.prediction.a-self.expected_输出)**2#cost
#正向传播
def forwardprop(自我):
对于范围内的x(self.num_层+1):
如果(x!=0):
self.layers[x]。输入=self.layers[x-1]。a
self.layers[x].forward()
self.prediction=self.layers[-1]#更新预测值
def backprop(自):
self.cost=(self.prediction.a-self.expected_输出)**2
对于范围内的x(透镜(自层)-1,-1,-1):
如果(x==len(self.layers)-1):
dcost_a=2*(self.prediction.a-self.expected_输出)#关于输出层激活的成本导数
其他:
#与隐藏层激活相关的成本衍生(链规则)
dcost_a=np.zeros((len(self.layers[x].inputs),self.num_)).T
dcost_a1=self.layers[x+1].dcost_a.T
da_z1=self.layers[x+1].da_z.T
dz_a=(self.layers[x+1].权重).T
对于范围内的z(len(dcost_a1)):
dcost_a+=((dcost_a1[z])*da_z1)
对于范围内的j(len(dcost_a)):
dcost_a[j]*=dz_a[z][j]
dcost\u a=dcost\u a.T
self.layers[x].dcost\u a=dcost\u a
#活化对z的导数
da_z=tanh_导数(self.layers[x].z)
self.layers[x].da_z=da_z
#z对权的导数
dz_w=[]
如果x=0:
dz_w=self.layers[x-1].a
其他:
dz_w=自输入
self.layers[x].dz_w=dz_w
#更改权重和偏差
对于范围内的x(透镜(自层)-1,-1,-1):
#对所有训练样本中的每个导数求平均值
self.layers[x].dcost\u a=np.average(self.layers[x].dcost\u a,axis=0)
self.layers[x].da_z=np.average(self.layers[x]
[[0.01  ]
 [0.0101]
 [0.0102]
 ...
 [1.0097]
 [1.0098]
 [1.0099]]
[[0.37656753]
 [0.37658777]
 [0.37660802]
 ...
 [0.53088048]
 [0.53089046]
 [0.53090043]]
[[0.00999983]
 [0.01009983]
 [0.01019982]
 ...
 [0.84667225]
 [0.84672546]
 [0.84677865]]
def update_learning_rate(self):
    if(len(self.cost_history) < 2):
        return

    if(self.cost_history[0] > self.cost_history[1]):
        self.learning_rate /= 2
    else:
        self.learning_rate *= 1.05