例如,融合失败

时间:2019-01-22 11:19:24

标签: python neural-network

我正在关注《建立自己的神经网络》和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)

1 个答案:

答案 0 :(得分:0)

乙状结肠通常表现不佳。如果您输入的值非常高或非常低,则斜率几乎是平坦的,即:几乎没有学习。 您可以尝试几种解决方案:

1)更改权重的初始化。

2)更改激活功能(建议)。您可以尝试通常效果更好的激活,例如ReLU或Leaky-ReLU。

希望这会有所帮助!