深度学习入门基于python的理论与实现-第三章神经网络

激活函数

激活函数是连接感知机和神经网络的桥梁

阶跃函数

阶跃函数是在感知机中使用的激活函数。

\[h(x)=\begin{cases} 0 \quad x<0\\ 1 \quad x>=0\\ \end{cases} \]

图像:
image

实现

import numpy as np


def step_function(x):
    y = x > 0
    return y.astype(np.int)


print(step_function(np.array([1, -1, 1, 3, -3, -4])))

sigmoid函数

\[h(x)=\frac{1}{1+e^{-x}} \]

其中\(e=2.7182...\)是纳皮尔常数。
图像:
image

实现

import numpy as np
import matplotlib.pyplot as plt


# numpy array具有广播功能
def sigmoid(x):
    return 1 / (1 + np.exp(-x))


# x = np.arange(-5, 5, 0.1)
# y = sigmoid(x)
# plt.plot(x, y)
# plt.ylim(-0.1, 1.1)
# plt.show()

在感知机中使用的是阶跃函数,在神经网络中我们引入了sigmoid函数。
可以先比较两种函数
从两方面去比较
不同点:

  1. 平滑性:阶跃函数是不平滑的,sigmoid函数是平滑的
  2. 返回值:阶跃函数只能返回两种值0|1,sigmoid可以返回的值是[0,1]之间的实数
    相同点:
  3. 从宏观上去看,两者的趋势比较一致或者说形状吧
  4. 两者均属于非线性函数

神经网络中的激活函数必须使用非线性函数。
为什么呢?
可以考虑使用线性函数,我们知道神经网络是一层一层这样叠加下去,使用线性函数的话,无论叠加多少层,到最后我们的函数都可以等价为只使用一个等价的线性函数

ReLU函数

\[h(x)=\begin{cases} 0 \quad x<0\\ x \quad x>=0\\ \end{cases} \]

图像
image
实现

import numpy as np
from matplotlib import pyplot as plt


def relu(x):
    return np.maximum(0, x)

# x = np.arange(-5, 5, 0.3)
# y = relu(x)
# plt.plot(x, y)
# plt.ylim(-5, 10)
# plt.show()

三层神经网络的实现

第0层到第1层

X = np.array([1.0, 0.5])
W1 = np.array([[0.1, 0.3, 0.5],
               [0.2, 0.4, 0.6]])
B1 = np.array([0.1, 0.2, 0.3])

# print(W1.shape)
# print(X.shape)
# print(B1.shape)

# 通过矩阵运算,使得信息向前传递
A1 = np.dot(X, W1) + B1
# 激活函数
Z1 = sigmoid(A1)

# print(A1)
# print(Z1)

第1层到第2层

W2 = np.array([[0.1, 0.4],
               [0.2, 0.5],
               [0.3, 0.6]])

B2 = np.array([0.1, 0.2])

A2 = np.dot(Z1, W2) + B2
Z2 = sigmoid(A2)
# print(A2)
# print(Z2)

第2层到输出层

# 第2层到输出层
W3 = np.array([[0.1, 0.3],
               [0.2, 0.4]])
B3 = np.array([0.1, 0.2])

A3 = np.dot(Z2, W3) + B2

# 恒等函数,将第2层结果传递到输出层
Y = identity_function(A3)

将上面代码整合一下就可以得到下面代码


def init_network():
    network = {}
    network['W1'] = np.array([[0.1, 0.3, 0.5],
                              [0.2, 0.4, 0.6]])
    network['B1'] = np.array([0.1, 0.2, 0.3])
    network['W2'] = np.array([[0.1, 0.4],
                              [0.2, 0.5],
                              [0.3, 0.6]])
    network['B2'] = np.array([0.1, 0.2])
    network['W3'] = np.array([[0.1, 0.3],
                              [0.2, 0.4]])
    network['B3'] = np.array([0.1, 0.2])

    return network


def forward(network, x):
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['B1'], network['B2'], network['B3']

    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 = identity_function(a3)

    return y


network = init_network()
x = np.array([1.0, 0.5])
y = forward(network, x)
print(y)

init_network()中做的工作是,初始化权重和偏置,并用一个字典存储作为返回值
forward,是将输入信号进行计算得出输出信号,[forward的含义是表示从输入到输出方向传递]

输出层设计

我们知道神经网络的运用一般是分类和回归,根据不同的任务,我们可以设计不同的输出,不同的输出可以通过不同的输出层激活函数来实现。
具体而言,回归问题使用恒等函数\((identity_function)\),分类问题使用\(softmax\)函数

恒等函数和softmax函数

恒等函数顾名思义就是恒等函数

import numpy as np

def identity_function(x):
    return x

softmax函数

\[y_k=\frac{e^{a_k}}{\sum_{i=1}^{n}{e^{a_i}}} \]

import numpy as np


def softmax(x):
    exp_x = np.exp(x)
    sum_exp_x = np.sum(exp_x)
    y = exp_x / sum_exp_x
    return y
 
# a = np.array([0.3, 2.9, 4.0])
# print(softmax(a))

softmax函数的一些小优化防止溢出

import numpy as np


def softmax(x):
    c = np.max(x)
    exp_x = np.exp(x - c)
    sum_exp_x = np.sum(exp_x)
    y = exp_x / sum_exp_x
    return y

softmax函数的性质,观察softmax函数的式子可以发现,softmax函数值在[0,1]内,同时所有的函数值加起来为1,这个性质和概率的的定义比较像,所以我们可以把它解释为概率

输出层的神经元数量

在分类问题中输出层神经元的数量由分类的类别确定

手写数字识别

机器学习解决问题一般分为两个步骤,一是学习,而是推理。
学习的过程就是最优化我们权重的过程,推理的过程是通过学习到的权重对问题进行处理。
推理的过程也被称之为前向传播\((forward propagation)\)

MINIST数据集

MINIST数据集通常是指手写数字识别数据集,其中包含大量的手写数字图像和相应的标签。这个数据集通常用于机器学习和深度学习领域的算法测试和验证。MINIST数据集包含了来自高中学生和美国人口普查局员工的手写数字样本,涵盖了数字0到9。
MINIST数据集通常包含以下几个部分:
训练集:用于训练机器学习模型的数据集,包含许多手写数字图像及其对应的标签。
测试集:用于评估模型性能的数据集,也包含手写数字图像及其标签,但是这些数据不用于模型的训练,只用于测试。
每个图像通常都是28x28像素的灰度图像,标签是0到9之间的数字,表示相应图像中的手写数字。MINIST数据集是一个相对较小的数据集,适合用于快速验证和测试机器学习模型的原型。

MINIST数据集是很多深度学习入门书上的例子,很经典。
有很大的学习价值。

神经网络的推理处理

# coding: utf-8
import pickle
import sys, os
from sigmoid import *
from softmax import *
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
import numpy as np
from dataset.mnist import load_mnist

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']
    a1 = np.dot(x, W1)
    z1 = sigmoid(a1)

    a2 = np.dot(z1, W2)
    z2 = sigmoid(a2)

    a3 = np.dot(z2, W3)
    y = softmax(a3)

    return y


# 输入数据
x, t = get_data()

# 创建网络

network = init_network()

# 精度(准确度的计算)
accuracy_cnt = 0
for i in range(len(x)):
    y = predict(network, x[i])
    # 获取概率最高的索引
    p = np.argmax(y)
    if p == t[i]:
        accuracy_cnt = accuracy_cnt + 1

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

批处理

  1. 向量化运算: 在现代的深度学习框架中,通常会利用高度优化的线性代数库(如NumPy、TensorFlow、PyTorch等)来执行批处理操作。这些库能够利用硬件加速器(如GPU)进行并行化操作,从而高效地进行向量化运算。相比逐个样本处理,批处理可以充分发挥这些库的优势,使得计算速度大大提高。

  2. 减少数据传输开销: 在训练过程中,数据的传输开销可能成为瓶颈之一,尤其是当数据量较大时。通过批处理,可以减少数据传输的次数,因为一次传输可以处理多个样本。这样可以显著减少由数据传输引起的延迟。

  3. 优化内存访问: 当处理一批数据时,可以利用现代计算机架构的缓存机制,从而更有效地利用内存。在批处理中,连续的数据通常会被放置在内存中相邻的位置,这有助于减少内存访问的随机性,提高数据访问效率。

  4. 并行计算: 许多深度学习框架支持在GPU上并行计算,批处理可以更充分地利用GPU的并行计算能力。通过一次处理多个样本,可以同时执行多个神经网络计算步骤,从而加快整体训练速度。


x, t = get_data()
network = init_network()

batch_size = 100  # 批数量
accuracy_cnt = 0

# range(start, end, step),start表示起始下标,end表示结束下标的下一个,step为步长[start, end)
for i in range(0, len(x), batch_size):
	# numpy中的切片操作
    x_batch = x[i:i + batch_size]
    y_batch = predict(network, x_batch)
    # axis=1表示确定第0维求,第二维最大值的下标
	p = np.argmax(y_batch, axis=1)
    accuracy_cnt += np.sum(p == t[i:i + batch_size])

print("Accuracy:" + str(float(accuracy_cnt) / len(x)))
posted @ 2024-03-15 20:13  cxy8  阅读(5)  评论(0编辑  收藏  举报