【深度学习笔记】神经网络的学习(1)


神经网络的一个特征是可以从数据中学习,自动调整权重参数,这是传统机器学习无法发做到的,传统的机器学习往往是人工决定参数,对于大量的数据,寻找恰当的参数这个过程是十分艰难的,深度学习从数据中自动学习的这一特性极大的减少了人的投入。根据“感知机收敛定理”,对于线性可分的问题,通过有限次的学习是可解的。

数据是机器学习命根子,没有数据,机器学习也就无法工作。这些数据,可以是音频、视频,也可以是图像、文本等。以图像为例,其大致步骤为从图像中提取特征量(CV领域常用特征量如:SIFT、SURF、HOG等),特征量一般是向量的形式,对于这些特征量,利用KNN、SVM这些机器学习技术进行分类学习。深度学习和机器学习的一个区别便在于机器学习的特征量要人工介入,由人来设计,而深度学习则可以自己完成这一步骤。如下图:

在机器学习中,通常将数据分为训练数据和测试数据,因为我们追求模型的泛化能力(即处理训练数据之外的其他数据的能力),所以我们也必须将数据分为训练数据和测试数据。训练数据也称监督数据。

与模型的泛化能力相对应的,是过拟合,即对模型当前训练模型的数据集精度很高,而对于其他不包含在训练数据中的数据,精度并不理想。避免过拟合,是机器学习中一个重要的课题。

损失函数

损失函数描述的是权重参数的优劣,表示神经网络性能的“恶劣程度”,即当前的数据在多大程度上不拟合,如果“不拟合”这种描述感觉奇怪,可以对损失函数取一个负值,就可以解释为“多大程度上拟合”,但其本质上是一样的。

均方误差

均方误差是最有名的损失函数,其数学公式如下:

其中 yk 表示神经网络的输出,tk 表示监督数据,k为数据的维数,例如:

# y 为神经网络输出
# t 为监督数据(one-hot表示法,正确结果为 2,则其他标签的值为 0, 2 的标签为 1)
y = np.array([0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0])
t1 = np.array([0, 0, 1, 0, 0, 0, 0, 0, 0, 0])

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

print('test1:{}'.format(mean_squared_error(y, t)))

t2 = np.array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0])
print('test2:{}'.format(mean_squared_error(y, t2)))

以上代码输出为:

test1:0.09750000000000003
test2:0.5974999999999999

输出解释

test1:正确的结果为2(代码中的t1),神经网络的输出为2,输出结果与实际结果相似,损失函数的值很小。

test2:正确的结果为0(代码中的t2),神经网络的输出为2,输出结果与实际结果相差较大,损失函数的值较大。

交叉熵误差

交叉熵误差是最常用的损失函数之一,其数学公式如下:

其中 yk 表示神经网络的输出,tk 表示监督数据,k为数据的维数,例如:

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

# 交叉熵误差
def cross_entropy_error(y, t):
    # 当 y = 0 时,log y = -∞
    # 为了保证计算正常,引入微小值 Δ
    delta = 1e-7
    return -np.sum(t*np.log(y+delta))

print('test1:{}'.format(cross_entropy_error(y, t)))

t2 = np.array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0])
print('test2:{}'.format(cross_entropy_error(y, t)))

以上代码输出为:

test1:0.510825457099338
test2:2.302584092994546

输出解释

test1:正确的结果为2(代码中的t1),神经网络的输出为2,输出结果与实际结果相似,损失函数的值很小。

test2:正确的结果为0(代码中的t2),神经网络的输出为2,输出结果与实际结果相差较大,损失函数的值较大。

mini-batch学习

神经网络的学习(训练)过程,就是一个求最优解的过程,根据损失函数的解释,我们可以知到损失函数的值越小,神经网络性能越好,所以学习的过程,就是寻找使损失函数的值最小的参数的过程(类比理解为求最小值)。

针对单个数据,我们可以通过上述方法相对容易地算出损失函数,但如果有100个数据,那我们就要计算100次。所以我们对损失函数做一个小小地改进,以交叉熵误差为例(均方误差同理),改进后公式如下:

将求单个数据的损失函数扩大到求N个数据的损失函数,最后取平均损失函数

通常,我们用于神经网络学习的数据量会很大,比如几百万条,甚至几千万条,显然如果我们求全部数据的平均损失函数不太现实,因此,我们从数据中随机抽取一部分数据进行学习,然后计算这批数据的损失函数。

比如:现在有60000条数据,随机从中抽取100条,再用这100条数据进行学习。

# 模拟 60000 条数据
data = np.array(range(1, 60000, 1))

# 产生 100 个 小于60000 的数据
batch_mask = np.random.choice(60000, 100)
# 取得这100个数据并进行学习(这里使用输出代替学习)
# data[batch_mask]  取到数据
print('随机100个: {}'.format(data[batch_mask]))

声明:迟於|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 【深度学习笔记】神经网络的学习(1)


栖迟於一丘