写在前面
好久不见,前几天忙着复习就没有更新啦~经过预训练之后,发现模型表现的不太好,准确率大概也就在45%,经过分析之后发现了之前程序的一个bug,并进行了修复,本篇文章将记录问题以及解决过程。
上次遗留
用ROC曲线等评估模型性能:因为模型初调的时候准确率不高,大概在45%,远不能满足要求,因此我就没有用该方法进行验证,而是通过观察程序、对照公式等方法查找问题。
模型经过初调(1w张训练集,1w张验证集),学习率0.05,双隐层,每层各16个神经元,表现如下所示:
可以看到最后的准确率都是45%多一点点,不咋地,所以今天主要是在提升这个。
在这里我不得不提一下batch的好处了,当我刚开始没用batch的时候硬跑整个数据集,就是下面这个结果:
正确率只有12.6%。
今天的工作
我之前的双隐层用的ReLu函数,输出层用的是sigmoid函数,但是我发现了一个问题,那就是我的神经元的阈值会出现负数,那么神经元输出小于0的可能性就比较大,那么在ReLU函数中,当神经元的输入小于0的时候,这个神经元根本就是没有用的,相当于少了很多的信息。
之前我用的sigmoid函数,但是后来舍弃的主要原因是它会发生梯度消失,但是当时我没分batch进行训练,所以我觉得分了batch之后效果可能会好很多,最起码在我的这个神经网络里面,ReLU函数的表现确实不如人意,因此我将其换回了sigmoid函数。
我将batch size设置成了100,跑1w张,100个epoch,学习率0.1
训练函数更新为如下所示:
@jit
def TrainBody(w, v, gamma, theta_1, theta_2, theta_3, x,\
dw, dv, dgamma, dtheta_1, dtheta_2, dtheta_3, \
m, m_out, n, n_out, y, y_out, y_pre):
for i in range(total_y):
dtheta_3[0][i] = dtheta_3[0][i] + (y[0][i] - y_out[0][i]) * dsigmoid(y_pre[0][i])
for i in range(n_num):
for k in range(total_y):
dtheta_2[0][i] = dtheta_2[0][i] + (y[0][k] - y_out[0][k]) * dsigmoid(y_pre[0][k]) * \
gamma[i][k] * dsigmoid(n[0][i])
for i in range(m_num):
for j in range(total_y):
for k in range(n_num):
dtheta_1[0][i] = dtheta_1[0][i] + (y[0][j] - y_out[0][j]) * dsigmoid(y_pre[0][j]) * \
gamma[k][j] * dsigmoid(n[0][k]) * v[i][k] * dsigmoid(m[0][i])
for i in range(n_num):
for j in range(total_y):
dgamma[i][j] = dgamma[i][j] + (y_out[0][j] - y[0][j]) * n_out[0][i] * dsigmoid(y_pre[0][j])
for i in range(m_num):
for j in range(n_num):
for k in range(total_y):
dv[i][j] = dv[i][j] + (y_out[0][k] - y[0][k]) * gamma[j][k] * dsigmoid(y_pre[0][k]) * \
m_out[0][i] * dsigmoid(n[0][j])
for i in range(total_x):
for j in range(m_num):
for k in range(total_y):
for l in range(n_num):
dw[i][j] = dw[i][j] + (y_out[0][k] - y[0][k]) * dsigmoid(y_pre[0][k]) * gamma[l][k] * \
dsigmoid(n[0][l]) * v[j][l] * dsigmoid(m[0][j]) * x[i]
其中,batch的参数更新方式如下所示:
if (k + 1) % division == 0:
# update w,v,gama,theta_1,theta_2,theta_3
w = w - (study_step * dw) / division
v = v - (study_step * dv) / division
gamma = gamma - (study_step * dgamma) / division
theta_1 = theta_1 - (study_step * dtheta_1) / division
theta_2 = theta_2 - (study_step * dtheta_2) / division
theta_3 = theta_3 - (study_step * dtheta_3) / division
dw = np.zeros(((total_x, m_num)), dtype=float) # (()) is used to confirm line and row
dv = np.zeros((m_num, n_num), dtype=float)
dgamma = np.zeros((n_num, total_y), dtype=float)
dtheta_1 = np.zeros(((1, m_num)), dtype=float)
dtheta_2 = np.zeros(((1, n_num)), dtype=float)
dtheta_3 = np.zeros(((1, total_y)), dtype=float)
print("\rtrain_n is %d" % (k), end='')
今天我也学习到了输出控制台不换行,在同一行内更新输出的办法,如下所示:
print("\rtrain_n is %d" % (k), end='')
明日工作
1:根据今天晚上模型训练的结果,如果结果理想,明天就加大训练集的数量继续训练,如果结果不太理想那就说明不是激活函数的问题,可能是公式出问题,回溯之前的公式推导工作。
2:学习batch normalization相关知识。
评论(0)
您还未登录,请登录后发表或查看评论