Python深度学习精华笔记5:机器学习基础

2023-09-09 14:14:22 浏览数 (1)

公众号:机器学习杂货店 作者:Peter 编辑:Peter

持续更新《Python深度学习》一书的精华内容,仅作为学习笔记分享。

本小节是第5篇:主要是介绍机器学习/深度学习的基础知识,主要包含:

  • 机器学习的多种形式
  • 评估机器学习的模型的规范化流程
  • 深度学习的数据准备
  • 数据预处理、特征工程
  • 解决过拟合问题
  • 处理机器学习问题的通用工作流程

机器学习的四大分支

监督学习

监督学习supervised learning:机器学习中最常见的类型,它可以学会将输入数据映射到已知目标annotation。比如回归问题和分类问题(二分类、多分类问题等)是最常见的监督学习的例子。

其他监督学习的应用例子:

  • 序列生成sequence generation
  • 语法树预测syntax tree prediction
  • 目标检测object detection
  • 图像分割image segmentation

分类问题和回归问题的常用术语:

  • 样本或输入:进入模型的数据点
  • 预测或输出:从模型出来的结果
  • 目标:真实值;理想状态下,模型应该能够预测到的值
  • 类别:分类问题中供选择的一组标签
  • 真值或标注:数据集的所有目标,通常是人工收集
  • 二分类:binary classification,一种分类任务,比如是否两个互斥的类别
  • 多分类:multiclass classfitication,也是一种分类任务,每个输入样本被划分到两个以上的互斥类别中
  • 多标签分类:multilabel classification,也是一种分类任务,每个样本都可以被分配到多个标签中。比如一幅图像里可能既有猫又有狗,那么应该同时标注猫和狗的标签。
  • 标量回归:scalar regression,目标是连续标量值的任务。预测房价的例子。
  • 向量回归:vector regression,目标是一组连续值的任务。如果对多个值进行回归,就是向量回归。
  • 小批量:mini-batch,模型能够同时处理的小部分样本。通常是8~128,样本数一般是2的倍数,便于GPU上的内存分配。

无监督学习

无监督学习是机器学习任务的一种,它从无标记的训练数据中推断结论,它是进行数据分析的必要步骤。无监督学习的两种主要方法:降维dimensionality reduction和聚类clustering。

  • 无监督学习最典型的例子是聚类分析,它可以在探索性数据分析阶段用于发现隐藏的模式或者对数据进行分组。给定数据,寻找隐藏的结构。在无监督学习中,所有的标记(分类)是未知的,因此训练样本的岐义性高。
  • 无监督学习被广泛应用于数据挖掘,如降维的PCA、T-SNE算法,用于聚类的K-Means等,以及用于异常检测的LOF、SVDD算法等,用于分割的Mean-shift和高斯混合模型等,此外还有强化学习和生成模型。

自监督学习

自监督学习是没有人工标注的标签的监督学习。但是标签是仍然存在的,标签是在输入数据中生成的。通常使用的是启发式算法生成。

自监督学习是另一种类型的无监督学习,其通过利用数据本身的结构和相关性来生成监督信号,从而进行训练。在自监督学习中,通常会设计一个预定义的变换(或变换组合),该变换可以将输入数据转换为另一种具有明显差异的数据,然后训练一个模型来预测这个变换后的数据。 自监督学习的核心思想是利用大规模无标签数据,挖掘数据自身的结构信息和相关性,生成能够指导模型训练的监督信息,以此提高无监督学习效果。自监督学习是一种重要的无监督学习方法,在自然语言处理、计算机视觉等多个领域都得到了广泛的应用。

自编码器autoencoder是很有名的自监督学习的例子。

强化学习

强化学习(Reinforcement Learning, RL)是机器学习的范式和方法论之一,用于描述和解决智能体(agent)在与环境的交互过程中通过学习策略以达成回报最大化或实现特定目标的问题。常见模型是标准的马尔可夫决策过程(Markov Decision Process, MDP)

强化学习可以分为基于模式的强化学习(model-based RL)和无模式强化学习(model-free RL),以及主动强化学习(active RL)和被动强化学习(passive RL)。

求解强化学习问题所使用的算法可分为策略搜索算法和值函数(value function)算法两类。深度学习模型可以在强化学习中得到使用,形成深度强化学习。

评估机器学习模型

一个现象:模型在训练集上性能始终在提高,但是在验证集表现得不好,即出现了过拟合overfit

机器学习的目的是得到泛化generalize的模型,即在前所未见的数据集表现良好。

训练集、验证集和测试集

数据集的划分:

  • 训练集
  • 验证集
  • 测试集

如果数据本身就很少,可以使用交叉验证的方式:简单的留出验证、K折验证、以及带有打乱数据顺序的重复K折验证

3种验证法

简单的留出验证hold-out validation

留出一定的比例作为测试集;在剩余的数据上训练模型

代码语言:python代码运行次数:0复制
# 留出验证代码实现

num_validation_sample = 10000

np.random.shuffle(data)  # 打乱数据

validation_data = data[:num_validation_sample]  # 定义验证集-前面10000个数据
data = data[num_validation_sample:]

train_data = data.copy()  # 定义训练集

model = get_model()

# 在训练集上训练模型;并且在验证集上评估模型
model.train(train_data)
validation_score = model.evaluate(validation_data)

# 调节模型-重新训练-再评估模型
model = get_model()
model.train(np.concatenate([train_data,validation_data]))  # 一旦调节好超参数,通常在所有非测试集上从头训练,得到最终的模型
test_score = model.evaluate(test_data)

方法简单,一个缺点:如果数据本身就很少,验证集和测试集的数据就太少了,无法从统计学上代表数据

如果在划分数据前进行不同的随机打乱,最终得到的模型性能差别将会很大。

K-fold 交叉验证(k-fold validation)

思想:K折交叉验证是一种用于评估机器学习模型性能的技术,其基本思想是将原始数据集分成K个子集,每次选择其中的K-1个子集作为训练数据集,剩余的一个子集作为测试数据集,这样共进行K次交叉验证。每次实验都会得到一个错误率,最终的评估结果是这K次实验错误率的平均值

这种技术可以有效地避免过拟合和欠拟合,并且可以评估模型的泛化能力。

代码语言:python代码运行次数:0复制
# k折交叉验证

k = 5

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)]  # 验证集数据
    train_data = data[:num_validation_samples*fold]   data[num_validation_samples*(fold 1):]  # 训练集数据

    model = get_model()  
    model.train(train_data)  # 基于训练集train_data来训练模型
    validation_score = model.evaluate(validation_data)  # 验证集评估模型
    validation_scores.append(validation_score)  # 验证集上得分列表

validation_score = np.mean(validation_scores)  # 得分均值

model = model.get_model()
model.train(data)  # 基于全部数据data重新训练模型
test_score = model.evaluate(test_data)

注意一点:原始数据分成训练集train、验证集valid和测试集test;先在训练集上进行训练,接着在验证集进行评估;模型通过后,然后在train valid的完整测非测试集上进行训练,得到最终的模型。

基于sklearn快速实现k折交叉验证一个案例:

代码语言:python代码运行次数:0复制
from sklearn.model_selection import KFold  
from sklearn.model_selection import cross_val_score  
from sklearn.datasets import load_iris  
from sklearn.linear_model import LogisticRegression  

# 加载数据集  
iris = load_iris()  
X = iris.data  
y = iris.target  

# 创建KFold对象  
kfold = KFold(n_splits=5)  

# 创建模型  
model = LogisticRegression()  

# 使用K折交叉验证评估模型性能  
scores = cross_val_score(model, X, y, cv=kfold)  

# 输出平均准确率和标准差  
print("Accuracy: %.3f%% ( /-%.3f%%)" % (scores.mean()*100.0, scores.std()*100.0/len(scores)))
带有打乱数据的重复K折交叉验证(iterated k-fold validation with shuffling)

带有打乱数据的重复K折交叉验证是一种用于评估机器学习模型性能的更加严谨的技术。

它与K折交叉验证类似,但是在每次交叉验证中,数据集的顺序会被随机打乱,然后再进行K折划分。这样做可以避免由于数据集顺序的影响而产生偏差的评估结果。

这种方法总共需要训练和评估K*P个模型(P代表重复次数)。

基于sklearn实现:

代码语言:python代码运行次数:0复制
from sklearn.model_selection import RepeatedKFold  
from sklearn.metrics import accuracy_score  
from sklearn.datasets import load_iris  
from sklearn.linear_model import LogisticRegression  

# 加载数据集  
iris = load_iris()  
X = iris.data  
y = iris.target  

# 创建RepeatedKFold对象  
rbf = RepeatedKFold(n_splits=5, n_repeats=3)    # k=5,重复次数为3

# 创建模型  
model = LogisticRegression()  

# 使用重复K折交叉验证评估模型性能  
scores = cross_val_score(model, X, y, cv=rbf)  

# 输出平均准确率和标准差  
print("Accuracy: %.3f%% ( /-%.3f%%)" % (scores.mean()*100.0, scores.std()*100.0/len(scores)))

评估模型注意事项

选择模型评估方法时的注意事项:

  • 数据代表性:在划分数据的时候通常进行随机打乱
  • 时间箭头:在时序分析的相关数据中,时间是否先后顺序的,通常不应该随机打乱数据;否则会造成时间泄露temporal leak。始终确保训练集早于测试集。
  • 数据冗余:确保验证集和训练集之间没有交集。在机器学习建模中,数据冗余指的是在同一个数据集中,存在着相同或者相似的数据。这种冗余可能是由于数据输入错误、数据复制或数据合并等原因导致的。数据冗余会浪费存储空间,增加数据处理的负担,同时也可能导致数据不一致性。在机器学习建模中,数据冗余可能会影响模型的准确性和效率。

数据预处理、特征工程和特征处理

神经网络的数据预处理

向量化

所有神经网络的输入数据都必须是浮点数张量(极少特殊情况可以是整数张量)。

向量化是一种将数据从一维数组转换为多维数组的数学操作,它可以将原始数据转换为更适合神经网络处理的形式。

具体来说,神经网络的输入数据通常需要是一维数组或者多维数组的形式,其中每个元素对应一个特征。而原始数据往往是一维数组的形式,其中每个元素对应一个样本。因此,为了将原始数据直接输入神经网络进行训练,需要对数据进行向量化操作。

值标准化

在神经网络中,数据进行标准化(归一化)处理是一个非常重要的步骤。归一化的作用主要是将输入数据的特征缩放到一个相对较小的区间,以提高模型的训练效率和防止出现过拟合现象。具体来说,标准化可以使不同尺度的特征具有相同的尺度,从而使得网络在处理不同特征时能够有相同的学习速率。

比如图像处理中,图像数据被编码在0~255之间的整数,表示灰度值。在输入网络前需要除以255,这样缩放得到0~1范围的浮点数。

输入数据的两个特征:

  1. 取值较小:大部分的值控制在0到1之间
  2. 同质性homogenous:所有特征的值都应该在大致相同的范围内
代码语言:python代码运行次数:0复制
# numpy数组实现标准化:均值为0,标准差为1
import numpy as np

x -= x.mean(axis=0)
x /= x.std(axis=0)
处理缺失值

在处理数据中缺失值的方法,有以下几种常见的方法:

  1. 删除含有缺失值的数据行或列:这是一种简单的方法,可以直接删除含有缺失值的行或列,但可能会造成数据的损失和浪费。
  2. 填充缺失值:使用某种方法填充缺失值,使得数据完整。常见的方法有:
    • 固定值填充:选择一个固定的值来填充缺失值。例如,可以将所有的缺失值都填充为0,或者使用该列的平均值、中位数或众数等来进行填充。
    • 均值填充:使用该列所有非缺失值的平均值来填充缺失值。
    • 中位数填充:使用该列所有非缺失值的中位数来填充缺失值。
    • 众数填充:使用该列所有非缺失值的众数来填充缺失值。
    • K最近邻算法:使用K个最近的非缺失值来预测缺失值。通过计算这些非缺失值与缺失值之间的距离,选择距离最近的K个点,然后使用这些点的平均值、中位数或众数等来预测缺失值。
    • 回归拟合:使用线性回归或其他回归方法拟合数据,并预测缺失值。
    • 使用人工智能模型预测:使用机器学习或深度学习模型来预测缺失值。这种方法需要大量的数据和计算资源,但可以获得更好的预测效果。
  3. 不处理缺失值:如果缺失值较少,或者在某些情况下不会对数据分析结果产生太大影响,可以选择不处理缺失值,直接使用原始数据进行数据分析。

一般来说,神经网络中缺失值设置为0是安全的,只要0不是一个有意义的值。网络从数据学到0表示着缺失数据,并且会忽略这个值。

特征工程feature engieering

特征工程是指从原始数据中提取有用的特征,以便能够更好地训练机器学习模型。

这个过程包括从原始数据中选择有用的特征,转换特征以便更容易处理,或者构造新的特征,以提高模型的准确性。

特征工程是建立机器学习模型的第一步,因为它能够使模型的表现与所使用的特征有很大的关系。

过拟合和欠拟合

机器学习的根本问题是优化泛化之间的对立。

优化optimization:调节模型,在训练集上得到最佳性能

泛化generalization:训练好的模型在前所未见的数据上的性能好坏。泛化是无法控制的

欠拟合underfit:欠拟合是指机器学习模型在训练数据上的性能不佳,其泛化能力也较差。这意味着模型无法很好地掌握训练数据背后的复杂关系或模式,因此在新数据上的表现也不尽如人意。模型在训练集合验证集都表现得很差

过拟合overfit:模型在训练集上标签良好,但是验证集上表现得很差。

获取更多的数据

为了防止模型从训练数据中学到错误或者无关紧要的模式,最优的办法是提供更多的训练数据。模型训练的数据越多,泛化能力自然也越好。

常用降低过拟合的方法叫做正则化regularization,下面介绍几种方法:

减小网络大小

减小网络大小是解决过拟合现象的一种常用方法。通过减小网络大小,可以限制模型的复杂度,减少模型对训练数据的过度拟合,从而提高模型在新数据上的泛化能力。

具体来说,减小网络大小可以通过以下几种方式实现:

  1. 减少层数:减少网络中的层数可以降低模型的复杂度,从而减少过拟合的风险。
  2. 减少节点数:减少每层的节点数也可以降低模型的复杂度,减少过拟合的风险。

添加权重正则化

  • L1正则化:基于权重系数的绝对值
  • L2正则化:也叫权重衰减,基于权重系数的平方
代码语言:python代码运行次数:0复制
# 向模型添加L2权重正则化

from keras import regularizers
from keras import layers, models

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正则化:

代码语言:python代码运行次数:0复制
from keras import regularizers

regularizers.l1(0.001)

regularizers.l1_l2(l1=0.001,l2=0.001)  # 同时进行l1-l2正则化

添加dropout正则化

对某一层使用dropout,就是在训练过程中对该层的一些输出特征值进行随机舍弃。

比如对向量的dropout操作:[0.2,0.5,1.3,0.8,1.6]经过操作后变成[0,0.5,1.3,0,1.6],部分元素随机变成0。

被设为0的输出特征的比例称之为dropout rate,通常取值在0.2~0.5之间。

在keras中的使用方法:

代码语言:python代码运行次数:0复制
model = model.Sequential()
model.add(layers.Dense(16,activation="relu",input_shape=(X_trian.shape[1],)))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(16,activation="relu"))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(1,activation="sigmoid"))

防止神经网络过拟合的方法总结

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

机器学习的通用工作流程

  1. 定义问题,收集数据
  2. 选择衡量成功的标准
  3. 确定评估标准
  4. 准备数据
  5. 开发比基准好的模型
  6. 扩大模型的规模:开发过拟合的模型
  7. 模型正则化与超参数调节

0 人点赞