机器学习速成课程(Machine Learning Crash Course with TensorFlow APIs)
https://developers.google.cn/machine-learning/crash-course.
文章目录
Introduction to Machine Learning
了解掌握机器学习技术的实际优势
理解机器学习技术背后的理念
一、Framing
基本术语的介绍:标签、特征、样本、模型、回归与分类
什么是(监督式)机器学习?简单来说,它的定义如下:
机器学习系统通过学习如何组合输入信息来对从未见过的数据做出有用的预测。
下面我们来了解一下机器学习的基本术语。
- 标签
标签是我们要预测的事物,即简单线性回归中的 y 变量。标签可以是小麦未来的价格、图片中显示的动物品种、音频剪辑的含义或任何事物。 - 特征
特征是输入变量,即简单线性回归中的 x 变量。简单的机器学习项目可能会使用单个特征,而比较复杂的机器学习项目可能会使用数百万个特征,按如下方式指定:x1,x2…xn - 样本
样本是指数据的特定实例:x,我们将样本分为以下两类:
有标签样本:有标签样本同时包含特征和标签。我们使用有标签样本来训练模型。
无标签样本:包含特征,但不包含标签。在使用有标签样本训练模型之后,我们会使用该模型预测无标签样本的标签。 - 模型
模型定义了特征与标签之间的关系。例如,垃圾邮件检测模型可能会将某些特征与“垃圾邮件”紧密联系起来。我们来重点介绍一下模型生命周期的两个阶段:
训练是指创建或学习模型。也就是说,向模型展示有标签样本,让模型逐渐学习特征与标签之间的关系。
推断是指将训练后的模型应用于无标签样本。也就是说,使用经过训练的模型做出有用的预测 (y’)。例如,在推断期间,您可以针对新的无标签样本预测 medianHouseValue。 - 回归与分类
回归模型可预测连续值。例如,回归模型做出的预测可回答如下问题:
加利福尼亚州一栋房产的价值是多少?
分类模型可预测离散值。例如,分类模型做出的预测可回答如下问题:
某个指定电子邮件是垃圾邮件还是非垃圾邮件?
二、Descending into ML
直观介绍线性回归,为介绍线性回归的机器学习方法奠定基础。
1.线性回归
模型方程式:
其中:
y’ 指的是预测标签(理想输出值)。
b指的是偏差(y 轴截距)。而在一些机器学习文档中,它称为 。
w1指的是特征 1 的权重。权重与上文中用 表示的“斜率”的概念相同。
x1指的是特征(已知输入项)。
2.训练与损失
训练模型表示通过有标签样本来学习(确定)所有权重和偏差的理想值。
在监督式学习中,机器学习算法通过以下方式构建模型:
检查多个样本并尝试找出可最大限度地减少损失的模型;这一过程称为经验风险最小化。
损失是对糟糕预测的惩罚。也就是说,损失是一个数值,表示对于单个样本而言模型预测的准确程度。
如果模型的预测完全准确,则损失为零,否则损失会较大。
训练模型的目标是从所有样本中找到一组平均损失“较小”的权重和偏差。
上图左侧显示的是损失较大的模型,右侧显示的是损失较小的模型
(红色箭头表示损失,蓝线表示预测)
一种常见的损失函数是平方损失:
均方误差 (MSE) 指的是每个样本的平均平方损失。
要计算 MSE,请求出各个样本的所有平方损失之和,然后除以样本数量:
三、Reducing Loss
1. 迭代方法
下图显示了机器学习算法用于训练模型的迭代试错过程:
我们来看图的“计算参数更新”部分。机器学习系统就是在此部分检查损失函数的值,并为b 和w1生成新值。现在,假设这个神秘的绿色框会产生新值,然后机器学习系统将根据所有标签重新评估所有特征,为损失函数生成一个新值,而该值又产生新的参数值。这种学习过程会持续迭代,直到该算法发现损失可能最低的模型参数。通常,您可以不断迭代,直到总体损失不再变化或至少变化极其缓慢为止。这时候,我们可以说该模型已收敛。
2. 梯度下降法
凸形问题只有一个最低点;即只存在一个斜率正好为 0 的位置。这个最小值就是损失函数收敛之处。
通过计算整个数据集中 每个可能值的损失函数来找到收敛点这种方法效率太低。我们来研究一种更好的机制,这种机制在机器学习领域非常热门,称为梯度下降法。
梯度始终指向损失函数中增长最为迅猛的方向。梯度下降法算法会沿着负梯度的方向走一步,以便尽快降低损失。
3. 学习率
正如之前所述,梯度矢量具有方向和大小。梯度下降法算法用梯度乘以一个称为学习速率(有时也称为步长)的标量,以确定下一个点的位置。例如,如果梯度大小为 2.5,学习速率为 0.01,则梯度下降法算法会选择距离前一个点 0.025 的位置作为下一个点。
超参数是编程人员在机器学习算法中用于调整的旋钮。
学习率是典型的超参数
大多数机器学习编程人员会花费相当多的时间来调整学习速率。
学习率过小会就会花费太长的学习时间,过大会在曲线底部反复横跳,应选择合适的学习率
上图从左到右分别是学习率过小与学习率过大
4.随机梯度下降法
在梯度下降法中,批量指的是用于在单次迭代中计算梯度的样本总数。
到目前为止,我们一直假定批量是指整个数据集。就 Google 的规模而言,数据集通常包含数十亿甚至数千亿个样本。此外,Google 数据集通常包含海量特征。因此,一个批量可能相当巨大。如果是超大批量,则单次迭代就可能要花费很长时间进行计算。
包含随机抽样样本的大型数据集可能包含冗余数据。实际上,批量大小越大,出现冗余的可能性就越高。一些冗余可能有助于消除杂乱的梯度,但超大批量所具备的预测价值往往并不比大型批量高。
如果我们可以通过更少的计算量得出正确的平均梯度,会怎么样?通过从我们的数据集中随机选择样本,我们可以通过小得多的数据集估算(尽管过程非常杂乱)出较大的平均值。 随机梯度下降法 (SGD) 将这种想法运用到极致,它每次迭代只使用一个样本(批量大小为 1)。如果进行足够的迭代,SGD 也可以发挥作用,但过程会非常杂乱。“随机”这一术语表示构成各个批量的一个样本都是随机选择的。
四、Introduction to TensorFlow
下图显示了 TensorFlow 工具包的当前层次结构:
1. 线性回归在人造数据上的训练和测试
#a Linear Regression example
my_feature = ([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0])
my_label = ([5.0, 8.8, 9.6, 14.2, 18.8, 19.5, 21.4, 26.8, 28.9, 32.0, 33.8, 38.2])
learning_rate=0.01
epochs=450
my_batch_size=12
my_model = build_model(learning_rate)
trained_weight, trained_bias, epochs, rmse = train_model(my_model, my_feature,
my_label, epochs,
my_batch_size)
plot_the_model(trained_weight, trained_bias, my_feature, my_label)
plot_the_loss_curve(epochs, rmse)
#The loss curve suggests that the model does converge.
Epoch 450/450
1/1 [==============================] - 0s 3ms/step - loss: 0.8783 - root_mean_squared_error: 0.9372
2. 调整batch size等超参
系统在每次迭代后重新计算模型的损失值,并调整模型的权重和偏差。每一次迭代(iteration)的跨度是系统处理一个批次。例如,如果批次大小(batch size)为6,那么系统每处理6个例子后,就会重新计算模型的损失值,并调整模型的权重和偏置。
完整一轮(epoch)需要足够的迭代来处理数据集中的每一个例子。例如,如果批次大小是12个,那么每个epoch持续一次迭代。然而,如果批次大小是6,那么每个epoch消耗两次迭代。
下例子中展示了batch size设置为1,模型也有正确的结果
#a Linear Regression example
learning_rate=0.05
epochs=125
my_batch_size=1 # Wow, a batch size of 1 works!
my_model = build_model(learning_rate)
trained_weight, trained_bias, epochs, rmse = train_model(my_model, my_feature,
my_label, epochs,
my_batch_size)
plot_the_model(trained_weight, trained_bias, my_feature, my_label)
plot_the_loss_curve(epochs, rmse)
Epoch 125/125
12/12 [==============================] - 0s 1ms/step - loss: 1.3971 - root_mean_squared_error: 1.1637
3. 超参调整的总结
训练损失应该稳步下降,一开始是陡峭的,然后更慢,直到曲线的斜率达到或接近零。如果训练损失没有收敛,就训练更多的epoch。如果训练损失减少得太慢,就提高学习率。
请注意,将学习率设置得过高也会使训练损失无法收敛。
如果训练损失变化很大(即训练损失四处跳动),降低学习率。
降低学习率,同时增加epoch或批次大小通常是一个很好的组合。
将批次大小设置为一个非常小的批次数也会导致不稳定。首先,尝试大批次值。然后,减少批次大小,直到你看到损失下降。
请记住:超参数的理想组合取决于数据,所以你必须始终进行实验和验证。
4. 真实数据集上的应用
使用真实的数据集来预测加州的房屋价格。
代码如下:
# Import the dataset.
training_df = pd.read_csv(filepath_or_buffer="https://download.mlcc.google.com/mledu-datasets/california_housing_train.csv")
# Scale the label.
training_df["median_house_value"] /= 1000.0
# Print the first rows of the pandas DataFrame.
training_df.head()
# Define a synthetic feature
training_df["rooms_per_person"] = training_df["total_rooms"] / training_df["population"]
my_feature = "rooms_per_person"
# Tune the hyperparameters.
learning_rate = 0.06
epochs = 24
batch_size = 30
# Don't change anything below this line.
my_model = build_model(learning_rate)
weight, bias, epochs, mae = train_model(my_model, training_df,
my_feature, my_label,
epochs, batch_size)
plot_the_loss_curve(epochs, mae)
predict_house_values(15, my_feature, my_label)
上述结果并不理想,课程又使用了关系矩阵找出对房价影响大的特征值
其中median_income对房价的影响最大,但关系矩阵并不能反映全部,后续会讲从潜在特征中释放预测能力。
五、Generalization
泛化是指模型很好地拟合以前未见过的新数据(从创建该模型的同一分布中抽取)的能力。
奥卡姆的威廉是 14 世纪一位崇尚简单的修士和哲学家。他认为科学家应该优先采用更简单(而非更复杂)的公式或理论。奥卡姆剃刀定律在机器学习方面的运用如下:
机器学习模型越简单,良好的实证结果就越有可能不仅仅基于样本的特性(过拟合风险低)
机器学习模型旨在根据以前未见过的新数据做出良好预测。但是,如果您要根据数据集构建模型,如何获得以前未见过的数据呢?一种方法是将您的数据集分成两个子集:
训练集 - 用于训练模型的子集。
测试集 - 用于测试模型的子集。
六、Training and Test Sets
可以想象按下图形式划分测试集和训练集
请勿对测试数据进行训练,如果您的评估指标取得了意外的好结果,则可能表明您不小心对测试集进行了训练。例如,高准确率可能表明测试数据泄露到了训练集。
例如,假设一个模型要预测某封电子邮件是否是垃圾邮件,它使用主题行、邮件正文和发件人的电子邮件地址作为特征。我们按照 80-20 的拆分比例将数据拆分为训练集和测试集。在训练之后,该模型在训练集和测试集上均达到了 99% 的精确率。我们原本预计测试集上的精确率会低于此结果,因此再次查看数据后发现,测试集中的很多样本与训练集中的样本是重复的(由于疏忽,我们在拆分数据之前,没有将输入数据库中的相同垃圾邮件重复条目清理掉)。我们无意中对一些测试数据进行了训练,因此无法再准确衡量该模型泛化到新数据的效果。
七、 Validation Set
使用验证集评估训练集的效果。然后,在模型“通过”验证集之后,使用测试集再次检查评估结果。下图展示了这一新工作流程:
在这一经过改进的工作流程中:
- 选择在验证集上获得最佳效果的模型。
- 使用测试集再次检查该模型。
该工作流程之所以更好,原因在于它暴露给测试集的信息更少。
下列代码展示了模型的训练、验证、和测试
train_df = pd.read_csv("https://download.mlcc.google.com/mledu-datasets/california_housing_train.csv")
test_df = pd.read_csv("https://download.mlcc.google.com/mledu-datasets/california_housing_test.csv")
scale_factor = 1000.0
# Scale the training set's label.
train_df["median_house_value"] /= scale_factor
# Scale the test set's label
test_df["median_house_value"] /= scale_factor
#@title Double-click to view the complete implementation.
# The following variables are the hyperparameters.
learning_rate = 0.08
epochs = 70
batch_size = 100
# Split the original training set into a reduced training set and a
# validation set.
validation_split=0.2
# Identify the feature and the label.
my_feature="median_income" # the median income on a specific city block.
my_label="median_house_value" # the median value of a house on a specific city block.
# That is, you're going to create a model that predicts house value based
# solely on the neighborhood's median income.
# Discard any pre-existing version of the model.
my_model = None
# Shuffle the examples.
shuffled_train_df = train_df.reindex(np.random.permutation(train_df.index))
# Invoke the functions to build and train the model. Train on the shuffled
# training set.
my_model = build_model(learning_rate)
epochs, rmse, history = train_model(my_model, shuffled_train_df, my_feature,
my_label, epochs, batch_size,
validation_split)
plot_the_loss_curve(epochs, history["root_mean_squared_error"],
history["val_root_mean_squared_error"])
#测试集上的测试
x_test = test_df[my_feature]
y_test = test_df[my_label]
results = my_model.evaluate(x_test, y_test, batch_size=batch_size)
最后的rmse在三者上相近