机器学习

Posted by Kay on 2023-06-20
Estimated Reading Time 7 Minutes
Words 1.9k In Total
Viewed Times

4.1 从数据中学习

神经网络的特征就是可以从数据中学习。所谓“从数据中学习”,是指神经网络可以通过数据自行决定最合适的权重参数。

4.1.1数据驱动

数据是机器学习的命根子。从数据中寻找答案、从数据中发现模式、根据数据讲故事…

数据驱动的方法,脱离了过往以人为中心的方法。

传统的机器学习,需要先由认为提取数据的特征量,然后再由SVM,KNN等分类器进行学习。然而在神经网络中,不需要认为提取特征量,神经网络直接进行从数据到输出的学习,提取特征量的过程都是由神经网络来实现的。(也因此,深度学习有时也被称为端到端的机器学习,端到端的意思也就是从原始数据(输入)到目标结果(输出)的意思)

4.1.2训练数据和测试数据

在机器学习过程中,一般将数据分类训练数据(或者称为监督数据)和测试数据两部分来进行学习和推理。为了正确评估模型的泛化能力和避免模型过拟合,必须划分训练数据和测试数据。

补充:模型只对某个数据集过度拟合的状态称为过拟合

4.2 损失函数

就像我们可以使用一个数值指标来判度自己的幸福程度一样。神经网络的学习通过某个指标表示现在的状态,然后以这个状态为基准,寻找最优权重参数。神经网络中所使用的指标就是损失函数。**损失函数是衡量网络性能的“恶劣程度”的指标,即当前的神经网络对监督数据在多大程度上不拟合,在多大程度上不一致。**如果给损失函数乘上一个负值,就可以解释为“在多大程度上不坏”,即“性能有多好”。

4.2.1 均方误差

均方误差作为损失函数如下:
$$E = \frac{1}{2}\sum_k(y_k-t_k)^2$$
其中$y_k$表示神经网络的输出,$t_k$表示监督数据,$k$表示数据的维数。

4.2.2 交叉熵损失

交叉熵作为损失函数如下:
$$E = -\sum_k t_klogy_k$$
$t_k$实际中一般为one-hot标签,所以交叉熵损失实际上计算的是对应正确解标签的输出的自然对数的负值,这个值越接近0越好

1
2
3
4
5
6
7
8
import numpy as np

def mean_squared_error(y, t):
return 0.5 * np.sum((y-t)**2)

def cross_entropy_error(y, t):
delta = 1e-7 # 避免出现log 0
return -np.sum(t*np.log(y+delta))

4.2.3 mini-batch学习

机器学习使用训练数据进行学习,也就是使用训练数据计算损失函数的值,找出使该值尽可能小的参数,因此计算损失函数必须将所有的训练数据作为对象。也就是如果由N个数据的话,我们就要把这N个数据的损失函数的总和或算数平均作为学习的目标。

在实验中,如果遇到海量的数据,比如几百万,几千万之多,这种情况下以全体数据作为对象计算损失函数是不现实的。因此,在实际中,我们会从全部数据中随机选出一部分,作为全部数据的“近似”,也就是从训练数据中选出一批数据(称为mini-batch,小批量),然后对每个mini-batch进行学习,这种学些方式称为mini-batch学习,mini-batch学习的过程中也用到了批处理的思想。(这种方法就是统计学中的,以抽样样本的情况来代表总体样本的情况)

4.2.4 为什么需要损失函数(重要)

我们来关注神经网络中的某一个权重参数,此时,对该权重参数的损失函数求导,表示的就是“如果稍微改变这个权重参数的值,损失函数的值如何变化”。如果导数的值为负数,通过该权重参数向正方向改变,可以减小损失函数的值;反过来,导数值为正,权重参数向负方向改变,也可以减小损失函数的值。当导数为0时,无论权重参数向哪个方向改变,损失函数的值都不会改变,此时该权重参数的更新会停留在此处。

注意:在神经网络的学习中,不能将识别精度作为指标。因为如果以识别精度为指标,则参数的导数在绝大多数地方都会变为0

4.3 数值微分

4.3.1 导数

采用微小的差分实现求导数二点过程称为数值微分

4.3.2 偏导数

自行复习

4.4 梯度

由全部变量组成的向量称为梯度
梯度有以下特征:

  1. 梯度指向各点处函数值降低的地方,更严格地说,梯度指示的方向是各点处函数值减小最多的方向
  2. 越靠近鞍点,梯度的大小越大

4.4.1 梯度法

梯度法是寻找函数最大值或最小值的方法:

在梯度法中,函数的取值从当前位置沿着梯度方向前进一定距离,然后在新的地方重新求梯度,再沿着新梯度方向前进,如此反复,不断地沿着梯度方向前进。

数学表示:
$$ x_0 = x_0-\eta \frac{\varphi f}{\varphi x_0} $$

其中$\eta$称为学习率,需要人为确定,学习率过大或过小,都无法使梯度法达到一个“好的位置”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# mini-batch版的cross entropy error
import numpy as np
def cross_entropy_error(y, t): # one-hot版本
if y.ndim == 1:
t = t.reshape(1, t.size)
y = y.reshape(1, y.size)
print(y)
print(t)
batch_size = y.shape[0]
return -np.sum(t*np.log(y+1e-7))/batch_size


y1 = np.array([[0.2,0.3,0.5],[0.8,0.1,0.1],[0.6,0.1,0.3]])
t1 = np.array([[0,1,0],[1,0,0],[1,0,0]])
print(y1)
print(t1)
y2 = np.array([0.8,0.1,0.1])
t2 = np.array([1,0,0])
print(y2)
print(t2)

print(cross_entropy_error(y1,t1))
print(cross_entropy_error(y2,t2))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 一元函数的数值微分实例

import numpy as np

def function_1(x):
return 0.01*x**2+0.1*x

def numerical_differentiation(f,x):
h = 1e-4 # 使用程序实现数值微分,差分采用0.0001即可获得很好的效果
return (f(x+h)-f(x-h))/(2*h)


print(numerical_differentiation(function_1,5))
print(numerical_differentiation(function_1,10))

def numerical_gradient(f, x):
h = 1e-4
grad = np.zeros_like(x)

for idx in range(x.size): # 轮流计算每个偏导数
tmp_val = x[idx]

x[idx] = tmp_val+h
fxh1 = f(x)

x[idx] = tmp_val-h
fxh2 = f(x)

grad[idx] = (fxh1-fxh2)/(2*h)
x[idx] = tmp_val

return grad

def gradient_descent(f, init_x, lr = 0.01, step_num =100):
x = init_x

for i in range(step_num):
grad = gradient_descent(f, x)
x -= lr*grad

return x

4.5 学习算法的实现

class TwoLayerNet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 两层神经网络的实现

import sys, os
sys.path.append(os.curdir)
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): # 初始化模型
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['b1'] = np.zeros(output_size)

def predict(self, x):
a1 = np.dot(x, self.params['W1'])+self.params['b1']
z1 = sigmoid(a1)
a2 = np.dot(z1, self.params['W2'])+self.params['b2']
z2 = softmax(a2)

return z2

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)


如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !