本文的主要内容是介绍机器学习的基础概念,包含:
最常见的机器学习类型。给定一组样本(通常是人工标准),它可以学会将数据映射到已知目标(也叫标注)。监督学习广泛应用到光学字符识别、语音识别、图像分类和语言翻译。
监督学习除了回归和分类,还有其他变体:
无监督学习是指在没有目标的情况下寻找输入数据的有趣变换,目的是在于数据可视化、数据压缩、数据去噪或者更好地理解数据中的相关性。
主要是降维和聚类
自监督学习是监督学习的特例。自监督学习可以看做是没有人工标注的标签的监督学习。
标签是仍然存在的,但是他们是从输入数据中生成的,通常是使用启发式算法生成的。
一个常见的例子就是:自编码器autoencoder,其目标就是未经修改的输入。
给定视频中过去的帧来预测下一帧,或者给定文本中前面的词语来预测下一个次,都是属于自监督学习的例子(这两个例子是时序监督学习的例子)
强化学习是因为谷歌的DeepMind公司将其成功应用于学习完Atari游戏(还有围棋阿尔法狗)中,才开始被广泛关注。
在强化学习中,智能体agent接收有关其环境的信息,并学会选择使其某种奖励最大化的行动。
总结一下回归和分类中常出现的术语:
机器学习的目的是得到可以泛化的模型:在前所未见的数据集上也能够表现的很好,而过拟合则是核心难点。
评估模型的重点是将数据划分为:训练集、验证集和测试集
模型一定不能读取与测试集任何相关的信息,即使是间接读取也不行。3大经典评估方法:
留出一定的比例的数据作为测试集,在剩余的数据集上训练数据,然后在测试集上评估模型。
为了防止信息泄露,我们不能基于测试集来调节模型,必须保留一个验证集。
# 代码实现
num_validation_samples = 10000
# 打乱数据
np.random.shuffle(data)
validation_data = data[:num_validation_samples] # 验证集
data = data[num_validation_samples:]
train_data = data # 训练集
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折验证和重复的K折验证来解决这个问题。
使用K折交叉验证的基本原来:
如何K折交叉验证:以3折交叉验证为例
# 代码实现
k = 4
num_validation_samples = len(data) // k
# 随机打乱数据
np.random.shuffle(data)
validation_scores = []
for fold in range(k):
# 验证集
validation_data = data[fold * num_validation_samples: (fold + 1) * num_validation_samples]
# 训练集
train_data = data[: fold * num_validation_samples] + data[(fold + 1) * num_validation_samples:]
model = get_model()
model.train(train_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) # data = train_data + validation_data 所有非测试集上进行训练
test_score = model.evaluate(test_data) # 测试集上进行评估
如果数据很少,又想精确地评估模型,可以使用打乱数据的K折交叉验证:iterated K-fold validation with shuffling。
具体做法:在每次将数据划分为k个分区之前,先将数据打乱,最终分数是每个K折验证分数的均值
注意:这个做法一共要训练和评估P*K个模型,P是重复次数,计算代价很大。
预处理的主要步骤:
神经网络的所有输入和输出都必须是浮点张量。都必须转成张量,这一步叫做向量化data vectorization
数据输入网络前,对每个特征分别做标准化,使其均值为0,标准差为1。
输入神经网络的数据应该具有以下特征:
Numpy实现的标准化过程:
X -= X.mean(axis=0) # 假定X是个二维矩阵
X -= X.std(axis=0)
在神经网络中,一般将缺失值用0填充。
根据已有的知识对数据进行编码的转换,以改善模型的效果。
特征工程的本质:用更简单的方式表述问题,从而使得问题变得更容易。
现在大部分的深度学习是不需要特征工程的,因为神经网络能够从原始数据中自动提取有用的特征。
机器学习的根本问题是优化和泛化的对立。
优化:调节模型以在训练集上得到最佳性能;泛化:训练好的模型在未知数据上的性能好坏。
1、欠拟合问题,根本的原因是特征维度过少,导致拟合的函数无法满足训练集,误差较大。
解决方法:欠拟合问题可以通过增加特征维度来解决。
2、过拟合问题,根本的原因则是特征维度过多,导致拟合的函数完美的经过训练集,但是对新数据的预测结果则较差。解决过拟合问题,则有2个途径:
防止过拟合最简单的方案:减小模型大小,即减少模型中学习参数的个数(层数和每层的单元个数决定)。
容量:在深度学习中,模型中可学习参数的个数称之为容量。
使用的模型必须具有足够多的参数,以防止过拟合,即模型应该避免记忆资源不足。
# 电影评论分类的原网络
import tensorflow as tf # add
import keras as models
import keras as layers
model = models.Sequential()
model.add(tf.keras.Dense(16, activation="relu",input_shape=(10000, )))
model.add(tf.keras.Dense(16, activation="relu"))
model.add(tf.keras.Dense(1, activation="sigmoid"))
用一个更小的网络来替代:
model = models.Sequential()
model.add(tf.keras.Dense(4, activation="relu",input_shape=(10000, )))
model.add(tf.keras.Dense(4, activation="relu"))
model.add(tf.keras.Dense(1, activation="sigmoid"))
我们发现:更小的网络开始过拟合的时间要晚于之前的网络;而且小网络的性能变差的速度也更慢。
换成更大的模型:
model = models.Sequential()
model.add(tf.keras.Dense(512, activation="relu",input_shape=(10000, )))
model.add(tf.keras.Dense(512, activation="relu"))
model.add(tf.keras.Dense(1, activation="sigmoid"))
网络的容量越大,拟合训练数据的速度也越快,更容易过拟合。
奥卡姆剃刀(Occams razor) 原理:如果一件事有两种解释,那么最可能正确的就是最简单的那个,即假设更少的那个。
权重正则化:强制让模型权重只能取较小的值,从而限制模型的复杂度,使得权重的分布更加规则regular。其实现方法:向网络损失函数中添加与较大权重值相关的成本。
具体两种方式:
神经网络中的L2正则化也叫做权重衰减weight decay。
Keras中添加权重正则化的方法是向层传递:权重正则化实例 作为关键字参数,以添加L2权重正则化为例:
from keras import regularizers
model = models.Sequential()
model.add(tf.keras.layers.Dense(16,kernel_regularizer=regularizers.l2(0.001),
activation="relu",
input_shape=(10000,)))
model.add(tf.keras.layers.Dense(16,kernel_regularizer=regularizers.l2(0.001),
activation="relu"))
model.add(tf.keras.layers.Dense(1,activation="sigmoid"))
l2(0.001)的意思是该层权重矩阵的每个系数都会使网络总损失增加0.001*weight_coeffient_value
由于这个惩罚项只在训练时添加,所以网络的训练损失会比测试损失大的多
添加L2正则项前后对比:
其他权重正则化的添加方式:
from keras import regularizers
regularizers.l1(0.001) # l1正则化
regularizers.l1_l2(l1=0.001, l2=0.001) # 同时添加
dropout是神经网络中最有效也是最常用的正则化方式之一,做法:在训练过程中随机将该层的一些输入特征舍弃(设置为0)
dropout的比例就是被设置为0的特征所占的比例,通常在0.2-0.5之间。添加dropout的具体过程:
model.add(tf.keras.layers.Dropout(0.5))
要应用在前面一层的输出
model = models.Sequential()
model.add(tf.keras.layers.Dense(16,activation="relu",input_shape=(10000,)))
model.add(tf.keras.layers.Dropout(0.5)) # 添加
model.add(tf.keras.layers.Dense(16,activation="relu"))
model.add(tf.keras.layers.Dropout(0.5)) # 添加
model.add(tf.keras.layers.Dense(1,activation="sigmoid"))
防止神经网络过拟合的方法:
机器学习中无处不在的对立是优化和泛化的对立,理想的模型是刚好在欠拟合和过拟合的边界上,在容量不足和容量过大的边界上。
为了弄清楚我们需要多大的模型,就必须开发一个过拟合的模型:
在训练的过程中始终监控训练损失和验证损失,以及我们关心的指标。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有