[英]Simple ANN model converges with tanh(x) as the activation function, but it doesn't with leaky ReLu
我正在训练一个简单的 ANN model (MLP) 用作激活 function 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)
之后,我尝试将激活 function 更改为leaky 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)
编辑:
经过一些修改,这是我的 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)
您需要向网络添加偏差。
你试图 model 的方程是y = 6 - x
,如果你可以使用6
作为截距(偏差),这很简单,但我认为如果你不这样做实际上是不可能的。
一旦添加了偏差,许多函数就更容易表示,这就是为什么包括一个是标准做法的原因。 这个关于偏见在神经网络中的作用的问答更彻底地解释了。
我修改了您的代码以添加偏见,并遵循更典型的命名约定,它对我来说是收敛的。
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.