Я слежу за книгой «Создай свою собственную нейронную сеть» и 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)