第三章.神经网络的学习—损失函数

第三章.神经网络的学习

3.1 损失函数

损失函数是表示神经网络性能“恶劣程度”的指标,即当前神经网络对监督数据在多大程度上不拟合,在多大程度上不一致。

1.均方误差(mean_squared_error)

1).公式:

在这里插入图片描述

  • 参数说明:
    yk:神经网络输出
    tk:监督数据
    k:数据维度

2).代码实现:

import numpy as np


# 均方误差
def mean_squared_error(y, t):
    return 0.5 * np.sum((y - t) ** 2)


y = np.array([0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0])
t = np.array([0, 0, 1, 0, 0, 0, 0, 0, 0, 0])

mean_squared_error = mean_squared_error(y, t)
print(mean_squared_error)

3).结果显示:

在这里插入图片描述

2.交叉熵误差(cross_entropy_error)

1).公式:

  • 单个数据:
    在这里插入图片描述

  • 小批量(mini-bitch):
    在这里插入图片描述

  • 参数说明:
    yk :神经网络输出
    tk:监督数据
    ynk :第n个数据的第k个元素神经网络的值
    tnk:第n个数据的第k个元素监督数据的值
    k:数据维度
    N:N个数据

2).代码实现:

  • 注意:

    ①.函数内部在计算np.log时,加上一个微小值delta=1e-7.(原因:当出现np.log(0)时,np.log(0)会变为负无穷大的-inf,这样一来就会导致后续计算无法进行,作为保护政策,增加一个微小值可以防止负无穷大的发生。)

    ②.程序中的sample_weight.pkl文件的所在位置在上一章节导入方式中有涉及,放在工程的当前运行目录下: sample_weight.pkl
    在这里插入图片描述

·代码:

import pickle
import numpy as np
import sys, os

sys.path.append(os.pardir)
from dataset.mnist import load_mnist


# 加载数据
def get_data():
    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
    return x_train, t_train


# 初始化权重和偏置
def init_network():
    with open('sample_weight.pkl', 'rb') as f:
        network = pickle.load(f)
        return network


# 激活函数:sigmoid
def sigmoid(x):
    return 1 / (1 + np.exp(-x))


# 输出层函数:softmax
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))


# 正向传播:3层神经元,激活函数:sigmoid函数,输出层函数softmax函数
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) + b1
    z1 = sigmoid(a1)

    # 第二层
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)

    # 输出层
    a3 = np.dot(z2, W3) + b3
    y = softmax(a3)

    return y


# 交叉熵误差
def cross_entropy_error(y, t):
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)

    # 监督数据是one-hot-vector的情况下,转换为正确解标签的索引
    if t.size == y.size:
        t = t.argmax(axis=1)

    batch_size = y.shape[0]
    return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size


# 加载数据
x_train, t_train = get_data()

# 从训练数据中随机抽取10笔数据
train_size = x_train.shape[0]
batch_size = 10
batch_mask = np.random.choice(train_size, batch_size)
print(batch_mask)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]

network = init_network()
y_batch = predict(network, x_batch)

print(y_batch.shape)
print(t_batch.shape)

# 交叉熵误差
cross_entropy_error = cross_entropy_error(y_batch, t_batch)
print(cross_entropy_error)

3).结果显示:

在这里插入图片描述

3.在神经网络学习时,不能将识别精度作为指标的原因:参数的导数在绝大多数都为0,导致参数无法更新。

1).示意图:

在这里插入图片描述

  • 识别精度对微小的参数变化基本上没有什么反应,即便有反应,也是不连续的,突然的变化。

  • 阶跃函数:在绝大多数地方(除了0以外的地方)均为0,若使用了阶跃函数,即使将损失函数作为指标,参数的微小变化也会被阶跃函数抹杀,导致损失函数的值不会发生任何变化0。

  • sigmoid函数:不仅函数的输出(数轴的值)是连续变化的,导数(曲线的斜率)也是连续变化的,sigmoid函数的导数在任何地方都不为0,神经网络的学习得以正常进行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值