神经网络入门学习笔记

原创 2018年04月17日 20:59:07

关于神经网络的一些基本概念在这里就不做介绍,首先我们进行一些概念和符号上的约定。

假设一个矩阵如下:

X=[123231321]

点乘

XX=[112233223311332211]=[149491941]

叉乘*

XX=[11+22+3312+23+3213+21+3121+32+1322+33+1223+31+1131+22+1332+23+1233+21+11]=[14148111510101412]

已知数据: 矩阵X为训练数据集,矩阵y为训练数据集的标签

最简单的神经网络

基于Numpy实现神经网络:反向传播

最简单的神经网络就是只有输入层和输出层的网络结构(双层神经网络)。

关于激活函数简单介绍:

如果不使用激活函数,那么就与多层感知机(MLP)相当。引入之后,下一层的输入就不再是线性组合,输出就有意义。

如果不使用激活函数,那么输入与输出都是线性变换,无法做到非线性分类。

激活函数

这是公式,值域为[0,1],它的导数自证。

作用:

  1. 引入非线性因素
  2. 线性变换
  3. 激活函数,并不是去激活什么,而是指如何把“激活的神经元的特征”通过函数把特征保留并映射出来(保留特征,去除一些数据中是的冗余。激励就是样本的特征值),这是神经网络能解决非线性问题关键。

sigmoid的导数,即使用了deriv=True

作用:用它的输出创建它的导数,降低高信度预测的错误

注意:如果神经网络提前达到预期的结果(损失函数小于一定的范围),可以提前终止

# coding: utf-8
# 矩阵计算
import numpy as np
# 生成随机数
import random

# 定义激活函数, 这里用sigmoid函数
def sigmoid(x, deriv=False):
    # 如果满足条件就返回sigmoid的导数
    if (deriv == True):
        return x * (1 - x)
    # 不满足直接返回sigmoid函数
    return 1 / (1 + np.exp(-x))

# 指定训练数据, X规模为4x3, y规模为4x1
X = np.array([[0,0,1],[0,1,1],[1,0,1],[1,1,1]])
y = np.array([[0,1,1,0]]).T

# 初始化权重数据, 用随机数进行初始化,矩阵规模3x1
syn_0 = 2 * np.random.random((3, 1)) - 1

# 进行迭代
for _ in range(10000):
    # 输入层为训练数据
    l0 = X
    # np.dot表示叉乘, 进行激活操作, 输出层
    l1 = sigmoid(np.dot(l0, syn_0))
    # 计算偏差
    l1_error = y - l1
    # 误(偏)差加权导数。偏差乘以sigmoid在l1处的斜率,用以更新权重
    l1_delta = l1_error * sigmoid(l1, deriv=True)
    syn_0 += np.dot(l0.T, l1_delta)

# 训练完成,输出l1看看
print(l1)

三层神经网络

增加了一层网络,在输入层和输出层中间。这里做一个规定,在输入层和输出层之间的网络结构我们称为隐藏层。

一层隐层网络就是一层特征层次,每一个神经元可以类似看作一个特征属性

# coding: utf-8
import numpy as np
import random

def sigmoid(x, deriv=False):
    if (deriv == True):
        return x * (1 - x)
    return 1 / (1 + np.exp(-x))
X = np.array([[0,0,1],[0,1,1],[1,0,1],[1,1,1]])
y = np.array([[0,1,1,0]]).T

# 初始化权重数据, 用随机数进行初始化, 这里的规模同X、y矩阵的规模
syn_0 = 2 * np.random.random((3, 4)) - 1
syn_1 = 2 * np.random.random((4, 1)) - 1

for _ in range(10000):
    l0 = X
    l1 = sigmoid(np.dot(l0, syn_0))
    # 加了一层神经网络,称为隐藏层
    l2 = sigmoid(np.dot(l1, syn_1))
    l2_error = y - l2
    l2_delta = l2_error * sigmoid(l2, deriv=True)
    # 计算完l2的误差之后,再用结果去计算l1的误差
    l1_error = np.dot(l2_delta, syn_1.T)
    l1_delta = l1_error * sigmoid(l1, deriv=True)
    syn_1 += np.dot(l1.T, l2_delta)
    syn_0 += np.dot(l0.T, l1_delta)

print(l1)

改进神经网络v1.0——增加梯度

A Neural Network in 13 lines of Python (Part 2 - Gradient Descent)

关于梯度的定义请自行了解。

增加了梯度可以更快的找到较为理想的结果。

关于梯度上升有下面几种方法(梯度下降同理):

  1. 原始的梯度上升

    目标:找到某个函数的最大值。每次沿函数的梯度方向探寻。一直进行迭代,直到到达某个停止条件(迭代次数限制或某个误差范围)

  2. 随机梯度上升(SGD)

    不同点在于,第一种方法每次是遍历所有的数据集(一百以内的数据集可以接受用上面的方法)。而随机梯度则是只使用一个样本点来更新回归系数。

  3. 改进版随机梯度上升

    用随机的一个样本来更新回归系数。

  4. 批梯度上升

    切分样本集,随机取出切分后的某些样本,进行遍历

损失函数(代价函数)

  1. 二次代价函数

    C=12nn[y(x)aL(x)]2

  2. 交叉熵代价函数

    C=12nx[ylna(1y)ln(1a)]

  3. 对数似然函数

    C=1nxkyklogak

    前向传播是函数求偏导,反向传播减少了这个计算量

# coding: utf-8
import numpy as np
import random

def sigmoid(x, deriv=False):
    if (deriv == True):
        return x * (1 - x)
    return 1 / (1 + np.exp(-x))
X = np.array([[0,0,1],[0,1,1],[1,0,1],[1,1,1]])
y = np.array([[0,1,1,0]]).T

syn_0 = 2 * np.random.random((3, 4)) - 1
syn_1 = 2 * np.random.random((4, 1)) - 1

# 加入步长
alphas = [0.001,0.01,0.1,1,10,100,1000]

for alpha in alphas:
    for _ in range(10000):
        l0 = X
        l1 = sigmoid(np.dot(l0, syn_0))
        # 加了一层神经网络,称为隐藏层
        l2 = sigmoid(np.dot(l1, syn_1))
        l2_error = y - l2
        l2_delta = l2_error * sigmoid(l2, deriv=True)
        # 计算完l2的误差之后,再用结果去计算l1的误差
        l1_error = np.dot(l2_delta, syn_1.T)
        l1_delta = l1_error * sigmoid(l1, deriv=True)
        # 更新权重的时候加入步长
        syn_1 += alpha * np.dot(l1.T, l2_delta)
        syn_0 += alpha * np.dot(l0.T, l1_delta)

    print("alpha:", alpha, "l1:", l1)

改进神经网络v2.0——增加隐层

更改网络的神经元个数,这个可能就是所谓的玄学调参

# coding: utf-8
import numpy as np
import random

def sigmoid(x, deriv=False):
    if (deriv == True):
        return x * (1 - x)
    return 1 / (1 + np.exp(-x))
X = np.array([[0,0,1],[0,1,1],[1,0,1],[1,1,1]])
y = np.array([[0,1,1,0]]).T

# 定义神经元个数,随机
hidden_dim = np.random.randint(2, 8)

syn_0 = 2 * np.random.random((3, hidden_dim)) - 1
syn_1 = 2 * np.random.random((hidden_dim, 1)) - 1

for _ in range(10000):
    l0 = X
    l1 = sigmoid(np.dot(l0, syn_0))
    l2 = sigmoid(np.dot(l1, syn_1))
    l2_error = y - l2
    l2_delta = l2_error * sigmoid(l2, deriv=True)
    l1_error = np.dot(l2_delta, syn_1.T)
    l1_delta = l1_error * sigmoid(l1, deriv=True)
    syn_1 += np.dot(l1.T, l2_delta)
    syn_0 += np.dot(l0.T, l1_delta)

print(l1)

改进神经网络v3.0——dropout

Hinton’s Dropout in 3 Lines of Python

增加dropout_percent。目的是为了防止过拟合,一种正则化的手段。在迭代的时候,对某一(几)层神经网络进行drop_out。这里举例用二项分布采样的方法进行。np.random.binomial(n, p, size=None)

Dropout是指在模型训练时随机让网络某些隐含层节点的权重不工作,不工作的那些节点可以暂时认为不是网络结构的一部分,但是它的权重得保留下来(只是暂时不更新而已)。

一些理由解释:

  1. 权值的更新不依赖于一些固定关系隐含节点的共同作用。阻止了某些特征仅仅在其它特定特征下才有效果的情况。即随机选取当前隐含层的部分节点
  2. 模型平均概念(选取每次计算过程的相对最优解),使用了dropout之后每次的网络结构不同,样本不同对应的输出模型也不同。(个人感觉有点像加入随机)
  3. 生物进化解释,不断适应变化情况,有效阻止过拟合(避免环境改变物种面临死亡)
  4. 朴素贝叶斯(native bayes)属于dropout的一种特例:各个特征之间相互独立。在训练样本少的情况下,单独对每个特征进行学习(dropout是训练一部分特征)。

这里假设对l1进行drop_out。

定义len(x)=3, hidden_dim=4, dropout_percent=0.2

代入数值计算,

np.random.binomial([array([[ 1.,  1.,  1.,  1.],
                         [ 1.,  1.,  1.,  1.],
                         [ 1.,  1.,  1.,  1.]])], 0.8)[0] * (1/0.8)
# 默认的dropout_percent是0.5, 即如果不加如dropout_percent的话
# 如果是对图像进行操作的话,建议不超过0.25
dropout_percent = 0.2

...
l1 *= np.random.binomial([np.ones((len(X), hidden_dim))],1 - dropout_percent)[0] *(1.0/(1 - dropout_percent))
...

P.S:

对二项分布进行采样。这里的n为[np.ones((len(X), hidden_dim))],p为1-dropout_percent

np.random.binomial(n, p, size=None)

公式如下:

P(N)=Cn0p0(1p)n=(1p)n

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wnma3mz/article/details/79980706

自然语言处理的神经网络入门学习笔记

  • 2018年03月06日 22:16
  • 13.52MB
  • 下载

Andrew Ng机器学习入门学习笔记(四)之神经网络(二)

本文主要记录了神经网络的代价函数,神经网络中梯度下降的用法,反向传播,梯度检验,随机初始化等理论,并附上课程作业中相关部分的matlab代码及注释。有关神经网络的概念,模型,以及利用前向传播预测分类的...
  • SCUT_Arucee
  • SCUT_Arucee
  • 2015-12-04 15:54:48
  • 2719

Lua学习笔记(1):简单入门

前言:在 jetson TX1 上安装 torch 的时候,安装了 LUA。 原因:github 上很多神经网络(例如我想用的RNN,lstm等),用的是torch框架,而torch主要得益于一个简单...
  • moses1994
  • moses1994
  • 2017-03-23 12:02:11
  • 632

深度学习笔记——TensorFlow学习笔记(一)入门

本文只是在学习TensorFlow前期的一些入门知识总结,并结合一个用TensorFlow实现神经网络的例子来进一步加深对TensorFlow的理解。...
  • mpk_no1
  • mpk_no1
  • 2017-06-02 22:54:11
  • 2063

TensorFlow学习笔记(4)——深层神经网络

1 深度学习与深层神经网络维基百科对深度学习的精确定义为“一类通过多层非线性变换对高复杂性数据建模算法的合集”。可见深度学习的两个重要特性:多层和非线性。1 非线性模型的局限性一个线性模型中通过输入得...
  • Eric_KEY
  • Eric_KEY
  • 2017-07-16 22:18:14
  • 887

王小草【深度学习】笔记第一弹--神经网络

【深度学习】笔记第一弹–神经网络王小草深度学习笔记课程来自:寒小阳 笔记整理者:王小草 时间:2016/08/15 欢迎交流:qq:1057042131...
  • sinat_33761963
  • sinat_33761963
  • 2016-08-16 12:33:48
  • 2825

Andrew Ng机器学习入门学习笔记(四)之神经网络(一)

一.神经网络的优势对于复杂的非线性分类问题,当特征变量个数nn很大时,用逻辑回归时S型函数g(θTx)中的θTxS型函数g(\theta^Tx)中的\theta^Tx如果用二次多项式表示,则二次项数目...
  • SCUT_Arucee
  • SCUT_Arucee
  • 2015-12-02 09:58:04
  • 2131

神经网络入门基础知识 neural networks basics

神经网络入门基础知识 neural networks basics 也许现在提到深度学习(deep learning)连非计算机专业的人都听说过,尤其是最近“人机大战”更是掀起了人们对深度学习的极...
  • u012328159
  • u012328159
  • 2016-04-13 22:29:25
  • 12420

脉冲神经网络学习笔记(综述)

脉冲神经网络学习笔记,是综述性质的学习笔记
  • sadfassd
  • sadfassd
  • 2017-11-26 16:03:05
  • 1601

神经网络入门 ,源码1

神经网络源码1 (以下为《神经网络入门》连载1-6 相关的cpp文件,不含头文件) 目 录...
  • zzwu
  • zzwu
  • 2017-03-17 17:53:16
  • 1651
收藏助手
不良信息举报
您举报文章:神经网络入门学习笔记
举报原因:
原因补充:

(最多只允许输入30个字)