【深度学习入门:基于Python的理论与实现】

感知机

感知机接收多个输入信号,输出一个信号。感知机的信号只有“流 / 不流”(1/0)两种取值。在本书中,0 对应“不传递信号”,1 对应“传递信号”。图 2-1 是一个接收两个输入信号的感知机的例子。x1、x2 是输入信号, y是输出信号,w1、w2 是权重(w是weight的首字母)。图中的○称为“神经元”或者“节点”。输入信号被送往神经元时,会被分别乘以固定的权重(w1x1、w2x2)。神经元会计算传送过来的信号的总和,只有当这个总和超过了某个界限值时,才会输出1。这也称为“神经元被激活”。这里将这个界限值称为阈值,用符号 θ 表示。
图 2-1 有两个输入的感知机
把上述内容用数学式来表示,就是式(2.1):
请添加图片描述
把式(2.1)的θ换成−b,于是就可以用式(2.2)来表示感知机的行为。
请添加图片描述

这里把−θ命名为偏置b,注意偏置和权重w1、w2的作用是不一样的。具体地说,w1和w2是控制输入信号的重要性的参数,权重越大,对应该权重的信号的重要性就越高。而偏置是调整神经元被激活的容易程度(输出信号为1的程度)的参数。

叠加了多 层的感知机也称为多层感知机。
“单层感知机无法表示的东西,通过增加一层就可以解决”。也就是说,通过叠加层(加深层),感知机能进行更加灵活的表示。

神经网络

感知机的缺点是需要人工设定即确定合适的、能符合预期的输入与输出的权重,而神经网络可以自动地从数据中学习到合适的权重参数。

从感知机到神经网络

神经网络的例子

图3-1 神经网络的例子

本书约定:

  1. 图3-1中,第0层对应输入层,第1层对应中间层,第2层对应输出层
    图3-1中的网络一共由3层神经元构成,但实质上只有2层神经元有权重,因此将其称为“2层网络”。有的书也会根据构成网络的层数,把图 3-1的网络称为3层网络。本书将根据
    实质上拥有权重的层数(输入层、隐藏层、输出层的总数减去 1后的数量)来表示网络的名称。

复习感知机

图3-2 复习感知机
图3-2中的感知机接收x1、x2、1三个输入信号,输出y。b是被称为偏置的参数,用于控制神经元被激活的容易程度;而w1和w2是表示各个信号的权重的参数,用于控制各个信号的重要性。用数学式来表示则如式(3.1)所示
在这里插入图片描述
图3-2将x1、x2、1三个信号作为神经元的输入,将其和各自的权重相乘后,传送至下一个神经元。在下一个神经元中,计算这些加权信号的总和。如果这个总和超过0,则输出1,否则输出0,我们用一个函数来表示这种分情况的动作,引入新函数h(x),将式(3.1)改写成下面的式(3.2)和式(3.3)。
在这里插入图片描述
在这里插入图片描述

激活函数登场

刚才登场的h(x)函数会将输入信号的总和转换为输出信号,这种函数一般称为激活函数,用于决定如何来激活输入信号的总和。
如果将式(3.2)写得详细一点,则可以分成下面两个式子:
在这里插入图片描述
如果要在图中明确表示出式(3.4)和式(3.5),则可以像图3-4这样做。
图3-4 明确显示激活函数的计算过程
如图3-4所示,表示神经元的○中明确显示了激活函数的计算过程,即信号的加权总和为神经元a,然后神经元a被激活函数h()转换成神经元y

激活函数是连接感知机和神经网络的桥梁。本书在使用“感知机”一词时,没有严格统一它所指的算法。一般而言,“朴素感知机”是指单层网络,指的是激活函数使用了阶跃函数A 的模型。“多层感知机”是指神经网络,即使用 sigmoid函数(后述)等平滑的激活函数的多层网络。

激活函数

式(3.3)表示的激活函数以阈值为界,一旦输入超过阈值,就切换输出。这样的函数称为“阶跃函数”。因此,可以说感知机中使用了阶跃函数作为激活函数。如果将激活函数从阶跃函数换成其他函数,就可以进入神经网络的世界了。下面我们就来介绍一下神经网络使用的激活函数

sigmoid函数

神经网络中经常使用的一个激活函数就是式(3.6)表示的sigmoid函数
在这里插入图片描述

阶跃函数的实现

阶跃函数如式(3.3)所示,当输入超过0时,输出1,否则输出0。可以像下面这样简单地实现阶跃函数。

def step_function(x):
 if x > 0:
 return 1
 else:
 return 0

上述实现中,参数x只能接受实数(浮点数),不允许参数取NumPy数组。为了便于后面的操作,我们把它修改为支持NumPy数组的实现,先准备一个NumPy数组x,并对这个NumPy数组进行了不等号运算。

>>> import numpy as np
>>> x = np.array([-1.0, 1.0, 2.0])
>>> x
array([-1., 1., 2.])
>>> y = x > 0
>>> y
array([False, True, True], dtype=bool)

对NumPy数组进行不等号运算后,数组的各个元素都会进行不等号运算,生成一个布尔型数组。这里,数组x中大于0的元素被转换为True,小于等于0的元素被转换为False,从而生成一个新的数组y。
数组y是一个布尔型数组,但是我们想要的阶跃函数是会输出int型的0或1的函数。因此,需要把数组y的元素类型从布尔型转换为int型。

>>> y = y.astype(np.int)
>>> y
array([0, 1, 1])

如上所示,可以用astype()方法转换NumPy数组的类型。astype()方法通过参数指定期望的类型,这个例子中是np.int型。Python中将布尔型转换为int型后,True会转换为1,False会转换为0

sigmoid函数的实现

def sigmoid(x):
 return 1 / (1 + np.exp(-x))

参数x为NumPy数组时,结果也能被正确计算,这是因为NumPy的广播功能

sigmoid函数和阶跃函数的比较

图3-8 阶跃函数与sigmoid函数(虚线是阶跃函数)
相同点:

  1. 具有相似的形状。实际上,两者的结构均是“输入小时,输出接近0(为0);随着输入增大,输出向1靠近(变成1)”。也就是说,当输入信号为重要信息时,阶跃函数和sigmoid函数都会输出较大的值;当输入信号为不重要的信息时,两者都输出较小的值。
  2. 不管输入信号有多小,或者有多大,输出信号的值都在0到1之间
  3. 两者均为非线性函数。

神经网络的激活函数必须使用非线性函数。因为使用线性函数的话,加深神经网络的层数就没有意义了。线性函数的问题在于,不管如何加深层数,总是存在与之等效的“无隐藏层的神经网络”。

不同点:

  1. “平滑性”的不同。sigmoid函数是一条平滑的曲线,输出随着输入发生连续性的变化。而阶跃函数以0为界,输出发生急剧性的变化。
  2. 相对于阶跃函数只能返回0或1,sigmoid函数可以返回0.731 …、0.880 …等实数(这一点和刚才的平滑性有关)。也就是说,感知机中神经元之间流动的是0或1的二元信号,而神经网络中流动的是连续的实数值信号。

ReLU函数

在神经网络发展的历史上,sigmoid函数很早就开始被使用了,而最近则主要使用ReLU(Rectified Linear Unit)函数。ReLU函数在输入大于0时,直接输出该值;在输入小于等于0时,输
出0(图3-9)。ReLU函数可以表示为下面的式(3.7)。
在这里插入图片描述
图3-9 ReLU函数
ReLU函数的实现:

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

3层神经网络的实现

符号确认

图3-16 权重的符号
权重和隐藏层的神经元的右上角有一个“(1)”,它表示权重和神经元的层号(即第1层的权重、第1层的神经元)。此外,权重的右下角有两个数字,它们是后一层的神经元和前一层的神经元的索引号。

代码实现

# 保存每一层所需的参数(权重和偏置)
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) # [ 0.31682708 0.69627909]

输出层的设计

神经网络可以用在分类问题和回归问题上,不过需要根据情况改变输出层的激活函数。一般而言,回归问题用恒等函数,分类问题用softmax函数。

机器学习的问题大致可以分为分类问题和回归问题。分类问题是数据属于哪一个类别的问题。比如,区分图像中的人是男性还是女性的问题就是分类问题。而回归问题是根据某个输入预测一个(连续的)数值的问题。比如,根据一个人的图像预测这个人的体重的问题就是回归问题(类似“57.4kg”这样的预测)

恒等函数和softmax函数

恒等函数会将输入按原样输出,对于输入的信息,不加以任何改动地直接输出。
分类问题中使用的softmax函数可以用下面的式(3.10)表示,其输出可以理解为“概率”
在这里插入图片描述
实现softmax函数

>>> a = np.array([0.3, 2.9, 4.0])
>>>
>>> exp_a = np.exp(a) # 指数函数
>>> print(exp_a)
[ 1.34985881 18.17414537 54.59815003]
>>>
>>> sum_exp_a = np.sum(exp_a) # 指数函数的和
>>> print(sum_exp_a)
74.1221542102
>>>
>>> y = exp_a / sum_exp_a
>>> print(y)
[ 0.01821127 0.24519181 0.73659691]

上面的实现虽然正确描述了式(3.10),但在计算机的运算上可能出现溢出问题。softmax函数的实现中要进行指数函数的运算,但是此时指数函数的值很容易变得非常大。比如,e10的值会超过20000,e100会变成一个后面有40多个0的超大值,e1000的结果会返回一个表示无穷大的inf。如果在这些超大值之间进行除法运算,结果会出现“不确定”的情况。据此,我们做以下改进:
在这里插入图片描述
首先,式(3.11)在分子和分母上都乘上C这个任意的常数。然后,把这个C移动到指数函数(exp)中,记为log C。最后,把log C替换为另一个符号C’。式(3.11)说明,在进行softmax的指数函数的运算时,加上(或者减去)某个常数并不会改变运算的结果。这里的C’可以使用任何值,但是为了防止溢出,一般会使用输入信号中的最大值。综上,我们可以像下面这样实现softmax函数。

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

一般而言,神经网络只把输出值最大的神经元所对应的类别作为识别结果。并且,即便使用softmax函数,输出值最大的神经元的位置也不会变。因此,神经网络在进行分类时,输出层的softmax函数可以省略。在实际的问题中,由于指数函数的运算需要一定的计算机运算量,因此输出层的softmax函数一般会被省略。

求解机器学习问题的步骤可以分为“学习”A 和“推理”两个阶段。首先,在学习阶段进行模型的学习B,然后,在推理阶段,用学到的模型对未知的数据进行推理(分类)。如前所述,推理阶段一般会省略输出层的 softmax函数。在输出层使用 softmax函数是因为它和神经网络的学习有关系

输出层的神经元数量

对于分类问题,输出层的神经元数量一般设定为类别的数量。

手写数字识别

和求解机器学习问题的步骤(分成学习和推理两个阶段进行)一样,使用神经网络解决问题时,也需要首先使用训练数据(学习数据)进行权重参数的学习;进行推理时,使用刚才学习到的参数,对输入数据进行分类,推理处理也称为神经网络的前向传播

MNIST数据集

MNIST数据集的一般使用方法是,先用训练图像进行学习,再用学习到的模型度量能在多大程度上对测试图像进行正确的分类。MNIST的图像数据是28像素 × 28像素的灰度图像(1通道),各个像素
的取值在0到255之间。每个图像数据都相应地标有“7”“2”“1”等标签。
本书提供了便利的Python脚本mnist.py,该脚本支持从下载MNIST数据集到将这些数据转换成NumPy数组等处理(mnist.py在dataset目录下),使用mnist.py中的load_mnist()函数,就可以按下述方式轻松读入MNIST数据。

import sys, os
sys.path.append(os.pardir) # 为了导入父目录中的文件而进行的设定
from dataset.mnist import load_mnist
# 第一次调用会花费几分钟 ……
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True,
normalize=False)
# 输出各个数据的形状
print(x_train.shape) # (60000, 784)
print(t_train.shape) # (60000,)
print(x_test.shape) # (10000, 784)
print(t_test.shape) # (10000,)

上述代码在mnist_show.py文件中。mnist_show.py文件的当前目录是ch03,但包含load_mnist()函数的mnist.py文件在dataset目录下。因此,mnist_show.py文件不能跨目录直接导入mnist.py文件。sys.path.append(os.pardir)语句实际上是把父目录deep-learning-from-scratch加入到sys.path(Python的搜索模块的路径集)中,从而可以导入deep-learning-from-scratch下的任何目录(包括dataset目录)中的任何文件
load_mnist函数以“(训练图像 ,训练标签 ),(测试图像,测试标签 )”的形式返回读入的MNIST数据。此外,还可以像load_mnist(normalize=True, flatten=True, one_hot_label=False) 这 样,设 置 3 个 参 数。第 1 个参数normalize设置是否将输入图像正规化为0.0~1.0的值。如果将该参数设置为False,则输入图像的像素会保持原来的0~255。第2个参数flatten设置是否展开输入图像(变成一维数组)。如果将该参数设置为False,则输入图像为1 × 28 × 28的三维数组;若设置为True,则输入图像会保存为由784个元素构成的一维数组。第3个参数one_hot_label设置是否将标签保存为one-hot表示(one-hot representation)。one-hot表示是仅正确解标签为1,其余皆为0的数组,就像[0,0,1,0,0,0,0,0,0,0]这样。当one_hot_label为False时,只是像7、2这样简单保存正确解标签;当one_hot_label为True时,标签则保存为one-hot表示

Python有 pickle这个便利的功能。这个功能可以将程序运行中的对象保存为文件。如果加载保存过的 pickle文件,可以立刻复原之前程序运行中的对象。用于读入MNIST数据集的load_mnist()函数内部也使用了 pickle功能(在第 2次及以后读入时)。利用 pickle功能,可以高效地完成MNIST数据的准备工作。

显示一张MNIST图像(源代码在ch03/mnist_show.py中)

import sys, os
sys.path.append(os.pardir)
import numpy as np
from dataset.mnist import load_mnist
from PIL import Image
def img_show(img):
 pil_img = Image.fromarray(np.uint8(img))
 pil_img.show()
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True,
normalize=False)
img = x_train[0]
label = t_train[0]
print(label) # 5
print(img.shape) # (784,)
img = img.reshape(28, 28) # 把图像的形状变成原来的尺寸
print(img.shape) # (28, 28)
img_show(img)

这里需要注意的是,flatten=True时读入的图像是以一列(一维)NumPy数组的形式保存的。因此,显示图像时,需要把它变为原来的28像素 × 28像素的形状。可以通过reshape()方法的参数指定期望的形状,更改NumPy数组的形状。此外,还需要把保存为NumPy数组的图像数据转换为PIL用的数据对象,这个转换处理由Image.fromarray()来完成。
图3-25 显示MNIST图像

神经网络的推理处理

神经网络 的输入层有 784 个神经元,输出层有 10 个神经元。输入层的 784 这个数字来 源于图像大小的 28 × 28 = 784,输出层的 10 这个数字来源于 10 类别分类(数 字 0 到 9,共 10 类别)。此外,这个神经网络有 2 个隐藏层,第 1 个隐藏层有 50 个神经元,第 2 个隐藏层有 100 个神经元。这个 50 和 100 可以设置为任何值。 下面我们先定义 get_data()、init_network()、predict() 这 3 个函数(代码在 ch03/neuralnet_mnist.py 中)。

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

# init_network()会读入保存在pickle文件sample_weight.pkl中的学习到的权重参数A。这个文件中以字典变量的形式保存了权重和偏置参数
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) + b1 z1 = sigmoid(a1)
	a2 = np.dot(z1, W2) + b2 z2 = sigmoid(a2)
	a3 = np.dot(z2, W3) + b3 y = softmax(a3)
	return y

首先获得 MNIST 数据集,生成网络。接着,用 for 语句逐一取出保存 在 x 中的图像数据,用 predict() 函数进行分类。predict() 函数以 NumPy 数 组的形式输出各个标签对应的概率。比如输出[0.1, 0.3, 0.2, …, 0.04]的 数组,该数组表示“0”的概率为 0.1,“1”的概率为 0.3,等等。然后,我们 取出这个概率列表中的最大值的索引(第几个元素的概率最高),作为预测结 果。可以用 np.argmax(x) 函数取出数组中的最大值的索引,np.argmax(x) 将 获取被赋给参数 x 的数组中的最大值元素的索引。最后,比较神经网络所预 测的答案和正确解标签,将回答正确的概率作为识别精度。

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 += 1
		
print("Accuracy:" + str(float(accuracy_cnt) / len(x)))

执行上面的代码后,会显示“Accuracy:0.9352”。这表示有 93.52 % 的数据被正确分类了

在这个例子中,我们把 load_mnist 函数的参数 normalize 设置成了 True。将 normalize 设置成 True 后,函数内部会进行转换,将图像的各个像 素值除以 255,使得数据的值在 0.0~1.0 的范围内。像这样把数据限定到某 个范围内的处理称为正规化(normalization)。此外,对神经网络的输入数据 进行某种既定的转换称为预处理(pre-processing)。这里,作为对输入图像的 一种预处理,我们进行了正规化。
实际上,很多预处理都会考虑到数据的整体分布。比如,利用数据 整体的均值或标准差,移动数据,使数据整体以 0 为中心分布,或 者进行正规化,把数据的延展控制在一定范围内。除此之外,还有 将数据整体的分布形状均匀化的方法,即数据白化(whitening)等。

批处理

使用 Python 解释器,输出刚才的神经网络的各层的权重的形状。

>>> x, _ = get_data()
>>> network = init_network()
>>> W1, W2, W3 = network['W1'], network['W2'], network['W3'] 
>>>
>>> x.shape (10000, 784) >>> x[0].shape (784,)
>>> W1.shape
(784, 50) 
>>> W2.shape 
(50, 100) 
>>> W3.shape 
(100, 10)

如图3-26所示,输入一个由784个元素(原本是一 个 28 × 28 的二维数组)构成的一维数组后,输出一个有 10 个元素的一维数组。 这是只输入一张图像数据时的处理流程。
图 3-26 数组形状的变化
现在我们来考虑打包输入多张图像的情形。比如,我们想用 predict() 函数一次性打包处理 100 张图像。为此,可以把 x 的形状改为 100 × 784,将 100 张图像打包作为输入数据。用图表示的话,如图 3-27 所示。
图 3-27 批处理中数组形状的变化
如图3-27所示,输入数据的形状为100 × 784,输出数据的形状为 100 × 10。这表示输入的 100 张图像的结果被一次性输出了。比如,x[0] 和y[0] 中保存了第 0 张图像及其推理结果。

这种打包式的输入数据称为批(batch)。

下面我们进行基于批处理的代码实现:

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

batch_size = 100 # 批数量 
accuracy_cnt = 0

for i in range(0, len(x), batch_size):
	x_batch = x[i:i+batch_size]
	y_batch = predict(network, x_batch)
	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)))

range() 函数若指定为range(start, end),则会生成一个由start到end-1之间的整数构成的列表。若像range(start, end, step)这样指定3个整数,则生成的列表中的下一个元素会增加 step 指定的值。我们来看一个例子。

>>> list( range(0, 10) )
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> list( range(0, 10, 3) )
[0, 3, 6, 9]

在 range() 函数生成的列表的基础上,通过 x[i:i+batch_size] 从输入数 据中抽出批数据。x[i:i+batch_n] 会取出从第 i 个到第 i+batch_n 个之间的数据。
然后,通过argmax()获取值最大的元素的索引。需要注意的是,我们给定了参数axis=1。这指定了在100×10的数组中,沿着第1维方向(以第1维为轴)找到值最大的元素的索引(第0维对应第1个维度)A。这里也来 看一个例子。

>>> x = np.array([[0.1, 0.8, 0.1], [0.3, 0.1, 0.6], ... [0.2, 0.5, 0.3], [0.8, 0.1, 0.1]])
>>> y = np.argmax(x, axis=1)
>>> print(y)
[1 2 1 ... 0]

矩阵的第0维是列方向,第1维是行方向

最后,我们比较一下以批为单位进行分类的结果和实际的答案。为此, 需要在NumPy数组之间使用比较运算符(==)生成由True/False构成的布尔 型数组,并计算True的个数。我们通过下面的例子进行确认。

>>> y = np.array([1, 2, 1, 0]) 
>>> t = np.array([1, 2, 0, 0]) 
>>> print(y==t)
[True True False True]
>>> np.sum(y==t) 3

神经网络的学习

神经网络的特征就是可以从数据中学习。所谓“从数据中学习”,是指可以由数据自动决定权重参数的值

通过有限次数的学习,线性可分问题是可解的。但是,非线性可分问题则无法通过(自动)学习来解决

从数据中学习

先从图像中提取特征量,再用机器学习技术学习这些特征量的模式。这里所说的“特征量”是指可以
从输入数据(输入图像)中准确地提取本质数据(重要的数据)的转换器。图像的特征量通常表示为向量的形式

不管要求解的问题是识别5,还是识别狗,抑或是识别人脸,神经网络都是通过不断地学习所提供的数据,尝试发现待求解的问题的模式

训练数据和测试数据

机器学习中,一般将数据分为训练数据和测试数据两部分来进行学习和实验等。首先,使用训练数据进行学习,寻找最优的参数;然后,使用测试数据评价训练得到的模型的实际能力。为什么需要将数据分为训练数据和测试数据呢?因为我们追求的是模型的泛化能力。为了正确评价模型的泛化能力,就必须划分训练数据和测试数据。另外,训练数据也可以称为监督数据。泛化能力是指处理未被观察过的数据(不包含在训练数据中的数据)的能力。获得泛化能力是机器学习的最终目标。

只对某个数据集过度拟合的状态称为过拟合

损失函数

神经网络的学习通过某个指标表示现在的状态,即神经网络以某个指标为线索寻找最优权重参数。神经网络的学习中所用的指标称为损失函数(loss function)。这个损失函数可以使用任意函数,但一般用均方误差和交叉熵误差等。
损失函数是表示神经网络性能的“恶劣程度”的指标,即当前的神经网络对监督数据在多大程度上不拟合,在多大程度上不一致。

均方误差

最有名的损失函数是均方误差:
在这里插入图片描述
yk是表示神经网络的输出,tk表示监督数据,k表示数据的维数。比如,在3.6节手写数字识别的例子中,yk、tk是由如下10个元素构成的数据。

>>> y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
>>> t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]

数组元素的索引从第一个开始依次对应数字“0”“1”“2”…… 这里,神经网络的输出y是softmax函数的输出。由于softmax函数的输出可以理解为概率,因此上例表示“0”的概率是0.1,“1”的概率是0.05,“2”的概率是0.6等。t是监督数据,将正确解标签设为1,其他均设为0。这里,标签“2”为1,表示正确解是“2”。将正确解标签表示为1,其他标签表示为0的表示方法称为one-hot表示

猜你喜欢

转载自blog.csdn.net/CaraYQ/article/details/131104510