写在前面

今天重新实现了神经网络,主要是梯度下降公式的更新和神经网络正向传输的公式更新,并且查看,分析了损失函数的图像。

昨天的问题

1:输出层的10个神经元经过训练之后都有相应的正常的输出变化,也即标签对应的神经元输出值应该是最大的,且逼近于1;

2:对单张图片训练了100次之后的损失函数如图所示:

可能是因为学习率过低 + 训练次数不够(训练真的是太慢了,训练一个epoch需要花24s左右的时间),所以经过100次的迭代之后并没有达到最小数值;

3:我还发现了我之前写程序的时候有一个逻辑错误,是关于求导的,正确是求导姿势应该是将输入神经元之前的数值送到求导公式中进行求导,而我之前一直是将神经元输出的数值送到求导公式中进行求导,这是个之前遗留的BUG;

求导和激励函数公式实现如下:

def sigmoid(x):
    s = 1 / (1 + np.exp(-x))
    # print("sig:", s)
    return s

def dsigmoid(x):
    s = sigmoid(x) * (1 - sigmoid(x))
    return s

def ReLU(x):
    if x > 0:
        s = x
    else:
        s = 0
    return s

def dReLU(x):
    if x > 0:
        s = 1
    else:
        s = 0
    return s

今天的工作

今天我对python的梯度下降公式部分进行的更新,程序如下所示:

# update dw,dv,dgama,dtheta_1,dtheta_2,dtheta_3
for i in range(total_y):
    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] * dReLU(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] * dReLU(n[0][k]) * v[i][k] * dReLU(m[0][i])
for i in range(n_num):
    for j in range(total_y):
        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] * dReLU(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] * \
                    dReLU(n[0][l]) * v[j][l] * dReLU(m[0][j]) * x[i]

其实这也就是对昨天的我的公式做一个程序实现,还有正向传播的公式的python实现如下所示:

# print("w", w)
m = np.dot(x, w) - theta_1
# print("m:", m)
for i in range(0, m_num):
    m_out[0][i] = ReLU(m[0][i])
# print("m:", m)
n = np.dot(m_out, v) - theta_2
for i in range(0, n_num):
    n_out[0][i] = ReLU(n[0][i])
# print("n", n)
y_pre = np.dot(n, gamma) - theta_3
# print("y_out:", y_out)
for i in range(total_y):
    y_out = sigmoid(y_pre)

我修改了学习率之后损失函数的曲线如下图所示:

可以看到损失函数下降的很快,而且趋近于0,虽然这个只是针对单张图片的,但是离最终的成功更接近了一些。

明天任务

1:尝试使用GPU训练模型,单用CPU实在是是太慢了;

2:将48000张训练集分成若干个子集,将模型先在子集上进行训练,再求参数的均值,从而得到一个的模型参数;

3:尝试将中间数据保存成文件,这样可以就可以在训练中断的情况下继续训练。