Python 例如,收敛失败
我正在学习《创建自己的神经网络》一书,并在学习。我在做没有numpy、scipy、scikitlearn等的神经网络。我试图通过多次使用相同的输入输出组合训练以下网络来检查我的算法是否正确。然而,无论我采取多少步骤或增加循环计数器,网络根本不会学习输出 我希望代码可读,因为我假设代码是github源代码的音译 具体来说,第一个输出神经元的值永远不会改变(理想情况下,它应该收敛到0.01,但保持在0.5)。如果链接过期,代码将在上提供,并在下面显示。我也试过了,但是那里的代码是错误的[没有扩展到多个层]Python 例如,收敛失败,python,neural-network,Python,Neural Network,我正在学习《创建自己的神经网络》一书,并在学习。我在做没有numpy、scipy、scikitlearn等的神经网络。我试图通过多次使用相同的输入输出组合训练以下网络来检查我的算法是否正确。然而,无论我采取多少步骤或增加循环计数器,网络根本不会学习输出 我希望代码可读,因为我假设代码是github源代码的音译 具体来说,第一个输出神经元的值永远不会改变(理想情况下,它应该收敛到0.01,但保持在0.5)。如果链接过期,代码将在上提供,并在下面显示。我也试过了,但是那里的代码是错误的[没有扩展到多
import math,copy
def initArrZero(num):
l = []
for i in range(num):
l.append(0)
return l
def initMatrix(rows,cols):
m = []
for i in range(rows):
m.append(initArrZero(cols))
return m
def sigmoid(x):
return 1.0/(1.0 + math.e**(-x))
def sigmoid_m(x):
if isinstance(x,list):
lst = []
for i in x:
lst.append(sigmoid_m(i))
return lst
else:
return sigmoid(x)
def sigmoid_prime(x):
return sigmoid(x)*(1-sigmoid(x))
def sigmoid_prime_m(x):
if isinstance(x,list):
lst = []
for i in x:
lst.append(sigmoid_prime_m(i))
return lst
else:
return sigmoid_prime(x)
def transpose(m):
return [[m[j][i] for j in range(len(m))] for i in range(len(m[0]))]
def matmul(A,B):
result = initMatrix(len(A),len(B[0]))
for i in range(len(A)):
for j in range(len(B[0])):
for k in range(len(B)):
result[i][j] += A[i][k] * B[k][j]
return result
def matadd(X,Y):
result = copy.deepcopy(X)
for i in range(len(X)):
for j in range(len(X[0])):
result[i][j] = X[i][j] + Y[i][j]
return result
def hadamard(X,Y):
result = copy.deepcopy(X)
for i in range(len(X)):
for j in range(len(X[0])):
result[i][j] = X[i][j] * Y[i][j]
return result
def scalarmul(A,B):
if isinstance(A,list) and (isinstance(B,float) or isinstance(B,int)):
return scalarmul(B,A)
if isinstance(B,list):
lst = []
for i in B:
lst.append(scalarmul(A,i))
return lst
return A*B
def subtract(A,B):
if isinstance(A,list) and isinstance(B,list) and len(A)==len(B):
lst = []
for i in range(len(A)):
lst.append(subtract(A[i],B[i]))
return lst
else:
return A-B
class NN:
def __init__(self,arr):
assert len(arr)>1
l = len(arr)
input = initArrZero(arr[0]+1)
input[-1] = 1
self.layers = []
self.layers.append(input)
for i in range(1,l-1):
lst = initArrZero(arr[i])
self.layers.append(lst)
self.layers.append(initArrZero(arr[-1]))
self.weights = []
for i in range(l-1):
w = initMatrix(len(self.layers[i]),len(self.layers[i+1]))
self.weights.append(w)
def feedforward(self):
for i in range(0,len(self.layers)-1):
self.layers[i+1] = sigmoid_m(matmul(self.weights[i],self.layers[i]))
def backprop(self,actual,alpha):
self.wd = initArrZero(len(self.weights))
self.wdm = initArrZero(len(self.weights))
for i in range(len(self.weights)-1,-1,-1):
if i == len(self.weights)-1:
self.wd[i] = hadamard(subtract(self.layers[-1],actual),sigmoid_prime_m(matmul(self.weights[-1],self.layers[-2])))
else:
self.wd[i] = hadamard(matmul(transpose(self.weights[i+1]),self.wd[i+1]),sigmoid_prime_m(matmul(self.weights[i],self.layers[i])))
for i in range(len(self.weights)-1,-1,-1):
t = transpose(self.layers[i])
self.wdm[i] = matmul(self.wd[i],t)
for i in range(len(self.weights)-1,-1,-1):
self.weights[i] = matadd(self.weights[i],hadamard(scalarmul(-1*alpha,self.weights[i]),self.wdm[i]))
def show(self):
print "Layers : "
for p in self.layers:
print p
print "\n\n\n"
print "Weights : "
for i in range(len(self.weights)):
print self.weights[i]
print "\n\n\n"
n = NN([2,2,2])
n.layers[0] = [[0.05],[0.1],[1]]
n.weights[0] = transpose([[0.15,0.25],[0.2,0.3],[0.35,0.6]])
n.weights[1] = transpose([[0.4,0.5],[0.45,0.55]])
n.show()
for i in range(1000):
n.feedforward()
n.backprop([[0.01],[0.99]],5)
n.show()
预期:最后一层接近(0.01,0.99)
输出:
(0.5,0.9892866637557137)
乙状结肠畸形通常表现不佳。如果您输入的值非常高或非常低,则坡度几乎平坦,即:几乎没有学习。
您可以尝试以下几种解决方案:
1) 更改权重的初始化
2) 更改激活功能(建议)。您可以尝试通常性能更好的激活,例如ReLU或leaky ReLU
希望这有帮助 事实上,我尝试过训练XOR神经网络,但也失败了。我想知道我写的程序是否有bug。我将尝试使用leaky RELU并将结果发布在这里。有没有一个样本集,我可以训练乙状结肠激活来检查我的代码是否正确?没有!试过了ReLU和leaky ReLU。我想我的数学有问题。如果这不是太多的问题,请任何人给我回w.r.t.数学/代码?很抱歉听到这个。由于遍历他人的代码非常复杂,您可以设置调试器吗?如果您使用的是纯Python,那么就可以使用pdb库,一步一步地遍历执行过程,并了解导致问题的函数是什么。这是解决问题的第一步。我通常这样做:
从pdb导入将跟踪设置为bp
,然后在代码中需要的地方放置断点bp()。希望这有帮助!非常感谢你,伊万!很明显,我的代码正在执行预期的操作。然而,我感到困惑,因为我想知道神经网络是否可以学习一个带有sigmoid激活函数的小数据集。我要用leaky ReLU再做一次尝试,因为我被告知我用错误的方法实现了它,我会回到这里。从小数据集学习不仅对神经网络来说很困难,对任何ML算法来说都很困难。数据集的大小是多少?关于激活功能:据我所知,我所学的每一门课程,以及我读过的每一本书,他们都认为sigmoid的性能一般比其他激活功能差。然而,坚持使用乙状结肠仍然可以获得良好的效果。如果可以的话,尝试多个,然后选择一个效果最好的!