主要包括两大类问题:
变种问题主要有:
不给定目标值,模型需要从输入数据中寻找到有价值的变换,常常用来做数据可视化,数据压缩,数据去噪或者辅助我们更好理解数据中的相关性等。
无监督学习是数据分析的必备技能。
为了更好的理解数据集,无监督学习是一个必要步骤。比如降维和聚类分析方法。
这个是监督学习的一个特例。它的特殊之处在于没有人工标注的标签,但是标签仍然存在,而这些标签是如何生成的呢?它们来自输入数据,常常用启发式算法来生成。
智能体接收有关环境的信息,并学会选择使得奖励函数最大化的动作。
三者的具体分工是:在训练集上训练模型,在验证集上评估模型以及在测试集上最后测试。
在验证集上可以调节超参数,比如前面训练时,我们用验证集上的效果来得出训练多少轮次合适,这就是超参数选择的过程。调节模型时,是万万不能用到测试集的,测试集就像最后的高考,验证集则是月考,训练集则是我们平时的作业。
即留出一定比例的数据作为测试集,为了调节模型我们还需要从训练集中拿出一部分数据做验证集。
这个图只表达了划分出两部分数据,训练集里还要再细分出一部分数据做验证,本质上,验证集也是训练调节模型,大类仍可归于训练集。
num_validation_samples = 10000
np.random.shuffle(data) # 打乱数据
validation_data = data[:num_validation_samples] # 验证集
train_data = data[num_validation_samples:]
model = build_model()
model.fit(train_data, train_targets)
validation_score = model.evaluate(validation_data) # 验证集上评估模型并得出最优超参数
# 找到最优超参数,重新训练
model = build_model()
model.fit(np.concatenate([train_data, validation_data], train_targets)
test_score = model.evaluate(test_data)
在知晓超参数以后,重新训练模型时,验证集数据也作为训练集数据,这样可以更好的训练模型。
这个验证方法不适用于样本数据量较少的情况。
这个一图就说明白了,但还是需要特别强调一下,这里的数据确定后是个整体,当然之前可以先打乱使得分布均匀。然后砍成一段一段的,拼在一起就是完整的数据集。之所以这么强调,是为了和下面的打乱随机K折验证区分一下。
k = 3
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 = build_model()
model.fit(train_data)
validation_score = model.evaluate(validation_data)
validation_scores.append(validation_score)
validation_score = np.average(validation_scores)
model = build_model()
model.fit(data)
test_score = model.evaluate(test_data)
一句话描述就是,多次使用上面的K折验证,每次都打乱数据一下。假设重复P次,那么需要训练和评估的模型个数是PxK个,这种做法代价很大,但是效果很好,在Kaggle比赛里很有用。
数据代表性
将数据随机打乱,可以使得训练集和测试集都能代表当前数据。
时间箭头
如果是用过去数据来预测未来,则不能随机打乱数据,否则会导致时间泄露问题。
数据冗余
我们需要保证训练集和验证集之间不存在交集。
在具体使用模型之前,需要耗费很大精力来处理数据。
针对神经网络,我们将数据处理得更加适用于神经网络处理。主要包括如下几种方法:
通常机器学习模型无法从完全任意的数据中学习。所以我们需要利用先验知识对数据进行编码转换,以改善模型的效果。
特征工程的本质是:用更简单的方式表述问题,使得问题更加容易解决。这需要我们深入理解问题。
现代深度学习,大部分特征工程是不需要的。神经网络可以从原始数据中自动提取有用特征。但是并不表示深度神经网络不需要特征工程。使用特征工程,一方面可以用更少的资源解决问题,另一方面,定义良好的特征可以更少的数据解决问题。样本很少时,恰当的特征工程价值极大。
欠拟合表示模型仍有改进的空间,还需要继续训练,所以这个问题不大,更需要特别设计解决的是过拟合问题。降低过拟合的方法叫作正则化。常用的正则化的方法有:
这是防止过拟合的最简单的方法,通过减少模型的学习参数个数。
**模型容量:**可学习参数的个数。
深度学习模型通常都很擅长拟合训练数据,但是真正的挑战在于泛化,而不是拟合。
更大的网络的训练损失容易很快就接近0,即网络的容量越大,则拟合数据的速度就越快,也就容易过拟合。
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, kernel_regularizer=regularizers.l2(0.001), activation='relu'))
其中,l2(0.001)
的意思是:该层权重矩阵的每个系数都会使网络总损失增加0.001 * weight_coefficient_calue
,惩罚项只在训练时添加,测试时不计算,所以训练损失会大于测试损失。
这是训练神经网络最有效也最常用的方法。对某一层使用dropout,会在训练过程中随机将该层的一些输出特征置为0。设置的dropout比率是元素被设置为0的比例。测试时没有单元会被舍弃。
model = models.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
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'))
这部分再单独写一篇笔记,之前也写过一次。
END.
参考:
《Deep Learning with Python》