cs231n训练营学习笔记(8)简单双层全连接神经网络

全连接神经网络

前面的线性分类器是,x是一个列向量,W把结果变成10个元素的列向量

神经网络不同,例如一个简单二层网络f=W_{2}(max(0,W_{1}x)),里面是和上面一样的线性处理,得到中间变量,假设是100维的,然后做非线性处理,然后得到最后的10维列向量。非线性不会和线性的合并,所以才分了层。

参数W_{1},W_{2}通过训练,随机梯度下降和反向传播学到

对单个神经元建模

cs231n训练营学习笔记(8)简单双层全连接神经网络_第1张图片

每个神经元都对它的输入和权重进行点积,然后加上偏差,最后使用非线性函数(或称为激活函数)

本例中使用的是sigmoid函数

一些常见的激活函数:

cs231n训练营学习笔记(8)简单双层全连接神经网络_第2张图片

激活函数的操作概括起来就是,输入一个数字,把它限定在一定范围,比如(0,1)或者>0之类的

sigmoid函数,把神经元输出压缩在(0,1),即限定在0完全不激活和1完全激活,激活这个词代表这个神经元对后面的影响,如果激活函数输出为0,对于后面的神经元来说,这个神经元相当于睡过去了,完全没影响。

sigmoid函数的缺点,梯度消失和非0中心

 

输入层, 隐层 ,输出层的概念

cs231n训练营学习笔记(8)简单双层全连接神经网络_第3张图片

当我们说N层神经网络的时候,我们没有把输入层算入。和神经网络中其他层不同,输出层的神经元一般是不会有激活函数的。

每个隐层的权重存储隐层和下一层的连接,比如第3行的第2个权重值为0,就代表下一层的第3个神经元和该隐层的第2个神经元无连接,因为前面的神经元无论怎么变化,传到后面的神经元的数都是0。

two-layer.ipynb每个函数的作用及代码逻辑

先是初始化,然后计算scores,loss和grad

    f = lambda x: np.maximum(0, x)
    H1 = f(np.dot(X, W1) + b1)
    OUT = np.dot(H1, W2) + b2
    scores = OUT
    train_num = X.shape[0]
    scores -= np.max(scores, axis=1, keepdims=True)
    #loss -= np.log(np.exp(scores[range(train_num),y]) / np.sum(np.exp(scores), axis=1))
    scores = np.exp(scores) / np.sum(np.exp(scores), axis=1, keepdims=True)
    loss -= np.log(scores[range(train_num),y])
    loss = np.sum(loss) 
    ds = np.copy(scores)
    ds[range(train_num),y] -= 1
    ds /= train_num
    
    db2 = np.sum(ds)
    dW2 = np.dot(H1.T, ds) + reg * 2 * W2
    
    dh1 = np.dot(ds, W2.T) * (H1 > 0)
    db1 = np.sum(dh1)
    dW1 = np.dot(X.T, dh1) + reg * 2 * W1
        
    loss /= train_num 
    loss += reg * np.sum(W1*W1) + reg * np.sum(W2*W2)

 其中为什么ds和loss都有/=train_num这一步呢,这样得到的都是相对于单个输入的,如果更换了batch_size也能用。

反向传播的时候,先把计算图画好,然后把每层神经元数量和各个变量的维数写清楚,就比较不容易错

 

每层神经元数量与参数数量

input(4),hidden(10),output(3)

X1(5*4)        H1(5*10)       OUT(5*3)

W1(4*10)     W2(10*3)

b1(10,)         b2(3,)

 

训练曲线

cs231n训练营学习笔记(8)简单双层全连接神经网络_第4张图片

num_iters=1000, batch_size=200,迭代1000次,每次200个

cs231n训练营学习笔记(8)简单双层全连接神经网络_第5张图片

每个Epoch会衰减一次学习率

learning_rate *= learning_rate_decay

 每个Epoch处理的数据的数量等于所有训练集数量,但是是通过多次minibatch迭代做的

比如这个例子是49000个训练样本,每次迭代200个,每245次迭代后衰减学习率

SGD就会比原始方法更快更新权重值,快245倍

上面的图能看出来loss大致是线性衰减的,这说明学习率设低了

图还能看出来,训练和验证的准确性没有差异,说明模型性能低,要加深扩大模型来更加过拟合一些。

 

python中的lambda argument_list: expression,即lambda 参数列表:单行表达式

cs231n训练营学习笔记(8)简单双层全连接神经网络_第6张图片

这里就是定义了一个函数f,输入x,输出sigmoid

 

有研究证明,神经网络可以近似任何连续函数,虽然在理论上深层网络(使用了多个隐层)和单层网络的表达能力是一样的,但是就实践经验而言,深度网络效果比单层网络好。

另外,在实践中3层的神经网络会比2层的表现好,然而继续加深(做到4,5,6层)很少有太大帮助。卷积神经网络的情况却不同,在卷积神经网络中,对于一个良好的识别系统来说,深度是一个极端重要的因素,因为图像拥有层次化结构。

最后,不应该因为害怕出现过拟合而使用小网络。相反,应该进尽可能使用大网络,然后使用正则化技巧来控制过拟合,因为训练一个大的网络,你将发现许多不同的解决方法,但是最终损失值的差异将会小很多。这就是说,所有的解决办法都差不多,而且对于随机初始化参数好坏的依赖也会小很多。

你可能感兴趣的:(cs231n)