Простая модель ANN сходится с tanh (x) в качестве функции активации, но не с утечкой ReLu - PullRequest
0 голосов
/ 26 апреля 2020

Я обучаю простую модель ANN (MLP), используя в качестве функции активации tanh(x), и после некоторых взаимодействий она сходится с ошибкой, равной 10 ^ -5, вот мой полный код:

import numpy as np
import pandas as pd

# Base de dados a ser treinada
x = pd.DataFrame(
    [[1],
    [2],
    [3]],
    columns=['valores x'])

d = pd.DataFrame(
    [[5],
    [4],
    [3]],
    columns=['valores desejados'])

# Convertendo o dataframe em array e normalizando os valores desejados para ficar entre 0 e +1.
x = x.to_numpy()
d = d/(1.05*d.max())
d = d.to_numpy()


# Derivada de tanh(x) = sech²(x) = 1 - (tanh(x))²
def df(x):
    y = 1 - np.power(np.tanh(x), 2)
    return y

#def rede_mlp(n, x, d, net, k, precisao):

# Construindo a rede de duas camadas 
# net = número de neurônios na primeira camada
# n = taxa de aprendizagem
# precisao = precisão do erro quadrático médio
net=3
n = 0.1
precisao=0.00001
w1 = np.random.rand(net,len(x[0]))
w2 = np.random.rand(1,net)
E_M=1
epocas=0

while E_M>precisao:
    E_M=0
    errofinal=0
    for i in range(0,len(x)):

        # FOWARD
        i1 = np.matmul(w1, x[i].reshape(len(x[i]),1))
        y1 = np.tanh(i1)

        i2 = np.matmul(w2, y1)
        y2 = np.tanh(i2)

        # erro com o valor desejado
        erro = d[i].reshape(len(d[i]),1) - y2

        # BACKPROPAGATION
        delta_2 = erro*df(i2)
        w2 = w2 + n*(np.matmul(delta_2, y1.reshape(1, net)))

        delta_1 = (np.matmul(w2.T, delta_2))*df(i1)
        w1 = w1 + n*(np.matmul(delta_1, x[i].reshape(1, len(x[i]))))

        errofinal = errofinal + 0.5*erro**2

    E_M = errofinal/len(x)
    epocas+=1
    print(E_M)

После этого я попытался изменить функцию активации на ReLu с утечкой, но она не сходилась. Я несколько раз менял скорость обучения n, но ошибка все еще велика. Это около 7,95, что является большим для моих данных. Вот моя попытка:

import numpy as np
import pandas as pd


# Base de dados a ser treinada
x = pd.DataFrame(
    [[1],
    [2],
    [3]],
    columns=['valores x'])

d = pd.DataFrame(
    [[5],
    [4],
    [3]],
    columns=['valores desejados'])

# Convertendo o dataframe em array e normalizando os valores desejados para ficar entre 0 e +1.
x = x.to_numpy()
d = d.to_numpy()


def df(x):
    x = np.array(x)
    x[x<=0] = 0.01
    x[x>0] = 1
    return x

def f(x):
    return(np.where(x > 0, x, x * 0.01))



#def rede_mlp(n, x, d, net, k, precisao):

# Construindo a rede de duas camadas 
# net = número de neurônios na primeira camada
# n = taxa de aprendizagem
# precisao = precisão do erro quadrático médio
net=3
n = 1e-4
precisao=0.0001
w1 = np.random.rand(net,len(x[0]))
w2 = np.random.rand(1,net)
E_M=20
epocas=0

while E_M>precisao:
    E_M=0
    errofinal=0
    for i in range(0,len(x)):

        # FOWARD
        i1 = np.matmul(w1, x[i].reshape(len(x[i]),1))
        y1 = f(i1)



        i2 = np.matmul(w2, y1)
        y2 = f(i2)


        # erro com o valor desejado
        erro = d[i].reshape(len(d[i]),1) - y2


        # BACKPROPAGATION
        delta_2 = erro*df(i2)
        w2 = w2 + n*(np.matmul(delta_2, y1.reshape(1, net)))


        delta_1 = (np.matmul(w2.T, delta_2))*df(i1)
        w1 = w1 + n*(np.matmul(delta_1, x[i].reshape(1, len(x[i]))))

        errofinal = errofinal + 0.5*erro**2

    #E_M = errofinal/len(x)
    E_M = errofinal
    epocas+=1
    print(E_M)

EDITED :

После некоторых изменений вот мой код ReLu (но ошибка все еще высока ~ 7,77):

import numpy as np
import pandas as pd


# Base de dados a ser treinada
x = pd.DataFrame(
    [[1],
    [2],
    [3]],
    columns=['valores x'])

d = pd.DataFrame(
    [[5],
    [4],
    [3]],
    columns=['valores desejados'])

# Convertendo o dataframe em array e normalizando os valores desejados para ficar entre 0 e +1.
x = x.to_numpy()
d = d.to_numpy()


def df(x):
    return(np.where(x <= 0, 0.01, 1))

def f(x):
    return(np.where(x > 0, x, x * 0.01))


#def rede_mlp(n, x, d, net, k, precisao):

# Construindo a rede de duas camadas 
# net = número de neurônios na primeira camada
# n = taxa de aprendizagem
# precisao = precisão do erro quadrático médio
net=3
n = 1e-3
precisao=0.1
w1 = np.random.rand(net,len(x[0]))
w2 = np.random.rand(1,net)
E_M=20
epocas=0

while E_M>precisao:
    E_M=0
    errofinal=0
    for i in range(0,len(x)):

        # FOWARD
        i1 = np.matmul(w1, x[i].reshape(len(x[i]),1))
        y1 = f(i1)


        i2 = np.matmul(w2, y1)
        y2 = f(i2)


        # erro com o valor desejado
        erro = d[i].reshape(len(d[i]),1) - y2


        # BACKPROPAGATION
        delta_2 = erro*df(i2)
        delta_1 = (np.matmul(w2.T, delta_2))*df(i1)

        w2 = w2 + n*(np.matmul(delta_2, y1.reshape(1, net)))
        w1 = w1 + n*(np.matmul(delta_1, x[i].reshape(1, len(x[i]))))


        errofinal = errofinal + 0.5*erro**2

    #E_M = errofinal/len(x)
    E_M = errofinal
    epocas+=1
    print(E_M)

1 Ответ

2 голосов
/ 26 апреля 2020

Вам необходимо добавить смещение в сеть.

Уравнение, которое вы пытаетесь смоделировать, равно y = 6 - x, что тривиально, если вы можете использовать 6 как перехват (смещение), но я думаю, что на самом деле невозможно, если вы этого не сделаете.

Многие функции гораздо проще представить после добавления смещения, поэтому включение одной из них является стандартной практикой. Эти вопросы и ответы о роли смещения в NN объясняют более подробно.

Я изменил ваш код, добавив смещение, а также следуя более типичным соглашениям об именах, и он сходится для меня.

net = 3
n = 1e-3
precisao = 0.0001 

w1 = np.random.rand(net, len(x[0])) 
bias1 = np.random.rand()

w2 = np.random.rand(1, net) 
bias2 = np.random.rand()

E_M = 20 
epocas = 0 

while E_M > precisao: 
    E_M = 0 
    errofinal = 0 
    for i in range(0,len(x)): 
        a0 = x[i].reshape(-1, 1) 
        targ = d[i].reshape(-1, 1) 

        z1 = np.matmul(w1, a0) + bias1
        a1 = f(z1) 

        z2 = np.matmul(w2, a1) + bias2
        a2 = f(z2) 

        erro = a2 - targ

        # BACKPROPAGATION 
        delta_2 = erro * df(z2) 
        delta_1 = np.matmul(w2.T, delta_2) * df(z1) 
        bias2 -= n * delta_2
        bias1 -= n * delta_1
        w2 -= n * np.matmul(delta_2, a1.T)
        w1 -= n * np.matmul(delta_1, a0.T)

        errofinal = errofinal + 0.5*erro**2 

    #E_M = errofinal/len(x) 
    E_M = errofinal 
    epocas += 1 
    if epocas % 1000 == 0:
        print(epocas, E_M) 

Я увеличил скорость обучения, чтобы она быстрее сходилась.

1000 [[0.14401507]]
2000 [[0.00028834]]

Ранее предложенное исправление ошибки

Вы установка производной всегда равна 1.

def df(x):
    x = np.array(x)
    x[x<=0] = 0.01
    x[x>0] = 1
    return x

Линия x[x<=0] = 0.01 устанавливает все неположительные значения в 1/100, положительное значение. После этого каждое значение является положительным, поскольку уже положительные значения go через незатронутые и отрицательные или нулевые значения просто стали положительными. Поэтому следующая строка x[x>0] = 1 устанавливает все производные на 1.

Попробуйте это:

def df(x):
    return np.where(np.array(x) <= 0, 0.01, 1)
...