【神经网络入门】- 备忘笔记 (自用)

用到的函数


# 计算导数
def numerical_diff(f, x):
    h = 1e-4 # 0.0001
    return (f(x+h) - f(x-h)) / (2*h)

# 计算所有偏导数    =梯度
def numerical_gradient(f, x):
    h = 1e-4 # 0.0001
    grad = np.zeros_like(x) # 生成和x形状相同的数组
    for idx in range(x.size):
        tmp_val = x[idx]
        # f(x+h) 的计算
        x[idx] = tmp_val + h
        fxh1 = f(x)
        # f(x-h) 的计算
        x[idx] = tmp_val - h
        fxh2 = f(x)
        grad[idx] = (fxh1 - fxh2) / (2*h)
        x[idx] = tmp_val # 还原值
    return grad

# 梯度下降法 x0 = x0 - lr*grad
def gradient_descent(f, init_x, lr=0.01, step_num=100):
    x = init_x
    x_history = []

    for i in range(step_num):
        x_history.append( x.copy() )

        grad = numerical_gradient(f, x)
        x -= lr * grad

    return x, np.array(x_history)


def softmax(x):
    if x.ndim == 2:
        x = x.T
        x = x - np.max(x, axis=0)
        y = np.exp(x) / np.sum(np.exp(x), axis=0)
        return y.T

    x = x - np.max(x) # 溢出对策
    return np.exp(x) / np.sum(np.exp(x))

# 激活函数 softmax  元素和为1
# softmax函数的输出是0.0到1.0之间的实数。并且,softmax
# 函数的输出值的总和是1
def softmax(a):
    exp_a = np.exp(a)
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a
    return y

def softmax(a):
    c = np.max(a)
    exp_a = np.exp(a - c) # 溢出对策
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a
    return y

# 激活函数  平滑   阶跃函数和sigmoid函数 ReLU(Rectified Linear Unit)函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

在这里插入图片描述

// 3层神经网络的实现 代码实现
def init_network():
    with open("sample_weight.pkl", 'rb') as f:
        network = pickle.load(f)
    return network


def predict(network, x):
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']

    print(W1.shape)
    print(W2.shape)
    print(W3.shape)

    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, W3) + b3
    y = softmax(a3)

    return y

softmax函数

回归问题用恒等函数,分类问题用softmax函数

在这里插入图片描述
softmax函数的输出是0.0到1.0之间的实数。并且,softmax函数的输出值的总和是1。输出总和为1是softmax函数的一个重要性质。正因为有了这个性质,我们才可以把softmax函数的输出解释为“概率”。

3层神经网络的推理处理代码

import sys, os
sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import numpy as np
import pickle
from dataset.mnist import load_mnist
from common.functions import sigmoid, softmax


def get_data():
    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)
    return x_test, t_test


def init_network():
    with open("sample_weight.pkl", 'rb') as f:
        network = pickle.load(f)
    return network


def predict(network, x):
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']

    print(W1.shape)
    print(W2.shape)
    print(W3.shape)

    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, W3) + b3
    y = softmax(a3)

    return y


x, t = get_data()
print(x.shape)
network = init_network()
accuracy_cnt = 0

//评价它的识别精度(accuracy),即能在多大程度上正确分类
for i in range(len(x)):
    y = predict(network, x[i])
    p= np.argmax(y) # 获取概率最高的元素的索引
    if p == t[i]:
        accuracy_cnt += 1

print("Accuracy:" + str(float(accuracy_cnt) / len(x)))

损失函数

均方误差
在这里插入图片描述

4.2.5 为何要设定损失函数

在这里插入图片描述
在这里插入图片描述

交叉熵误差

在这里插入图片描述

梯度

在这里插入图片描述

神经网络的梯度

在这里插入图片描述

代码实现梯度
在这里插入图片描述

2层神经网络

# coding: utf-8
import sys, os

sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
from common.functions import *
from common.gradient import numerical_gradient


class TwoLayerNet:
    # 输入层的神经元数、隐藏层的神经元数、输出层的神经元数
    def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):
        # 初始化权重  params变量中保存了该神经网络所需的全部参数
        # params['W1'] 是第1层的权重,params['b1']是第1层的偏置。
        # params['W2']是第2层的权重,params['b2']是第2层的偏置

        self.params = {}
        self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
        self.params['b1'] = np.zeros(hidden_size)
        self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
        self.params['b2'] = np.zeros(output_size)

    def predict(self, x):
        W1, W2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']

        a1 = np.dot(x, W1) + b1
        z1 = sigmoid(a1)
        a2 = np.dot(z1, W2) + b2
        y = softmax(a2)

        return y

    # x:输入数据, t:监督数据
    def loss(self, x, t):
        y = self.predict(x)

        return cross_entropy_error(y, t)

    def accuracy(self, x, t):
        y = self.predict(x)
        y = np.argmax(y, axis=1)
        t = np.argmax(t, axis=1)

        accuracy = np.sum(y == t) / float(x.shape[0])
        return accuracy

    # 计算权重参数的梯度  ,计算各个参数相对于损失函数的梯度
    # x:输入数据, t:监督数据
    def numerical_gradient(self, x, t):
        loss_W = lambda W: self.loss(x, t)
        # grads['W1']是第1层权重的梯度,grads['b1']是第1层偏置的梯度。
        # grads['W2']是第2层权重的梯度,grads['b2']是第2层偏置的梯度
        grads = {}
        grads['W1'] = numerical_gradient(loss_W, self.params['W1'])
        grads['b1'] = numerical_gradient(loss_W, self.params['b1'])
        grads['W2'] = numerical_gradient(loss_W, self.params['W2'])
        grads['b2'] = numerical_gradient(loss_W, self.params['b2'])

        return grads

    # 计算权重参数的梯度。
    # numerical_gradient()的高速版,将在下一章实现
    def gradient(self, x, t):
        W1, W2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']
        grads = {}

        batch_num = x.shape[0]

        # forward
        a1 = np.dot(x, W1) + b1
        z1 = sigmoid(a1)
        a2 = np.dot(z1, W2) + b2
        y = softmax(a2)

        # backward
        dy = (y - t) / batch_num
        grads['W2'] = np.dot(z1.T, dy)
        grads['b2'] = np.sum(dy, axis=0)

        da1 = np.dot(dy, W2.T)
        dz1 = sigmoid_grad(a1) * da1
        grads['W1'] = np.dot(x.T, dz1)
        grads['b1'] = np.sum(dz1, axis=0)

        return grads



加法节点的反向传播

在这里插入图片描述
在这里插入图片描述

乘法节点的反向传播

在这里插入图片描述
在这里插入图片描述

ReLu层

在这里插入图片描述

在这里插入图片描述

Sigmoid层

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

Affine/Softmax层的实现

仿射变换
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Softmax-with-Loss 层

在这里插入图片描述
由于(y1,y2,y3)是 Softmax层的输 出 ,( t1,t2,t3)是监督数据,所以(y1−t1,y2−t2,y3−t3)是 Softmax层的输出和教师标签的差分。

神经网络的反向传播会把这个差分表示的误差传递给前面的层,这是神经网络学习中的重要性质。

神经网络学习的目的就是通过调整权重参数,使神经网络的输出(Softmax
的输出)接近教师标签。因此,必须将神经网络的输出与教师标签的误差高
效地传递给前面的层。刚刚的(y1−t1,y2−t2,y3−t3)正是 Softmax层的输出
与教师标签的差,直截了当地表示了当前神经网络的输出与教师标签的误差。

使用交叉熵误差作为softmax函数的损失函数后,反向传播得到
(y1 − t1,y2 − t2,y3 − t3)这样 “漂亮”的结果。实际上,这样“漂亮”
的结果并不是偶然的,而是为了得到这样的结果,特意设计了交叉
熵误差函数。回归问题中输出层使用“恒等函数”,损失函数使用
平方和误差”,也是出于同样的理由(3.5节)。也就是说,使用“平
方和误差”作为“恒等函数”的损失函数,反向传播才能得到(y1−
t1, y2 − t2, y3 − t3)这样“漂亮”的结果。

反向传播:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这里有错误 -1/s 应该为 1/s

在这里插入图片描述

SDG

在这里插入图片描述


class SGD:

    """随机梯度下降法(Stochastic Gradient Descent)"""
	//参数lr表示learning rate(学习率)
    def __init__(self, lr=0.01):
        self.lr = lr
        
    def update(self, params, grads):
        for key in params.keys():
            params[key] -= self.lr * grads[key] 


SGD低效的根本原因是,梯度的方向并没有指向最小值的方向

Momentum

在这里插入图片描述

AdaGrad

AdaGrad的Ada来自英文单词Adaptive,即“适当的”的意思
学习率衰减(learning rate decay)的方法,即随着学习的进行,使学习率逐渐减小。实际上,一开始“多”学,然后逐渐“少”学的方法,在神经网络的学习中经常被使用。

在这里插入图片描述

Adam

Momentum参照小球在碗中滚动的物理规则进行移动,AdaGrad为参
数的每个元素适当地调整更新步伐。如果将这两个方法融合在一起会怎么样呢?这就是Adam方法的基本思路。

在这里插入图片描述
Adam会设置3个超参数。一个是学习率(论文中以α出现),另外两个是一次momentum系数β1和二次momentum系数β2。根据论文,标准的设定值是β1为0.9,β2为0.999。设置了这些值后,大多数情况下都能顺利运行

对比4种方法:
在这里插入图片描述

观察权重初始值是如何影响隐藏层的激活值的分布的

在这里插入图片描述观察了各层的激活值分布,并从中了解到如果设定了合适的权重初始值,则各层的激活值分布会有适当的广度,从而可以顺利地进行学习。
那么,为了使各层拥有适当的广度,“强制性”地调整激活值的分布会怎样呢?实际上,Batch Normalization[11]方法就是基于这个想法而产生的。

Batch Normalization

在上一节,我们观察了各层的激活值分布,并从中了解到如果设定了合适的权重初始值,则各层的激活值分布会有适当的广度,从而可以顺利地进行学习。那么,为了使各层拥有适当的广度,“强制性”地调整激活值的分布会怎样呢?实际上,Batch Normalization[11]方法就是基于这个想法而产生的。

为什么Batch Norm这么惹人注目呢?因为Batch Norm有以下优点。
• 可以使学习快速进行(可以增大学习率)。
• 不那么依赖初始值(对于初始值不用那么神经质)。
• 抑制过拟合(降低Dropout等的必要性)

在这里插入图片描述
式(6.7)所做的是将mini-batch的输入数据{x1,x2,…,xm}变换为均值为0、方差为1的数据,非常简单。通过将这个处理插入到激活函数的前面(或者后面)A,可以减小数据分布的偏向。

权值衰减

权值衰减是一直以来经常被使用的一种抑制过拟合的方法。该方法通过在学习的过程中对大的权重进行惩罚,来抑制过拟合。很多过拟合原本就是因为权重参数取值过大才发生的。

在这里插入图片描述

Dropout

在这里插入图片描述
机器学习中经常使用集成学习。所谓集成学习,就是让多个模型单独进行学习,推理时再取多个模型的输出的平均值。用神经网络的语境来说,比如,准备5个结构相同(或者类似)的网络,分别进行学习,测试时,以这5个网络的输出的平均值作为答案。实验告诉们,通过进行集成学习,神经网络的识别精度可以提高好几个百分点。这个集成学习与Dropout有密切的关系。这是因为可以将Dropout理解为,通过在学习过程中随机删除神经元,从而每一次都让不同的模型进行学习。并且,推理时,通过对神经元的输出乘以删除比例(比如,0.5等),可以取得模型的平均值。也就是说,可以理解成,Dropout将集成学习的效果(模拟地)通过一个网络实现了。

超参数的验证

比如各层的神经元数量、batch大小、参数更新时的学习率或权值衰减等。如果这些超参数没有设置合适的值,模型的性能就会很差。虽然超参数的取值非常重要,但是在决定超参数的过程中一般会伴随很多的试错。本节将介绍尽可能高效地寻找超参数的值的方法。

训练数据用于参数(权重和偏置)的学习,验证数据用于超参数的性能评估。为了确认泛化能力,要在最后使用(比较理想的是只用一次)测试数据。

超参数的最优

在超参数的最优化中,如果需要更精炼的方法,可以使用贝叶斯最优化(Bayesian optimization)。贝叶斯最优化运用以贝叶斯定理为中心的数学理论,能够更加严密、高效地进行最优化。

在这里插入图片描述

卷积神经网络

CNN中新出现了卷积层(Convolution层)和池化层(Pooling层)

在这里插入图片描述

卷积层

全连接层存在的问题

全连接层存在什么问题呢?那就是数据的形状被“忽视”了。比如,输
入数据是图像时,图像通常是高、长、通道方向上的3维形状。但是,向全连接层输入时,需要将3维数据拉平为1维数据。实际上,前面提到的使用了MNIST数据集的例子中,输入图像就是1通道、高28像素、长28像素的(1,28,28)形状,但却被排成1列,以784个数据的形式输入到最开始的Affine层。

而卷积层可以保持形状不变。当输入数据是图像时,卷积层会以3维数据的形式接收输入数据,并同样以3维数据的形式输出至下一层。因此,在CNN中,可以(有可能)正确理解图像等具有形状的数据。另外,CNN中,有时将卷积层的输入输出数据称为特征图(feature map)。其中,卷积层的输入数据称为输入特征图(input featuremap), 输 出数据称为输出特征图(output feature map)。

乘积累加运算
在全连接的神经网络中,除了权重参数,还存在偏置。CNN中,滤波器的参数就对应之前的权重。并且,CNN中也存在偏置。

在这里插入图片描述
在这里插入图片描述

填充

在这里插入图片描述

步幅

在这里插入图片描述

下对于填充和步幅,如何计算输出大小。

在这里插入图片描述
通道数只能设定为和输入数据的通道数相同的值

通道方向上有多个特征图时,会按通道进行输入数据和滤波器的卷积运算,并将结果相加,从而得到输出

在这里插入图片描述

在这个例子中,数据输出是1张特征图。所谓1张特征图,换句话说,就是通道数为1的特征图。

在这里插入图片描述

如果要在通道方向上也拥有多个卷积运算的输出,该怎么做呢?为此,就需要用到多个滤波器(权重)。用图表示的话,如图7-11所示。

在这里插入图片描述

批处理

在这里插入图片描述

池化层

除了Max池化之外,还有Average池化等。相对于Max池化是从目标区域中取出最大值,Average池化则是计算目标区域的平均值。在图像识别领域,主要使用Max池化。

在这里插入图片描述

池化层有以下特征。

  • 没有要学习的参数
    池化层和卷积层不同,没有要学习的参数。池化只是从目标区域中取最大值(或者平均值),所以不存在要学习的参数。
  • 通道数不发生变化
    经过池化运算,输入数据和输出数据的通道数不会发生变化。如图7-15所示,计算是按通道独立进行的。
  • 对微小的位置变化具有鲁棒性(健壮)

基于im2col的展开

im2col这个名称是“image to column”的缩写,翻译过来就是“从图像到矩阵”的意思

对于输入数据,将应用滤波器的区域(3维方块)横向展开为1列。im2col会在所有应用滤波器的地方进行这个展开处理
在这里插入图片描述

在这里插入图片描述

接口

im2col (input_data, filter_h, filter_w, stride=1, pad=0)
• input_data―由(数据量,通道,高,长)的 4维数组构成的输入数据
• filter_h―滤波器的高
• filter_w―滤波器的长
• stride―步幅
• pad―填充

end

参考

  • 17
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值