我正在关注《建立自己的神经网络》和https://sudeepraja.github.io/Neural/一书。我正在做没有numpy,scipy,scikitlearn等的神经网络。我试图通过使用相同的输入-输出组合多次训练以下网络来检查我的算法是否正确。但是,无论我采取多少步骤或增加循环计数器,网络都根本不会学习输出。
我希望代码是可读的,因为我假设代码是github源的音译。
具体来说,第一个输出神经元的值永远不会改变(理想情况下,它应该收敛到0.01,但停留在0.5处)。该代码可从http://tpcg.io/ruufxJ获得,并在链接过期时在下面显示。我也尝试过https://github.com/Horopter/NeuralNetworks-2018/blob/master/NeuralNetwork.py,但是那里的代码只是错误的[没有扩展到多层]
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)
答案 0 :(得分:0)
乙状结肠通常表现不佳。如果您输入的值非常高或非常低,则斜率几乎是平坦的,即:几乎没有学习。 您可以尝试几种解决方案:
1)更改权重的初始化。
2)更改激活功能(建议)。您可以尝试通常效果更好的激活,例如ReLU或Leaky-ReLU。
希望这会有所帮助!