机器学习基础

机器学习基础

文章目录

  • 机器学习基础
    • 1、机器学习的四个分支
      • 1.1、监督学习
      • 1.2、无监督学习
      • 1.3、自监督学习
      • 1.4、强化学习
    • 2、评估机器学习的模型
      • 2.1、训练集、验证集和测试集
        • 2.1.1、简单的留出验证
        • 2.1.2、K 折验证
        • 2.1.3、带有打乱数据的重复 K 折验证
      • 2.2、评估模型的注意事项
    • 3、数据预处理、特征工程和特征学习
      • 3.1、神经网络的数据预处理
      • 3.2、特征工程
    • 4、过拟合和欠拟合
      • 4.1、减小网络大小
      • 4.2、添加权重正则化
      • 4.3、添加 dropout 正则化
    • 5、机器学习的通用工作流程
      • 5.1、定义问题,收集数据集
      • 5.2、选择衡量成功的指标
      • 5.3、确定评估方法
      • 5.4、准备数据
      • 5.5、开发比基准更好的模型
      • 5.6、扩大模型规模:开发过拟合的模型
      • 5.7、模型正则化与调节超参数

1、机器学习的四个分支

1.1、监督学习

给定一组样本(通常由人工标注),它可以学会将输入数据映射到已知目标[也叫标注( annotation)]

虽然监督学习主要包括分类和回归,但还有更多的奇特变体,主要包括如下几种:

  • 序列生成( sequence generation)。给定一张图像,预测描述图像的文字。序列生成有时可以被重新表示为一系列分类问题,比如反复预测序列中的单词或标记;
  • 语法树预测( syntax tree prediction)。给定一个句子,预测其分解生成的语法树
  • 目标检测( object detection)。给定一张图像,在图中特定目标的周围画一个边界框。这个问题也可以表示为分类问题(给定多个候选边界框,对每个框内的目标进行分类)或分类与回归联合问题(用向量回归来预测边界框的坐标)。
  • 图像分割( image segmentation)。给定一张图像,在特定物体上画一个像素级的掩模( mask)。

1.2、无监督学习

无监督学习是指在没有目标的情况下寻找输入数据的有趣变换,其目的在于数据可视化数据压缩数据去噪更好地理解数据中的相关性

无监督学习是数据分析的必备技能,在解决监督学习问题之前,为了更好地了解数据集,它通常是一个必要步骤。

降维( dimensionality reduction)和聚类( clustering)都是众所周知的无监督学习方法。

1.3、自监督学习

自监督学习是没有人工标注的标签的监督学习,你可以将它看作没有人类参与的监督学习。

标签仍然存在(因为总要有什么东西来监督学习过程),但它们是从输入数据中生成的,通常是使用启发式算法生成的。

1.4、强化学习

在强化学习中, 智能体( agent)接收有关其环境的信息,并学会选择使某种奖励最大化的行动。


2、评估机器学习的模型

机器学习的目的是得到可以泛化( generalize)的模型,即在前所未见的数据上表现很好的模型,而过拟合则是核心难点。

2.1、训练集、验证集和测试集

评估模型的重点是将数据划分为三个集合:训练集、验证集和测试集在训练数据上训练模型,在验证数据上评估模型。一旦找到了最佳参数,就在测试数据上最后测试一次

你可能会问,为什么不是两个集合:一个训练集和一个测试集?在训练集上训练模型,然后在测试集上评估模型。这样简单得多!

原因在于开发模型时总是需要调节模型配置,比如选择层数或每层大小[这叫作模型的超参数( hyperparameter)]这个调节过程需要使用模型在验证数据上的性能作为反馈信号。这个调节过程本质上就是一种学习在某个参数空间中寻找良好的模型配置。因此,如果基于模型在验证集上的性能来调节模型配置,会很快导致模型在验证集上过拟合,即使你并没有在验证集上直接训练模型也会如此。

造成这一现象的关键在于信息泄露( information leak)。

最后,你得到的模型在验证集上的性能非常好(人为造成的),因为这正是你优化的目的。你关心的是模型在全新数据上的性能,而不是在验证数据上的性能,因此你需要使用一个完全不同的、前所未见的数据集来评估模型,它就是测试集。你的模型一定不能读取与测试集有关的任何信息,既使间接读取也不行

2.1.1、简单的留出验证

留出一定比例的数据作为测试集在剩余的数据上训练模型,然后在测试集上评估模型。如前所述,为了防止信息泄露,你不能基于测试集来调节模型,所以还应该保留一个验证集

机器学习基础_第1张图片

num_validation_samples = 10000

np.random.shuffle(data) #通常需要打乱数据

validation_data = data[:num_validation_samples] #定义验证集
data = data[num_validation_samples:]

training_data = data[:]

"""
在训练数据上训练模型,
并在验证数据上评估模型
"""
model = get_model()
model.train(training_data)
validation_score = model.evaluate(validation_data)

# 现在你可以调节模型、重新训练、评估,然后再次调节……

"""
一旦调节好超参数,通常就在
所有非测试数据上从头开始训练最终模型
"""
model = get_model()
model.train(np.concatenate([training_data,
                            validation_data]))
test_score = model.evaluate(test_data)

这是最简单的评估方法,但有一个缺点:如果可用的数据很少,那么可能验证集和测试集包含的样本就太少,从而无法在统计学上代表数据。这个问题很容易发现:如果在划分数据前进行不同的随机打乱,最终得到的模型性能差别很大,那么就存在这个问题。接下来会介绍 K 折验证与重复的 K 折验证,它们是解决这一问题的两种方法。

2.1.2、K 折验证

K 折验证(K-fold validation)将数据划分为大小相同的 K 个分区对于每个分区 i,在剩余的 K-1 个分区上训练模型,然后在分区 i 上评估模型最终分数等于 K 个分数的平均值。对于不同的训练集 - 测试集划分,如果模型性能的变化很大,那么这种方法很有用。与留出验证一样,这种方法也需要独立的验证集进行模型校正。

机器学习基础_第2张图片

k = 4
num_validation_samples = len(data) // k

np.random.shuffle(data)

validation_scores = []
for fold in range(k):
    validation_data = data[num_validation_samples * fold:
        num_validation_samples * (fold + 1)] #选择验证数据分区
    training_data = data[:num_validation_samples * fold] +
        data[num_validation_samples * (fold + 1):] #使用剩余数据作为训练数据。注意,+ 运算符是列表合并,不是求和
        
    model = get_model() #创建一个全新的模型实例(未训练)
    model.train(training_data)
    validation_score = model.evaluate(validation_data)
    validation_scores.append(validation_score)
    
validation_score = np.average(validation_scores) #最终验证分数: K 折验证分数的平均值


# 在所有非测试数据上训练最终模型
model = get_model()
model.train(data)
test_score = model.evaluate(test_data)

2.1.3、带有打乱数据的重复 K 折验证

如果可用的数据相对较少,而你又需要尽可能精确地评估模型,那么可以选择带有打乱数据的重复 K 折验证( iterated K-fold validation with shuffling)。具体做法是多次使用 K 折验证,在每次将数据划分为 K 个分区之前都先将数据打乱最终分数是每次 K 折验证分数的平均值。注意,这种方法一共要训练和评估 P× K 个模型(P 是重复次数),计算代价很大。

2.2、评估模型的注意事项

  1. 数据代表性( data representativeness)。你希望训练集和测试集都能够代表当前数据;
  2. 时间箭头( the arrow of time)。如果想要根据过去预测未来(比如明天的天气、股票走势等),那么在划分数据前你不应该随机打乱数据,因为这么做会造成时间泄露( temporal leak);
  3. 数据冗余( redundancy in your data)。如果数据中的某些数据点出现了两次(这在现实中的数据里十分常见),那么打乱数据并划分成训练集和验证集会导致训练集和验证集之间的数据冗余。

3、数据预处理、特征工程和特征学习

将数据输入神经网络之前,如何准备输入数据和目标?

3.1、神经网络的数据预处理

数据预处理的目的是使原始数据更适于用神经网络处理,包括向量化、标准化、处理缺失值和特征提取

  1. 向量化

    神经网络的所有输入和目标都必须是浮点数张量(在特定情况下可以是整数张量)。无论处理什么数据(声音、图像还是文本),都必须首先将其转换为张量,这一步叫作数据向量化(data vectorization)。

  2. 值标准化

    一般来说,将取值相对较大的数据(比如多位整数,比网络权重的初始值大很多)或异质数据( heterogeneous data,比如数据的一个特征在 0~1 范围内,另一个特征在 100~200 范围内)输入到神经网络中是不安全的这么做可能导致较大的梯度更新,进而导致网络无法收敛

    为了让网络的学习变得更容易,输入数据应该具有以下特征:

    1. 取值较小:大部分值都应该在 0~1 范围内;
    2. 同质性( homogenous):所有特征的取值都应该在大致相同的范围内。

    此外,下面这种更严格的标准化方法也很常见,而且很有用,虽然不一定总是必需的:

    1. 将每个特征分别标准化,使其平均值为 0;
    2. 将每个特征分别标准化,使其标准差为 1;
  3. 处理缺失值

    一般来说,对于神经网络,将缺失值设置为 0 是安全的,只要 0 不是一个有意义的值。网络能够从数据中学到 0 意味着缺失数据,并且会忽略这个值
    注意,如果测试数据中可能有缺失值,而网络是在没有缺失值的数据上训练的,那么网络不可能学会忽略缺失值。在这种情况下,你应该人为生成一些有缺失项的训练样本:多次复制一些训练样本,然后删除测试数据中可能缺失的某些特征

3.2、特征工程

特征工程( feature engineering)是指将数据输入模型之前,利用你自己关于数据和机器学习算法(这里指神经网络)的知识对数据进行硬编码的变换(不是模型学到的),以改善模型的效果。多数情况下,一个机器学习模型无法从完全任意的数据中进行学习。呈现给模型的数据应该便于模型进行学习

特征工程的本质:用更简单的方式表述问题,从而使问题变得更容易。它通常需要深入理解问题。


4、过拟合和欠拟合

  • 机器学习的根本问题是优化和泛化之间的对立优化( optimization)是指调节模型以在训练数据上得到最佳性能(即机器学习中的学习),而**泛化( generalization)是指训练好的模型在前所未见的数据上的性能好坏**。机器学习的目的当然是得到良好的泛化,但你无法控制泛化,只能基于训练数据调节模型

  • 训练开始时,优化和泛化是相关的:训练数据上的损失越小,测试数据上的损失也越小。这时的模型是欠拟合( underfit)的,即仍有改进的空间,网络还没有对训练数据中所有相关模式建模但在训练数据上迭代一定次数之后,泛化不再提高,验证指标先是不变,然后开始变差,即模型开始过拟合这时模型开始学习仅和训练数据有关的模式,但这种模式对新数据来说是错误的或无关紧要的

  • 为了防止模型从训练数据中学到错误或无关紧要的模式, 最优解决方法是获取更多的训练数据模型的训练数据越多,泛化能力自然也越好。如果无法获取更多数据,次优解决方法是调节模型允许存储的信息量,或对模型允许存储的信息加以约束如果一个网络只能记住几个模式,那么优化过程会迫使模型集中学习最重要的模式,这样更可能得到良好的泛化

    这种降低过拟合的方法叫作正则化( regularization)

4.1、减小网络大小

  • 防止过拟合的最简单方法就是减小模型大小,即减少模型中可学习参数的个数(这由层数和每层的单元个数决定)

  • 在深度学习中,模型中可学习参数的个数通常被称为模型的容量( capacity)。直观上来看,参数更多的模型拥有更大的记忆容量( memorization capacity),因此能够在训练样本和目标之间轻松地学会完美的字典式映射,这种映射没有任何泛化能力

    始终牢记:深度学习模型通常都很擅长拟合训练数据,但真正的挑战在于泛化,而不是拟合

  • 与此相反,如果网络的记忆资源有限,则无法轻松学会这种映射

    因此,为了让损失最小化,网络必须学会对目标具有很强预测能力的压缩表示,这也正是我们感兴趣的数据表示。

    使用的模型应该具有足够多的参数,以防欠拟合,即模型应避免记忆资源不足

    在容量过大与容量不足之间要找到一个折中

  • 你必须评估一系列不同的网络架构(当然是在验证集上评估,而不是在测试集上),以便为数据找到最佳的模型大小。

    要找到合适的模型大小,一般的工作流程是开始时选择相对较少的层和参数,然后逐渐增加层的大小或增加新层,直到这种增加对验证损失的影响变得很小

更小的验证损失对应更好的模型,更小的网络开始过拟合的时间要晚于参考网络,而且开始过拟合之后,它的性能变差的速度也更慢

4.2、添加权重正则化

  • 简单模型比复杂模型更不容易过拟合;

  • 这里的简单模型(simple model)是指参数值分布的熵更小的模型,或参数更少的模型

    一种常见的降低过拟合的方法就是强制让模型权重只能取较小的值,从而限制模型的复杂度,这使得权重值的分布更加规则(regular)

    这种方法叫作权重正则化(weight regularization),其实现方法是向网络损失函数中添加与较大权重值相关的成本( cost)。这个成本有两种形式:

    1. L1 正则化( L1 regularization):添加的成本与权重系数的绝对值[权重的 L1 范数( norm)]成正比;
    2. L2 正则化( L2 regularization):添加的成本与权重系数的平方(权重的 L2 范数)成正比。神经网络的 L2 正则化也叫权重衰减( weight decay)。

    在 Keras 中,添加权重正则化的方法是向层传递权重正则化项实例( weight regularizer instance)作为关键字参数。

from keras import regularizers

model = models.Sequential()
model.add(layers.Dense(16, kernel_regularizer=regularizers.l2(0.001),
                        activation='relu', input_shape=(10000,)))
model.add(layers.Dense(16, kernel_regularizer=regularizers.l2(0.001),
                        activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
  • l2(0.001) 的意思是该层权重矩阵的每个系数都会使网络总损失增加 0.001 * weight_coefficient_value。注意,由于这个惩罚项只在训练时添加,所以这个网络的训练损失会比测试损失大很多。

4.3、添加 dropout 正则化

  • dropout 是神经网络最有效也最常用的正则化方法之一;

    对某一层使用 dropout,就是在训练过程中随机将该层的一些输出特征舍弃(设置为 0)

    dropout 比率( dropout rate)是被设为 0 的特征所占的比例,通常在 0.2~0.5 范围内

  • 在 Keras 中,你可以通过 Dropout 层向网络中引入 dropout, dropout 将被应用于前面一层的输出

model4 = models.Sequential()
model4.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
model4.add(layers.Dropout(0.5))
model4.add(layers.Dense(16, activation='relu'))
model4.add(layers.Dropout(0.5))
model4.add(layers.Dense(1, activation='sigmoid'))

总结一下,防止神经网络过拟合的常用方法包括:

  1. 获取更多的训练数据;
  2. 减小网络容量;
  3. 添加权重正则化;
  4. 添加 dropout。

5、机器学习的通用工作流程

5.1、定义问题,收集数据集

  • 你必须定义所面对的问题:

    1. 你的输入数据是什么?你要预测什么?辅导费只有拥有可用的训练数据,你才能学习预测某件事情。
    2. 你面对的是什么类型的问题?是二分类问题、多分类问题、标量回归问题、向量回归问题,还是多分类、多标签问题?或者是其他问题,比如聚类、生成或强化学习?确定问题类型有助于你选择模型架构、损失函数等。

    只有明确了输入、输出以及所使用的数据,你才能进入下一阶段。注意你在这一阶段所做的假设:

    1. 假设输出是可以根据输入进行预测的;
    2. 假设可用数据包含足够多的信息,足以学习输入和输出之间的关系。

    机器学习只能用来记忆训练数据中存在的模式

5.2、选择衡量成功的指标

  • 要取得成功,就必须给出成功的定义:精度?准确率( precision)和召回率( recall)?客户保留率?衡量成功的指标将指引你选择损失函数,即模型要优化什么。

    1. 对于平衡分类问题(每个类别的可能性相同),精度接收者操作特征曲线下面积( area under the receiver operating characteristic curve, ROC AUC)是常用的指标;
    2. 对于类别不平衡的问题,你可以使用准确率召回率
    3. 对于排序问题或多标签分类,你可以使用平均准确率均值( mean average precision)。

5.3、确定评估方法

  • 一旦明确了目标,你必须确定如何衡量当前的进展。前面介绍了三种常见的评估方法:

    1. 留出验证集。数据量很大时可以采用这种方法。
    2. K 折交叉验证。如果留出验证的样本量太少,无法保证可靠性,那么应该选择这种方法。
    3. 重复的 K 折验证。如果可用的数据很少,同时模型评估又需要非常准确,那么应该使用这种方法。

5.4、准备数据

  • 数据格式化,使其可以输入到机器学习模型中:

    1. 应该将数据格式化为张量
    2. 这些张量的取值通常应该缩放为较小的值,比如在 [-1, 1] 区间或 [0, 1] 区间
    3. 如果不同的特征具有不同的取值范围(异质数据),那么应该做数据标准化
    4. 你可能需要做特征工程,尤其是对于小数据问题。

5.5、开发比基准更好的模型

  • 这一阶段的目标是获得统计功效( statistical power),即开发一个小型模型,它能够打败纯随机的基准( dumb baseline)。

  • 如果一切顺利,你还需要选择三个关键参数来构建第一个工作模型:

    1. 最后一层的激活。它对网络输出进行有效的限制;
    2. 损失函数。它应该匹配你要解决的问题的类型;
    3. 优化配置。你要使用哪种优化器?学习率是多少?大多数情况下,使用 rmsprop 及其默认的学习率是稳妥的。
问题类型 最后一层激活 损失函数
二分类问题 sigmoid binary_crossentropy
多分类、单标签问题 softmax categorical_crossentropy
多分类、多标签问题 sigmoid binary_crossentropy
回归到任意值 mse
回归到 0~1 范围内的值 sigmoid mse 或 binary_crossentropy

5.6、扩大模型规模:开发过拟合的模型

  • 一旦得到了具有统计功效的模型,问题就变成了:模型是否足够强大?它是否具有足够多的层和参数来对问题进行建模?

    机器学习中无处不在的对立是优化和泛化的对立,理想的模型是刚好在欠拟合和过拟合的界线上,在容量不足和容量过大的界线上。为了找到这条界线,你必须穿过它

  • 要搞清楚你需要多大的模型,就必须开发一个过拟合的模型,这很简单:

    1. 添加更多的层;
    2. 让每一层变得更大;
    3. 训练更多的轮次。

    要始终监控训练损失验证损失,以及你所关心的指标的训练值和验证值。如果你发现模型在验证数据上的性能开始下降,那么就出现了过拟合

  • 下一阶段将开始正则化和调节模型,以便尽可能地接近理想模型,既不过拟合也不欠拟合。

5.7、模型正则化与调节超参数

  • 这一步是最费时间的:你将不断地调节模型、训练、在验证数据上评估(这里不是测试数据)、再次调节模型,然后重复这一过程,直到模型达到最佳性能。你应该尝试以下几项:

    1. 添加 dropout;
    2. 尝试不同的架构:增加或减少层数;
    3. 添加 L1 和 / 或 L2 正则化;
    4. 尝试不同的超参数(比如每层的单元个数或优化器的学习率),以找到最佳配置;
    5. (可选)反复做特征工程:添加新特征或删除没有信息量的特征。
  • 请注意:每次使用验证过程的反馈来调节模型,都会将有关验证过程的信息泄露到模型中

  • 一旦开发出令人满意的模型配置,你就可以在所有可用数据(训练数据 + 验证数据)上训练最终的生产模型,然后在测试集上最后评估一次。

  • 如果测试集上的性能比验证集上差很多,那么这可能意味着你的验证流程不可靠,或者你在调节模型参数时在验证数据上出现了过拟合。

    在这种情况下,你可能需要换用更加可靠的评估方法,比如重复的 K 折验证。

你可能感兴趣的:(Python深度学习,机器学习,人工智能,python)